OdysseyUI

Tree Filter

Animated tree-structured filter with nested checkboxes, live search, and indeterminate states.

Loading...

Installation

Usage

import {
  TreeFilter,
  TreeFilterSearch,
  TreeFilterGroup,
  TreeFilterList,
} from '@/components/odysseyui/tree-filter';

const items = [
  {
    id: 'fruits',
    label: 'Fruits',
    count: 3,
    children: [
      { id: 'apple', label: 'Apple', count: 1 },
      { id: 'banana', label: 'Banana', count: 2 },
    ],
  },
];

export default function Page() {
  return (
    <TreeFilter defaultChecked={['apple']}>
      <TreeFilterSearch placeholder="Search..." />
      <TreeFilterGroup label="Category">
        <TreeFilterList items={items} />
      </TreeFilterGroup>
    </TreeFilter>
  );
}

How It Works

  • TreeFilter owns the checked state and exposes it via context.
  • Parent nodes show an indeterminate state when only some children are checked.
  • Checking a parent toggles all its leaf descendants at once.
  • TreeFilterSearch filters the visible tree in real time — branches with any matching descendant stay visible.
  • Expand/collapse uses Radix Collapsible with a smooth animated chevron and height transition.

API Reference

TreeFilter

PropTypeDefault
defaultChecked?
string[]
[]

TreeFilterSearch

PropTypeDefault
placeholder?
string
"Search..."

TreeFilterGroup

PropTypeDefault
label?
string
-

TreeFilterList

PropTypeDefault
items
TreeNode[]
-

TreeNode shape

interface TreeNode {
  id: string;
  label: string;
  count?: number;
  children?: TreeNode[];
}

Built by Shr3kx & iam-sahil. The source code is available on GitHub.

Last updated: 3/26/2026