TabbedShowLayout
<TabbedShowLayout> groups Show fields into tabs.
Installation
pnpm dlx shadcn@latest add @shadmin/tabbed-show-layoutUsage
import { TabbedShowLayout } from "@/components/admin";
<TabbedShowLayout>
<TabbedShowLayout.Tab label="Main">
<TextField source="title" />
</TabbedShowLayout.Tab>
</TabbedShowLayout>;Before: teams had to infer this component from surrounding CRUD examples.
After: the component has a direct import example and a focused behavior note.
Props
| Prop | Required | Type | Default | Description |
|---|---|---|---|---|
| children | Required | ReactNode | - | Tab definitions and field content. |
| className | Optional | string | - | Additional CSS class applied to the outer wrapper. |
| divider | Optional | ReactNode | - | Element rendered between each field in a tab. |
| record | Optional | RaRecord | - | Explicit record to display (falls back to RecordContext). |
| spacing | Optional | number | - | Gap between fields within each tab's content panel (in px). |
| syncWithLocation | Optional | boolean | true | When true, tab changes update the URL. |
| tabs | Optional | ReactElement | - | Custom tab-strip renderer that replaces the default TabsList. |
| value | Optional | string | - | Controlled tab value; forces the Tabs component into controlled mode. |
spacing
Controls the gap between fields within each tab's content panel. The value is in pixels.
By default (when spacing is omitted), the gap is 1rem (gap-4). Passing spacing replaces that with an inline gap style scaled by a factor of 4: spacing={2} → gap: 8px, spacing={8} → gap: 32px.
<TabbedShowLayout spacing={8}>
<TabbedShowLayout.Tab label="Content">
<TextField source="title" />
<TextField source="author" />
</TabbedShowLayout.Tab>
</TabbedShowLayout>tabs
Replaces the default tab-strip with a custom ReactElement. The element receives no automatic props — it must render its own TabsList + TabsTrigger elements using TabbedShowLayoutTabsList or a fully custom implementation.
import { TabbedShowLayoutTabsList } from "@/components/admin";
const myTabs = (
<TabbedShowLayoutTabsList
tabs={
[
/* ShowTab elements */
]
}
syncWithLocation={false}
/>
);
<TabbedShowLayout tabs={myTabs}>
<TabbedShowLayout.Tab label="Content">
<TextField source="title" />
</TabbedShowLayout.Tab>
</TabbedShowLayout>;value
Forces the Tabs component into controlled mode by supplying the active tab value externally. When set, TabbedShowLayout ignores the URL and local state — the caller is responsible for updating value in response to tab changes.
The value must match the path/index string used for that tab. The first tab always has value "" when syncWithLocation is true, or "0" when false. Subsequent tabs use their path prop or their numeric index.
const [activeTab, setActiveTab] = React.useState("");
<TabbedShowLayout value={activeTab} syncWithLocation={false}>
<TabbedShowLayout.Tab label="Content">
<TextField source="title" />
</TabbedShowLayout.Tab>
<TabbedShowLayout.Tab label="Metadata">
<NumberField source="views" />
</TabbedShowLayout.Tab>
</TabbedShowLayout>;Behavior
Use this component inside the matching ra-core context. For example, list helpers belong inside a list, form helpers belong inside a form, and show-layout helpers belong inside a show view.