Back to catalog
Component detail entry
Forms
@vean/ui
SCascader

Cascader

Cascader belongs to the Forms category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

Cascader

Overview

A cascader for selecting values from hierarchical tree data. It renders a linked multi-column panel and supports single/multiple selection, full-path value mode, parent-child check-state propagation, local filtering and remote search, lazy loading of children, and virtual scrolling for large datasets. Use it when options are organized as a tree and selection must happen level by level; for flat option lists, prefer SSelect or SCombobox.

Usage

Features

  • 🗂 Linked multi-column panel — the path unfolds one level per column
  • ☑️ Single or multiple selection with cascading parent-child check states (showCheckedStrategy: child / parent)
  • 🛤 Full-path value mode (pathMode) — the model value carries the complete value/label path
  • ⏳ Data loading — lazy children (loadChildren), debounced remote search (searchDelay), local filtering (filter) with a localized empty state
  • 📜 Built-in per-column virtual scrolling (virtualScroll, configurable itemSize / height)
  • ⌨️ Full keyboard navigation — Arrow keys move across columns, Enter selects, plus click/hover expand
  • ♿ WAI-ARIA tree semantics — trigger role="combobox" + aria-haspopup="tree", option role="treeitem", axe-clean when open
  • 🎨 16 recipe slots and 7 size variants via cascaderVariants

Demos

Basic

Selected: "None"

Multiple

Searchable

Selected: None

LazyLoad

Selected: None

RemoteSearch

Selected: None

VirtualScroll

Selected: None

CustomOption

API

Aria Layer

17

Cascader<T, M, P>

