ListDetailLayout
A persistent URL-driven list and detail workspace with phone focus handoff and pane scroll continuity.@gemologic/sheen-patterns · applicationPlayground
This example has no scalar controls. Its validated source remains interactive below.
Back to messagesFirst message
<AppShell label="Inbox" router={router}><ListDetailLayout router={router} items={[{ id: "one", label: "First", href: "/inbox/one" }]} listLabel="Messages" detailLabel="Message" listHref="/inbox" backLabel="Back to messages" detail={<article>First message</article>} /></AppShell>Variant matrix
URL-selected detail
Back to messagesFirst message
Anatomy
- Package
@gemologic/sheen-patterns- Source
packages/patterns/src/ListDetailLayout.tsx- Tokens
--sheen-color-border--sheen-color-bg--sheen-color-bg-raised--sheen-color-bg-hover--sheen-color-bg-selected--sheen-color-fg-muted--sheen-color-focus-ring--sheen-color-focus-ring-offset
Accessibility
Role: region, list, linkKeyboard: Tab, Shift+Tab, ArrowUp, ArrowDown, Home, End, EnterDo
- Keep the layout mounted in a route layout so list DOM and scroll survive detail navigation.
- Drive detail content from the router's accepted location and retain it during revalidation.
Do not
- Do not mirror URL selection into optimistic local state.
- Do not replace the layout or either scroll viewport during background refresh.
Generated props
| Name | Type | Default | Description |
|---|---|---|---|
router * | RouterAdapter | — | Application router adapter whose accepted location selects the active item. |
items * | readonly ListDetailItem[] | — | Stable-ID local destinations shown in the list pane. |
listLabel * | string | — | Accessible name for the list scroll region. |
detailLabel * | string | — | Accessible name for the persistent detail scroll region. |
listHref * | string | — | Local destination used by the phone back link. |
backLabel * | string | — | Localized visible label for the phone back link. |
detail * | JSX.Element | — | Accepted route detail content; keep retained content here during background refresh. |
emptyDetail | JSX.Element | — | Optional desktop content shown when the URL matches no item. |
detailReady | boolean | — | False while accepted detail content cannot yet restore its saved scroll position. |
detailPaneId | string | — | Stable restoration identity when more than one layout can coexist. |