Cascade List
Display hierarchy levels side by side and select a leaf directly.
Usage
Location
Keep region, country, and city columns visible while choosing one destination.
Keep region, country, and city columns visible while choosing one destination.
<!-- Cascade List / Location -->
<script setup lang="ts">
import { CascadeListColumn, CascadeListItem, CascadeListRoot, CascadeListValue } from '@sectile/vue/cascade-list'
const nodes = [{ id: 'asia', parentID: null }, { id: 'kr', parentID: 'asia' }, { id: 'seoul', parentID: 'kr' }]
</script>
<template>
<CascadeListRoot :nodes="nodes" default-value="seoul" label="Destination" v-slot="{ columns }">
<CascadeListValue placeholder="Choose a destination" />
<div class="cascade-list-columns">
<CascadeListColumn v-for="(_, depth) in columns" :key="depth" :depth="depth" v-slot="{ items }">
<CascadeListItem v-for="item in items" :key="item" :value="item">{{ item }}</CascadeListItem>
</CascadeListColumn>
</div>
</CascadeListRoot>
</template>Disabled
Keep an unavailable branch visible while navigation continues through the remaining choices.
Keep an unavailable branch visible while navigation continues through the remaining choices.
<!-- Cascade List / Disabled -->
<script setup lang="ts">
import { CascadeListColumn, CascadeListItem, CascadeListRoot, CascadeListValue } from '@sectile/vue/cascade-list'
const nodes = [{ id: 'asia', parentID: null }, { id: 'kr', parentID: 'asia' }, { id: 'seoul', parentID: 'kr' }]
</script>
<template>
<CascadeListRoot :nodes="nodes" default-value="seoul" label="Destination" v-slot="{ columns }">
<CascadeListValue placeholder="Choose a destination" />
<div class="cascade-list-columns">
<CascadeListColumn v-for="(_, depth) in columns" :key="depth" :depth="depth" v-slot="{ items }">
<CascadeListItem v-for="item in items" :key="item" :value="item">{{ item }}</CascadeListItem>
</CascadeListColumn>
</div>
</CascadeListRoot>
</template>Controlled
Let the parent own the selected destination while the hierarchy stays available for navigation.
Let the parent own the selected destination while the hierarchy stays available for navigation.
<!-- Cascade List / Controlled -->
<script setup lang="ts">
import { CascadeListColumn, CascadeListItem, CascadeListRoot, CascadeListValue } from '@sectile/vue/cascade-list'
const nodes = [{ id: 'asia', parentID: null }, { id: 'kr', parentID: 'asia' }, { id: 'seoul', parentID: 'kr' }]
</script>
<template>
<CascadeListRoot :nodes="nodes" default-value="seoul" label="Destination" v-slot="{ columns }">
<CascadeListValue placeholder="Choose a destination" />
<div class="cascade-list-columns">
<CascadeListColumn v-for="(_, depth) in columns" :key="depth" :depth="depth" v-slot="{ items }">
<CascadeListItem v-for="item in items" :key="item" :value="item">{{ item }}</CascadeListItem>
</CascadeListColumn>
</div>
</CascadeListRoot>
</template>When to use it
Cascade List keeps each hierarchy level visible side by side. It fits filter panels, settings navigation, and condition builders where people need to compare the chosen path with the available next step. Use Cascade Select when the same hierarchy belongs in a compact trigger and popup.
| Component | Layout | Selection flow |
|---|---|---|
| Cascade List | Keeps columns in the page layout | Choosing a branch reveals the next column; choosing a leaf commits the value |
| Cascade Select | Places the columns in a popup below a trigger | Uses the same branch navigation and leaf selection inside the popup |
Both components share tree validation, active-item movement, disabled-item handling, and value selection rules. Their presentation differs to serve different layouts.
State ownership
Branch navigation updates highlightedValue and path; leaf selection commits modelValue. Start with internal state through defaultValue, or let the parent own the value with v-model. The columns remain in the page, so Escape keeps its surrounding page behavior.
API
Vue package: @sectile/vue/cascade-list
CascadeListRootCascadeListValueCascadeListColumnCascadeListItemCascadeListItemIndicatorCascadeListItemChevron
Props
CascadeListRootProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
defaultValueInitial value used when the component owns its state.
disabledWhether interaction is unavailable.
disabledItemsItem values excluded from focus and selection.
formID of the native form associated with the control.
labelAccessible name announced for the control.
modelValueCurrent value when state is controlled by the parent.
nameName used for native form submission.
nodesFlat hierarchy used to build the tree.
policiesBehavior policies that customize validation, movement, or selection.
readonlyWhether the value can be inspected but not changed.
requiredWhether the control must contain a valid value before submission.
textValueReturns searchable or presentational text for an item value.
CascadeListColumnProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
depthZero-based depth of this column in a cascading selection.
labelAccessible name announced for the control.
CascadeListItemProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
disabledWhether interaction is unavailable.
valueCurrent value exposed by this contract.
CascadeListPartProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
Slots
CascadeListRootSlotProps
columnsVisible cascade hierarchy columns.
disabledWhether interaction is unavailable.
highlightedValueValue currently highlighted for interaction.
pathCurrent selected path.
readonlyWhether the value can be inspected but not changed.
valueCurrent value exposed by this contract.
valuePathCurrent selected values from root to leaf.
CascadeListColumnSlotProps
depthDepth of the current hierarchical item.
itemsCurrent derived item collection.
parentValueValue that owns the current cascade column.
CascadeListItemSlotProps
branchWhether this item owns descendants.
disabledWhether interaction is unavailable.
expandedWhether descendants are visible.
highlightedWhether this item is highlighted for interaction.
selectedWhether this item is selected.
valueCurrent value exposed by this contract.
Events
CascadeListRoot
highlightEmitted when the highlighted item changes.
update:modelValueEmitted when the component requests a new controlled value.
Other types
CascadeListTextValueResolver
type CascadeListTextValueResolver = NonNullable<CascadeListRootProps['textValue']>CascadeListValueChangeHandler
type CascadeListValueChangeHandler = (value: string | null) => voidCascadeListHighlightHandler
type CascadeListHighlightHandler = (value: string | null) => voidParts
Shared scope: [data-scope="cascade-list"]. Combine it with a part selector to keep styles local to this component.
| Part | Selector | Role | Extra attributes |
|---|---|---|---|
root | [data-part="root"] | Defines the component boundary and owns its composed parts. | — |
value | [data-part="value"] | Displays the current committed value. | — |
column | [data-part="column"] | Groups one level of hierarchical choices. | — |
item | [data-part="item"] | Represents one selectable or actionable item. | — |
item-indicator | [data-part="item-indicator"] | Shows the item selection state. | — |
item-chevron | [data-part="item-chevron"] | Shows that an item opens a deeper level. | — |
Keyboard interaction
| Key | Behavior |
|---|---|
| Arrow Up / Arrow Down | Move between eligible items in the current column. |
| Arrow Left / Arrow Right | Move to the parent column or enter the highlighted branch. |
| Home / End | Move to the first or last eligible item in the current column. |
| Enter / Space | Open the highlighted branch or select the highlighted leaf. |
Accessibility
Every visible hierarchy level is a labeled listbox; options expose selection, branch, expanded, and disabled state.