44 Props9 Emits6 Slots
Props
PropTypeDefaultDescription
class
ClassValue
—
the class of cascader trigger
ui
Partial<CascaderUi>
—
Per-slot class overrides for the component.
size
ThemeSize
—
Visual size of the component.
showArrow
boolean
true
When `true`, the arrow icon is rendered.
placement
import("@/index").Placement
—
The placement of the content.
triggerProps
CascaderTriggerProps
—
Properties forwarded to the trigger part.
valueProps
CascaderValueProps
—
Properties forwarded to the value part.
searchInputProps
CascaderSearchInputProps
—
Properties forwarded to the search input part.
portalProps
PortalProps
—
Properties forwarded to the portal part.
contentProps
CascaderContentProps
—
Properties forwarded to the content part.
menuProps
CascaderMenuProps
—
Properties forwarded to every menu part.
optionProps
Partial<CascaderOptionProps<T>>
—
Properties forwarded to every option part.
emptyProps
CascaderEmptyProps
—
Properties forwarded to the empty part.
emptyLabel
string
The locale message
The text shown in the empty state.
clearLabel
string
The locale message
The accessible label of the clear button.
arrowProps
PopperArrowProps
—
Properties forwarded to the arrow part.
modelValue
CascaderValueType<T, M, P>
—
The controlled value of the selected node(s). Can be bound with `v-model`.
defaultValue
CascaderValueType<T, M, P>
—
The default value of the selected node(s).
multiple
M
—
When `true`, multiple nodes can be selected.
pathMode
P
false
When `true`, the model value is the full path array(s) instead of the node value(s).
options
CascaderOptionData<T>[]
—
Options of the cascader.
fieldKeys
CascaderFieldKeys
—
Field keys used to extract the option fields.
open
boolean
—
The controlled open state of the Cascader. Can be bound as `v-model:open`.
defaultOpen
boolean
—
The open state of the cascader when it is initially rendered.
disabled
boolean
—
When `true`, prevents the user from interacting with the Cascader.
clearable
boolean
—
When `true`, the value can be cleared by the clear button.
expandTrigger
'click' | 'hover'
'click'
The trigger to expand the children of a node.
checkStrictly
boolean
false
When `false`, only leaf nodes can be selected (single) or the parent-children check states are linked (multiple). When `true`, any node can be selected independently.
showCheckedStrategy
'child' | 'parent'
'child'
The strategy used to collect and display checked nodes in multiple mode. - `child`: collect the leaves of the checked region. - `parent`: collect the topmost checked nodes (fold fully-checked subtrees into parents).
separator
string
' / '
The separator used to join the path labels.
filterable
boolean
—
When `true`, the trigger becomes a search input and the panel shows flat filtered results.
filter
((pattern: string, option: CascaderOptionData<T>, path: string[]) => boolean)
—
Custom filter function used in local filtering mode. The default performs a case-insensitive `includes` match against every label of the path.
remote
boolean
—
When `true`, the panel loads its options from `onSearch` instead of filtering locally.
onSearch
((pattern: string) => Promise<CascaderOptionData<T>[]>)
—
Async search function used in remote mode. Returns the flat options for the keyword.
searchDelay
number
300
Debounce delay in milliseconds for filtering and remote search.
lazy
boolean
—
When `true`, children of a node are loaded asynchronously via `onLoad`.
onLoad
((option: CascaderNode<T>) => Promise<CascaderOptionData<T>[]>)
—
Async function used to load the children of a node when `lazy` is `true`.
virtualScroll
boolean
—
When `true`, only the visible rows of each column are rendered.
itemSize
number
34
The fixed height of a row used by virtual scrolling.
height
number
204
The height of the panel used by virtual scrolling.
dir
Direction
—
The reading direction of the component.
placeholder
string
—
The content shown when no node is selected.
name
string
—
The name of the field. Submitted with its owning form as part of a name/value pair.
required
boolean
—
When `true`, indicates that the user must set the value before the owning form can be submitted.
Emits
Emit NameParametersDescription
update:modelValue
CascaderValueType<T, M, P>
Event handler called when the value of the cascader changes. Can be bound as `v-model`.
update:open
boolean
Event handler called when the open state of the cascader changes. Can be bound as `v-model:open`.
change
CascaderValueType<T, M, P> | undefined, nodes: CascaderNode<T>[]
Event handler called when the value changes, with the selected nodes.
clear
—
Event handler called when the selection is cleared.
loaded
CascaderNode<T>
Event handler called when the children of a node have been loaded (lazy mode).
closeAutoFocus
Event
Emitted when close auto focus occurs.
escapeKeyDown
KeyboardEvent
Event handler called when the escape key is down. Can be prevented.
pointerDownOutside
PointerDownOutsideEvent
Event handler called when the a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented.
placed
—
Emitted when the content is placed.
Slots
Slot NameParametersDescription
trigger-icon
—
Custom content for the trigger icon (arrow).
trigger-value
CascaderCompactTriggerValueSlotProps<T, M, P>
Custom content for the trigger value.
search-input
—
Custom content for the search input.
option
CascaderCompactOptionSlotProps<T>
Custom content for a single option.
tag
CascaderCompactTagSlotProps<T>
Custom content for a tag in multiple mode.
empty
—
Custom content for the empty state.

CascaderArrow

CascaderClear

1 Props
Props
PropTypeDefaultDescription
ariaLabel
string
'清除'
The accessible label of the clear button.

CascaderCompact<T, M, P>

