Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Tree Component: Inconsistent Parent Node Indeterminate State Behavior #1458

Open
lanzosuarez opened this issue Nov 25, 2024 Discussed in #1457 · 1 comment
Open

Comments

@lanzosuarez
Copy link

Discussed in #1457

Originally posted by lanzosuarez November 26, 2024
Hi everyone,
I've noticed an inconsistency with the indeterminate state behavior in the Tree component. The issue manifests differently depending on the selection order:

When selecting a child first:

Parent node remains unchecked, doesn't enter indeterminate state

image

When selecting parent first, then unselecting a child:

Parent correctly enters indeterminate state

image

Is this intentional?

Expected Behavior:

The parent node should enter indeterminate state in both scenarios when some (but not all) children are selected, regardless of selection order.

Has anyone encountered this issue or have insights on how to achieve consistent indeterminate state behavior?
Let me know if you need any clarification or additional information about my setup.

Here's my code:

<script setup lang="ts">
import { TreeItem, TreeRoot } from "radix-vue";
import { NRSCheckbox, NRSIcon } from "@/main";

type TreeItemData = {
  title: string;
  icon?: string;
  children?: TreeItemData[];
  value: string;
};

interface Props {
  items: TreeItemData[];
  defaultExpanded?: string[];
}

const props = withDefaults(defineProps<Props>(), {
  defaultExpanded: () => [],
});

const value = defineModel<TreeItemData[]>();

// Watch for value changes (for debugging)
watchEffect(() => {
  if (value.value) {
    console.log(
      "Selected items:",
      value.value.map((item) => item.title)
    );
  }
});
</script>

<template>
  <TreeRoot
    v-model="value"
    v-slot="{ flattenItems }"
    class="nrs-tree"
    :items="items"
    :get-key="(item) => item.title"
    :default-expanded="props.defaultExpanded"
    multiple
    propagate-select
  >
    <slot name="header">
      <h2 class="nrs-tree-header">Directory Structure</h2>
    </slot>

    <TreeItem
      v-for="item in flattenItems"
      :key="item._id"
      v-bind="item.bind"
      v-slot="{ isSelected, isIndeterminate, isExpanded, handleSelect }"
      
      :style="{ '--item-level': `${item.level - 1}` }"
      class="nrs-tree-item"
    >
      <template v-if="item.hasChildren">
        <button @click="item.bind.onToggle">
          <NRSIcon
            class="nrs-tree-toggle-icon"
            :name="!isExpanded ? 'chevron-right' : 'chevron-down'"
          />
        </button>
      </template>
      <button
        tabindex="-1"
        @click="
          () => {
            handleSelect();
          }
        "
        @click.stop
      >
        <NRSCheckbox
          :checked="isSelected"
          :id="item._id"
          :indeterminate="isIndeterminate"
          :text="item.value.title"
        />
      </button>
    </TreeItem>
  </TreeRoot>
</template>
<style lang="scss" scoped>
.nrs-tree {
  list-style-type: none;
  user-select: none;
  width: 14rem;
  background-color: var(--nrs-white);
  border-radius: 0.5rem;
  padding: 0.5rem;
  font-size: 0.875rem;
  font-weight: 500;
}

.nrs-tree-header {
  font-weight: 600;
  font-size: 1rem;
  color: var(--nrs-gray-900);
  padding: 0.5rem;
  margin-top: 0.25rem;
}

.nrs-tree-item {
  display: flex;
  align-items: center;
  padding: 0.25rem 0.5rem;
  margin: 0.125rem 0;
  border-radius: 0.25rem;
  outline: none;
  padding-left: calc(var(--item-level) * 2.375rem);

  .nrs-tree-toggle-icon {
    margin-right: 0.25rem;
  }

  &:focus {
    outline: 1px solid red;
  }

  &[data-selected="true"] {
    background-color: var(--nrs-gray-100);
  }
}

.nrs-tree-icon {
  height: 1rem;
  width: 1rem;
  color: var(--nrs-gray-500);
}

.nrs-tree-content {
  padding-left: 0.5rem;
  color: var(--nrs-gray-900);
}

// Reset button styles
button {
  all: unset;
  cursor: pointer;
  display: flex;
  align-items: center;

  &:focus-visible {
    outline: 2px solid var(--nrs-primary-500);
    outline-offset: -2px;
  }
}
</style>


```</div>
@lanzosuarez lanzosuarez changed the title Tree Component: Inconsistent Parent Node Indeterminate State Behavior [Bug] Tree Component: Inconsistent Parent Node Indeterminate State Behavior Nov 25, 2024
@zernonia
Copy link
Member

zernonia commented Dec 4, 2024

This is intended behavior. However I think we can implement a bubbleSelect props to allow selecting children will set parent item to indeterminate or checked 😁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants