Knit UI
GitHub

Playground

Loading playground…

false
false
false
true
true
true
Playground
<TreeSelect
  data={[{ value: "fruit", label: "Fruit", children: [{ value: "apple", label: "Apple" }, { value: "banana", label: "Banana" }, { value: "citrus", label: "Citrus", children: [{ value: "lemon", label: "Lemon" }, { value: "orange", label: "Orange" }] }] }, { value: "vegetables", label: "Vegetables", children: [{ value: "carrot", label: "Carrot" }, { value: "broccoli", label: "Broccoli" }] }, { value: "dairy", label: "Dairy" }]}
  placeholder="Pick a food…"
  size="sm"
  clearable={false}
  searchable={false}
  disabled={false}
  allowDeselect
  expandOnClick
  withScrollArea
  maxDropdownHeight={250}
/>

Examples

Sizes

All seven sizes rendered side by side for quick visual comparison.

Loading example…

SizesSourceStorybook

Shadows

The shadow elevation prop, inherited from Box, across all token levels.

Loading example…

ShadowsSourceStorybook

Theme

Accent follows the Tamagui theme prop, not a Mantine-style color prop.

Loading example…

ThemeSourceStorybook

Disabled

Disabled state — the input is inert and the dropdown cannot be opened.

Loading example…

DisabledSourceStorybook

Read Only

Read-only — the selected value is visible but locked; the dropdown does not open.

Loading example…

Read OnlySourceStorybook

Default Value

Pre-selected value supplied via defaultValue (uncontrolled).

Loading example…

Default ValueSourceStorybook

Searchable

Typing in the input filters the tree to matching nodes only.

Loading example…

SearchableSourceStorybook

Clearable

Shows a clear button next to the chevron when a value is selected.

Loading example…

ClearableSourceStorybook

Deep Tree

A deep tree — three levels of nesting — shows nested expand/collapse.

Loading example…

Deep TreeSourceStorybook

Controlled

Fully controlled selection — selection state is owned by the parent.

Loading example…

ControlledSourceStorybook

No Deselect

allowDeselect={false} — pressing an already-selected node does not clear it.

Loading example…

No DeselectSourceStorybook

Styles

Per-slot styles targets individual parts — here the trigger and chevron.

Loading example…

StylesSourceStorybook

Props

PropTypeDefaultDescription
data requiredTreeNodeData[]Hierarchical data rendered in the dropdown.
allowDeselectboolean | undefinedtrueAllow deselecting by pressing the already-selected node again.
autoCapitalize"none" | (string & {}) | "off" | "on" | "sentences" | "words" | "characters" | undefined
autoCompletestring | undefined
autoCorrectstring | boolean | undefined
autoFocusboolean | undefined
autosizeboolean | undefinedfalseGrows with content on web (scrollHeight-based); tracks onContentSizeChange on native.
childrenReactNodeRendered inside the host element. Only meaningful for the `button` host (e.g. FileInput's trigger displays the picked file name); ignored for the native `input`/`textarea`/`select` hosts.
clearableboolean | undefinedfalseShow a clear button when a value is selected.
clearButtonPropsPartial<ComboboxClearButtonProps> | undefinedProps forwarded to the internal clear `Combobox.ClearButton`.
clearSectionMode"default" | "clear" | "rightSection" | "both" | undefined'both'How the clear button and right section coexist.
comboboxPropsPartial<ComboboxProps> | undefinedProps forwarded to the underlying `Combobox`.
componentInputHostTag | undefinedOverride the host element tag (defaults to `input`/`textarea`).
cursorColor"unset" | ColorTokens | undefined
defaultDropdownOpenedboolean | undefinedUncontrolled initial dropdown opened state.
defaultSearchValuestring | undefinedUncontrolled initial search value.
defaultValuestring | null | undefinedUncontrolled initial value.
descriptionReactNode
descriptionPropsGetFinalProps<RNTamaguiTextNonStyleProps, TextStylePropsBase, { span?: boolean | undefined; size?: string | number | undefined; inherit?: boolean | undefined; lineClamp?: number | undefined; truncate?: boolean | "end" | "start" | undefined;…
disabled systemboolean | undefinedfalse
dropdownOpenedboolean | undefinedControlled dropdown opened state.
enterKeyHint"search" | "enter" | "done" | "go" | "next" | "previous" | "send" | undefined
errorReactNode
errorPropsGetFinalProps<RNTamaguiTextNonStyleProps, TextStylePropsBase, { span?: boolean | undefined; size?: string | number | undefined; inherit?: boolean | undefined; lineClamp?: number | undefined; truncate?: boolean | "end" | "start" | undefined;…
expandOnClickboolean | undefinedtrueExpand a node with children when its row is pressed.
idstring | undefinedSame as the web id property for setting a uid on an element
inputContainer((children: ReactNode) => ReactNode) | undefined
inputSizestring | undefinedHost size attribute for the input element
inputWrapperOrderInputWrapperOrderItem[] | undefined
labelReactNode
labelElement"div" | "label" | undefined
labelPropsInputLabelProps | undefined
leftSectionReactNodeContent section displayed on the left side of the input
leftSectionPointerEventsInputSectionPointerEvents | undefined"none"Sets pointer-events styles on the left section element
leftSectionPropsPartial<GetFinalProps<RNTamaguiViewNonStyleProps, StackStyleBase, { shadow?: "xs" | "sm" | "md" | "lg" | "xl" | "xxs" | "xxl" | undefined; sectionPointerEvents?: "none" | "all" | undefined; }>> | undefinedProps passed down to the left section element
leftSectionWidthnumber | Animated.AnimatedNode | GetThemeValueForKey<"width"> | null | undefinedLeft section width, by default equals to the input height
loadingboolean | undefinedDisplays loading indicator in the left or right section
loadingPosition"left" | "right" | undefined"right"Position of the loading indicator
maxstring | number | undefined
maxDropdownHeightnumber | undefined250Max dropdown height in px before scrolling.
maxLengthnumber | undefined
maxRowsnumber | undefinedMaximum number of rows before scrolling (web). Caps height on native when autosize is on.
minstring | number | undefined
minLengthnumber | undefined
minRowsnumber | undefinedMinimum number of rows. Sets initial/minimum height on web; maps to numberOfLines on native.
multilineboolean | undefinedAdjusts padding and sizing calculations for multiline inputs
multipleboolean | undefined
namestring | undefined
nothingFoundMessageReactNodeMessage shown when no node matches the search.
onChange((value: string | null, node: TreeNodeData | null) => void) | undefinedCalled with the next value and its node (or `null`).
onChangeText((text: string) => void) | undefinedFires on every change with just the string value.
onClear(() => void) | undefinedCalled when the clear button is pressed.
onDropdownClose(() => void) | undefinedCalled when the dropdown closes.
onDropdownOpen(() => void) | undefinedCalled when the dropdown opens.
onSearchChange((value: string) => void) | undefinedCalled when the search value changes.
onSelectionChange((event: InputSelectionChangePayload) => void) | undefinedFires when the text selection changes.
onSubmitEditing((event: InputTextEventPayload) => void) | undefinedFires when Enter/Return is pressed.
patternstring | undefined
placeholderstring | undefinedPick a food…
placeholderTextColor"unset" | ColorTokens | undefined
pointerboolean | undefinedDetermines whether the input should have cursor: pointer style
radius systemstring | number | undefinedKey of theme radius or a valid CSS value to set border-radius
readOnlyboolean | undefined
requiredboolean | undefined
rightSectionReactNodeContent section displayed on the right side of the input
rightSectionPointerEventsInputSectionPointerEvents | undefined"none"Sets pointer-events styles on the right section element
rightSectionPropsPartial<GetFinalProps<RNTamaguiViewNonStyleProps, StackStyleBase, { shadow?: "xs" | "sm" | "md" | "lg" | "xl" | "xxs" | "xxl" | undefined; sectionPointerEvents?: "none" | "all" | undefined; }>> | undefinedProps passed down to the right section element
rightSectionWidthnumber | Animated.AnimatedNode | GetThemeValueForKey<"width"> | null | undefinedRight section width, by default equals to the input height
rootRefRef<TamaguiElement> | undefinedRoot element ref
rowsnumber | undefinedRows for textarea (when render="textarea")
searchableboolean | undefinedfalseAllow filtering nodes by typing.
searchValuestring | undefinedControlled search value.
selection{ start: number; end?: number; } | undefinedSelection range
selectionColor"unset" | ColorTokens | undefined
selectionHandleColor"unset" | ColorTokens | undefined
shadow system"xs" | "sm" | "md" | "lg" | "xl" | "xxs" | "xxl" | undefined
size system"xs" | "sm" | "md" | "lg" | "xl" | "xxs" | "xxl" | undefined
xxs · xs · sm · md · lg · xl · xxl
'md'Control size — matches InputBase / Combobox size tokens.
spellCheckboolean | undefinedControls spell checking.
stepstring | number | undefined
styles systemSlotStyles<TreeSelectStyles> | undefinedPer-slot style sugar — props spread onto the matching part.
textContentTypeInputTextContentType | undefinedText content type for iOS autofill. Use `autoComplete` where available.
theme systemThemeName | null | undefinedApplies a theme to this element
treeTreeController | undefinedExternal tree controller from `useTree`; created internally when omitted.
typestring | undefined
underlineColorAndroid"unset" | ColorTokens | undefined
valuestring | null | undefinedControlled selected node value.
variant systemInputVariant | undefined"default"Visual variant
withAriaboolean | undefinedtrueDetermines whether accessibility attributes should be added
withAsteriskboolean | undefined
withScrollAreaboolean | undefinedtrueWrap the dropdown tree in a `ScrollArea.Autosize`.
wrapperProps({ readonly br?: number | "$xs" | "$sm" | "$md" | "$lg" | "$xl" | "unset" | "$0" | "$true" | "$xxs" | "$xxl" | Variable<any> | `${number}rem` | UnionableNumber | "inherit" | `var(${string})` | Animated.AnimatedNode | null | undefined; label…Props passed down to the root element (`Input.Wrapper` component)

Style slots

Every part of TreeSelect can be styled through the styles prop. Explicit props on the component always win over slot styles.

SlotUsage
chevronstyles={{ chevron: { … } }}
clearButtonstyles={{ clearButton: { … } }}
dropdownstyles={{ dropdown: { … } }}
emptystyles={{ empty: { … } }}
nodestyles={{ node: { … } }}
nodeChevronstyles={{ nodeChevron: { … } }}
nodeLabelstyles={{ nodeLabel: { … } }}
rootstyles={{ root: { … } }}
treestyles={{ tree: { … } }}
triggerstyles={{ trigger: { … } }}
Accessibility & DOM props (218)
PropType
aboutstring | undefined
acceptstring | undefined
accessKeystring | undefined
altstring | undefined
aria-activedescendantstring | undefined
aria-atomic(boolean | "true" | "false") | undefined
aria-autocomplete"none" | "inline" | "list" | "both" | undefined
aria-braillelabelstring | undefined
aria-brailleroledescriptionstring | undefined
aria-colcountnumber | undefined
aria-colindexnumber | undefined
aria-colindextextstring | undefined
aria-colspannumber | undefined
aria-controlsstring | undefined
aria-currentboolean | "time" | "true" | "false" | "page" | "step" | "location" | "date" | undefined
aria-describedbystring | undefined
aria-descriptionstring | undefined
aria-detailsstring | undefined
aria-dropeffect"link" | "none" | "copy" | "move" | "execute" | "popup" | undefined
aria-errormessagestring | undefined
aria-flowtostring | undefined
aria-grabbed(boolean | "true" | "false") | undefined
aria-haspopupboolean | "dialog" | "menu" | "true" | "false" | "grid" | "tree" | "listbox" | undefined
aria-invalidboolean | "true" | "false" | "grammar" | "spelling" | undefined
aria-keyshortcutsstring | undefined
aria-levelnumber | undefined
aria-multiline(boolean | "true" | "false") | undefined
aria-multiselectable(boolean | "true" | "false") | undefined
aria-orientation"horizontal" | "vertical" | undefined
aria-ownsstring | undefined
aria-placeholderstring | undefined
aria-posinsetnumber | undefined
aria-pressedboolean | "true" | "false" | "mixed" | undefined
aria-readonly(boolean | "true" | "false") | undefined
aria-relevant"all" | "text" | "additions" | "additions removals" | "additions text" | "removals" | "removals additions" | "removals text" | "text additions" | "text removals" | undefined
aria-required(boolean | "true" | "false") | undefined
aria-roledescriptionstring | undefined
aria-rowcountnumber | undefined
aria-rowindexnumber | undefined
aria-rowindextextstring | undefined
aria-rowspannumber | undefined
aria-setsizenumber | undefined
aria-sort"none" | "ascending" | "descending" | "other" | undefined
autoSavestring | undefined
captureboolean | "user" | "environment" | undefined
checkedboolean | undefined
contentEditable"inherit" | (boolean | "true" | "false") | "plaintext-only" | undefined
contextMenustring | undefined
datatypestring | undefined
defaultCheckedboolean | undefined
dirstring | undefined
draggable(boolean | "true" | "false") | undefined
exportpartsstring | undefined
formstring | undefined
formActionstring | ((formData: FormData) => void | Promise<void>) | undefined
formEncTypestring | undefined
formMethodstring | undefined
formNoValidateboolean | undefined
formTargetstring | undefined
hiddenboolean | undefined
inertboolean | undefined
inlistany
inputMode"search" | "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | undefined
isstring | undefined
itemIDstring | undefined
itemPropstring | undefined
itemRefstring | undefined
itemScopeboolean | undefined
itemTypestring | undefined
keyKey | null | undefined
langstring | undefined
liststring | undefined
noncestring | undefined
onAbortReactEventHandler<HTMLInputElement> | undefined
onAbortCaptureReactEventHandler<HTMLInputElement> | undefined
onAnimationEndAnimationEventHandler<HTMLInputElement> | undefined
onAnimationEndCaptureAnimationEventHandler<HTMLInputElement> | undefined
onAnimationIterationAnimationEventHandler<HTMLInputElement> | undefined
onAnimationIterationCaptureAnimationEventHandler<HTMLInputElement> | undefined
onAnimationStartAnimationEventHandler<HTMLInputElement> | undefined
onAnimationStartCaptureAnimationEventHandler<HTMLInputElement> | undefined
onAuxClickMouseEventHandler<HTMLInputElement> | undefined
onAuxClickCaptureMouseEventHandler<HTMLInputElement> | undefined
onBeforeInputCaptureInputEventHandler<HTMLInputElement> | undefined
onBeforeToggleToggleEventHandler<HTMLInputElement> | undefined
onBlurCaptureFocusEventHandler<HTMLInputElement> | undefined
onCanPlayReactEventHandler<HTMLInputElement> | undefined
onCanPlayCaptureReactEventHandler<HTMLInputElement> | undefined
onCanPlayThroughReactEventHandler<HTMLInputElement> | undefined
onCanPlayThroughCaptureReactEventHandler<HTMLInputElement> | undefined
onChangeCaptureChangeEventHandler<HTMLInputElement, Element> | undefined
onClickCaptureMouseEventHandler<HTMLInputElement> | undefined
onCompositionEndCompositionEventHandler<HTMLInputElement> | undefined
onCompositionEndCaptureCompositionEventHandler<HTMLInputElement> | undefined
onCompositionStartCompositionEventHandler<HTMLInputElement> | undefined
onCompositionStartCaptureCompositionEventHandler<HTMLInputElement> | undefined
onCompositionUpdateCompositionEventHandler<HTMLInputElement> | undefined
onCompositionUpdateCaptureCompositionEventHandler<HTMLInputElement> | undefined
onContextMenuCaptureMouseEventHandler<HTMLInputElement> | undefined
onCopyCaptureClipboardEventHandler<HTMLInputElement> | undefined
onCutCaptureClipboardEventHandler<HTMLInputElement> | undefined
onDoubleClickCaptureMouseEventHandler<HTMLInputElement> | undefined
onDragCaptureDragEventHandler<HTMLInputElement> | undefined
onDragEndCaptureDragEventHandler<HTMLInputElement> | undefined
onDragEnterCaptureDragEventHandler<HTMLInputElement> | undefined
onDragExitDragEventHandler<HTMLInputElement> | undefined
onDragExitCaptureDragEventHandler<HTMLInputElement> | undefined
onDragLeaveCaptureDragEventHandler<HTMLInputElement> | undefined
onDragOverCaptureDragEventHandler<HTMLInputElement> | undefined
onDragStartCaptureDragEventHandler<HTMLInputElement> | undefined
onDropCaptureDragEventHandler<HTMLInputElement> | undefined
onDurationChangeReactEventHandler<HTMLInputElement> | undefined
onDurationChangeCaptureReactEventHandler<HTMLInputElement> | undefined
onEmptiedReactEventHandler<HTMLInputElement> | undefined
onEmptiedCaptureReactEventHandler<HTMLInputElement> | undefined
onEncryptedReactEventHandler<HTMLInputElement> | undefined
onEncryptedCaptureReactEventHandler<HTMLInputElement> | undefined
onEndedReactEventHandler<HTMLInputElement> | undefined
onEndedCaptureReactEventHandler<HTMLInputElement> | undefined
onErrorReactEventHandler<HTMLInputElement> | undefined
onErrorCaptureReactEventHandler<HTMLInputElement> | undefined
onFocusCaptureFocusEventHandler<HTMLInputElement> | undefined
onGotPointerCapturePointerEventHandler<HTMLInputElement> | undefined
onGotPointerCaptureCapturePointerEventHandler<HTMLInputElement> | undefined
onInputCaptureInputEventHandler<HTMLInputElement> | undefined
onInvalidReactEventHandler<HTMLInputElement> | undefined
onInvalidCaptureReactEventHandler<HTMLInputElement> | undefined
onKeyDownCaptureKeyboardEventHandler<HTMLInputElement> | undefined
onKeyPressKeyboardEventHandler<HTMLInputElement> | undefined
onKeyPressCaptureKeyboardEventHandler<HTMLInputElement> | undefined
onKeyUpCaptureKeyboardEventHandler<HTMLInputElement> | undefined
onLoadReactEventHandler<HTMLInputElement> | undefined
onLoadCaptureReactEventHandler<HTMLInputElement> | undefined
onLoadedDataReactEventHandler<HTMLInputElement> | undefined
onLoadedDataCaptureReactEventHandler<HTMLInputElement> | undefined
onLoadedMetadataReactEventHandler<HTMLInputElement> | undefined
onLoadedMetadataCaptureReactEventHandler<HTMLInputElement> | undefined
onLoadStartReactEventHandler<HTMLInputElement> | undefined
onLoadStartCaptureReactEventHandler<HTMLInputElement> | undefined
onLostPointerCapturePointerEventHandler<HTMLInputElement> | undefined
onLostPointerCaptureCapturePointerEventHandler<HTMLInputElement> | undefined
onMouseDownCaptureMouseEventHandler<HTMLInputElement> | undefined
onMouseMoveCaptureMouseEventHandler<HTMLInputElement> | undefined
onMouseOutCaptureMouseEventHandler<HTMLInputElement> | undefined
onMouseOverCaptureMouseEventHandler<HTMLInputElement> | undefined
onMouseUpCaptureMouseEventHandler<HTMLInputElement> | undefined
onPasteCaptureClipboardEventHandler<HTMLInputElement> | undefined
onPauseReactEventHandler<HTMLInputElement> | undefined
onPauseCaptureReactEventHandler<HTMLInputElement> | undefined
onPlayReactEventHandler<HTMLInputElement> | undefined
onPlayCaptureReactEventHandler<HTMLInputElement> | undefined
onPlayingReactEventHandler<HTMLInputElement> | undefined
onPlayingCaptureReactEventHandler<HTMLInputElement> | undefined
onPointerOutPointerEventHandler<HTMLInputElement> | undefined
onPointerOutCapturePointerEventHandler<HTMLInputElement> | undefined
onPointerOverPointerEventHandler<HTMLInputElement> | undefined
onPointerOverCapturePointerEventHandler<HTMLInputElement> | undefined
onProgressReactEventHandler<HTMLInputElement> | undefined
onProgressCaptureReactEventHandler<HTMLInputElement> | undefined
onRateChangeReactEventHandler<HTMLInputElement> | undefined
onRateChangeCaptureReactEventHandler<HTMLInputElement> | undefined
onResetReactEventHandler<HTMLInputElement> | undefined
onResetCaptureReactEventHandler<HTMLInputElement> | undefined
onScrollCaptureUIEventHandler<HTMLInputElement> | undefined
onScrollEndUIEventHandler<HTMLInputElement> | undefined
onScrollEndCaptureUIEventHandler<HTMLInputElement> | undefined
onSeekedReactEventHandler<HTMLInputElement> | undefined
onSeekedCaptureReactEventHandler<HTMLInputElement> | undefined
onSeekingReactEventHandler<HTMLInputElement> | undefined
onSeekingCaptureReactEventHandler<HTMLInputElement> | undefined
onSelectReactEventHandler<HTMLInputElement> | undefined
onSelectCaptureReactEventHandler<HTMLInputElement> | undefined
onStalledReactEventHandler<HTMLInputElement> | undefined
onStalledCaptureReactEventHandler<HTMLInputElement> | undefined
onSubmitSubmitEventHandler<HTMLInputElement> | undefined
onSubmitCaptureSubmitEventHandler<HTMLInputElement> | undefined
onSuspendReactEventHandler<HTMLInputElement> | undefined
onSuspendCaptureReactEventHandler<HTMLInputElement> | undefined
onTimeUpdateReactEventHandler<HTMLInputElement> | undefined
onTimeUpdateCaptureReactEventHandler<HTMLInputElement> | undefined
onToggleToggleEventHandler<HTMLInputElement> | undefined
onTouchCancelCaptureTouchEventHandler<HTMLInputElement> | undefined
onTouchMoveCaptureTouchEventHandler<HTMLInputElement> | undefined
onTouchStartCaptureTouchEventHandler<HTMLInputElement> | undefined
onTransitionCancelTransitionEventHandler<HTMLInputElement> | undefined
onTransitionCancelCaptureTransitionEventHandler<HTMLInputElement> | undefined
onTransitionEndTransitionEventHandler<HTMLInputElement> | undefined
onTransitionEndCaptureTransitionEventHandler<HTMLInputElement> | undefined
onTransitionRunTransitionEventHandler<HTMLInputElement> | undefined
onTransitionRunCaptureTransitionEventHandler<HTMLInputElement> | undefined
onTransitionStartTransitionEventHandler<HTMLInputElement> | undefined
onTransitionStartCaptureTransitionEventHandler<HTMLInputElement> | undefined
onVolumeChangeReactEventHandler<HTMLInputElement> | undefined
onVolumeChangeCaptureReactEventHandler<HTMLInputElement> | undefined
onWaitingReactEventHandler<HTMLInputElement> | undefined
onWaitingCaptureReactEventHandler<HTMLInputElement> | undefined
onWheelCaptureWheelEventHandler<HTMLInputElement> | undefined
partstring | undefined
popover"" | "auto" | "manual" | "hint" | undefined
popoverTargetstring | undefined
popoverTargetAction"hide" | "show" | "toggle" | undefined
prefixstring | undefined
propertystring | undefined
radioGroupstring | undefined
refRef<TamaguiElement> | undefined
resourcestring | undefined
resultsnumber | undefined
revstring | undefined
securitystring | undefined
slotstring | undefined
srcstring | undefined
suppressContentEditableWarningboolean | undefined
suppressHydrationWarningboolean | undefined
titlestring | undefined
translate"yes" | "no" | undefined
typeofstring | undefined
unselectable"off" | "on" | undefined
vocabstring | undefined

Plus 522 inherited style props from Box — the full Tamagui/React Native style surface, including token shorthands like p, mx, bg and c. See Tokens for the scales they accept, or the full list.