41 Props9 Emits6 Slots
Props
PropTypeDefaultDescription
showArrow
boolean
true
When `true`, the arrow icon is rendered.
placement
import("@/index").Placement
—
The placement of the content.
triggerProps
CascaderTriggerProps
—
Properties forwarded to the trigger part.
valueProps
CascaderValueProps
—
Properties forwarded to the value part.
searchInputProps
CascaderSearchInputProps
—
Properties forwarded to the search input part.
portalProps
PortalProps
—
Properties forwarded to the portal part.
contentProps
CascaderContentProps
—
Properties forwarded to the content part.
menuProps
CascaderMenuProps
—
Properties forwarded to every menu part.
optionProps
Partial<CascaderOptionProps<T>>
—
Properties forwarded to every option part.
emptyProps
CascaderEmptyProps
—
Properties forwarded to the empty part.
emptyLabel
string
The locale message
The text shown in the empty state.
clearLabel
string
The locale message
The accessible label of the clear button.
arrowProps
PopperArrowProps
—
Properties forwarded to the arrow part.
modelValue
CascaderValueType<T, M, P>
—
The controlled value of the selected node(s). Can be bound with `v-model`.
defaultValue
CascaderValueType<T, M, P>
—
The default value of the selected node(s).
multiple
M
—
When `true`, multiple nodes can be selected.
pathMode
P
false
When `true`, the model value is the full path array(s) instead of the node value(s).
options
CascaderOptionData<T>[]
—
Options of the cascader.
fieldKeys
CascaderFieldKeys
—
Field keys used to extract the option fields.
open
boolean
—
The controlled open state of the Cascader. Can be bound as `v-model:open`.
defaultOpen
boolean
—
The open state of the cascader when it is initially rendered.
disabled
boolean
—
When `true`, prevents the user from interacting with the Cascader.
clearable
boolean
—
When `true`, the value can be cleared by the clear button.
expandTrigger
'click' | 'hover'
'click'
The trigger to expand the children of a node.
checkStrictly
boolean
false
When `false`, only leaf nodes can be selected (single) or the parent-children check states are linked (multiple). When `true`, any node can be selected independently.
showCheckedStrategy
'child' | 'parent'
'child'
The strategy used to collect and display checked nodes in multiple mode. - `child`: collect the leaves of the checked region. - `parent`: collect the topmost checked nodes (fold fully-checked subtrees into parents).
separator
string
' / '
The separator used to join the path labels.
filterable
boolean
—
When `true`, the trigger becomes a search input and the panel shows flat filtered results.
filter
((pattern: string, option: CascaderOptionData<T>, path: string[]) => boolean)
—
Custom filter function used in local filtering mode. The default performs a case-insensitive `includes` match against every label of the path.
remote
boolean
—
When `true`, the panel loads its options from `onSearch` instead of filtering locally.
onSearch
((pattern: string) => Promise<CascaderOptionData<T>[]>)
—
Async search function used in remote mode. Returns the flat options for the keyword.
searchDelay
number
300
Debounce delay in milliseconds for filtering and remote search.
lazy
boolean
—
When `true`, children of a node are loaded asynchronously via `onLoad`.
onLoad
((option: CascaderNode<T>) => Promise<CascaderOptionData<T>[]>)
—
Async function used to load the children of a node when `lazy` is `true`.
virtualScroll
boolean
—
When `true`, only the visible rows of each column are rendered.
itemSize
number
34
The fixed height of a row used by virtual scrolling.
height
number
204
The height of the panel used by virtual scrolling.
dir
Direction
—
The reading direction of the component.
placeholder
string
—
The content shown when no node is selected.
name
string
—
The name of the field. Submitted with its owning form as part of a name/value pair.
required
boolean
—
When `true`, indicates that the user must set the value before the owning form can be submitted.
Emits
Emit NameParametersDescription
update:modelValue
CascaderValueType<T, M, P>
Event handler called when the value of the cascader changes. Can be bound as `v-model`.
update:open
boolean
Event handler called when the open state of the cascader changes. Can be bound as `v-model:open`.
change
CascaderValueType<T, M, P> | undefined, nodes: CascaderNode<T>[]
Event handler called when the value changes, with the selected nodes.
clear
—
Event handler called when the selection is cleared.
loaded
CascaderNode<T>
Event handler called when the children of a node have been loaded (lazy mode).
closeAutoFocus
Event
Emitted when close auto focus occurs.
escapeKeyDown
KeyboardEvent
Event handler called when the escape key is down. Can be prevented.
pointerDownOutside
PointerDownOutsideEvent
Event handler called when the a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented.
placed
—
Emitted when the content is placed.
Slots
Slot NameParametersDescription
trigger-icon
—
Custom content for the trigger icon (arrow).
trigger-value
CascaderCompactTriggerValueSlotProps<T, M, P>
Custom content for the trigger value.
search-input
—
Custom content for the search input.
option
CascaderCompactOptionSlotProps<T>
Custom content for a single option.
tag
CascaderCompactTagSlotProps<T>
Custom content for a tag in multiple mode.
empty
—
Custom content for the empty state.

