Sidebar
Use CSidebar for persistent application navigation or complementary tools. It gives header and footer content fixed positions around one scrollable region and supports rail or off-canvas collapse.
Sidebar at a glance
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class SidebarAtAGlance(Component):
template = """
<div class="sidebar-layout">
<c-CSidebar id="workspace" tag="nav" label="Workspace navigation">
<c-fill name="header"><strong>Northstar</strong></c-fill>
<c-fill name="default">
<c-CList variant="surface">
<c-CListItem href="#overview" c-current="True">
<c-fill name="start"><c-CIcon name="home" /></c-fill>
<c-fill name="default">Overview</c-fill>
</c-CListItem>
<c-CListItem href="#projects">
<c-fill name="start"><c-CIcon name="folder" /></c-fill>
<c-fill name="default">Projects</c-fill>
</c-CListItem>
<c-CListItem href="#reports">
<c-fill name="start"><c-CIcon name="file" /></c-fill>
<c-fill name="default">Reports</c-fill>
</c-CListItem>
</c-CList>
</c-fill>
<c-fill name="footer"><small>ada@example.com</small></c-fill>
</c-CSidebar>
<main><h2 id="overview">Overview</h2><p>The primary page remains ordinary application layout.</p></main>
</div>
"""
css = """
:where(.sidebar-layout) {
display: grid;
grid-template-columns: auto minmax(0, 1fr);
gap: 1.5rem;
min-block-size: 24rem;
}
:where(.sidebar-layout main) { padding: 1rem; }
"""
preview = SidebarAtAGlance()
preview # noqa: B018
Compose navigation from List
Sidebar does not invent a second navigation-item API. Compose CList for links, CDisclosure for expandable sections, and CMenu for command popovers. When rail-collapsed, List text stays visually clipped but remains the accessible name of each link.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class SidebarNavigation(Component):
template = """
<c-CSidebar tag="nav" label="Project navigation" c-collapsed="True">
<c-fill name="header"><span data-citry-sidebar-expanded-only><strong>Atlas</strong></span></c-fill>
<c-fill name="default">
<c-CList>
<c-CListItem href="#activity" c-current="True">
<c-fill name="start"><c-CIcon name="clock" /></c-fill>
<c-fill name="default">Activity</c-fill>
</c-CListItem>
<c-CListItem href="#members">
<c-fill name="start"><c-CIcon name="user" /></c-fill>
<c-fill name="default">Members</c-fill>
</c-CListItem>
<c-CListItem href="#settings">
<c-fill name="start"><c-CIcon name="settings" /></c-fill>
<c-fill name="default">Settings</c-fill>
</c-CListItem>
</c-CList>
</c-fill>
</c-CSidebar>
"""
preview = SidebarNavigation()
preview # noqa: B018
Choose a collapse mode
collapsible="rail" keeps an icon-width navigation rail. offcanvas hides the panel while retaining the native toggle. none renders a permanent region and rejects collapsed=True.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class SidebarCollapseModes(Component):
template = """
<div class="sidebar-modes">
<c-CSidebar label="Rail example" c-collapsed="True" collapsible="rail" size="sm">
<strong>Rail content remains available.</strong>
</c-CSidebar>
<c-CSidebar label="Offcanvas example" c-collapsed="True" collapsible="offcanvas" size="sm">
<strong>The panel starts hidden.</strong>
</c-CSidebar>
<c-CSidebar label="Permanent example" collapsible="none" size="sm">
<strong>No toggle is rendered.</strong>
</c-CSidebar>
</div>
"""
css = ":where(.sidebar-modes){display:flex;align-items:flex-start;gap:1rem;min-block-size:14rem}"
preview = SidebarCollapseModes()
preview # noqa: B018
Control collapse state
Supply collapsed through $c-props to control it. The callback is a request; keep or change your value to reject or accept it.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class SidebarControlled(Component):
template = """
<section x-data="{
collapsed:false,
last:'No request yet',
change(next){this.last=`Requested ${next ? 'collapse' : 'expand'}`;this.collapsed=next},
}">
<p><output x-text="last">No request yet</output></p>
<c-CSidebar
label="Controlled navigation"
$c-props="{collapsed,onCollapsedChange:change}"
>
<strong>Controlled Sidebar content</strong>
</c-CSidebar>
</section>
"""
preview = SidebarControlled()
preview # noqa: B018
Build sticky and floating Sidebars
Sticky Sidebars use --cui-sidebar-sticky-offset to leave room for an application header. variant="floating" adds a contained border, radius, and elevation without registering page-layout insets.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class SidebarPresentation(Component):
template = """
<c-CSidebar
label="Sticky tools"
variant="floating"
size="lg"
c-sticky="True"
c-style="{'--cui-sidebar-sticky-offset':'1rem'}"
>
<c-fill name="header"><strong>Inspector</strong></c-fill>
<c-fill name="default">
<p>Long tool content scrolls independently between fixed regions.</p>
<p>Keep adding contextual controls here.</p>
</c-fill>
<c-fill name="footer"><c-CButton size="sm">Apply</c-CButton></c-fill>
</c-CSidebar>
"""
preview = SidebarPresentation()
preview # noqa: B018
Customize Sidebar
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class SidebarCustomization(Component):
template = """
<c-CSidebar label="Custom navigation" variant="floating" side="inline-end" c-class_="['ocean-sidebar']">
<c-fill name="toggle"><c-CIcon name="menu" /></c-fill>
<c-fill name="header"><strong>Ocean lab</strong></c-fill>
<c-fill name="default"><p>Public variables and parts customize the stable landmark.</p></c-fill>
</c-CSidebar>
"""
css = """
:where(.ocean-sidebar) {
--cui-sidebar-background: light-dark(#eff8ff, #102a43);
--cui-sidebar-border-color: light-dark(#84caff, #2e90fa);
--cui-sidebar-width: 18rem;
}
"""
preview = SidebarCustomization()
preview # noqa: B018
Persistent Sidebar or mobile Drawer?
Sidebar remains in document layout and never traps focus, adds a scrim, or locks page scrolling. For modal mobile navigation, render the same application navigation component inside CDrawer placement="inline-start". A future AppShell can choose the responsive policy without changing either component.
Accessibility and localization
Choose tag="nav" when the content is navigation and aside for complementary tools. label is required. The native toggle owns aria-controls and aria-expanded; Enter and Space work without a custom keyboard model. If an off-canvas collapse would hide current focus, focus moves to the toggle first.
The Expand and Collapse labels are Citry UI catalog messages. Override them with expand_label and collapse_label; overrides stay fixed while catalog defaults react to a client locale switch.
API reference
Inputs
CSidebar server inputs
Server inputs are passed in a template through <c-CSidebar ... /> or in Python through CSidebar(...).
| Input | Type | Default | Effect |
|---|---|---|---|
id | str | None | generated | Sets the landmark ID and bases the controlled panel ID. |
label | str | required | Names the complementary or navigation landmark. |
tag | CSidebarTag (CSidebarTag) | "aside" | Selects complementary aside or navigation nav semantics. |
collapsed | bool | False | Sets initial expanded or collapsed state. |
collapsible | CSidebarCollapsible (CSidebarCollapsible) | "rail" | Selects rail offcanvas or permanent behavior. |
side | CSidebarSide (CSidebarSide) | "inline-start" | Selects the logical page edge and border/toggle placement. |
variant | CSidebarVariant (CSidebarVariant) | "plain" | Selects flush or floating surface treatment. |
size | CSidebarSize (CSidebarSize) | "md" | Selects the default expanded width. |
sticky | bool | False | Sticks the Sidebar at the public block offset within its scroll container. |
expand_label | str | "Expand sidebar" | Overrides the localized expanded-state action name. |
collapse_label | str | "Collapse sidebar" | Overrides the localized collapsed-state action name. |
class_ | CClassValue | None (CClassValue) | None | Adds classes to the native landmark. |
style | CStyleValue | None (CStyleValue) | None | Adds styles to the native landmark. |
attrs | Mapping[str, object] | None | None | Adds copied allowed landmark attributes without replacing owned semantics state or identity. |
CSidebar client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CSidebar />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
collapsed | boolean | null | Releases control to the committed value. | Controls expanded or collapsed state. |
collapsible | CSidebarCollapsible (CSidebarCollapsible) | Uses the server value. | Controls rail offcanvas or permanent behavior. |
side | CSidebarSide (CSidebarSide) | Uses the server value. | Controls logical placement. |
variant | CSidebarVariant (CSidebarVariant) | Uses the server value. | Controls surface treatment. |
size | CSidebarSize (CSidebarSize) | Uses the server value. | Controls width profile. |
sticky | boolean | Uses the server value. | Controls sticky positioning. |
onCollapsedChange | function | No semantic collapse callback. | Receives native toggle requests. |
Slots
Slots are passed as nested content or <c-fill> tags in a template, or through the slots={...} argument in Python.
CSidebar slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
default | yes | {} (CSidebarDefaultSlotData) | None. |
header | no | {} (CSidebarHeaderSlotData) | Omitted. |
footer | no | {} (CSidebarFooterSlotData) | Omitted. |
toggle | no | {collapsed} (CSidebarToggleSlotData) | Decorative neutral panel glyph. |
Events
Component events are callback inputs supplied through $c-props. Native browser events remain available through Alpine @... attributes.
CSidebar events
| Event | Signature | Trigger and timing | Detail | Controlled and cancellation behavior |
|---|---|---|---|---|
onCollapsedChange | (collapsed: boolean, detail: CSidebarCollapsedChangeDetail) => void (CSidebarCollapsedChangeDetail) | Native toggle activation requests a different state. | {collapsed, previousCollapsed, controlled, source, sourceEvent} (CSidebarCollapsedChangeDetail) | Uncontrolled state commits before notification; controlled state is request-only. |
Methods
-
CSS
CSS variables to theme the components. Set them on an ancestor or the component itself.
CSidebar CSS variables
Apply these variables to CSidebar or one of its ancestors.
| Variable | Type | Purpose | Default |
|---|---|---|---|
--cui-sidebar-width | length | Expanded inline size overriding the selected profile. | sm 14rem; md 16rem; lg 20rem |
--cui-sidebar-rail-width | length | Collapsed rail inline size. | 4rem |
--cui-sidebar-background | color | Landmark and toggle surface. | Adaptive neutral |
--cui-sidebar-foreground | color | Sidebar text and icon color. | CanvasText |
--cui-sidebar-border-color | color | Logical edge and floating border. | Adaptive neutral |
--cui-sidebar-shadow | shadow | Floating surface elevation. | Soft elevation |
--cui-sidebar-radius | length | Floating surface and toggle corner input. | 0.85rem |
--cui-sidebar-padding | length | Internal panel spacing. | 0.75rem |
--cui-sidebar-gap | length | Header content footer and offcanvas-trigger spacing. | 0.75rem |
--cui-sidebar-toggle-size | length | Native toggle target size. | 2.75rem |
--cui-sidebar-focus-color | color | Toggle focus outline. | Highlight |
--cui-sidebar-sticky-offset | length | Block offset reserved above a sticky Sidebar. | 0px |
Attributes
HTML attributes defined on the components that you can refer to for CSS, inspection, and testing. Read-only.
CSidebar attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
aria-label | Root landmark | string | Names the complementary or navigation region. |
data-collapsed | Root landmark | present | absent | Marks effective collapsed state. |
data-collapsible | Root landmark | CSidebarCollapsible (CSidebarCollapsible) | Mirrors collapse behavior. |
data-side | Root landmark | CSidebarSide (CSidebarSide) | Mirrors logical placement. |
data-variant | Root landmark | CSidebarVariant (CSidebarVariant) | Mirrors surface treatment. |
data-size | Root landmark | CSidebarSize (CSidebarSize) | Mirrors width profile. |
data-sticky | Root landmark | present | absent | Marks sticky positioning. |
aria-controls | Toggle Button | IDREF | Refers to the owned panel. |
aria-expanded | Toggle Button | boolean-string | Reflects expanded state. |
data-citry-sidebar-expanded-only | Authored descendant | present | absent | Hides authored content in rail mode. |
data-citry-sidebar-rail-only | Authored descendant | present | absent | Shows authored accessible replacement only in rail mode. |
Selectors
Selectors for the DOM nodes in the components that you can use for CSS, inspection, and testing.
CSidebar selectors
| Selector | Element | Purpose |
|---|---|---|
[data-citry-ui-part="sidebar"] | Native aside or nav root | State reflections and customization destination. |
[data-citry-ui-part="toggle"] | Native Button | Collapse control. |
[data-citry-ui-part="toggle-icon"] | Decorative span | Custom or fallback visual. |
[data-citry-ui-part="toggle-label"] | Visually hidden span | Localized state-dependent accessible name. |
[data-citry-ui-part="panel"] | Owned div | Visibility inertness and fixed/scroll region owner. |
[data-citry-ui-part="header"] | Optional header | Fixed branding and controls. |
[data-citry-ui-part="content"] | Scrollable div | Primary authored Sidebar content. |
[data-citry-ui-part="footer"] | Optional footer | Fixed account status or actions. |
Interfaces
Aliases and data shapes referenced above.
Input type aliases
| Interface | Definition |
|---|---|
CSidebarTag | Literal["aside", "nav"] |
CSidebarCollapsible | Literal["rail", "offcanvas", "none"] |
CSidebarSide | Literal["inline-start", "inline-end"] |
CSidebarVariant | Literal["plain", "floating"] |
CSidebarSize | Literal["sm", "md", "lg"] |
CClassValue | str | Mapping[str, bool] | Sequence[CClassValue] |
CStyleValue | str | Mapping[str, object] | Sequence[CStyleValue] |
CSidebarDefaultSlotData
Empty dataclass: {}.
CSidebarHeaderSlotData
Empty dataclass: {}.
CSidebarFooterSlotData
Empty dataclass: {}.
CSidebarToggleSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
collapsed | bool | - | Server-rendered initial collapsed state. |
CSidebarCollapsedChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
collapsed | bool | - | Requested collapsed state. |
previousCollapsed | bool | - | Effective state before the request. |
controlled | bool | - | Whether client state currently controls collapse. |
source | activation | - | Native toggle activation source. |
sourceEvent | Event | - | Native click 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.
CSidebar translation keys
| Key | Purpose | Variables | Override | Browser updates |
|---|---|---|---|---|
citry-ui-sidebar-expand | Names the action that expands a collapsed Sidebar. | None. | expand_label | Stable $c-tr text binding follows client locale changes. |
citry-ui-sidebar-collapse | Names the action that collapses an expanded Sidebar. | None. | collapse_label | Stable $c-tr text binding follows client locale changes. |