Skip to content

Cascader ​

Multi-level linked selection: multiple checkboxes, parent-child decoupled checking, value strategies, path search, lazy loading, controlled open and tag collapsing. Fully keyboard operable.

Basic Usage ​

Basic usage

Click to open the multi-level panel and drill down level by level until a leaf node is submitted.

Select & Submit ​

Select to submit (change-on-select)

With change-on-select enabled, clicking an option at any level (including nodes with children) immediately submits the current path.

Preset Path ​

Preset value (path array)

value is a JSON array holding the selected value of each level; it is displayed joined as "Zhejiang / Hangzhou".

Multiple ​

Multiple selection (multiple)

In multiple mode value is a JSON array of path arrays. Each panel row has a checkbox: checking a parent cascades to all children, and a partially checked parent shows an indeterminate state. The trigger echoes selections as removable tags; the panel stays open after checking for consecutive picks.

Check Strictly ​

Parent-child decoupled (check-strictly)

With check-strictly, parent and child checks are independent: checking a parent submits only the parent path, and the value is exactly the checked set (value-mode has no effect in this mode).

Value Mode ​

Value strategy (value-mode)

value-mode decides which paths are submitted in multiple mode: all (default) = every checked node (a parent enters the value once all its children are checked, consistent with the single-select full-path model); parentFirst = fully checked children collapse into the parent; onlyLeaf = only leaf paths. Echo tags mirror the literal value (host presets are never rewritten); interactions converge per strategy on submit.

Filterable ​

Searchable (filterable)

With filterable, a search box appears when the panel opens. Typing matches against the joined labels of every level and results are a flat path list; clicking a result selects that full path (checks it in multiple mode). An oas-search event is emitted while typing, and a custom matcher can be provided via el.filter = (query, path) => boolean (path is the array of option objects along the path).

Lazy Loading ​

Lazy loading (lazy + el.load)

After setting el.load = ({ option, path, depth }) => Promise<options>, expanding a not-yet-loaded node shows a loading state and fetches its children (option is null for the root level, so the first level can be lazy too). Options may declare isLeaf: true as leaves. This demo simulates a 500ms delay.

Hover Expand ​

Hover expand (expand-trigger=hover)

With expand-trigger="hover", hovering a parent option (after a ~120ms anti-mistap delay) expands its child column; clicking a leaf submits. Default is click.

Large Datasets (virtual scrolling) ​

Virtual scrolling (1000-item column)

With virtual, columns above the threshold (50 items) render only the visible window (reusing oas-virtual-list window math with top/bottom padding holding the scroll height) — thousands of options scroll smoothly and the panel height stays constant; item-height tunes the fixed row height (default 36). While navigating with ↑/↓ the window follows the highlighted row; short columns below the threshold, search results, and loading placeholders keep normal rendering.

Last Level & Separator ​

Last level only (show-all-levels) and separator

show-all-levels defaults to true (full path); setting it to false shows only the last label in the trigger. separator customizes the path separator (default /), also applied in search result rows.

Clearable ​

Clearable (clearable)

A clear button appears when a value exists; clicking it emits oas-clear (detail is the previous value) and oas-change (empty value).

Tag Collapsing ​

Tag collapsing (max-tag-count)

Tags wrap by default; explicitly setting max-tag-count folds them into +N by count (hover lists the hidden items), consistent with oas-select.

Size & Status ​

Size

Validation status

size supports small / medium / large (inheriting the nearest oas-config-provider global size); status supports error / warning / success (error syncs aria-invalid on the trigger; forms may also set host-level aria-invalid directly).

Controlled Open ​

Controlled open (open + oas-open-change)

Toggleopen: false

The open attribute is the single source of truth for the expanded state (controlled): open/close from inside or outside is written back to it, and oas-open-change (detail.open) is emitted on every flip; hosts may intercept the event to take full control. Esc closes and returns focus to the trigger.

Empty ​

Empty state

When options are empty (and el.load is not set) the panel shows the empty placeholder; a search with no matches shows the no-match placeholder.

Loading state (loading) ​

Loading state (loading)

Enter loadingLeave loading

While loading is set the trigger shows a spinner with aria-busy (replacing the chevron); an open panel only shows the loading placeholder without rendering options — ideal while the host fetches remote cascading data.

Field mapping (field-names) ​

Field mapping (field-names)

field-names is a JSON field alias ({ label, value, children, disabled }, matching the oas-tree-select contract); the component reads your raw data through the aliases (isLeaf always reads its original key). Data returned from lazy el.load goes through the same mapping. In the example above "Design / UI" is disabled via the off field.

Disabled ​

Disabled

Accessible Name (label) ​

label (accessible name)

label is the accessible name (aria-label) of the trigger: screen readers announce it and it takes precedence over the selected value text and the placeholder; without it the component falls back to value text / placeholder (matching the oas-select contract).

