Layout & display
PageShell
The page frame: the gutter, the content cap, the centering and the rhythm between sections, all
owned by the shell so a page cannot pick its own. Wrap a page in it and add sections as children.
It renders no landmark, so it sits inside the <main> your app shell already owns.
Basic
The gap between sections belongs to the shell, so adding a section is appending a child rather than remembering to put a margin on it. The title comes from PageHeader, rendered flush because the shell supplies the gap below it. A title with no spaces, such as a tenant slug, breaks inside the page width instead of widening the page.
Breadcrumb and actions
The breadcrumb and the title are one group, so the distance between them is fixed and does not change with whether a description is set.
Content width
Four named caps replace picking a max-w per page. The name carries the decision, so a page
chooses a role rather than a number.
wideis every page inside an app's shell: a list, a settings form, a detail page. One cap keeps the content's left edge in one place from screen to screen. A form stays readable inside it because its card and its fields carry their own width.fulltakes no cap, for a canvas, a split pane or a page that scrolls itself. Passfillwith it.narrowis for a page outside the shell, such as a first-run setup step.defaultis kept for pages outside an app's shell. No console page uses it.
Name a width on every page. Left unset, the shell falls back to default, which then
reads as a decision nobody made, and the LyEve consoles' UI lints refuse a PageShell that names
none.
Full height
A fill page owns the viewport instead of sitting in it: the content takes no cap and no
gutter, and every pixel the title row does not take goes to it. Use it for a split pane or a canvas
that scrolls inside the page rather than scrolling the page.
The title row keeps the page gutter and the full-size title, so a full-height page begins at the
same distance from the edge as every other page and its name is the same size. Owning the viewport
is a statement about the content pane, not about the heading. Pass compact when the
page genuinely has no room for a heading. It is independent of fill, so any page may
ask for it and a full-height page may refuse it.
The browser tab
PageShell titles the browser tab once your app states how a tab title reads. Call setDocumentTitleFormat once, in the root layout, while it initializes. Every
PageShell below it then renders the document title from its title.
<script lang="ts">
import { setDocumentTitleFormat } from '@lyeve-labs/ui-kit';
let { children } = $props();
setDocumentTitleFormat((title) => `${title} | Acme`);
</script>
{@render children()}documentTitle gives the tab other words than the heading, such as a record's name on a
page whose heading says what is done to it. For an entry named "Spring launch", the page below is headed
"Edit entry" and its tab reads "Spring launch | Acme".
<PageShell title="Edit entry" documentTitle={entry.name} width="wide">...</PageShell>A format that reads reactive state, such as a tenant's name, is run again when that state changes, so the tab follows it. Remove a page's own title element once the shell titles it, or the two race. An app that states no format gets no title element from PageShell, so a title it renders itself stays in charge.
API
| Prop | Type | Default | Description |
|---|---|---|---|
title required | string | no default | The page's only h1, rendered through PageHeader. Also the browser tab's title, once the app states a format. |
documentTitle | string | no default | What the browser tab shows when it should read differently from title. Read only once the app states a format. |
description | string | no default | Sub-description below the title. |
width | 'narrow' | 'default' | 'wide' | 'full' | 'default' | Content cap. Name one on every page: wide inside an app shell, full with fill for a page that scrolls itself. |
fill | boolean | false | A full-height page that manages its own scrolling. The content loses the gutter and the cap. The title row keeps both. |
compact | boolean | false | Drop the title to body size and hide the description, for a page with no room for a heading. |
titleHidden | boolean | false | Keeps the h1 for screen readers and draws no title row, for a page whose toolbar is its header. |
breadcrumb | Snippet | no default | Rendered above the title at one fixed distance. |
back | { href: string; label: string } | no default | A link back to the parent page, above the title, with an arrow and the parent's label. |
actions | Snippet | no default | Right-aligned controls in the title row. |
class | string | no default | Extra classes on the frame. |
children required | Snippet | no default | The page sections. The gap between them belongs to the shell. |
Document title
| Prop | Type | Default | Description |
|---|---|---|---|
setDocumentTitleFormat(format) | (DocumentTitleFormat) => void | no default | States the tab title format for every PageShell below the calling component. Call it while the root layout initializes. |
DocumentTitleFormat | (title: string) => string | no default | Turns a page's title into the words its browser tab shows. |