CascaderCompactOption

CascaderCompactTag

CascaderCompactTriggerValue

CascaderContent

24 Props4 Emits
Props
PropTypeDefaultDescription
menuProps
CascaderMenuProps
—
Properties forwarded to every menu part.
emptyProps
CascaderEmptyProps
—
Properties forwarded to the empty part.
open
boolean
true
Whether the floating layer is open. Drives the positioning lifecycle (`isPositioned` resets when open flips); the positioning primitive itself has no open state, so consumers wire their own open state here.
placement
Placement
undefined
The placement of the floating element. If used, it will override the `side` and `align` props.
side
Side
'bottom'
The preferred side of the anchor to render against when open. Will be reversed when collisions occur and avoidCollisions is enabled.
sideOffset
number
0
The distance in pixels from the anchor.
sideFlip
boolean
true
Flip to the opposite side when colliding with boundary.
align
Align
'center'
The preferred alignment against the anchor. May change when collisions occur.
alignOffset
number
0
An offset in pixels from the `start` or `end` alignment options.
alignFlip
boolean
true
Flip alignment when colliding with boundary. May only occur when `prioritizePosition` is true.
avoidCollisions
boolean
true
When `true`, overrides the side and align preferences to prevent collisions with boundary edges.
collisionBoundary
Element | (Element | null)[] | null
[ ]
The element used as the collision boundary. By default this is the viewport, though you can provide additional element(s) to be included in this check.
collisionPadding
Padding
0
The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { top: 20, left: 20 }.
arrowPadding
number
0
The padding between the arrow and the edges of the content. If your content has border-radius, this will prevent it from overflowing the corners.
hideShiftedArrow
boolean
false
When `true`, hides the arrow when it cannot be centered to the reference element.
sticky
'partial' | 'always'
'partial'
The sticky behavior on the align axis. `partial` will keep the content in the boundary as long as the anchor is at least partially in the boundary whilst "always" will keep the content in the boundary regardless.
hideWhenDetached
boolean
false
Whether to hide the content when the anchor becomes fully occluded.
positionStrategy
'fixed' | 'absolute'
'fixed'
The type of CSS position property to use.
updatePositionStrategy
'always' | 'optimized'
'optimized'
Strategy to update the position of the floating element on every animation frame.
disableUpdateOnLayoutShift
boolean
false
Whether to disable the update position for the content when the layout shifted.
prioritizePosition
boolean
false
Force content to be position within the viewport. Might overlap the reference element, which may not be desired.
reference
ReferenceElement
—
The custom element or virtual element that will be set as the reference to position the floating element. If provided, it will replace the default anchor element.
disableOutsidePointerEvents
boolean
—
When `true`, hover/focus/click interactions will be disabled on elements outside the `DismissableLayer`. Users will need to click twice on outside elements to interact with them: once to close the `DismissableLayer`, and again to trigger the element.
forceMount
boolean
—
Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries.
Emits
Emit NameParametersDescription
closeAutoFocus
Event
Emitted when close auto focus occurs.
escapeKeyDown
KeyboardEvent
Event handler called when the escape key is down. Can be prevented.
pointerDownOutside
PointerDownOutsideEvent
Event handler called when the a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented.
placed
—
Emitted when the content is placed.

CascaderEmpty

CascaderMenu

2 Props
Props
PropTypeDefaultDescription
level
number
—
The depth of the menu column.
optionProps
Partial<CascaderOptionProps<DefinedValue>>
—
Properties forwarded to every option part.

