ListDetailLayout
ListDetailLayout pairs a master list with a detail pane: CRM contacts to a
record, research runs to a report, conversations to a thread. It’s responsive to
the layout’s own width, side by side when wide, and one at a time when narrow,
showing the list or the selected detail with a back affordance to return.
import { ListDetailLayout } from "@nimblebrain/synapse/ui";
<ListDetailLayout selected={selected !== null} onBack={() => setSelected(null)}> <ListDetailLayout.List>{/* rows */}</ListDetailLayout.List> <ListDetailLayout.Detail> <ListDetailLayout.Back /> {/* detail */} </ListDetailLayout.Detail></ListDetailLayout>;Anatomy
Section titled “Anatomy”ListDetailLayout.List: the master list. On a narrow layout it’s hidden once something isselected, handing the stage to the detail.ListDetailLayout.Detail: the detail pane.ListDetailLayout.Back: a back link placed at the top ofDetail; it renders only on a narrow layout and callsonBack.
Each pane runs edge to edge (its scrollbar sits on the frame’s edge or the
divider) and insets its own content by the gutter:
the detail by the gutter, the list by the gutter less a ListRow’s own padding,
so row text lands on the line your page’s title and tabs sit on. Other content
in the list, such as a SearchField above the rows, sits a row’s padding
(0.75rem) inside that line. Put the layout in AppFrame.Body bleed, so nothing
around it adds a second inset. Pass inset={false} to a pane whose content runs
edge to edge itself.
selected is driven by your own selection state. Read the responsive state with
the useListDetail() hook for custom back affordances.
| Prop | Type | Default |
|---|---|---|
selected |
boolean |
false |
onBack |
() => void |
None |
listWidth |
number | string |
320 |
breakpoint |
number |
720 |
ListDetailLayout.List and ListDetailLayout.Detail
Section titled “ListDetailLayout.List and ListDetailLayout.Detail”| Prop | Type | Default |
|---|---|---|
inset |
boolean |
true |