Cascader
Use CCascader when a value is meaningful only as a path through related levels. Each CCascaderOption declares a globally unique value and plain label; nested Options create the next column.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class CascaderAtAGlance(Component):
template = """
<c-CCascader c-value="['europe','czechia','prague']">
<c-CCascaderOption value="europe" label="Europe">
<c-CCascaderOption value="czechia" label="Czechia">
<c-CCascaderOption value="prague" label="Prague" />
</c-CCascaderOption>
<c-CCascaderOption value="germany" label="Germany">
<c-CCascaderOption value="berlin" label="Berlin" />
</c-CCascaderOption>
</c-CCascaderOption>
</c-CCascader>
"""
preview = CascaderAtAGlance()
preview # noqa: B018
Submit the complete path
Set name to produce one hidden input per accepted segment, in root-to-leaf order. form supports an external native form. Without JavaScript, the initial path remains visible and submits normally.
Show code
# ruff: noqa: E501 - embedded Citry templates remain readable as authored HTML
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class CascaderForms(Component):
template = """
<form>
<c-CCascader name="category" c-value="['hardware','cameras','mirrorless']">
<c-CCascaderOption value="hardware" label="Hardware"><c-CCascaderOption value="cameras" label="Cameras"><c-CCascaderOption value="mirrorless" label="Mirrorless" /></c-CCascaderOption></c-CCascaderOption>
</c-CCascader>
<button type="submit">Save category</button>
</form>
"""
preview = CascaderForms()
preview # noqa: B018
Control selection
Pass value and onValueChange through $c-props for controlled state. The callback receives the path plus labels, previous path, selected Option element, controlled flag, interaction source, and native event. Invalid controlled value or open values are diagnosed once and retain the last valid effective state. Omitting value returns to the retained uncontrolled path; omitting open releases control without changing the current open state.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class CascaderControlled(Component):
template = """
<div x-data="{place:['earth','north'], last:''}">
<c-CCascader $c-props="{value:place,onValueChange:(value)=>{place=value;last=value.join(' / ')}}">
<c-CCascaderOption value="earth" label="Earth">
<c-CCascaderOption value="north" label="Northern hemisphere" />
<c-CCascaderOption value="south" label="Southern hemisphere" />
</c-CCascaderOption>
</c-CCascader>
<output x-text="last"></output>
</div>
"""
preview = CascaderControlled()
preview # noqa: B018
Allow parent paths
The default requires a leaf. Set change_on_select=True when a category at any depth is a complete result. Activating a collapsed branch selects it and opens its children. Activating the expanded branch again collapses its child level.
Show code
# ruff: noqa: E501 - embedded Citry templates remain readable as authored HTML
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class CascaderParentSelection(Component):
template = """
<c-CCascader c-change_on_select="True">
<c-CCascaderOption value="design" label="Design"><c-CCascaderOption value="research" label="Research" /><c-CCascaderOption value="systems" label="Design systems" /></c-CCascaderOption>
<c-CCascaderOption value="engineering" label="Engineering"><c-CCascaderOption value="platform" label="Platform" /></c-CCascaderOption>
</c-CCascader>
"""
preview = CascaderParentSelection()
preview # noqa: B018
Disable unavailable paths
A disabled Option cannot be opened or selected, and an initial value cannot pass through it. Root disabled also disables form inputs.
Show code
# ruff: noqa: E501 - embedded Citry templates remain readable as authored HTML
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class CascaderDisabled(Component):
template = """
<c-CCascader>
<c-CCascaderOption value="available" label="Available"><c-CCascaderOption value="one" label="Warehouse one" /></c-CCascaderOption>
<c-CCascaderOption value="maintenance" label="Under maintenance" c-disabled="True"><c-CCascaderOption value="two" label="Warehouse two" /></c-CCascaderOption>
</c-CCascader>
"""
preview = CascaderDisabled()
preview # noqa: B018
Support keyboard and constrained layouts
Arrow keys move within and across columns; Home, End, typeahead, Enter, Space, Escape, and Tab follow the popup tree contract. Pointer activation, Enter, and Space toggle a branch's child level without changing an already accepted leaf. Use aria_label or aria_labelledby to give the trigger an application-specific accessible name. Active columns sit side by side whenever their preferred width fits the viewport. Only when they do not fit do they stack vertically at the trigger width, avoiding page-level and nested horizontal scrollbars. While open, the popup also shifts back inside the viewport when its trigger sits near an inline edge. RTL reverses both column progression and branch indicators. The labeled taxonomy deliberately uses wider columns to demonstrate the stacked form in its constrained preview.
Show code
# ruff: noqa: E501 - embedded Citry templates remain readable as authored HTML
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class CascaderAccessibility(Component):
template = """
<label id="team-label">Owning team</label>
<c-CCascader aria_labelledby="team-label" c-value="['product','experience','research']" size="lg" variant="soft" c-style="{'--cui-cascader-column-width': '14rem'}">
<c-CCascaderOption value="product" label="Product">
<c-CCascaderOption value="experience" label="Customer experience">
<c-CCascaderOption value="research" label="Customer research" />
</c-CCascaderOption>
</c-CCascaderOption>
<c-CCascaderOption value="operations" label="Operations">
<c-CCascaderOption value="support" label="Customer support">
<c-CCascaderOption value="priority" label="Priority support" />
</c-CCascaderOption>
</c-CCascaderOption>
</c-CCascader>
"""
preview = CascaderAccessibility()
preview # noqa: B018
Search, multiple paths, async child loading, and virtualized levels are not silent modes of this API; they remain separate future contracts.
API reference
Inputs
CCascader server inputs
Server inputs are passed in a template through <c-CCascader ... /> or in Python through CCascader(...).
| Input | Type | Default | Effect |
|---|---|---|---|
value | Sequence[str] | "()" | Supplies the accepted continuous root-to-Option path. |
id | str | None | generated | Sets root and related popup IDs. |
aria_label | str | None | None | Gives the trigger an explicit accessible name. |
aria_labelledby | str | None | None | Associates the trigger with external labeling elements. |
name | str | None | None | Emits one hidden input per accepted path segment. |
form | str | None | None | Associates hidden inputs with an external form. |
placeholder | str | "Choose an option" | Supplies empty trigger text or overrides its catalog message. |
separator | str | " / " | Joins application Option labels in the trigger. |
change_on_select | bool | False | Allows branches as complete selected paths. |
open | bool | False | Supplies initial uncontrolled popup state. |
disabled | bool | False | Disables selection and form output. |
size | CCascaderSize (CCascaderSize) | "md" | Selects trigger height. |
variant | CCascaderVariant (CCascaderVariant) | "outline" | Selects trigger presentation. |
empty_label | str | "No options" | Overrides empty-hierarchy text. |
selected_label | str | "Selected {path}" | Overrides selected-path announcement and must retain path. |
class_ | CClassValue | None (CClassValue) | None | Adds root classes. |
style | CStyleValue | None (CStyleValue) | None | Adds root styles. |
attrs | Mapping[str, object] | None | None | Adds copied allowed root attributes. |
CCascader client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CCascader />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
value | string[] | Uncontrolled server path. | Controls the accepted path. |
open | boolean | Uncontrolled server open state. | Controls popup visibility. |
disabled | boolean | Uses the server value. | Reactively disables interaction and form inputs. |
onValueChange | function | No component callback runs. | Receives selection requests. |
onOpenChange | function | No component callback runs. | Receives popup requests. |
CCascaderOption server inputs
Server inputs are passed in a template through <c-CCascaderOption ... /> or in Python through CCascaderOption(...).
| Input | Type | Default | Effect |
|---|---|---|---|
value | str | required | Supplies globally unique stable Option identity. |
label | str | required | Supplies visible plain application-localized text. |
disabled | bool | False | Prevents opening or selecting this path. |
class_ | CClassValue | None (CClassValue) | None | Adds Option classes. |
style | CStyleValue | None (CStyleValue) | None | Adds Option styles. |
attrs | Mapping[str, object] | None | None | Adds copied allowed Option attributes. |
Slots
Slots are passed as nested content or <c-fill> tags in a template, or through the slots={...} argument in Python.
CCascader slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
default | no | {} (CCascaderDefaultSlotData) | Empty hierarchy status; accepts root Option declarations only. |
CCascaderOption slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
default | no | {parent_value, level} (CCascaderOptionDefaultSlotData) | Leaf Option; accepts child Option declarations only. |
Events
Component events are callback inputs supplied through $c-props. Native browser events remain available through Alpine @... attributes.
CCascader events
| Event | Signature | Trigger and timing | Detail | Controlled and cancellation behavior |
|---|---|---|---|---|
onValueChange | (value: string[], detail: CCascaderValueChangeDetail) => void (CCascaderValueChangeDetail) | An allowed Option is activated. | {value, labels, previousValue, controlled, source, option, sourceEvent} (CCascaderValueChangeDetail) | Commits only while uncontrolled. |
onOpenChange | (open: boolean, detail: CCascaderOpenChangeDetail) => void (CCascaderOpenChangeDetail) | The popup is requested open or closed. | {open, reason, sourceEvent} (CCascaderOpenChangeDetail) | Commits only while uncontrolled. |
Methods
-
CSS
CSS variables to theme the components. Set them on an ancestor or the component itself.
CCascader CSS variables
Apply these variables to CCascader or one of its ancestors.
| Variable | Type | Purpose | Default |
|---|---|---|---|
--cui-cascader-width | length | Trigger inline size. | 18rem |
--cui-cascader-column-width | length | Preferred width of one hierarchy column before measured-fit stacking. | 11rem |
--cui-cascader-max-height | length | Maximum column height. | 18rem |
--cui-cascader-border | complete border | Trigger popup and column boundaries. | Adaptive 1px neutral |
--cui-cascader-surface | color | Trigger and popup surface. | Canvas |
--cui-cascader-active-surface | color | Active branch and selected Option. | Adaptive indigo |
--cui-cascader-radius | length | Trigger and popup corners. | 0.625rem |
--cui-cascader-shadow | shadow | Popup elevation. | Soft elevation |
--cui-cascader-focus | color | Trigger and Option focus. | Highlight |
Attributes
HTML attributes defined on the components that you can refer to for CSS, inspection, and testing. Read-only.
CCascader attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
data-open | Root | present | absent | Reflects effective popup visibility. |
data-disabled | Root and Option | present | absent | Reflects unavailable interaction. |
data-size | Root | CCascaderSize (CCascaderSize) | Reflects presentation size. |
data-variant | Root | CCascaderVariant (CCascaderVariant) | Reflects presentation variant. |
data-active | Option | present | absent | Marks the branch whose child column is visible. |
data-selected | Option | present | absent | Marks the accepted path endpoint. |
data-value | Option | string | Exposes stable Option identity. |
data-level | Option | positive integer string | Exposes one-based hierarchy depth. |
aria-level | Option | positive integer string | Preserves hierarchy depth while visual columns are siblings. |
aria-posinset | Option | positive integer string | Exposes the Option position in its logical group. |
aria-setsize | Option | positive integer string | Exposes the number of Options in its logical group. |
aria-owns | Branch Option | ID reference | Owns the sibling visual group that contains its children. |
Selectors
Selectors for the DOM nodes in the components that you can use for CSS, inspection, and testing.
CCascader selectors
| Selector | Element | Purpose |
|---|---|---|
[data-citry-ui-part="cascader"] | Root | State and theme destination. |
[data-citry-ui-part="trigger"] | Native button | Accepted value and popup control. |
[data-citry-ui-part="value"] | Span | Selected path or placeholder. |
[data-citry-ui-part="indicator"] | Decorative span | Indicates popup disclosure. |
[data-citry-ui-part="popup"] | Popup div | Responsive visual-column container. |
[data-citry-ui-part="tree"] | Root tree | Composite keyboard owner. |
[data-citry-ui-part="group"] | Logically owned sibling group | One child column. |
[data-citry-ui-part="option"] | Treeitem | Focus branch and selection unit. |
[data-citry-ui-part="option-row"] | Div | Visible Option surface. |
[data-citry-ui-part="option-label"] | Span | Application Option label. |
[data-citry-ui-part="option-indicator"] | Decorative span | Indicates children in the current inline direction. |
[data-citry-ui-part="empty"] | Paragraph | Empty-hierarchy status. |
[data-citry-ui-part="inputs"] | Hidden span | Native ordered path controls. |
[data-citry-ui-part="status"] | Polite status | Selection announcement. |
Interfaces
Aliases and data shapes referenced above.
Input type aliases
| Interface | Definition |
|---|---|
CCascaderSize | Literal["sm", "md", "lg"] |
CCascaderVariant | Literal["outline", "soft", "plain"] |
CCascaderChangeSource | Literal["pointer", "keyboard", "reset"] |
CClassValue | str | Mapping[str, bool] | Sequence[CClassValue] |
CStyleValue | str | Mapping[str, object] | Sequence[CStyleValue] |
CCascaderDefaultSlotData
Empty dataclass: {}.
CCascaderOptionDefaultSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
parent_value | str | - | Parent Option value. |
level | int | - | One-based parent level. |
CCascaderValueChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
value | list[str] | - | Requested path. |
labels | list[str] | - | Application labels for that path. |
previousValue | list[str] | - | Previously accepted path. |
controlled | bool | - | Whether value was supplied as a client prop. |
source | CCascaderChangeSource (CCascaderChangeSource) | - | Request interaction source. |
option | object | - | Requested treeitem element. |
sourceEvent | object | - | Native source Event. |
CCascaderOpenChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
open | bool | - | Requested popup visibility. |
reason | str | - | Trigger selection escape tab or outside. |
sourceEvent | object | - | Native source Event. |
Translation keys
Catalog keys used by this family. An explicit component input or slot listed in Override takes precedence over the catalog for that instance.
CCascader translation keys
| Key | Purpose | Variables | Override | Browser updates |
|---|---|---|---|---|
citry-ui-cascader-placeholder | Labels an empty trigger. | None. | placeholder | Runtime i18n.bind() while the accepted path is empty. |
citry-ui-cascader-empty | Labels an empty hierarchy. | None. | empty_label | Stable $c-tr text. |
citry-ui-cascader-selected | Announces an accepted path. | path: str | selected_label with {path} | Browser one-shot i18n.tr() with a server-localized fallback pattern. |