InputsReact
A button that opens a hierarchy as columns side by side, one column per level, to pick an item deep in it, such as a city under its country and continent.
Rendered by React 19.3.1
Loading React…Installation
npm i @hamur/reactNot on npm yet. The package goes out under the chosen name.
Anatomy
Import the component and assemble its parts:
<Cascader.Root>
<Cascader.Label />
<Cascader.Trigger>
<Cascader.Value />
<Cascader.Icon />
</Cascader.Trigger>
<Cascader.Clear />
<Cascader.Portal>
<Cascader.Positioner>
<Cascader.Popup>
<Cascader.Columns>
<Cascader.Column>
<Cascader.Item>
<Cascader.ItemText />
<Cascader.ItemIndicator />
<Cascader.ItemIcon />
</Cascader.Item>
</Cascader.Column>
</Cascader.Columns>
</Cascader.Popup>
</Cascader.Positioner>
</Cascader.Portal>
</Cascader.Root>
// Not in this example: Cascader.Arrow, Cascader.Backdrop, Cascader.Empty, Cascader.Input, Cascader.StatusExamples
Multiple
multiple with cascade and cascadeValue="parents": checking Europe checks its countries and reports one value, unchecking one of them leaves Europe mixed.
Search
An Input at the top of the popup: typing swaps the columns for one column of the matching cities shown with their paths, and "No cities found" shows when nothing matches.
Lazy
Inline columns whose children come from loadChildren: a highlighted region shows its column loading, then its offices.
API reference
72 props across 20 parts, in React syntax. className, style, render are listed once, under Shared props.
ArrowCascader.Arrow
Displays an element positioned against the popover anchor. Renders a <div>.
| Data attribute | Description |
|---|---|
data-open | Present when the popup is open. |
data-closed | Present when the popup is closed. |
data-side | Indicates which side the popup is positioned relative to the trigger. |
data-align | Indicates how the popup is aligned relative to specified side. |
data-uncentered | Present when the popover arrow is uncentered. |
BackdropCascader.Backdrop
An overlay displayed beneath the popover. Renders a <div>.
| Data attribute | Description |
|---|---|
data-open | Present when the popup is open. |
data-closed | Present when the popup is closed. |
data-starting-style | Present when the popup begins animating in. |
data-ending-style | Present when the popup is animating out. |
ClearCascader.Clear
Empties the value. Place it outside the trigger. Renders nothing while the value is empty. Renders a <button>.
| Prop | Type | Default |
|---|---|---|
nativeButtonWhether the component renders a native <button> element when replacing it | boolean | true |
ColumnCascader.Column
One column: the first level, the children of an item on the open path, or the search results. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
columnrequiredThe column to render, as Cascader.Columns hands it over. | CascaderColumn<any> | — |
childrenThe items: a node, or a function that renders each item of the column. | React.ReactNode | ((item: any, index: number) => React.ReactNode) | — |
ColumnsCascader.Columns
The tree: the columns of the open path side by side, or the search results, followed by its status region. Without Cascader.Popup around it, it is the control itself. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
childrenThe columns: a node, or a function that renders each column of the open path. | React.ReactNode | ((column: CascaderColumn<any>) => React.ReactNode) | — |
EmptyCascader.Empty
Content shown while the search has no results, or the first column has no items. Renders nothing otherwise. Renders a <div>.
IconCascader.Icon
An icon that shows the trigger opens a popup. Hidden from assistive technology. Renders a <span>.
InputCascader.Input
A text input that searches the cascader's paths. It keeps focus while the keys move the highlight through the columns, named by aria-activedescendant. Renders an <input>.
ItemCascader.Item
An item of a column. A parent's press opens its column; a selectable item's press chooses it. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
valuerequiredThe item, one of its column's items. | any | — |
indexThe item's index in its column, when the column renders only some of its items. | number | — |
ItemIconCascader.ItemIcon
A parent's chevron, rendered for parents only. Hidden from assistive technology. Renders a <span>.
ItemIndicatorCascader.ItemIndicator
Shows whether the item is selected or checked. A press toggles the item with multiple. Renders a <span>.
| Prop | Type | Default |
|---|---|---|
keepMountedWhether to keep the indicator in the DOM while the item is neither selected nor checked. | boolean | false |
ItemTextCascader.ItemText
The item's text: its label, or its path in the search results. Renders a <span>.
LabelCascader.Label
A label that names the trigger, or the columns when they are inline. A press focuses the trigger (the highlighted item inline). Renders a <div>.
PopupCascader.Popup
The container of the columns and the optional Input. Focus moves to the Input, else to the highlighted item, when it opens, and returns to the trigger when it closes. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
initialFocusDetermines the element to focus when the popover is opened. | boolean | React.RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | void | HTMLElement | null) | — |
finalFocusDetermines the element to focus when the popover is closed. | boolean | React.RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | void | HTMLElement | null) | — |
PortalCascader.Portal
A portal element that moves the popup to a different part of the DOM. By default, the portal element is appended to <body>. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
keepMountedWhether to keep the portal mounted in the DOM while the popup is hidden. | boolean | false |
containerA parent element to render the portal element into. | HTMLElement | ShadowRoot | React.RefObject<HTMLElement | ShadowRoot | null> | null | — |
PositionerCascader.Positioner
Positions the popup against the trigger; it moves as columns are added. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
alignHow to align the popup relative to the specified side. | Align | 'start' |
anchorAn element to position the popup against. | Element | VirtualElement | React.RefObject<Element | null> | (() => Element | VirtualElement | null) | null | — |
positionMethodDetermines which CSS position property to use. | "absolute" | "fixed" | 'absolute' |
sideWhich side of the anchor element to align the popup against. | Side | 'bottom' |
sideOffsetDistance between the anchor and the popup in pixels. | number | OffsetFunction | 0 |
alignOffsetAdditional offset along the alignment axis in pixels. | number | OffsetFunction | 0 |
collisionBoundaryAn element or a rectangle that delimits the area that the popup is confined to. | Boundary | 'clipping-ancestors' |
collisionPaddingAdditional space to maintain from the edge of the collision boundary. | Padding | 5 |
stickyWhether to maintain the popup in the viewport after | boolean | false |
arrowPaddingMinimum distance to maintain between the arrow and the edges of the popup. | number | 5 |
disableAnchorTrackingWhether to disable the popup from tracking any layout shift of its positioning anchor. | boolean | false |
collisionAvoidanceDetermines how to handle collisions when positioning the popup. | CollisionAvoidance | — |
RootCascader.Root
Groups all parts of the cascader: a trigger that opens columns of a hierarchy in a popup, or the columns alone, inline., only the form inputs. Doesn’t render its own element.
| Prop | Type | Default |
|---|---|---|
children | React.ReactNode | — |
idThe id of the field control, for the hidden input. | string | — |
itemsrequiredThe items of the first column. | readonly Value[] | — |
getItemChildrenThe children of an item: an array (a parent), null (a parent not loaded) or undefined | ((item: Value) => readonly Value[] | null | undefined) | — |
valueThe selected item, or items with multiple. | CascaderInputValue<Value, Multiple> | null | — |
defaultValueThe selected item, or items with multiple, when initially rendered. | CascaderInputValue<Value, Multiple> | null | null |
onValueChangeEvent handler called when the value changes. | ((value: CascaderOutputValue<Value, Multiple>, eventDetails: CascaderRootChangeEventDetails) => void) | — |
multipleWhether several items can be selected. | Multiple | false |
cascadeWith multiple: checking an item checks its enabled descendants. | boolean | false |
cascadeValueWhat the value holds under cascade: 'all', 'parents' or 'leaves'. | TreeCascadeValue | 'all' |
disallowEmptySelectionWhether the last selected item of a multiple cascader cannot be deselected. | boolean | false |
allowParentSelectionWhether parents can be chosen as well as leaves. | boolean | false |
isItemSelectableWhether an item can be chosen. | ((item: Value) => boolean) | — |
isItemDisabledWhether an item is disabled; its descendants are too. | ((item: Value) => boolean) | — |
itemToStringLabelConverts an item to its text: ItemText, typeahead, the path text and values not in the data. | ((item: Value) => string) | — |
itemToStringValueConverts an item to a string for form submission. | ((item: Value) => string) | — |
isItemEqualToValueCustom comparison logic used to determine if an item matches the value. | ((itemValue: Value, value: Value) => boolean) | — |
loadChildrenCalled when the highlight lands on a parent whose children are null. | ((item: Value, options: { signal: AbortSignal; }) => Promise<void | readonly Value[]>) | — |
onLoadChildrenErrorCalled when loadChildren rejects. | ((item: Value, error: unknown) => void) | — |
highlightedValueThe highlighted item, which decides the open path. | Value | — |
onHighlightChangeEvent handler called when the highlight moves. | ((value: Value) => void) | — |
onItemHighlightedVirtualized only: called when the highlight moves, with the item's index and level, so the | ((item: Value, eventDetails: CascaderHighlightDetails) => void) | — |
expandOnHoverWhether resting the pointer on an item moves the highlight there. | boolean | false |
expandDelayHow long the pointer rests on an item before it is highlighted, in milliseconds. | number | 100 |
loopFocusWhether Down on the last item of a column moves to the first, and Up on the first to the last. | boolean | false |
separatorThe text between the items of a path. | string | ' / ' |
inputValueThe text of Cascader.Input. | string | — |
defaultInputValueThe text of Cascader.Input when initially rendered. | string | '' |
onInputValueChangeEvent handler called when the text of Cascader.Input changes. | ((value: string, eventDetails: CascaderRootInputValueChangeEventDetails) => void) | — |
filterWhether an item matches the query: it receives the item, the query and a function that gives | ((item: Value, query: string, itemToString: (item: Value) => string) => boolean) | null | — |
filteredItemsThe results to show while there is a query, in place of filtering. | readonly Value[] | — |
virtualizedWhether the app renders only the visible items of each column. | boolean | false |
openWhether the popup is open. | boolean | — |
defaultOpenWhether the popup is initially open. | boolean | false |
onOpenChangeEvent handler called when the popup opens or closes. | ((open: boolean, eventDetails: CascaderRootOpenChangeEventDetails) => void) | — |
onOpenChangeCompleteEvent handler called after any animations complete when the popup opens or closes. | ((open: boolean) => void) | — |
actionsRefA ref to imperative actions. | React.RefObject<PopoverRootActions | null> | — |
modalWhether the rest of the page is inert while the popup is open. | boolean | "trap-focus" | true |
disabledWhether the component should ignore user interaction. | boolean | false |
readOnlyWhether the user should be unable to change the value. | boolean | false |
requiredWhether the user must choose a value before submitting a form. | boolean | false |
nameIdentifies the field when a form is submitted. | string | — |
formIdentifies the form that owns the hidden inputs. | string | — |
inputRefA ref to access the hidden input element. | React.Ref<HTMLInputElement> | — |
labelsThe texts of the status region. | Partial<CascaderLabels> | — |
StatusCascader.Status
A polite status region for the app's text, such as the number of results. Renders a <div>.
TriggerCascader.Trigger
A button that opens the popup and shows the value. It is a combobox whose popup is a tree. Renders a <button>.
| Prop | Type | Default |
|---|---|---|
nativeButtonWhether the component renders a native <button> element when replacing it | boolean | true |
idID of the trigger. | string | — |
ValueCascader.Value
The text of the value: each value's path, joined by the separator. Renders a <span>.
| Prop | Type | Default |
|---|---|---|
childrenWhat to show for the value instead of the path texts: a node, or a function of the value and | React.ReactNode | ((value: any, paths: any[][]) => React.ReactNode) | — |
placeholderWhat to show while nothing is selected. | React.ReactNode | — |
Shared props
Every part that renders an element takes these.
| Prop | Type |
|---|---|
classNameCSS class applied to the element, or a function that
returns a class based on the component's state. | string | ((state: State) => string | undefined) |
styleStyle applied to the element, or a function that
returns a style object based on the component's state. | React.CSSProperties | ((state: State) => React.CSSProperties | undefined) |
renderAllows you to replace the component's HTML element
with a different tag, or compose it with another component. | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, State> |
Keyboard and accessibility
Keyboard
| Keys | Does | Part |
|---|---|---|
| EnterSpaceArrowDownArrowUp | Opens the popup on the chosen item with its path open | Trigger |
| ArrowDownArrowUp | Moves within the column; the next column follows the highlight | Item |
| HomeEnd | Moves to the first or last item of the column | Item |
| ArrowRight | Enters the first child of a parent | Item |
| ArrowLeft | Goes back to the parent; the deeper columns close | Item |
| EnterSpace | Chooses a leaf, closes the popup and returns focus to the Trigger | Item |
| Spacemultiple | Checks or unchecks the item and keeps the popup open | Item |
| Move to the next item of the column whose text starts with them | Item | |
| Escape | Closes the popup and returns focus to the Trigger | Popup |
| Tab | Closes the popup and chooses nothing | Popup |
| ArrowDownArrowUpInput | Moves the highlight through the results while focus stays in the Input | Input |
| EnterInput | Chooses the highlighted result, closes the popup and clears the search | Input |
| EscapeInput | Clears the search first, then closes the popup | Input |
Accessibility
| Part | Sets | So that |
|---|---|---|
| Trigger | role="combobox", aria-haspopup="tree", aria-expanded and, while open, aria-controls; labelled by Label | the button says it opens a tree, and whether it is open |
| Icon | aria-hidden | the chevron is for sight |
| Columns | role="tree", named by Label or aria-label, with aria-multiselectable under multiple | the columns are read as one tree, not as several lists |
| Column | role="group" for each column after the first, owned by the item it shows the children of | a screen reader hears each column as the children of its parent |
| Item | role="treeitem", aria-level, aria-setsize, aria-posinset, aria-expanded on a parent, and aria-selected or, under multiple, aria-checked | each item says where it is in the hierarchy and whether it is chosen |
| ItemIcon | aria-hidden | the chevron of a parent is for sight; aria-expanded says it |
| Input | aria-controls the results and aria-activedescendant the highlighted one | a screen reader follows the highlight while focus stays in the text |
| Status | a polite role="status" region | a load of children, its failure and an empty result are announced |
| Clear | a button named "Clear" when it has no content, or by its text or aria-label | the value is emptied from the keyboard |
Focus order
- The
Triggeris the Tab stop, thenClearwhen there is one. Nothing takes focus on mount. - Opening moves focus to the chosen item with its path open, or the first item; with an
Input, to theInput. - Choosing a leaf or
Escapereturns focus to theTrigger;Tabcloses the popup. - Inline, the
Columnsare one Tab stop, on the highlighted item.