For AI agents: the complete documentation index is available at https://ifhover.github.io/leaf-ui/v/0.6.0/en/llms.txt, the full documentation bundle is available at https://ifhover.github.io/leaf-ui/v/0.6.0/en/llms-full.txt, and this page is available as Markdown at https://ifhover.github.io/leaf-ui/v/0.6.0/en/components/cascader.md.
  • English
  • Cascader

    Choose a value through a hierarchy of options.

    Examples

    A selection is committed at a leaf option. onChange supplies both the path and its options. Named fields submit a JSON array string. Use arrow keys to navigate levels, Enter to choose and Escape to close.

    basic.tsx
    import { Cascader, Form, FormField } from '@ifhover/leaf-ui';
    
    const options = [
      {
        value: 'design',
        label: 'Design',
        children: [
          { value: 'interface', label: 'Interface design' },
          { value: 'brand', label: 'Brand design' },
        ],
      },
      {
        value: 'engineering',
        label: 'Engineering',
        children: [
          { value: 'frontend', label: 'Frontend development' },
          { value: 'backend', label: 'Backend development' },
        ],
      },
      { value: 'archived', label: 'Archived category', disabled: true },
    ];
    
    export function CascaderBasic() {
      return (
        <Form layout="vertical">
          <FormField label="Project category">
            <Cascader aria-label="Project category" options={options} placeholder="Choose a category" />
          </FormField>
          <FormField label="Default category">
            <Cascader
              aria-label="Default category"
              options={options}
              defaultValue={['design', 'interface']}
            />
          </FormField>
          <FormField label="Disabled category">
            <Cascader aria-label="Disabled category" options={options} disabled />
          </FormField>
        </Form>
      );
    }
    
    Selected path:zhejiang → hangzhou → xihu
    controlled.tsx
    import { Cascader, Form, FormField, Text } from '@ifhover/leaf-ui';
    
    import { useState } from 'react';
    
    import { regions } from './options';
    
    export function CascaderControlled() {
      const [value, setValue] = useState<string[]>(['zhejiang', 'hangzhou', 'xihu']);
      return (
        <Form layout="vertical">
          <FormField label="Delivery region">
            <Cascader
              aria-label="Delivery region"
              options={regions}
              value={value}
              onChange={setValue}
            />
          </FormField>
          <Text tone="muted">Selected path:{value.join(' → ') || 'Not selected'}</Text>
        </Form>
      );
    }
    

    Search, multiple paths and lazy loading

    Search, multiple paths and intermediate levels
    Lazy loading and explicit cache refresh
    capabilities.tsx
    import type { CascaderOption } from '@ifhover/leaf-ui';
    
    import { Button, Cascader, Flex, Space, Text } from '@ifhover/leaf-ui';
    
    import { useCallback, useState } from 'react';
    
    const options = [
      {
        value: 'product',
        label: 'Product',
        children: [
          { value: 'ui', label: 'UI' },
          { value: 'web', label: 'Web' },
        ],
      },
      { value: 'team', label: 'Team', children: [{ value: 'design', label: 'Design' }] },
    ];
    
    const lazy: CascaderOption[] = [{ value: 'remote', label: 'Remote', isLeaf: false }];
    
    export function Capabilities() {
      const [version, setVersion] = useState(0);
      const load = useCallback(async (option: CascaderOption, signal: AbortSignal) => {
        await new Promise<void>((resolve, reject) => {
          const timer = setTimeout(resolve, 350);
          signal.addEventListener(
            'abort',
            () => {
              clearTimeout(timer);
              reject(signal.reason);
            },
            { once: true },
          );
        });
        return [{ value: `${option.value}-child`, label: 'Loaded item', isLeaf: true }];
      }, []);
      return (
        <Space direction="vertical" align="stretch">
          <Flex direction="column" gap="sm" align="center">
            <Text>
              {'Search, multiple paths and intermediate levels'}
            </Text>
            <Cascader options={options} showSearch multiple changeOnSelect />
          </Flex>
          <Flex direction="column" gap="sm" align="center">
            <Text>{'Lazy loading and explicit cache refresh'}</Text>
            <Cascader options={lazy} loadData={load} cacheKey={version} allowClear />
          </Flex>
          <Button variant="outline" onClick={() => setVersion(version + 1)}>
            {'Refresh data'}
          </Button>
        </Space>
      );
    }
    

    Single-line selections

    Set tagWrap={false} to keep selected values on one line. Long labels truncate; extra values collapse into +N. In very narrow controls, only the count is shown. Open the popup to review or change selections. maxTagCount can further limit the visible tags; maxTagCount="responsive" also enables automatic single-line collapsing.

    single-line.tsx
    import { Cascader } from '@ifhover/leaf-ui';
    
    const options = [
      {
        value: 'product',
        label: 'Product',
        children: [
          { value: 'design', label: 'Experience design' },
          { value: 'web', label: 'Web development' },
          { value: 'mobile', label: 'Mobile development' },
        ],
      },
    ];
    
    export function SingleLine() {
      return (
        <Cascader
          aria-label="Product teams"
          multiple
          showSearch
          tagWrap={false}
          options={options}
          defaultValue={[
            ['product', 'design'],
            ['product', 'web'],
            ['product', 'mobile'],
          ]}
        />
      );
    }
    

    Cascader API

    PropertyTypeDefaultDescription
    popupPlacement'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end'—Placement relative to the trigger.
    popupClassNamestring—Custom class for the popup.
    popupStyleCSSProperties—Custom popup styles.
    popupRender(content: React.ReactNode) => React.ReactNode—Wrap or extend popup content; retain the supplied content to preserve interaction.
    getPopupContainer() => Element | DocumentFragment—Return a popup container, including a ShadowRoot.
    optionsreadonly CascaderOption[]RequiredRequired. Hierarchical options
    size'sm' | 'md' | 'lg''md'Control size
    status'error' | 'warning'—Validation appearance
    placeholderstringLocale defaultPlaceholder when empty; localized by ConfigProvider
    namestring—Field name / associated form ID
    requiredbooleanfalseRequire a non-empty value; compound controls validate once.
    allowClearbooleantrueClearing returns two empty arrays
    onOpenChange(open: boolean) => void—Panel open-state changes
    openboolean—Control whether the panel is open.
    defaultOpenboolean—Initial open state.
    readOnlyboolean—Lock the value against typing, selection, clearing and removal.
    showSearchboolean—Enable search input.
    changeOnSelectboolean—Allow selecting intermediate levels.
    displayRender(labels: ReactNode[], selectedOptions: CascaderOption[]) => ReactNode—Customize displayed paths.
    optionRender(option: CascaderOption) => ReactNode—Customize option content.
    loadData(option: CascaderOption, signal: AbortSignal) => Promise<readonly CascaderOption[]>—Load child nodes asynchronously and respect AbortSignal.
    onLoadError(error: unknown, option: CascaderOption) => void—Called on loading failure, for retry feedback.
    cacheKeystring | number—Changing the data version clears lazy caches and cancels stale requests.
    tagWrapbooleantrueAllow selected tags to wrap; false keeps one line and collapses overflow.
    maxTagCountnumber | 'responsive'—Maximum visible tags; responsive collapses them to the available width.
    multiplefalse | truefalseEnable multiple selection; value and callback types change accordingly.
    valuereadonly string[] | readonly (readonly string[])[]RequiredValue; unique at the same level
    defaultValuereadonly string[] | readonly (readonly string[])[][]Controlled path / initial uncontrolled path
    onChange((value: string[], selectedOptions: CascaderOption[]) => void) | ((value: string[][], selectedOptions: CascaderOption[][]) => void)—Runs when a leaf is selected or the path is cleared
    disabledbooleanfalseDisable interaction.
    formstring—ID of the associated native form.
    refRef<HTMLButtonElement>—DOM reference
    childrenreadonly CascaderOption[]—Content, or child nodes for hierarchical records.

    CascaderOption

    PropertyTypeDefaultDescription
    valuestringRequiredValue; unique at the same level
    labelstringRequiredOption label
    disabledbooleanfalseDisable this option and its descendants
    childrenreadonly CascaderOption[]—Child options; an option without children can be selected

    Types

    Import CascaderProps to describe component props. Option types in the API table link to their detailed fields above.

    import type { CascaderProps, CascaderOption } from '@ifhover/leaf-ui';

    Forms and localization

    Use name to include values in FormData. Uncontrolled fields follow form reset; reset controlled values in application state. Place controls in FormField for labels, help and errors. ConfigProvider supplies regional themes and translated built-in UI. Application labels and options are your responsibility.

    CascaderOption

    PropertyTypeDefaultDescription
    valuestring—Required. Controlled value.
    labelReactNode—Required. Visible label or content.
    searchLabelstring—Plain text used for searching.
    isLeafboolean—Identify a leaf node, including in lazy data.
    disabledboolean—Disable interaction.
    childrenreadonly CascaderOption[]—Content, or child nodes for hierarchical records.

    CascaderFieldNames

    PropertyTypeDefaultDescription
    valuestring—Controlled value.
    labelstring—Visible label or content.
    childrenstring—Content, or child nodes for hierarchical records.
    disabledstring—Disable interaction.
    isLeafstring—Identify a leaf node, including in lazy data.