Popover
Use CPopover for compact interactive content that belongs beside one Button without blocking the rest of the page. It enters the browser top layer, so it escapes clipping while keeping its original DOM, theme, and Form relationships.
Popover at a glance
Open each Button to compare concise content, a description, an explicit action, and trigger-width matching.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class PopoverAtAGlance(Component):
template = """
<section class="popover-sampler">
<c-CPopover placement="bottom-start">
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">
Europa
</c-CButton>
</c-fill>
<c-fill name="title">Europa</c-fill>
<c-fill name="default">An ocean world beneath fractured ice.</c-fill>
</c-CPopover>
<c-CPopover placement="top">
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton variant="outline" c-attrs="activator_attrs">
Enceladus
</c-CButton>
</c-fill>
<c-fill name="title">Enceladus</c-fill>
<c-fill name="description">Saturn II</c-fill>
<c-fill name="default">Bright plumes erupt above its south pole.</c-fill>
</c-CPopover>
<c-CPopover placement="bottom-end" match_width>
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton variant="ghost" c-attrs="activator_attrs">
Titan atmosphere
</c-CButton>
</c-fill>
<c-fill name="title">Titan</c-fill>
<c-fill name="default">A dense nitrogen sky conceals methane lakes.</c-fill>
<c-fill name="actions" data="{ close_attrs }">
<c-CButton size="sm" c-attrs="close_attrs">
Mark explored
</c-CButton>
</c-fill>
</c-CPopover>
</section>
"""
css = """
:where(.popover-sampler) {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.75rem;
min-block-size: 12rem;
padding-block: 2rem;
}
"""
preview = PopoverAtAGlance()
preview # noqa: B018
Build a Popover
Provide an activator, visible title, and body. Spread activator_attrs onto one native Button. CButton renders the required Button when href is omitted.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class MoonInspector(Component):
template = """
<section class="moon-inspector">
<p>Jovian system</p>
<h2>Four worlds orbit a striped giant</h2>
<c-CPopover>
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">
Inspect Europa
</c-CButton>
</c-fill>
<c-fill name="title">
Europa
</c-fill>
<c-fill name="description">
Jupiter II ยท mean radius 1,560.8 km
</c-fill>
<c-fill name="default">
Its fractured water-ice crust may cover a global saltwater ocean.
</c-fill>
</c-CPopover>
</section>
"""
css = """
:where(.moon-inspector) {
display: grid;
gap: 0.75rem;
justify-items: start;
max-inline-size: 42rem;
color: CanvasText;
font-family: ui-sans-serif, system-ui, sans-serif;
}
:where(.moon-inspector h2, .moon-inspector p) {
margin: 0;
}
:where(.moon-inspector > p) {
color: light-dark(#4338ca, #a5b4fc);
font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
"""
preview = MoonInspector()
preview # noqa: B018
<c-CPopover>
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">
Inspect Europa
</c-CButton>
</c-fill>
<c-fill name="title">
Europa
</c-fill>
<c-fill name="description">
Jupiter II ยท mean radius 1,560.8 km
</c-fill>
<c-fill name="default">
Its fractured water-ice crust may cover a global ocean.
</c-fill>
</c-CPopover>
The title becomes the accessible name. Keep description concise; place structured or lengthy content in the body.
The activator must resolve to exactly one native Button. Do not use an anchor, generic element, or several controls. Disable that Button itself when opening is unavailable so native semantics, styling, and Popover behavior agree.
Add interactive content and actions
The body accepts native controls and nested components. Content stays mounted, so edits survive closing and reopening. Spread close_attrs only onto actions that should request closure.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class InteractivePopover(Component):
template = """
<section class="orbit-editor">
<c-CPopover>
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">
Adjust orbit note
</c-CButton>
</c-fill>
<c-fill name="title">
Orbit note
</c-fill>
<c-fill name="description">
Changes stay in the native Form after closing.
</c-fill>
<c-fill name="default">
<form id="orbit-form">
<label for="orbit-label">Label</label>
<input id="orbit-label" name="label" value="Perijove pass" />
<label for="orbit-detail">Detail</label>
<textarea id="orbit-detail" name="detail">Closest approach before sunrise.</textarea>
</form>
</c-fill>
<c-fill name="actions" data="{ close_attrs }">
<c-CButton variant="ghost" c-attrs="close_attrs">
Cancel
</c-CButton>
<c-CButton c-attrs="close_attrs">
Keep note
</c-CButton>
</c-fill>
</c-CPopover>
</section>
"""
css = """
:where(.orbit-editor) {
min-block-size: 15rem;
padding-block: 3rem;
}
:where(#orbit-form) {
display: grid;
gap: 0.5rem;
}
:where(#orbit-form input, #orbit-form textarea) {
box-sizing: border-box;
inline-size: 100%;
padding: 0.5rem 0.625rem;
border: 1px solid color-mix(in srgb, CanvasText 25%, transparent);
border-radius: 0.5rem;
background: Canvas;
color: CanvasText;
font: inherit;
}
"""
preview = InteractivePopover()
preview # noqa: B018
<c-fill name="actions" data="{ close_attrs }">
<c-CButton variant="ghost" c-attrs="close_attrs">
Cancel
</c-CButton>
<c-CButton c-attrs="close_attrs">
Keep note
</c-CButton>
</c-fill>
Popover never closes merely because body content was clicked. This keeps links, inputs, selectors, and nested components predictable.
Control visibility
Client inputs are passed in the browser through $c-props="{...}". Supply a Boolean open to control visibility. onOpenChange reports requests; update the owner value to accept one or leave it unchanged to decline it.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class ControlledPopover(Component):
template = """
<section
class="controlled-popover"
x-data="{ open: false, locked: false, lastReason: 'none' }"
>
<c-CPopover
$c-props="{
open,
onOpenChange: (nextOpen, detail) => {
lastReason = detail.reason;
if (!locked) open = nextOpen;
},
}"
>
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">
Mission controls
</c-CButton>
</c-fill>
<c-fill name="title">Mission controls</c-fill>
<c-fill name="default">
The owner may accept or decline every visibility request.
</c-fill>
<c-fill name="actions" data="{ close_attrs }">
<c-CButton c-attrs="close_attrs">Close panel</c-CButton>
</c-fill>
</c-CPopover>
<label>
<input type="checkbox" x-model="locked" />
Decline visibility requests
</label>
<output x-text="`Last request: ${lastReason}`"></output>
</section>
"""
css = """
:where(.controlled-popover) {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1rem;
min-block-size: 12rem;
padding-block: 2rem;
}
:where(.controlled-popover output) {
flex-basis: 100%;
color: color-mix(in srgb, CanvasText 70%, transparent);
}
"""
preview = ControlledPopover()
preview # noqa: B018
<c-CPopover
$c-props="{
open,
onOpenChange: (nextOpen, detail) => {
if (mayApply(nextOpen, detail)) open = nextOpen;
},
}"
>
...
</c-CPopover>
Without a client open, Popover commits user requests itself and then notifies. Removing the client value or passing null releases control without resetting the current state. Owner commits do not call back.
The callback detail identifies trigger, action, escape, outside, focus-outside, unavoidable external native changes, and safety closures caused by an ancestor or modal. It also includes controlled ownership, whether the close was forced, and the browser source.
Choose dismissal behavior
dismissible=True allows Escape, outside pointer, and focus-outside requests. The activator and controls carrying close_attrs always remain explicit paths.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class PopoverDismissal(Component):
template = """
<section class="dismissal-samples">
<c-CPopover>
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">Dismissible</c-CButton>
</c-fill>
<c-fill name="title">Dismissible panel</c-fill>
<c-fill name="default">Escape, outside pointer, or focus outside may close it.</c-fill>
</c-CPopover>
<c-CPopover c-dismissible="False">
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton variant="outline" c-attrs="activator_attrs">
Explicit action only
</c-CButton>
</c-fill>
<c-fill name="title">Protected observation</c-fill>
<c-fill name="default">Outside interaction leaves this panel open.</c-fill>
<c-fill name="actions" data="{ close_attrs }">
<c-CButton c-attrs="close_attrs">Acknowledge</c-CButton>
</c-fill>
</c-CPopover>
</section>
"""
css = """
:where(.dismissal-samples) {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
min-block-size: 12rem;
padding-block: 2rem;
}
"""
preview = PopoverDismissal()
preview # noqa: B018
Use dismissible=False when the user must choose an explicit action. Always provide a clear close path. In controlled mode, declining a passive request keeps the surface open and prevents that request from closing an ancestor.
Place the surface
Server inputs are passed in Python through <c-CPopover ... /> attributes or a CPopover(...) composition call. placement accepts top-start, top, top-end, bottom-start, bottom, or bottom-end. The same client input can change it in the browser. Use client matchWidth or server match_width when the surface should be at least as wide as the Button.
Customize example
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class PopoverPlacements(Component):
template = """
<section
class="placement-preview"
x-data="{ placement: 'bottom-start', match_width: false }"
@citry-ui-preview-controls.window="Object.assign($data, $event.detail)"
>
<c-CPopover
$c-props="{ placement, matchWidth: match_width }"
>
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">
Position orbital summary
</c-CButton>
</c-fill>
<c-fill name="title">Orbital summary</c-fill>
<c-fill name="default">
Collision fallback may flip the requested side near a viewport edge.
</c-fill>
</c-CPopover>
</section>
"""
css = """
:where(.placement-preview) {
display: grid;
place-items: center;
min-block-size: 22rem;
}
"""
preview_controls = (
{
"name": "placement",
"label": "Placement",
"type": "select",
"default": "bottom-start",
"options": (
("top-start", "Top start"),
("top", "Top"),
("top-end", "Top end"),
("bottom-start", "Bottom start"),
("bottom", "Bottom"),
("bottom-end", "Bottom end"),
),
},
{
"name": "match_width",
"label": "Match activator width",
"type": "checkbox",
"default": False,
},
)
preview = PopoverPlacements()
preview # noqa: B018
Placement is a preference. The browser may flip it near an edge. Start and end are logical, so they follow text direction. Change the activator gap with --cui-popover-offset; use --cui-popover-inline-size or style for width.
Popover uses native top-layer rendering and CSS anchors. It does not teleport under <body>, start a JavaScript geometry loop, or publish a generic placement engine.
Nest Popovers
Nested Popovers are valid inside a body or action. Escape and outside interaction affect only the top open layer.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class NestedPopovers(Component):
template = """
<section class="nested-popovers">
<c-CPopover>
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">Inspect Saturn</c-CButton>
</c-fill>
<c-fill name="title">Saturn</c-fill>
<c-fill name="default">
<p>Its rings contain countless ice-rich particles.</p>
<c-CPopover placement="bottom-end">
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton size="sm" variant="outline" c-attrs="activator_attrs">
Inspect ring gap
</c-CButton>
</c-fill>
<c-fill name="title">Cassini Division</c-fill>
<c-fill name="default">
A broad region shaped by orbital resonance with Mimas.
</c-fill>
</c-CPopover>
</c-fill>
</c-CPopover>
</section>
"""
css = """
:where(.nested-popovers) {
min-block-size: 14rem;
padding-block: 3rem;
}
"""
preview = NestedPopovers()
preview # noqa: B018
Closing a child returns focus to its child activator and leaves the parent open. Prefer shallow layers; a page section is clearer when content no longer feels compact or locally related.
Choose the right surface
Popover is a named, non-modal dialog with rich interactive content.
- Use
CDialogwhen a task blocks the page or needs contained focus. - Use
CMenufor command/choice collection semantics and menu keyboard behavior. - Use
CTooltipfor brief noninteractive text shown by hover and focus. - Use
CAlertfor persistent status or feedback.
Adding a role to Popover content does not turn it into those components; each has different activation, focus, dismissal, and assistive-technology rules.
Theme and customize Popover
Set public --cui-popover-* variables on an ancestor or one surface. Use public part selectors for targeted regions.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class CustomizedPopover(Component):
template = """
<section class="custom-popovers">
<c-CPopover class_="aurora-popover">
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">Aurora palette</c-CButton>
</c-fill>
<c-fill name="title">Auroral oval</c-fill>
<c-fill name="default">Charged particles paint green arcs above the poles.</c-fill>
</c-CPopover>
<c-CPopover class_="lunar-popover">
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton variant="outline" c-attrs="activator_attrs">Lunar palette</c-CButton>
</c-fill>
<c-fill name="title">Lunar highlands</c-fill>
<c-fill name="default">Ancient pale terrain surrounds younger dark maria.</c-fill>
</c-CPopover>
</section>
"""
css = """
:where(.custom-popovers) {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
min-block-size: 12rem;
padding-block: 2rem;
}
:where(.aurora-popover) {
--cui-popover-background: light-dark(#ecfdf5, #052e2b);
--cui-popover-foreground: light-dark(#064e3b, #d1fae5);
--cui-popover-border-color: light-dark(#6ee7b7, #34d399);
--cui-popover-radius: 1.25rem;
}
:where(.lunar-popover) {
--cui-popover-background: light-dark(#f8fafc, #172033);
--cui-popover-foreground: light-dark(#1e293b, #f1f5f9);
--cui-popover-border-color: light-dark(#94a3b8, #64748b);
--cui-popover-shadow: 0 1.25rem 2.75rem rgb(15 23 42 / 30%);
}
"""
preview = CustomizedPopover()
preview # noqa: B018
.aurora-popover {
--cui-popover-background: light-dark(#ecfdf5, #052e2b);
--cui-popover-foreground: light-dark(#064e3b, #d1fae5);
--cui-popover-border-color: light-dark(#6ee7b7, #34d399);
--cui-popover-radius: 1.25rem;
}
class_, style, and attrs target the Popover surface. The activator remains owned by its own component. Unlayered consumer CSS overrides Citry UI defaults; named layers follow the site-wide layer-order contract.
The documented variables, selectors, and reflected attributes are public CSS API. .cui-* classes, --_cui-* variables, host markup, initialization markers, and anchor names are private.
Keyboard, focus, and forms
Opening focuses [autofocus], then the first tabbable descendant, then the surface itself. Popover does not trap Tab: the rest of the page remains available. Leaving a dismissible surface closes it after focus reaches the new destination.
Escape closes only the top open layer. Trigger, action, and Escape closure return focus to the activator when focus was inside. Outside closure preserves the browser's new focus destination.
Controls inside Popover retain native Form owners, values, reset, validation, and FormData behavior. Closing does not reset them because content stays in its original DOM and remains mounted.
Support narrow viewports and RTL
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class ResponsivePopover(Component):
template = """
<section class="responsive-popover" dir="rtl">
<c-CPopover
placement="bottom-start"
style="--cui-popover-inline-size: 28rem"
>
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">ุงูุชุญ ุณุฌู ุงูู
ุฑูุฎ</c-CButton>
</c-fill>
<c-fill name="title">ุณุฌู ุงูู
ุฑูุฎ ุงูุทููู</c-fill>
<c-fill name="description">ู
ุญุชูู ูุฎุชุจุฑ ุงูุงุชุฌุงู ูุงูุนุฑุถ ุงูุถูู</c-fill>
<c-fill name="default">
<p>ูุจูู ุงูุณุทุญ ุฏุงุฎู ู
ุณุงุญุฉ ุงูุนุฑุถ ููุชูุญ ุงูุชู
ุฑูุฑ ุนูุฏ ุงูุญุงุฌุฉ.</p>
<p>OlympusMonsSummitTraverseObservationIdentifier2026</p>
<p>ูุจุทุช ุงูู
ุฑูุจุฉ ูุฑุจ ุณูู ุตุฎุฑู ูุงุณุนุ ุซู
ุจุฏุฃุช ููุงุณ ุงูุบุจุงุฑ ูุงูุฑูุงุญ.</p>
</c-fill>
</c-CPopover>
</section>
"""
css = """
:where(.responsive-popover) {
min-block-size: 14rem;
padding-block: 3rem;
}
"""
preview = ResponsivePopover()
preview # noqa: B018
Logical dimensions, viewport maxima, wrapping, and body scrolling keep content reachable at narrow widths and high zoom. The surface follows surrounding light/dark scope even in the top layer. Forced colors preserve its boundary; reduced-motion users receive immediate transitions.
Without JavaScript, an initially closed Popover stays hidden. An initially open Popover renders readable content in document flow, then activation upgrades it to the top layer.
API reference
Inputs
CPopover server inputs
Server inputs are passed in a template through <c-CPopover ... /> or in Python through CPopover(...).
| Input | Type | Default | Effect |
|---|---|---|---|
id | str | None | generated | Sets native identity and title, description, and activator relationships. |
open | bool | False | Sets the server-visible initial state and uncontrolled fallback. A valid client open input controls later state. |
dismissible | bool | True | Permits Escape, outside-pointer, and focus-outside close requests. Trigger and explicit actions remain available when false. |
placement | "top-start" | "top" | "top-end" | "bottom-start" | "bottom" | "bottom-end" (CPopoverPlacement) | "bottom-start" | Sets the preferred logical placement. Collision fallback may choose a different rendered side. |
match_width | bool | False | Makes the Popover at least as wide as its activator. |
class_ | str | Mapping[str, bool] | Sequence[CClassValue] | None (CClassValue) | None | Adds surface classes and merges them with attrs. |
style | str | Mapping[str, str | int | float | bool | None] | Sequence[CStyleValue] | None (CStyleValue) | None | Adds surface inline styles and merges them with attrs; Citry retains anchor ownership. |
attrs | Mapping[str, object] | None | None | Adds allowed native, ARIA, Alpine, and data attributes to the Popover surface. Owned presence, semantics, focus, and relationships are rejected. |
CPopover client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CPopover />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
open | boolean | null | Releases control and preserves the current committed state. null has the same effect. | Controls visible state while supplied as a Boolean. An invalid value reports once and releases control from the current state. |
dismissible | boolean | Uses the server input. | Controls passive Escape, outside-pointer, and focus-outside dismissal. |
placement | "top-start" | "top" | "top-end" | "bottom-start" | "bottom" | "bottom-end" (CPopoverPlacement) | Uses the server input. | Controls requested placement and data-placement. |
matchWidth | boolean | Uses the server input. | Controls trigger-width matching and data-match-width. |
onOpenChange | function | Does not notify a component callback. | Receives trigger, explicit-action, passive-dismissal, and external-native visibility requests. |
Slots
Slots are passed as nested content or <c-fill> tags in a template, or through the slots={...} argument in Python.
CPopover slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
activator | yes | {activator_attrs: dict[str, object]} (CPopoverActivatorSlotData) | none |
title | yes | {} (CPopoverTitleSlotData) | none |
description | no | {} (CPopoverDescriptionSlotData) | Omitted, with no aria-describedby. |
default | yes | {} (CPopoverDefaultSlotData) | none |
actions | no | {close_attrs: dict[str, object]} (CPopoverActionsSlotData) | omitted |
Events
Component events are callback inputs supplied through $c-props. Native browser events remain available through Alpine @... attributes.
CPopover events
| Event | Signature | Trigger and timing | Detail | Controlled and cancellation behavior |
|---|---|---|---|---|
onOpenChange | (requestedOpen: boolean, detail: CPopoverOpenChangeDetail) => void (CPopoverOpenChangeDetail) | An owned activator, explicit action, Escape, outside pointer, focus outside, or external native Popover operation requests a different state. | {reason: "trigger" | "action" | "escape" | "outside" | "focus-outside" | "native" | "ancestor" | "modal", controlled: boolean, forced: boolean, source: Element | EventTarget | null} (CPopoverOpenChangeDetail) | Uncontrolled requests commit before notification. Controlled requests wait for the owner. Owner commits do not notify. |
Methods
-
CSS
CSS variables to theme the components. Set them on an ancestor or the component itself.
CPopover CSS variables
Apply these variables to CPopover or one of its ancestors.
| Variable | Type | Purpose | Default |
|---|---|---|---|
--cui-popover-background | color | Surface background. | Canvas |
--cui-popover-foreground | color | Surface text and inherited control context. | CanvasText |
--cui-popover-border-color | color | Surface boundary. | Subtle CanvasText mix. |
--cui-popover-border-width | length | Boundary width. | 1px |
--cui-popover-radius | length | Surface corner radius. | 0.75rem |
--cui-popover-shadow | shadow | Top-layer elevation. | 0 1rem 3rem rgb(15 23 42 / 22%) |
--cui-popover-inline-size | length | Preferred surface width. | 20rem |
--cui-popover-max-inline-size | length | Maximum responsive width. | calc(100dvi - 1rem) |
--cui-popover-max-block-size | length | Maximum responsive height. | calc(100dvb - 1rem) |
--cui-popover-padding | length | Region inline and edge padding. | 1rem |
--cui-popover-gap | length | Gap between header, body, and actions. | 0.75rem |
--cui-popover-offset | length | Gap between activator and surface. | 0.5rem |
--cui-popover-duration | time | Entry and exit duration; reduced motion resolves to zero. | 140ms |
--cui-popover-easing | easing | Entry and exit easing. | cubic-bezier(0.2, 0.8, 0.2, 1) |
--cui-popover-focus-color | color | Surface fallback focus outline. | Highlight |
Attributes
HTML attributes defined on the components that you can refer to for CSS, inspection, and testing. Read-only.
CPopover attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
popover | Surface | "manual" | Uses native top-layer presence while Citry owns dismissal and control. |
role | Surface | "dialog" | Identifies the named non-modal interactive surface. |
aria-labelledby | Surface | IDREF | References the required visible title. |
aria-describedby | Surface | IDREF | absent | References the optional concise description. |
data-open | Surface | present | absent | Mirrors logical visible ownership; absent during exit. |
data-placement | Surface | six placement strings (CPopoverPlacement) | Mirrors requested placement, not the collision fallback result. |
data-match-width | Surface | present | absent | Indicates trigger-width matching. |
aria-haspopup | Activator Button | "dialog" | Announces the kind of surface controlled by the Button. |
aria-controls | Activator Button | IDREF | References the Popover surface. |
aria-expanded | Activator Button | "true" | "false" | Mirrors logical open state. |
Selectors
Selectors for the DOM nodes in the components that you can use for CSS, inspection, and testing.
CPopover selectors
| Selector | Element | Purpose |
|---|---|---|
[data-citry-ui-part="popover"] | Surface | Semantic root, visual surface, and attrs destination. |
[data-citry-ui-part="header"] | Header | Title and optional-description layout. |
[data-citry-ui-part="title"] | Title | Required visible accessible name. |
[data-citry-ui-part="description"] | Description | Optional concise supporting text. |
[data-citry-ui-part="body"] | Body | Required rich interactive content region. |
[data-citry-ui-part="actions"] | Actions | Optional explicit-action row. |
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] |
CPopoverPlacement | Literal["top-start", "top", "top-end", "bottom-start", "bottom", "bottom-end"] |
CPopoverActivatorSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
activator_attrs | dict[str, object] | - | Owned trigger marker, CSS anchor, aria-haspopup, aria-controls, and synchronized aria-expanded. |
CPopoverTitleSlotData
Empty dataclass: {}.
CPopoverDescriptionSlotData
Empty dataclass: {}.
CPopoverDefaultSlotData
Empty dataclass: {}.
CPopoverActionsSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
close_attrs | dict[str, object] | - | Marks an explicit action control as a close request. |
CPopoverOpenChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
reason | "trigger" | "action" | "escape" | "outside" | "focus-outside" | "native" | "ancestor" | "modal" | - | Source of the requested visibility change. |
controlled | boolean | - | Whether a valid client open Boolean currently owns state. |
forced | boolean | - | Whether structural or modal safety required the component to close regardless of controlled ownership. |
source | Element | EventTarget | null | - | Browser source associated with the request. |
Translation keys
-