Sidebar
A composable, collapsible navigation panel wired to a Stimulus controller. Build app shells with a persistent left (or right) drawer that collapses off-canvas.
Installation
bin/rails g shadcnrb:component sidebar
Note
Because this docs page is itself rendered inside a sidebar layout, embedding a full
sidebar_wrapper in the preview
would create a nested layout conflict. Instead, the individual building blocks are shown
below. For a full working demo, see the
live sidebar test.
Usage — individual pieces
Child parts are reached via the proxy yielded by
sui.sidebar_wrapper do |s|. For
isolated demos outside a wrapper, sui.sidebar_proxy
returns the same proxy without rendering the shell.
menu_button mirrors Rails
link_to — pass a name + path and the active state is
auto-detected via current_page?.
<!-- default --> <%= s.menu_button "Dashboard", "#" %> <!-- active: true --> <%= s.menu_button "Active item", "#", active: true %> <!-- icon: :home --> <%= s.menu_button "Home", "#", icon: :home %>
For anything beyond a plain link — button_to with
method: :delete, Turbo options, nested icons — pass a
block. The wrapper renders a styled <div role="button">
and your Rails helper fills the row.
<!-- menu_button (block form with button_to) --> <div class="w-64 bg-sidebar rounded-md p-2"> <%= s.menu_button do %> <%= button_to "Sign out", "#", method: :delete %> <% end %> </div> <!-- group_label --> <div class="w-48 bg-sidebar rounded-md"> <%= s.group_label "Platform" %> </div> <!-- separator --> <div class="w-48 bg-sidebar rounded-md py-2"> <%= s.separator %> </div>
Full structure (code only)
Assemble these methods to build a complete sidebar shell. The
sidebar_wrapper owns the
Stimulus controller; s.trigger
and s.rail both dispatch
the toggle action.
sui.sidebar_wrapper do |s|
s.sidebar do
s.header do
tag.span "My App", class: "font-semibold text-sm px-2"
end
s.content do
s.group do
s.group_label "Platform"
s.group_content do
s.menu do
s.menu_item do
s.menu_button "Dashboard", root_path
end
s.menu_item do
s.menu_button "Settings", settings_path
end
end
end
end
s.separator
s.group do
s.group_label "Account"
s.group_content do
s.menu do
s.menu_item do
s.menu_button "Profile", profile_path
end
end
end
end
end
s.footer do
tag.span "Footer content"
end
s.rail
end
s.inset do
tag.header(class: "flex items-center gap-2 p-4") do
s.trigger
end
tag.div(class: "p-4") do
tag.p "Main content area"
end
end
end
API
| method | signature | description |
|---|---|---|
sui.sidebar_wrapper | (**opts, &block) | Outermost div. Mounts the Stimulus sidebar controller and sets CSS custom properties for width. Yields a proxy s. |
sui.sidebar_proxy | — | Returns a bare proxy for rendering individual pieces outside a wrapper (e.g. docs previews). |
s.sidebar | (side:, variant:, collapsible:, **opts, &block) | The sidebar panel itself. side: is :left (default) or :right. |
s.header | (**opts, &block) | Flex column at the top of the sidebar, typically for a logo or app name. |
s.content | (**opts, &block) | Scrollable flex column that fills the remaining vertical space. |
s.group | (**opts, &block) | A labelled section inside sidebar content, padded on all sides. |
s.group_label | (name = nil, **opts, &block) | Small muted heading above a group of links. |
s.group_content | (**opts, &block) | Wrapper div for the group's menu list. |
s.menu | (**opts, &block) | Unordered list (ul) that holds menu items with gap spacing. |
s.menu_item | (**opts, &block) | List item (li) wrapper for a single menu button. |
s.menu_button | (name, options, active: nil, **html_opts, &block) | An anchor styled as a sidebar row. Mirrors link_to. Auto-sets active via current_page?; pass active: true/false to override. |
s.separator | (**opts) | Horizontal rule styled with sidebar border colour, with side margins. |
s.footer | (**opts, &block) | Flex column pinned to the bottom of the sidebar. |
s.inset | (**opts, &block) | The main content area (main) that sits beside the sidebar, grows to fill remaining space. |
s.trigger | (**opts) | Icon button that dispatches shadcnrb--sidebar--component#toggle on click to expand/collapse the sidebar. |
s.rail | (**opts) | Narrow invisible hit-area along the sidebar edge — also toggles on click, visible as a faint line on hover. |