CascaderOption<T>

5 Props2 Emits
Props
PropTypeDefaultDescription
node
CascaderNode<T extends DefinedValue = DefinedValue>
—
The node rendered by the option.
index
number
—
The position of the node inside its column.
level
number
—
The depth of the column the option belongs to.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
select
CascaderSelectEvent<T>
Event handler called when the node is selected. Can be prevented by calling `event.preventDefault`.
expand
CascaderExpandEvent<T>
Event handler called when the node is expanded. Can be prevented by calling `event.preventDefault`.

CascaderPortal

4 Props
Props
PropTypeDefaultDescription
to
string | HTMLElement
—
Vue native teleport component prop `:to` {@link https://vuejs.org/guide/built-ins/teleport.html#basic-usage}
disabled
boolean
—
Disable teleport and render the component inline {@link https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport}
defer
boolean
—
Defer the resolving of a Teleport target until other parts of the application have mounted (requires Vue 3.5.0+) {@link https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport}
forceMount
boolean
—
Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries.

CascaderRoot<T, M, P>

28 Props5 Emits
Props
PropTypeDefaultDescription
modelValue
CascaderValueType<T, M, P>
—
The controlled value of the selected node(s). Can be bound with `v-model`.
defaultValue
CascaderValueType<T, M, P>
—
The default value of the selected node(s).
multiple
M
—
When `true`, multiple nodes can be selected.
pathMode
P
false
When `true`, the model value is the full path array(s) instead of the node value(s).
options
CascaderOptionData<T>[]
—
Options of the cascader.
fieldKeys
CascaderFieldKeys
—
Field keys used to extract the option fields.
open
boolean
—
The controlled open state of the Cascader. Can be bound as `v-model:open`.
defaultOpen
boolean
—
The open state of the cascader when it is initially rendered.
disabled
boolean
—
When `true`, prevents the user from interacting with the Cascader.
clearable
boolean
—
When `true`, the value can be cleared by the clear button.
expandTrigger
'click' | 'hover'
'click'
The trigger to expand the children of a node.
checkStrictly
boolean
false
When `false`, only leaf nodes can be selected (single) or the parent-children check states are linked (multiple). When `true`, any node can be selected independently.
showCheckedStrategy
'child' | 'parent'
'child'
The strategy used to collect and display checked nodes in multiple mode. - `child`: collect the leaves of the checked region. - `parent`: collect the topmost checked nodes (fold fully-checked subtrees into parents).
separator
string
' / '
The separator used to join the path labels.
filterable
boolean
—
When `true`, the trigger becomes a search input and the panel shows flat filtered results.
filter
((pattern: string, option: CascaderOptionData<T>, path: string[]) => boolean)
—
Custom filter function used in local filtering mode. The default performs a case-insensitive `includes` match against every label of the path.
remote
boolean
—
When `true`, the panel loads its options from `onSearch` instead of filtering locally.
onSearch
((pattern: string) => Promise<CascaderOptionData<T>[]>)
—
Async search function used in remote mode. Returns the flat options for the keyword.
searchDelay
number
300
Debounce delay in milliseconds for filtering and remote search.
lazy
boolean
—
When `true`, children of a node are loaded asynchronously via `onLoad`.
onLoad
((option: CascaderNode<T>) => Promise<CascaderOptionData<T>[]>)
—
Async function used to load the children of a node when `lazy` is `true`.
virtualScroll
boolean
—
When `true`, only the visible rows of each column are rendered.
itemSize
number
34
The fixed height of a row used by virtual scrolling.
height
number
204
The height of the panel used by virtual scrolling.
dir
Direction
—
The reading direction of the component.
placeholder
string
—
The content shown when no node is selected.
name
string
—
The name of the field. Submitted with its owning form as part of a name/value pair.
required
boolean
—
When `true`, indicates that the user must set the value before the owning form can be submitted.
Emits
Emit NameParametersDescription
update:modelValue
CascaderValueType<T, M, P>
Event handler called when the value of the cascader changes. Can be bound as `v-model`.
update:open
boolean
Event handler called when the open state of the cascader changes. Can be bound as `v-model:open`.
change
CascaderValueType<T, M, P> | undefined, nodes: CascaderNode<T>[]
Event handler called when the value changes, with the selected nodes.
clear
—
Event handler called when the selection is cleared.
loaded
CascaderNode<T>
Event handler called when the children of a node have been loaded (lazy mode).

CascaderSearchInput

CascaderTags

2 Slots
Slots
Slot NameParametersDescription
tag
CascaderCompactTagSlotProps<T>
Custom content for a single tag in multiple mode.
value
—
Custom content shown when there is no selection.

CascaderTrigger

4 Props
Props
PropTypeDefaultDescription
disabled
boolean
—
When `true`, prevents the user from interacting with the trigger.
reference
ReferenceElement
—
—
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

CascaderValue

1 Props
Props
PropTypeDefaultDescription
placeholder
string
—
The content shown when no node is selected.

Notes

Architecture and benchmark differences

VeanUI implements cascader with a self-developed data engine (useCascaderData) rather than reusing the listbox selection/collection bases, whose flat single-value model does not fit tree cascading: shallowReactive node trees cache pathValues / pathLabels / level for O(1) lookups, the menus computed derives the visible columns, and cascading checks run setCheckedDeep / recomputeAncestors / collectCheckedNodes. CascaderOption dispatches cancellable select / expand custom events (reka-ui style). The scv() recipe cascaderVariants declares 16 slots and 7 size variants.

CapabilityVeanUIAnt Design Cascaderreka-ui CascaderElement Plus Cascader
Aria/styled split✅—✅—
Multi-column panel✅✅✅✅
Cascading checks + half-check✅✅—✅
Lazy loading / remote search✅✅✅✅
showCheckedStrategy✅✅——
pathMode (path values)✅✅——
Virtual scrolling✅———
Cancellable custom events✅—✅—
Localized strings (not hardcoded)✅——✅
axe-clean (open state)✅———

Cautions

  • All built-in strings are localized (LocaleCascaderMessages); override per instance with emptyLabel / clearLabel or the matching aria-label attrs.
  • In filterable mode the trigger becomes tabindex=-1 and focus lives in the search input — keyboard navigation starts there.
  • Clicking a non-leaf node in search mode only highlights it; the multi-column path does not expand (differs from AntD) — expand on demand if you need that behavior.
  • select / expand events still fire on disabled items (emitted before the guard) without changing the model value; guard in the consumer if needed.

FAQ

How do I get the full path instead of the last value?

Enable pathMode; the model value then carries the complete value/label path rather than the deepest node only.

How do I load children lazily from an API?

Pass loadChildren returning the children for a node; the engine tracks the loading state and emits loaded when it finishes.

How do I filter remotely?

Use searchDelay for debouncing and provide your own filter implementation (or feed filtered items); the built-in filtering matches path labels client-side.

How do I emit only checked leaves?

Configure showCheckedStrategy: 'child' to collect only leaf nodes when a parent is checked, or 'parent' to emit the checked parents.

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.31.0

2026-08-31

Compare release

Optimization

improve search input, keyboard select closing, and panel spacing

Scope: cascaderAuthors: soybeanjsView commit3c6a9

v0.30.0

2026-08-20

Compare release

Fix

Corrected the highlighting logic and style of the parent node in the cascading selector.

Scope: cascaderAuthors: soybeanjsView commit73f50

Optimization

optimize style and fix multiple logic

Scope: cascaderAuthors: soybeanfeView commit7e1dc

Fix

Corrected the highlighting logic and style of the parent node in the cascading selector.

Scope: cascaderAuthors: soybeanjsView commit73f50

Optimization

optimize style and fix multiple logic

Scope: cascaderAuthors: soybeanfeView commit7e1dc