Theme
Version
GitHub PyPI Discord
On this page

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.

Compose Sidebar navigation
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.

Compare Sidebar collapse modes
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.

Control Sidebar collapse
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.

Choose Sidebar presentation
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

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(...).

InputTypeDefaultEffect
idstr | NonegeneratedSets the landmark ID and bases the controlled panel ID.
labelstrrequiredNames the complementary or navigation landmark.
tagCSidebarTag (CSidebarTag)"aside"Selects complementary aside or navigation nav semantics.
collapsedboolFalseSets initial expanded or collapsed state.
collapsibleCSidebarCollapsible (CSidebarCollapsible)"rail"Selects rail offcanvas or permanent behavior.
sideCSidebarSide (CSidebarSide)"inline-start"Selects the logical page edge and border/toggle placement.
variantCSidebarVariant (CSidebarVariant)"plain"Selects flush or floating surface treatment.
sizeCSidebarSize (CSidebarSize)"md"Selects the default expanded width.
stickyboolFalseSticks the Sidebar at the public block offset within its scroll container.
expand_labelstr"Expand sidebar"Overrides the localized expanded-state action name.
collapse_labelstr"Collapse sidebar"Overrides the localized collapsed-state action name.
class_CClassValue | None (CClassValue)NoneAdds classes to the native landmark.
styleCStyleValue | None (CStyleValue)NoneAdds styles to the native landmark.
attrsMapping[str, object] | NoneNoneAdds 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 />.

InputTypeOmitted behaviorEffect
collapsedboolean | nullReleases control to the committed value.Controls expanded or collapsed state.
collapsibleCSidebarCollapsible (CSidebarCollapsible)Uses the server value.Controls rail offcanvas or permanent behavior.
sideCSidebarSide (CSidebarSide)Uses the server value.Controls logical placement.
variantCSidebarVariant (CSidebarVariant)Uses the server value.Controls surface treatment.
sizeCSidebarSize (CSidebarSize)Uses the server value.Controls width profile.
stickybooleanUses the server value.Controls sticky positioning.
onCollapsedChangefunctionNo 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

SlotRequiredDataFallback
defaultyes{} (CSidebarDefaultSlotData)None.
headerno{} (CSidebarHeaderSlotData)Omitted.
footerno{} (CSidebarFooterSlotData)Omitted.
toggleno{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

EventSignatureTrigger and timingDetailControlled 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.

VariableTypePurposeDefault
--cui-sidebar-widthlengthExpanded inline size overriding the selected profile.sm 14rem; md 16rem; lg 20rem
--cui-sidebar-rail-widthlengthCollapsed rail inline size.4rem
--cui-sidebar-backgroundcolorLandmark and toggle surface.Adaptive neutral
--cui-sidebar-foregroundcolorSidebar text and icon color.CanvasText
--cui-sidebar-border-colorcolorLogical edge and floating border.Adaptive neutral
--cui-sidebar-shadowshadowFloating surface elevation.Soft elevation
--cui-sidebar-radiuslengthFloating surface and toggle corner input.0.85rem
--cui-sidebar-paddinglengthInternal panel spacing.0.75rem
--cui-sidebar-gaplengthHeader content footer and offcanvas-trigger spacing.0.75rem
--cui-sidebar-toggle-sizelengthNative toggle target size.2.75rem
--cui-sidebar-focus-colorcolorToggle focus outline.Highlight
--cui-sidebar-sticky-offsetlengthBlock 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

AttributeElementTypeMeaning
aria-labelRoot landmarkstringNames the complementary or navigation region.
data-collapsedRoot landmarkpresent | absentMarks effective collapsed state.
data-collapsibleRoot landmarkCSidebarCollapsible (CSidebarCollapsible)Mirrors collapse behavior.
data-sideRoot landmarkCSidebarSide (CSidebarSide)Mirrors logical placement.
data-variantRoot landmarkCSidebarVariant (CSidebarVariant)Mirrors surface treatment.
data-sizeRoot landmarkCSidebarSize (CSidebarSize)Mirrors width profile.
data-stickyRoot landmarkpresent | absentMarks sticky positioning.
aria-controlsToggle ButtonIDREFRefers to the owned panel.
aria-expandedToggle Buttonboolean-stringReflects expanded state.
data-citry-sidebar-expanded-onlyAuthored descendantpresent | absentHides authored content in rail mode.
data-citry-sidebar-rail-onlyAuthored descendantpresent | absentShows 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

SelectorElementPurpose
[data-citry-ui-part="sidebar"]Native aside or nav rootState reflections and customization destination.
[data-citry-ui-part="toggle"]Native ButtonCollapse control.
[data-citry-ui-part="toggle-icon"]Decorative spanCustom or fallback visual.
[data-citry-ui-part="toggle-label"]Visually hidden spanLocalized state-dependent accessible name.
[data-citry-ui-part="panel"]Owned divVisibility inertness and fixed/scroll region owner.
[data-citry-ui-part="header"]Optional headerFixed branding and controls.
[data-citry-ui-part="content"]Scrollable divPrimary authored Sidebar content.
[data-citry-ui-part="footer"]Optional footerFixed account status or actions.

Interfaces

Aliases and data shapes referenced above.

Input type aliases

InterfaceDefinition
CSidebarTagLiteral["aside", "nav"]
CSidebarCollapsibleLiteral["rail", "offcanvas", "none"]
CSidebarSideLiteral["inline-start", "inline-end"]
CSidebarVariantLiteral["plain", "floating"]
CSidebarSizeLiteral["sm", "md", "lg"]
CClassValuestr | Mapping[str, bool] | Sequence[CClassValue]
CStyleValuestr | Mapping[str, object] | Sequence[CStyleValue]

CSidebarDefaultSlotData

Empty dataclass: {}.

CSidebarHeaderSlotData

Empty dataclass: {}.

CSidebarFooterSlotData

Empty dataclass: {}.

CSidebarToggleSlotData

FieldTypeDefaultMeaning
collapsedbool-Server-rendered initial collapsed state.

CSidebarCollapsedChangeDetail

FieldTypeDefaultMeaning
collapsedbool-Requested collapsed state.
previousCollapsedbool-Effective state before the request.
controlledbool-Whether client state currently controls collapse.
sourceactivation-Native toggle activation source.
sourceEventEvent-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

KeyPurposeVariablesOverrideBrowser updates
citry-ui-sidebar-expandNames the action that expands a collapsed Sidebar.None.expand_labelStable $c-tr text binding follows client locale changes.
citry-ui-sidebar-collapseNames the action that collapses an expanded Sidebar.None.collapse_labelStable $c-tr text binding follows client locale changes.