Menu
Use CMenu for a temporary application-command collection. It supports native links, grouped commands, check/radio choices, and nested submenus with direct focus, typeahead, touch-safe activation, and logical placement.
Use CPopover for arbitrary controls, forms, or explanatory content. Menu items accept text and decorative content, not nested interactive controls.
Menu at a glance
Open the archive menu to see commands, navigation, a submenu, a separator, and destructive emphasis together.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class MenuAtAGlance(Component):
template = """
<section class="archive-menu-demo">
<p>Enchanted archive</p>
<c-CMenu>
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Open archive menu</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="rename">Rename folio</c-CMenuItem>
<c-CMenuItem href="#moon-catalog">Open moon catalog</c-CMenuItem>
<c-CMenuSubmenu value="send-to">
<c-fill name="label">Send to collection</c-fill>
<c-fill name="default">
<c-CMenuItem value="astronomy">Astronomy</c-CMenuItem>
<c-CMenuItem value="mythology">Mythology</c-CMenuItem>
</c-fill>
</c-CMenuSubmenu>
<c-CMenuSeparator />
<c-CMenuItem value="banish" intent="danger">Banish folio</c-CMenuItem>
</c-fill>
</c-CMenu>
</section>
"""
css = """
:where(.archive-menu-demo) {
display: grid;
gap: 0.75rem;
justify-items: start;
min-block-size: 17rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
:where(.archive-menu-demo > p) {
margin: 0;
color: light-dark(#7a4b18, #e8bd76);
font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
"""
preview = MenuAtAGlance()
preview # noqa: B018
Compose a Menu
Provide exactly one native Button through activator. Put Menu-family declarations directly in the default slot.
<c-CMenu>
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Open archive</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="rename">Rename folio</c-CMenuItem>
<c-CMenuItem href="/catalog">Open catalog</c-CMenuItem>
<c-CMenuSeparator />
<c-CMenuItem value="delete" intent="danger">Delete folio</c-CMenuItem>
</c-fill>
</c-CMenu>
Forward both activator fields. activator_attrs carries relationships and the anchor; activator_disabled goes through CButton's disabled input. A native button also sets type="button" directly.
For Python composition, supply one component whose output contains the direct declarations. Transparent components may generate declarations when they add no wrapper or other output.
CMenuItem, CMenuCheckboxItem, CMenuRadioGroup, CMenuRadioItem, CMenuGroup, CMenuSeparator, and CMenuSubmenu are not standalone.
Run commands and follow links
Give a command value when the root onAction callback should identify it. Anonymous commands use native @click. Supplying href renders a real anchor and preserves navigation, link context menus, and browser behavior.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class MenuCommandsAndLinks(Component):
template = """
<section
class="archive-command-demo"
x-data="{lastAction: 'none'}"
>
<c-CMenu
$c-props="{
onAction: (value) => lastAction = value,
}"
>
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Folio actions</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="duplicate">Duplicate folio</c-CMenuItem>
<c-CMenuItem @click="lastAction = 'annotate'">Add annotation</c-CMenuItem>
<c-CMenuItem href="#restricted-shelf">Visit restricted shelf</c-CMenuItem>
</c-fill>
</c-CMenu>
<output x-text="`Last command: ${lastAction}`">Last command: none</output>
</section>
"""
css = """
:where(.archive-command-demo) {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1rem;
min-block-size: 14rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
:where(.archive-command-demo output) {
color: light-dark(#66451f, #dec08f);
}
"""
preview = MenuCommandsAndLinks()
preview # noqa: B018
Links do not call onAction. Disabled links temporarily omit href and never navigate.
Add item content
Use start, default, description, and end for icons, the visible label, supporting text, and shortcuts. Only the default label names the item; the description is exposed separately.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class MenuItemContent(Component):
template = """
<section class="archive-content-demo">
<c-CMenu>
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Catalog tools</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="search">
<c-fill name="start"><c-CIcon name="search" /></c-fill>
<c-fill name="default">Search illuminated texts</c-fill>
<c-fill name="description">Find titles, scribes, and sigils.</c-fill>
<c-fill name="end"><kbd>⌘ K</kbd></c-fill>
</c-CMenuItem>
<c-CMenuItem value="bookmark">
<c-fill name="start"><c-CIcon name="star" /></c-fill>
<c-fill name="default">Mark this passage</c-fill>
<c-fill name="end"><kbd>M</kbd></c-fill>
</c-CMenuItem>
</c-fill>
</c-CMenu>
</section>
"""
css = """
:where(.archive-content-demo) {
min-block-size: 15rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
:where(.archive-content-demo kbd) {
padding: 0.1rem 0.35rem;
border: 1px solid color-mix(in srgb, CanvasText 20%, transparent);
border-radius: 0.3rem;
font: inherit;
font-size: 0.75rem;
}
"""
preview = MenuItemContent()
preview # noqa: B018
Keep every item region to noninteractive phrasing content. Set text_value when the visible label does not produce concise typeahead text.
Control visibility and configuration
Server inputs are passed in Python through <c-CMenu ... /> attributes or a CMenu(...) composition call. Client inputs are passed in the browser through $c-props="{...}".
Customize example
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class ControlledMenu(Component):
template = """
<section
class="archive-controlled-demo"
x-data="{open: false, disabled: false, locked: false, size: 'md', lastReason: 'none'}"
@citry-ui-preview-controls.window="Object.assign($data, $event.detail)"
>
<c-CButton size="sm" @click="open = !open">Toggle from owner</c-CButton>
<c-CMenu
$c-props="{
open,
disabled,
size,
onOpenChange: (nextOpen, detail) => {
lastReason = detail.reason;
if (!locked) open = nextOpen;
},
}"
>
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Controlled grimoire</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="translate">Translate runes</c-CMenuItem>
<c-CMenuItem value="restore">Restore missing page</c-CMenuItem>
</c-fill>
</c-CMenu>
<output x-text="`Last request: ${lastReason}`">Last request: none</output>
</section>
"""
css = """
:where(.archive-controlled-demo) {
display: grid;
gap: 1rem;
min-block-size: 17rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
"""
preview_controls = (
{
"name": "size",
"label": "Size",
"type": "select",
"default": "md",
"options": (("sm", "Small"), ("md", "Medium"), ("lg", "Large")),
},
{
"name": "disabled",
"label": "Disabled",
"type": "checkbox",
"default": False,
},
{
"name": "locked",
"label": "Decline visibility requests",
"type": "checkbox",
"default": False,
},
)
preview = ControlledMenu()
preview # noqa: B018
A Boolean client open owns visibility. Omit it or pass null to release control from the current committed state. onOpenChange reports requests; forced ancestor/modal/disabled closes cannot be rejected.
Add application choices
Checkbox and radio items model application preferences, not native Form controls. They contribute no FormData and emit no native input/change event.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class MenuChoices(Component):
template = """
<section
class="archive-choice-demo"
x-data
x-init="Alpine.store('archiveMenuChoices', {glow: 'mixed', script: 'elvish'})"
>
<c-CMenu c-close_on_select="False">
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Reading preferences</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuCheckboxItem
value="glow"
checked="mixed"
$c-props="{
checked: $store.archiveMenuChoices.glow,
onCheckedChange: (value) => $store.archiveMenuChoices.glow = value,
}"
>
Glow around enchanted passages
</c-CMenuCheckboxItem>
<c-CMenuSeparator />
<c-CMenuRadioGroup
value="elvish"
$c-props="{
value: $store.archiveMenuChoices.script,
onValueChange: (value) => $store.archiveMenuChoices.script = value,
}"
>
<c-fill name="label">Translation script</c-fill>
<c-fill name="default">
<c-CMenuRadioItem value="elvish">Elvish</c-CMenuRadioItem>
<c-CMenuRadioItem value="draconic">Draconic</c-CMenuRadioItem>
<c-CMenuRadioItem value="celestial">Celestial</c-CMenuRadioItem>
</c-fill>
</c-CMenuRadioGroup>
</c-fill>
</c-CMenu>
<output
x-text="`Glow: ${$store.archiveMenuChoices.glow}; script: ${$store.archiveMenuChoices.script}`"
></output>
</section>
"""
css = """
:where(.archive-choice-demo) {
display: grid;
gap: 1rem;
min-block-size: 17rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
"""
preview = MenuChoices()
preview # noqa: B018
Checkboxes support false, true, and "mixed"; activating mixed requests true. A radio group owns one value. Set close_on_select=False when readers should make several choices before leaving the Menu.
Group commands
CMenuGroup owns a visible accessible label. CMenuSeparator divides adjacent command families. Radio groups have their own optional label.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class MenuGroups(Component):
template = """
<section class="archive-group-demo">
<c-CMenu>
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Archive sections</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuGroup>
<c-fill name="label">Public halls</c-fill>
<c-fill name="default">
<c-CMenuItem value="maps">Star maps</c-CMenuItem>
<c-CMenuItem value="herbals">Moonlit herbals</c-CMenuItem>
</c-fill>
</c-CMenuGroup>
<c-CMenuSeparator />
<c-CMenuGroup>
<c-fill name="label">Restricted vaults</c-fill>
<c-fill name="default">
<c-CMenuItem value="prophecies">Sealed prophecies</c-CMenuItem>
<c-CMenuItem value="curses" disabled>Curses under glass</c-CMenuItem>
</c-fill>
</c-CMenuGroup>
</c-fill>
</c-CMenu>
</section>
"""
css = """
:where(.archive-group-demo) {
min-block-size: 18rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
"""
preview = MenuGroups()
preview # noqa: B018
Do not put separators first, last, or consecutively. Generic groups cannot be nested inside generic groups.
Nest submenus
CMenuSubmenu is one item plus another Menu surface. Give it a stable value, a label fill, and direct declarations in its default fill.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class NestedMenus(Component):
template = """
<section class="archive-submenu-demo">
<c-CMenu>
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Choose a collection</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuSubmenu value="skies">
<c-fill name="label">Celestial archives</c-fill>
<c-fill name="default">
<c-CMenuItem value="constellations">Constellations</c-CMenuItem>
<c-CMenuSubmenu value="moons">
<c-fill name="label">Moon records</c-fill>
<c-fill name="default">
<c-CMenuItem value="silver">Silver moon</c-CMenuItem>
<c-CMenuItem value="ember">Ember moon</c-CMenuItem>
</c-fill>
</c-CMenuSubmenu>
</c-fill>
</c-CMenuSubmenu>
<c-CMenuSubmenu value="seas">
<c-fill name="label">Sunken archives</c-fill>
<c-fill name="default">
<c-CMenuItem value="tides">Tide almanacs</c-CMenuItem>
<c-CMenuItem value="leviathans">Leviathan sightings</c-CMenuItem>
</c-fill>
</c-CMenuSubmenu>
</c-fill>
</c-CMenu>
</section>
"""
css = """
:where(.archive-submenu-demo) {
display: grid;
place-items: start center;
min-block-size: 22rem;
padding-inline: 5rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
"""
preview = NestedMenus()
preview # noqa: B018
Arrow direction follows text direction. Pointer intent uses the submenu's actual collision-resolved geometry. Deep nesting works, but one level is usually easier to scan and operate.
Keyboard and typeahead
Arrow Down/Up moves direct focus, Home/End reaches the edges, and printable characters perform buffered prefix matching. Repeating one character cycles matching labels. loop controls wrapping.
Customize example
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class MenuKeyboard(Component):
template = """
<section
class="archive-keyboard-demo"
x-data="{loop: true, close: false}"
@citry-ui-preview-controls.window="Object.assign($data, $event.detail)"
>
<c-CMenu
c-close_on_select="False"
$c-props="{loop, closeOnSelect: close}"
>
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Browse spell index</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="aegis">Aegis</c-CMenuItem>
<c-CMenuItem value="alchemy">Alchemy</c-CMenuItem>
<c-CMenuItem value="astral">Astral projection</c-CMenuItem>
<c-CMenuItem value="binding">Binding</c-CMenuItem>
<c-CMenuItem value="blessing">Blessing</c-CMenuItem>
<c-CMenuItem value="conjuring">Conjuring</c-CMenuItem>
<c-CMenuItem value="divination">Divination</c-CMenuItem>
<c-CMenuItem value="enchantment">Enchantment</c-CMenuItem>
<c-CMenuItem value="illusion">Illusion</c-CMenuItem>
<c-CMenuItem value="restoration">Restoration</c-CMenuItem>
<c-CMenuItem value="warding">Warding</c-CMenuItem>
</c-fill>
</c-CMenu>
</section>
"""
css = """
:where(.archive-keyboard-demo) {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1rem;
min-block-size: 20rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
:where(.archive-keyboard-demo) {
--cui-menu-max-block-size: 13rem;
}
"""
preview_controls = (
{
"name": "loop",
"label": "Loop navigation",
"type": "checkbox",
"default": True,
},
{
"name": "close",
"label": "Close on action",
"type": "checkbox",
"default": False,
},
)
preview = MenuKeyboard()
preview # noqa: B018
Escape closes one submenu or the root. Tab closes the whole tree and continues normal page order. Disabled items remain discoverable by Menu navigation but never activate.
Disable Menu safely
Menu disabled and native disabled fieldset ancestry are authoritative. Buttons inside the Menu always use type=button, so commands never submit an enclosing Form.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class MenuDisabledAndForms(Component):
template = """
<section
class="archive-disabled-demo"
x-data="{locked: true, submits: 0}"
>
<c-CButton size="sm" @click="locked = !locked">
Toggle archive seal
</c-CButton>
<form @submit.prevent="submits += 1">
<fieldset :disabled="locked">
<legend>Archive desk</legend>
<c-CMenu>
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Desk commands</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="catalog">Catalog folio</c-CMenuItem>
<c-CMenuItem value="sealed" disabled>Break royal seal</c-CMenuItem>
</c-fill>
</c-CMenu>
<button type="submit">Submit native form</button>
</fieldset>
</form>
<output x-text="`Form submits: ${submits}`">Form submits: 0</output>
</section>
"""
css = """
:where(.archive-disabled-demo) {
display: grid;
gap: 0.75rem;
min-block-size: 18rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
:where(.archive-disabled-demo fieldset) {
display: flex;
gap: 0.75rem;
align-items: center;
padding: 1rem;
border: 1px solid color-mix(in srgb, CanvasText 20%, transparent);
border-radius: 0.75rem;
}
"""
preview = MenuDisabledAndForms()
preview # noqa: B018
Place the surface
Choose one of six logical block placements. match_width follows the activator only up to the viewport-safe maximum. Submenus prefer logical inline-end, flip inline, then use a centered block fallback when neither side is usable.
Customize example
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class MenuPlacement(Component):
template = """
<section
class="archive-placement-demo"
x-data="{placement: 'bottom-start', rtl: false, match: true}"
:dir="rtl ? 'rtl' : 'ltr'"
@citry-ui-preview-controls.window="Object.assign($data, $event.detail)"
>
<c-CMenu $c-props="{placement, matchWidth: match}">
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton
class_="archive-placement-demo__wide"
c-disabled="activator_disabled"
c-attrs="activator_attrs"
>
A deliberately wide enchanted-volume trigger
</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="north">Northern shelf</c-CMenuItem>
<c-CMenuItem value="south">Southern shelf</c-CMenuItem>
<c-CMenuSubmenu value="hidden-wing">
<c-fill name="label">Hidden wing</c-fill>
<c-fill name="default">
<c-CMenuItem value="mirrors">Hall of mirrors</c-CMenuItem>
</c-fill>
</c-CMenuSubmenu>
</c-fill>
</c-CMenu>
</section>
"""
css = """
:where(.archive-placement-demo) {
display: grid;
gap: 1rem;
justify-items: center;
min-block-size: 21rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
:where(.archive-placement-demo__wide) {
inline-size: min(34rem, 150dvi);
}
"""
preview_controls = (
{
"name": "placement",
"label": "Placement",
"type": "select",
"default": "bottom-start",
"options": (
("bottom-start", "Bottom start"),
("bottom", "Bottom"),
("bottom-end", "Bottom end"),
("top-start", "Top start"),
("top", "Top"),
("top-end", "Top end"),
),
},
{
"name": "match",
"label": "Match activator width",
"type": "checkbox",
"default": True,
},
{
"name": "rtl",
"label": "Right-to-left",
"type": "checkbox",
"default": False,
},
)
preview = MenuPlacement()
preview # noqa: B018
Choose a size
sm, md, and lg change the whole family’s item geometry.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class MenuSizes(Component):
template = """
<section class="archive-size-demo">
<c-CMenu size="sm">
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton size="sm" c-disabled="activator_disabled" c-attrs="activator_attrs">Small</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="index">Pocket index</c-CMenuItem>
<c-CMenuItem value="notes">Margin notes</c-CMenuItem>
</c-fill>
</c-CMenu>
<c-CMenu size="md">
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Medium</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="index">Reading index</c-CMenuItem>
<c-CMenuItem value="notes">Scribe notes</c-CMenuItem>
</c-fill>
</c-CMenu>
<c-CMenu size="lg">
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton size="lg" c-disabled="activator_disabled" c-attrs="activator_attrs">Large</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="index">Grand index</c-CMenuItem>
<c-CMenuItem value="notes">Archivist notes</c-CMenuItem>
</c-fill>
</c-CMenu>
</section>
"""
css = """
:where(.archive-size-demo) {
display: flex;
flex-wrap: wrap;
align-items: start;
gap: 1rem;
min-block-size: 17rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
"""
preview = MenuSizes()
preview # noqa: B018
Customize Menu
Override public variables on an ancestor or one wrapper. Stable part selectors target the surface, item regions, groups, indicators, separators, and submenus.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class CustomizedMenus(Component):
template = """
<section class="archive-theme-demo">
<div class="archive-theme-demo__moon">
<c-CMenu>
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Moon archive</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="phases">Moon phases</c-CMenuItem>
<c-CMenuItem value="eclipses">Eclipse records</c-CMenuItem>
</c-fill>
</c-CMenu>
</div>
<div class="archive-theme-demo__ember">
<c-CMenu>
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Ember archive</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="dragons">Dragon chronicles</c-CMenuItem>
<c-CMenuItem value="ashes" intent="danger">Destroy ash record</c-CMenuItem>
</c-fill>
</c-CMenu>
</div>
</section>
"""
css = """
:where(.archive-theme-demo) {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
min-block-size: 18rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
:where(.archive-theme-demo__moon) {
--cui-menu-background: light-dark(#f4f2ff, #17142d);
--cui-menu-border-color: light-dark(#8f83c7, #7065aa);
--cui-menu-focus-background: light-dark(#4c3e92, #b6a9ff);
--cui-menu-focus-foreground: light-dark(#ffffff, #17142d);
--cui-menu-radius: 1rem;
}
:where(.archive-theme-demo__ember) {
--cui-menu-background: light-dark(#fff7ed, #2a1710);
--cui-menu-border-color: light-dark(#d97706, #f59e0b);
--cui-menu-focus-background: light-dark(#9a3412, #fdba74);
--cui-menu-focus-foreground: light-dark(#ffffff, #2a1710);
--cui-menu-danger-color: light-dark(#991b1b, #fecaca);
--cui-menu-radius: 0.35rem;
}
"""
preview = CustomizedMenus()
preview # noqa: B018
Every styled family member exposes top-level class_ and style on its documented root. Unlayered consumer CSS overrides Citry UI defaults; named layers follow the site-wide layer-order contract.
Compose with other overlays
Menu, Popover, Tooltip, and Dialog share one logical layer coordinator. Closing an ancestor closes descendant submenus first. Opening an unrelated modal Dialog suppresses outside anchored layers and gives the Dialog Escape/focus ownership.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class MenuLifecycle(Component):
template = """
<section class="archive-lifecycle-demo" x-data>
<c-CPopover>
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">Open reading room</c-CButton>
</c-fill>
<c-fill name="title">Reading room</c-fill>
<c-fill name="default">
<c-CMenu>
<c-fill name="activator" data="{ activator_attrs, activator_disabled }">
<c-CButton c-disabled="activator_disabled" c-attrs="activator_attrs">Nested folio menu</c-CButton>
</c-fill>
<c-fill name="default">
<c-CMenuItem value="inspect">Inspect binding</c-CMenuItem>
<c-CMenuSubmenu value="editions">
<c-fill name="label">Other editions</c-fill>
<c-fill name="default">
<c-CMenuItem value="first">First edition</c-CMenuItem>
</c-fill>
</c-CMenuSubmenu>
</c-fill>
</c-CMenu>
</c-fill>
</c-CPopover>
<c-CButton @click="$refs.vault.showModal()">Open modal vault</c-CButton>
<dialog x-ref="vault" aria-labelledby="vault-title">
<h2 id="vault-title">Royal vault</h2>
<p>Opening this modal closes unrelated anchored layers.</p>
<button type="button" @click="$refs.vault.close()">Close vault</button>
</dialog>
</section>
"""
css = """
:where(.archive-lifecycle-demo) {
display: flex;
flex-wrap: wrap;
gap: 1rem;
min-block-size: 20rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
:where(.archive-lifecycle-demo dialog) {
max-inline-size: min(26rem, calc(100dvi - 2rem));
padding: 1.25rem;
border: 1px solid color-mix(in srgb, CanvasText 24%, transparent);
border-radius: 0.85rem;
background: Canvas;
color: CanvasText;
}
:where(.archive-lifecycle-demo dialog::backdrop) {
background: rgb(15 23 42 / 45%);
}
"""
preview = MenuLifecycle()
preview # noqa: B018
Trust boundary
Text is escaped. Values are plain, nonempty canonical strings; generated IDs do not expose raw values. href remains a trusted application URL boundary. Attribute maps reject owned semantics, focus, visibility, anchoring, structural Alpine directives, and Citry runtime namespaces. Use Popover when item content needs links, Buttons, inputs, editing, or independent Tab stops.
API reference
Inputs
CMenu server inputs
Server inputs are passed in a template through <c-CMenu ... /> or in Python through CMenu(...).
| Input | Type | Default | Effect |
|---|---|---|---|
id | str | None | generated | Sets the Menu surface and activator relationship identity. |
open | bool | False | Sets initial visibility and the uncontrolled fallback. |
disabled | bool | False | Disables the activator and force-closes the tree. Native disabled fieldset ancestry also applies. |
loop | bool | True | Wraps arrow navigation and typeahead matching. |
placement | "top-start" | "top" | "top-end" | "bottom-start" | "bottom" | "bottom-end" (CMenuPlacement) | "bottom-start" | Sets the preferred logical root placement. |
match_width | bool | False | Matches the activator width up to the viewport-safe maximum. |
close_on_select | bool | True | Sets the default command and choice close policy. |
size | "sm" | "md" | "lg" (CMenuSize) | "md" | Sets item geometry for the whole tree. |
class_ | str | Mapping[str, bool] | Sequence[CClassValue] | None (CClassValue) | None | Adds surface classes and merges with attrs. |
style | str | Mapping[str, str | int | float | bool | None] | Sequence[CStyleValue] | None (CStyleValue) | None | Adds surface styles; private anchor ownership merges last. |
attrs | Mapping[str, object] | None | None | Adds allowed native, ARIA, Alpine, and data attributes to the Menu surface. |
CMenu client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CMenu />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
open | boolean | null | Releases control from committed state. null has the same effect. | Controls root visibility while supplied as a Boolean. |
disabled | boolean | Uses the server input. | Controls local disabledness; native fieldset disabledness remains authoritative. |
loop | boolean | Uses the server input. | Controls keyboard wrapping. |
placement | six logical placement strings (CMenuPlacement) | Uses the server input. | Controls requested placement. |
matchWidth | boolean | Uses the server input. | Controls clamped activator-width matching. |
closeOnSelect | boolean | Uses the server input. | Controls the tree default close policy. |
size | "sm" | "md" | "lg" (CMenuSize) | Uses the server input. | Controls tree geometry. |
onOpenChange | function | Does not notify a visibility callback. | Receives visibility requests and forced close notices. |
onAction | function | Does not notify a root action callback. | Receives valued command and choice activations. |
CMenuItem server inputs
Server inputs are passed in a template through <c-CMenuItem ... /> or in Python through CMenuItem(...).
| Input | Type | Default | Effect |
|---|---|---|---|
value | str | None | None | Supplies optional canonical command identity for root onAction; rejected with href. |
href | str | None | None | Renders a real anchor and preserves native navigation. |
disabled | bool | False | Makes the item focusable but inactive. |
close_on_select | bool | None | None | Overrides the root close policy when supplied. |
intent | "default" | "danger" (CMenuIntent) | "default" | Sets visual emphasis. |
text_value | str | None | None | Overrides label-derived typeahead text. |
class_ | CClassValue | None (CClassValue) | None | Adds semantic-root classes. |
style | CStyleValue | None (CStyleValue) | None | Adds semantic-root styles. |
attrs | Mapping[str, object] | None | None | Adds allowed semantic-root attributes. |
CMenuItem client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CMenuItem />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
disabled | boolean | Uses the server input. | Controls inactive behavior and aria-disabled. |
closeOnSelect | boolean | null | Inherits the root policy. null has the same effect. | Controls per-item close behavior. |
intent | "default" | "danger" (CMenuIntent) | Uses the server input. | Controls emphasis and data-intent. |
textValue | string | null | Uses the server fallback. | Controls typeahead text; a null fallback may read current label text. |
CMenuCheckboxItem server inputs
Server inputs are passed in a template through <c-CMenuCheckboxItem ... /> or in Python through CMenuCheckboxItem(...).
| Input | Type | Default | Effect |
|---|---|---|---|
value | str | required | Sets unique canonical choice identity. |
checked | bool | "mixed" (CMenuChecked) | False | Sets initial checked state. |
disabled | bool | False | Makes the item focusable but inactive. |
close_on_select | bool | None | None | Overrides the root close policy. |
text_value | str | None | None | Overrides label-derived typeahead text. |
class_ | CClassValue | None (CClassValue) | None | Adds item classes. |
style | CStyleValue | None (CStyleValue) | None | Adds item styles. |
attrs | Mapping[str, object] | None | None | Adds allowed item attributes. |
CMenuCheckboxItem client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CMenuCheckboxItem />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
checked | boolean | "mixed" | null (CMenuChecked) | Releases control from committed state. null has the same effect. | Controls checked state. |
disabled | boolean | Uses the server input. | Controls inactive behavior. |
closeOnSelect | boolean | null | Inherits the root policy. | Controls per-item close behavior. |
textValue | string | null | Uses the server fallback. | Controls typeahead text. |
onCheckedChange | function | Does not notify a checked callback. | Receives requested checked values. |
CMenuRadioGroup server inputs
Server inputs are passed in a template through <c-CMenuRadioGroup ... /> or in Python through CMenuRadioGroup(...).
| Input | Type | Default | Effect |
|---|---|---|---|
value | str | required | Sets the required initial direct-radio selection. |
class_ | CClassValue | None (CClassValue) | None | Adds group classes. |
style | CStyleValue | None (CStyleValue) | None | Adds group styles. |
attrs | Mapping[str, object] | None | None | Adds allowed group attributes. |
CMenuRadioGroup client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CMenuRadioGroup />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
value | string | null | Releases control from committed state. null has the same effect. | Controls the selected radio value. |
onValueChange | function | Does not notify a value callback. | Receives activation and structural-removal value requests. |
CMenuRadioItem server inputs
Server inputs are passed in a template through <c-CMenuRadioItem ... /> or in Python through CMenuRadioItem(...).
| Input | Type | Default | Effect |
|---|---|---|---|
value | str | required | Sets canonical identity unique in the radio group. |
disabled | bool | False | Makes the item focusable but inactive. |
close_on_select | bool | None | None | Overrides the root close policy. |
text_value | str | None | None | Overrides label-derived typeahead text. |
class_ | CClassValue | None (CClassValue) | None | Adds item classes. |
style | CStyleValue | None (CStyleValue) | None | Adds item styles. |
attrs | Mapping[str, object] | None | None | Adds allowed item attributes. |
CMenuRadioItem client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CMenuRadioItem />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
disabled | boolean | Uses the server input. | Controls inactive behavior. |
closeOnSelect | boolean | null | Inherits the root policy. | Controls per-item close behavior. |
textValue | string | null | Uses the server fallback. | Controls typeahead text. |
CMenuGroup server inputs
Server inputs are passed in a template through <c-CMenuGroup ... /> or in Python through CMenuGroup(...).
| Input | Type | Default | Effect |
|---|---|---|---|
class_ | CClassValue | None (CClassValue) | None | Adds group classes. |
style | CStyleValue | None (CStyleValue) | None | Adds group styles. |
attrs | Mapping[str, object] | None | None | Adds allowed group attributes. |
CMenuSeparator server inputs
Server inputs are passed in a template through <c-CMenuSeparator ... /> or in Python through CMenuSeparator(...).
| Input | Type | Default | Effect |
|---|---|---|---|
class_ | CClassValue | None (CClassValue) | None | Adds separator classes. |
style | CStyleValue | None (CStyleValue) | None | Adds separator styles. |
attrs | Mapping[str, object] | None | None | Adds allowed separator attributes. |
CMenuSubmenu server inputs
Server inputs are passed in a template through <c-CMenuSubmenu ... /> or in Python through CMenuSubmenu(...).
| Input | Type | Default | Effect |
|---|---|---|---|
value | str | required | Sets a canonical path segment unique at its menu level. |
disabled | bool | False | Makes the trigger inactive and force-closes its child. |
intent | "default" | "danger" (CMenuIntent) | "default" | Sets trigger emphasis. |
text_value | str | None | None | Overrides label-derived typeahead text. |
class_ | CClassValue | None (CClassValue) | None | Adds neutral-wrapper classes. |
style | CStyleValue | None (CStyleValue) | None | Adds neutral-wrapper styles inherited by the child surface. |
attrs | Mapping[str, object] | None | None | Adds allowed neutral-wrapper attributes. |
trigger_attrs | Mapping[str, object] | None | None | Adds allowed submenu-trigger attributes. |
menu_attrs | Mapping[str, object] | None | None | Adds allowed child Menu-surface attributes. |
CMenuSubmenu client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CMenuSubmenu />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
disabled | boolean | Uses the server input. | Controls inactive behavior and child closure. |
intent | "default" | "danger" (CMenuIntent) | Uses the server input. | Controls trigger emphasis. |
textValue | string | null | Uses the server fallback. | Controls typeahead text. |
Slots
Slots are passed as nested content or <c-fill> tags in a template, or through the slots={...} argument in Python.
CMenu slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
activator | yes | {activator_attrs: dict[str, object], activator_disabled: bool} (CMenuActivatorSlotData) | none |
default | yes | {} (CMenuDefaultSlotData) | none |
CMenuItem slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
start | no | {} (CMenuItemStartSlotData) | omitted |
default | yes | {} (CMenuItemDefaultSlotData) | none |
description | no | {} (CMenuItemDescriptionSlotData) | omitted |
end | no | {} (CMenuItemEndSlotData) | omitted |
CMenuCheckboxItem slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
start | no | {} (CMenuItemStartSlotData) | omitted |
default | yes | {} (CMenuItemDefaultSlotData) | none |
description | no | {} (CMenuItemDescriptionSlotData) | omitted |
end | no | {} (CMenuItemEndSlotData) | omitted |
CMenuRadioItem slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
start | no | {} (CMenuItemStartSlotData) | omitted |
default | yes | {} (CMenuItemDefaultSlotData) | none |
description | no | {} (CMenuItemDescriptionSlotData) | omitted |
end | no | {} (CMenuItemEndSlotData) | omitted |
CMenuRadioGroup slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
label | no | {} (CMenuRadioGroupLabelSlotData) | omitted |
default | yes | {} (CMenuRadioGroupDefaultSlotData) | none |
CMenuGroup slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
label | yes | {} (CMenuGroupLabelSlotData) | none |
default | yes | {} (CMenuGroupDefaultSlotData) | none |
CMenuSubmenu slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
start | no | {} (CMenuSubmenuStartSlotData) | omitted |
label | yes | {} (CMenuSubmenuLabelSlotData) | none |
description | no | {} (CMenuSubmenuDescriptionSlotData) | omitted |
end | no | {} (CMenuSubmenuEndSlotData) | Built-in direction-aware chevron. |
default | yes | {} (CMenuSubmenuDefaultSlotData) | none |
Events
Component events are callback inputs supplied through $c-props. Native browser events remain available through Alpine @... attributes.
CMenu events
| Event | Signature | Trigger and timing | Detail | Controlled and cancellation behavior |
|---|---|---|---|---|
onOpenChange | (requestedOpen: boolean, detail: CMenuOpenChangeDetail) => void (CMenuOpenChangeDetail) | A visibility request occurs or a forced safety close changes effective open state. | {reason, controlled, forced, source} (CMenuOpenChangeDetail) | Uncontrolled requests commit before notification; controlled requests wait except forced closes. |
onAction | (value: string, detail: CMenuActionDetail) => void (CMenuActionDetail) | An enabled valued command or choice activates. | {kind, item, event, path} (CMenuActionDetail) | Fires once after a choice-specific request and before the close request. Links and anonymous commands do not fire it. |
CMenuCheckboxItem events
| Event | Signature | Trigger and timing | Detail | Controlled and cancellation behavior |
|---|---|---|---|---|
onCheckedChange | (requestedChecked: boolean, detail: CMenuCheckedChangeDetail) => void (CMenuCheckedChangeDetail) | An enabled checkbox item activates. | {checked, previousChecked, controlled, item, event, path} (CMenuCheckedChangeDetail) | Controlled items wait for owner acceptance. |
CMenuRadioGroup events
| Event | Signature | Trigger and timing | Detail | Controlled and cancellation behavior |
|---|---|---|---|---|
onValueChange | (requestedValue: string, detail: CMenuRadioChangeDetail) => void (CMenuRadioChangeDetail) | A different enabled radio activates or the selected radio is structurally removed in either ownership mode. | {value, previousValue, reason, controlled, item, event, path} (CMenuRadioChangeDetail) | Controlled groups wait for owner acceptance. |
Methods
-
CSS
CSS variables to theme the components. Set them on an ancestor or the component itself.
CMenu CSS variables
Apply these variables to CMenu or one of its ancestors.
| Variable | Type | Purpose | Default |
|---|---|---|---|
--cui-menu-background | color | Menu surfaces. | Canvas |
--cui-menu-foreground | color | Item text. | CanvasText |
--cui-menu-muted-color | color | Descriptions, labels, and shortcuts. | color-mix(in srgb, current foreground 72%, transparent) |
--cui-menu-border-color | color | Surface and separator boundaries. | color-mix(in srgb, CanvasText 18%, transparent) |
--cui-menu-border-width | length | Surface boundary width. | 1px |
--cui-menu-radius | length | Surface corners. | 0.75rem |
--cui-menu-shadow | shadow | Root elevation. | 0 0.75rem 2rem rgb(15 23 42 / 18%) |
--cui-menu-submenu-shadow | shadow | Nested elevation. | 0 1rem 2.5rem rgb(15 23 42 / 22%) |
--cui-menu-inline-size | length | Preferred width. | 14rem |
--cui-menu-min-inline-size | length | Minimum useful inline submenu corridor. | 10rem |
--cui-menu-max-inline-size | length | Viewport-safe width. | calc(100dvi - 1rem) |
--cui-menu-max-block-size | length | Scroll limit. | min(24rem, calc(100dvb - 1rem)) |
--cui-menu-padding | length | Surface edge spacing. | 0.375rem |
--cui-menu-item-block-size | length | Item minimum height. | Size-derived. |
--cui-menu-item-padding-inline | length | Item inline spacing. | Size-derived. |
--cui-menu-item-gap | length | Item-region gap. | 0.625rem |
--cui-menu-item-radius | length | Item corners. | 0.5rem |
--cui-menu-hover-background | color | Pointer hover fill. | color-mix(in srgb, CanvasText 8%, transparent) |
--cui-menu-focus-background | color | Focused item fill. | light-dark(#175cd3, #84adff) |
--cui-menu-focus-foreground | color | Focused item content. | light-dark(#ffffff, #101828) |
--cui-menu-focus-outline-color | color | Focus-visible outline. | light-dark(#175cd3, #84adff) |
--cui-menu-danger-color | color | Destructive item content. | light-dark(#b42318, #fda29b) |
--cui-menu-disabled-opacity | number | Disabled content opacity. | 0.5 |
--cui-menu-offset | length | Root anchor gap. | 0.375rem |
--cui-menu-submenu-offset | length | Nested anchor gap. | 0.25rem |
--cui-menu-duration | time | Entry and exit duration. | 120ms |
--cui-menu-easing | easing | Entry and exit easing. | cubic-bezier(0.2, 0.8, 0.2, 1) |
Attributes
HTML attributes defined on the components that you can refer to for CSS, inspection, and testing. Read-only.
CMenu attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
popover | Menu surface | "manual" | Native top-layer presence with Citry dismissal. |
role | Menu surface | "menu" | Application Menu composite. |
aria-labelledby | Menu surface | activator IDREF | Names the Menu from its Button. |
data-open | Menu surface | present | absent | Mirrors logical open ownership. |
data-placement | Menu surface | six requested placement strings (CMenuPlacement) | Requested logical placement, not collision result. |
data-match-width | Menu surface | present | absent | Indicates clamped activator-width matching. |
data-size | Menu surface | "sm" | "md" | "lg" (CMenuSize) | Effective item geometry. |
aria-haspopup | Activator Button | "menu" | Announces the controlled popup kind. |
aria-controls | Activator Button | IDREF | References the Menu surface. |
aria-expanded | Activator Button | "true" | "false" | Mirrors logical open state. |
CMenuItem attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
role | Item root | "menuitem" | Command or native-link semantics. |
aria-labelledby | Item root | owned label IDREF | Exact visible accessible name. |
aria-describedby | Item root | description IDREF | absent | Optional separate description. |
aria-disabled | Item root | "true" | absent | Focusable inactive item. |
data-disabled | Item root | present | absent | Disabled styling mirror. |
data-intent | Item root | "default" | "danger" (CMenuIntent) | Visual emphasis. |
CMenuCheckboxItem attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
role | Item Button | "menuitemcheckbox" | Checkable command semantics. |
aria-checked | Item Button | "false" | "true" | "mixed" | Effective checked value. |
data-checked | Item Button | "false" | "true" | "mixed" | Styling mirror. |
CMenuRadioItem attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
role | Item Button | "menuitemradio" | Exclusive choice semantics. |
aria-checked | Item Button | "false" | "true" | Effective group selection. |
data-checked | Item Button | "false" | "true" | Styling mirror. |
CMenuGroup attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
role | Group root | "group" | Owns grouped direct Menu items. |
aria-labelledby | Group root | group-label IDREF | Names the group from its visible label. |
CMenuRadioGroup attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
role | Radio-group root | "group" | Owns exclusive radio items. |
aria-labelledby | Radio-group root | label IDREF | absent | Names the group when a label is supplied. |
CMenuSeparator attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
role | Horizontal rule | "separator" | Divides vertically stacked item families. |
CMenuSubmenu attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
role | Wrapper / trigger / surface | "none" / "menuitem" / "menu" | Keeps the trigger and immediate sibling child Menu relationship. |
aria-haspopup | Submenu trigger | "menu" | Announces the child Menu. |
aria-controls | Submenu trigger | child Menu IDREF | References the child surface. |
aria-expanded | Submenu trigger | "true" | "false" | Mirrors child open state. |
data-open | Wrapper / child surface | present | absent | Mirrors logical child open ownership. |
Selectors
Selectors for the DOM nodes in the components that you can use for CSS, inspection, and testing.
CMenu selectors
| Selector | Element | Purpose |
|---|---|---|
[data-citry-ui-part="menu"] | Root or submenu surface | Popover presence and collection focus. |
[data-citry-ui-part="menu-item"] | Command/link/check/radio semantic root | Item styling. |
[data-citry-ui-part="menu-item-start"] | Decorative start wrapper | Start-region layout. |
[data-citry-ui-part="menu-item-label"] | Visible item label | Layout and exact accessible-name target. |
[data-citry-ui-part="menu-item-description"] | Optional description | Supporting text and accessible description. |
[data-citry-ui-part="menu-item-end"] | Decorative end wrapper | Shortcut/end-region layout. |
[data-citry-ui-part="menu-choice-indicator"] | Decorative choice indicator | Checked/radio marker. |
[data-citry-ui-part="menu-group"] | Labelled group root | Group layout. |
[data-citry-ui-part="menu-group-label"] | Visible group label | Exact group name and layout. |
[data-citry-ui-part="menu-radio-group"] | Radio-group root | Exclusive choice grouping. |
[data-citry-ui-part="menu-separator"] | Horizontal separator | Collection division. |
[data-citry-ui-part="menu-submenu"] | Neutral submenu wrapper | Trigger/surface ownership and inherited customization. |
[data-citry-ui-part="menu-submenu-trigger"] | Submenu Button | Child Menu activation and placement anchor. |
Interfaces
Aliases and data shapes referenced above.
Input type aliases
| Interface | Definition |
|---|---|
CClassValue | str | Mapping[str, bool] | Sequence[CClassValue] |
CStyleValue | str | Mapping[str, str | int | float | bool | None] | Sequence[CStyleValue] |
CMenuPlacement | Literal["top-start", "top", "top-end", "bottom-start", "bottom", "bottom-end"] |
CMenuSize | Literal["sm", "md", "lg"] |
CMenuIntent | Literal["default", "danger"] |
CMenuChecked | bool | Literal["mixed"] |
CMenuActivatorSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
activator_attrs | dict[str, object] | - | Owned trigger marker, anchor identity, and synchronized ARIA relationships. |
activator_disabled | bool | - | Server-owned disabled value to forward through the activator component input. |
CMenuDefaultSlotData
Empty dataclass: {}.
CMenuItemStartSlotData
Empty dataclass: {}.
CMenuItemDefaultSlotData
Empty dataclass: {}.
CMenuItemDescriptionSlotData
Empty dataclass: {}.
CMenuItemEndSlotData
Empty dataclass: {}.
CMenuGroupLabelSlotData
Empty dataclass: {}.
CMenuGroupDefaultSlotData
Empty dataclass: {}.
CMenuRadioGroupLabelSlotData
Empty dataclass: {}.
CMenuRadioGroupDefaultSlotData
Empty dataclass: {}.
CMenuSubmenuStartSlotData
Empty dataclass: {}.
CMenuSubmenuLabelSlotData
Empty dataclass: {}.
CMenuSubmenuDescriptionSlotData
Empty dataclass: {}.
CMenuSubmenuEndSlotData
Empty dataclass: {}.
CMenuSubmenuDefaultSlotData
Empty dataclass: {}.
CMenuOpenChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
reason | "trigger" | "escape" | "outside" | "focus-outside" | "tab" | "action" | "native" | "disabled" | "ancestor" | - | Cause of the requested or forced visibility change. |
controlled | boolean | - | Whether a valid client Boolean owns desired state. |
forced | boolean | - | Whether native/structural safety overrides owner rejection. |
source | Element | EventTarget | null | - | Browser source associated with the change. |
CMenuActionDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
kind | "command" | "checkbox" | "radio" | - | Activated semantic item kind. |
item | Element | - | Activated item root. |
event | Event | - | Native activation event. |
path | list[str] | - | Canonical ancestor-submenu path from the root. |
CMenuCheckedChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
checked | boolean | - | Requested checked value; activation moves mixed to true and otherwise negates the prior state. |
previousChecked | boolean | "mixed" (CMenuChecked) | - | Prior effective value. |
controlled | boolean | - | Whether a valid client value owns state. |
item | Element | - | Activated checkbox item. |
event | Event | - | Native activation event. |
path | list[str] | - | Canonical ancestor-submenu path. |
CMenuRadioChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
value | string | - | Requested radio value. |
previousValue | string | - | Prior selected value. |
reason | "activation" | "removal" | - | Request source. |
controlled | boolean | - | Whether a valid client value owns state. |
item | Element | null | - | Activated item or null for structural removal. |
event | Event | null | - | Native activation event or null for removal. |
path | list[str] | - | Canonical ancestor-submenu path. |
Translation keys
-