Skip to content
LyEve UI v0.60.1

Layout & display

AppShell

The authed application frame: the sidebar, the header bar and the content column. One frame, so a product with several consoles renders one shell rather than one per app.

Why it exists

Three apps hand rolled this frame and no two agreed. The sidebar was 224px in one and 240px in the other two, opaque in two and translucent in the third, built from SidebarNav in one and from inline anchors in the others. Two of the three had no header above md:, so the current page had no name on screen and there was no fixed place for a theme toggle or an account menu. Every one of those was defensible from inside the app that made it, and together they read as three products.

Anatomy

Everything is a snippet, so the shell owns the measurements and the app owns the content. It renders the main landmark and the drawer's dialog role, and nothing else: the navigation landmark comes from your SidebarNav, and the page's own PageShell owns the one h1. The section name in the header is a span for that reason.

Instances

Ada Lovelace

ada@example.com

Instances

The page renders here, inside its own PageShell.

The drawer

Below md: the sidebar becomes a drawer behind a hamburger the header grows for it. There is one aside at every width: rendering a second copy for the drawer puts every nav link in the page twice, which is what a strict-mode locator trips on and what a screen reader reads out.

The open drawer is a real dialog. It moves focus in, keeps Tab inside, and hands focus back to the hamburger when it closes, so aria-modal describes what actually happens rather than what was claimed. Escape and the backdrop both close it. The dialog role sits on a wrapper and not on the aside, because a complementary landmark cannot take an interactive role.

The drawer slides in from the edge it is docked on and back out, the right edge in a right-to-left page, and the dimmed page behind it fades in and out, as a Drawer does.

navOpen is bindable so your router can close it after a navigation. Without that, a tapped link leaves the drawer sitting over the page it just opened.

Where the account goes

In the header, through AccountMenu, never in the sidebar foot. That column is already the full height of the window, so a menu opened in its last row grows past the bottom edge, and the entry that gets cut is Sign out every time. The header has room below it by construction.

API

PropTypeDefaultDescription
section string no defaultThe current section, shown in the header. Rendered as a span, not a heading: the page's own PageShell owns the h1.
navOpen booleanfalseBindable. Set it to false after a navigation so the drawer does not stay open.
collapsible booleanfalseAdds a header control that puts the sidebar away above md.
collapsed booleanfalseBindable: whether the sidebar is put away above md. Nothing persists it for you.
rail booleanfalseNarrows the sidebar to the icon rail at every width above md, not only between md and lg.
headerHidden booleanfalseBindable: puts the header bar away above md, for a page that owns the viewport. Keep a way back on screen.
sidebarLabel string'Sidebar'Accessible name for the sidebar region.
drawerLabel string'Navigation'Accessible name for the drawer, below md: where the sidebar is a dialog.
brand Snippet no defaultThe product mark, in the sidebar brand row.
nav Snippet no defaultThe navigation. A SidebarNav, given class="min-h-0 w-full flex-1 px-inline".
sidebarFooter Snippet no defaultA status band at the foot of the sidebar. Not the account: that is header work.
headerActions Snippet no defaultThe right end of the header. The theme toggle and the account menu live here.
class string no defaultExtra classes on the outer frame.
children requiredSnippet no defaultThe page, inside main.
panel Snippet no defaultA panel on the right. From lg it docks beside the main area and its edge resizes between 320 and 560 pixels. Below lg it opens as a drawer. Put the button that opens it in headerActions.
panelOpen booleanfalseBindable. Whether the panel is open.
panelLabel string no defaultThe panel's accessible name, as a complementary region and as the drawer's title.
panelStorageKey string no defaultThe localStorage key the panel's width is kept under. Without one the width lasts the page.