Placement (placement) ​

placement (12 directions)

placement supports 12 directions: top / bottom / left / right × start / end / centered (e.g. top-start, right-end), defaulting to bottom (opens below, auto-flips when space runs out); invalid values fall back silently. Declare the direction directly for edge-adjacent scenarios such as sidebars or inside tables.

Custom Suffix Icon (suffix-icon slot) ​

suffix-icon (replaces the default arrow)

template[slot="suffix-icon"] replaces the default dropdown arrow on the trigger (rotating with the container when expanded; the spinner still takes over during loading).

Custom Option Rendering (option slot) ​

option (custom option rows)

template[slot="option"] is cloned into every option row (both panel rows and search-result rows); the [data-option-label] node is bound to the display text (the option label for panel rows, the full path text for search rows). Hosts can also rewrite row content via render events.

Events ​

Selection events

Listen to oas-change; detail.value is a path array in single mode, or an array of path arrays in multiple mode:

Focus Events (oas-focus / oas-blur) ​

focus / blur events

Trigger focus/blur dispatches oas-focus / oas-blur (detail.value shares the oas-change shape: a path array in single mode, an array of path arrays in multiple mode). Internal focus transfers between the trigger, search box, and chip buttons do not cause false reports.

Mobile form (bottom sheet) ​

On touch screens (coarse pointer) or narrow viewports (<768px), the multi-level panels are automatically hosted by an oas-bottom-sheet bottom sheet: rises from the viewport bottom + backdrop + drag handle swipe-down to close (backdrop click / Esc also close), with bottom safe-area inset; panel columns scroll horizontally inside the sheet; the desktop form keeps the original floating dropdown.

API ​

oas-cascader ​

Attributes ​

AttributeDescriptionTypeDefault
change-on-selectSubmit when selecting any levelboolean—
check-strictlyDecouple parent/child checking in multi-select (checking a parent does not cascade)boolean—
clearableClearable (fires oas-clear)boolean—
disabledDisabledboolean—
expand-triggerSub-level expansion trigger: click (default) / hover (120ms delay to prevent misfires)stringclick
field-namesField-alias JSON ({ label, value, children, disabled }) matching the tree-select contract; lazy-load results are mapped alikestring—
filterableSearchable (flat path results)boolean—
item-heightFixed virtual row height in px (with virtual, default 36)string36
labelAccessible name of the trigger (aria-label), taking priority over value/placeholderstring—
loadingLoading state: trigger spinner + aria-busy; the panel shows a loading placeholderboolean—
max-tag-countCollapse multi-select tags beyond the count into +N (with title listing hidden items)number—
multipleMulti-select (cascading checkboxes; fully-checked children roll the parent into the value)boolean—
openControlled open state (single source of truth); in the mobile form (touch / viewport <768px) the open panel is hosted by an oas-bottom-sheet bottom sheet (swipe-down/backdrop/Esc to close); desktop keeps the floating dropdownboolean—
optionsCascade options, JSON array, supports children / disabledCascaderOption[] | string[]
placeholderPlaceholder text——
placementPanel placement in 12 directions (invalid falls back to bottom; auto-flip kept)stringbottom
separatorPath separator (default /)string/
show-all-levelsShow the full path (default true); false shows only the leafstringtrue
sizeSize preset small / medium (default) / largestringmedium
statusValidation status: error / warning / success; error mirrors aria-invalidstring—
valuePath array (JSON), e.g. ["zj","hz"]string[] | string[][] | null[]
value-modeMulti-select value strategy: all (default, full paths) / parentFirst / onlyLeafstringall
virtualPer-column virtual scrolling (columns above 50 items render via oas-virtual-list; short columns/search/loading keep normal rendering)boolean—

Property (JS property; see each row for attribute reflection) ​

PropertyDescriptionTypeDefault
valueCurrent value: the selected path array, or an array of selected paths when multiplestring[] | string[][] | null—

Events ​

EventDescription
oas-blurDispatched on trigger blur; detail.value shares the oas-change shape (inner focus moves do not false-fire)
oas-changeSelection change, detail: { value } (path array)
oas-clearFires on clear-button click; detail is the pre-clear value
oas-focusDispatched on trigger focus; detail.value shares the oas-change shape (inner focus moves do not false-fire)
oas-open-changeOpen state flips, detail: { open }
oas-searchFires on filterable input, detail: { value }

Slots ​

NameDescription
template[slot="option"]Custom option row template; [data-option-label] nodes bind the option text
template[slot="suffix-icon"]Custom trailing trigger icon (replaces the default arrow; yields to the spinner while loading)

CSS Variables ​

CSS VariableDefault
--oas-cascader-dropdown-height240px
--oas-glass-blurnone
--oas-glass-ringtransparent

Released under the MIT OR Apache-2.0 License.