<TabbedShowLayout>
The <TabbedShowLayout>
pulls the record
from the RecordContext
. It renders a set of <Tabs>
, each of which contains a list of record fields in a single-column layout (via Material UI’s <Stack>
component). <TabbedShowLayout>
delegates the actual rendering of fields to its children, which should be <TabbedShowLayout.Tab>
elements. <TabbedShowLayout.Tab>
wraps each field inside a <Labeled>
component to add a label.
Switching tabs will update the current url. By default, it uses the tabs indexes and the first tab will be displayed at the root url. You can customize the path by providing a path
prop to each <TabbedShowLayout.Tab>
component. If you’d like the first one to act as an index page, just omit the path
prop.
Usage
Use <TabbedShowLayout>
as descendant of a <Show>
component (or any component creating a <RecordContext>
), define the tabs via <TabbedShowLayout.Tab>
children, and set the fields to be displayed as children of each tab:
import { Show, TabbedShowLayout } from 'react-admin'
export const PostShow = () => (
<Show>
<TabbedShowLayout>
<TabbedShowLayout.Tab label="summary">
<TextField label="Id" source="id" />
<TextField source="title" />
<TextField source="teaser" />
</TabbedShowLayout.Tab>
<TabbedShowLayout.Tab label="body" path="body">
<RichTextField source="body" label={false} />
</TabbedShowLayout.Tab>
<TabbedShowLayout.Tab label="Miscellaneous" path="miscellaneous">
<TextField label="Password (if protected post)" source="password" type="password" />
<DateField label="Publication date" source="published_at" />
<NumberField source="average_note" />
<BooleanField label="Allow comments?" source="commentable" defaultValue />
<TextField label="Nb views" source="views" />
</TabbedShowLayout.Tab>
<TabbedShowLayout.Tab label="comments" path="comments">
<ReferenceManyField reference="comments" target="post_id" label={false}>
<Datagrid>
<TextField source="body" />
<DateField source="created_at" />
<EditButton />
</Datagrid>
</ReferenceManyField>
</TabbedShowLayout.Tab>
</TabbedShowLayout>
</Show>
);
Props
children
: components rendering a tabclassName
: passed to the root componentdivider
: optional element to render between each fieldrecord
: can be injected when outside a RecordContextspacing
: optional integer to set the spacing between the fieldssx
: Override the stylessyncWithLocation
: optional boolean to disable storing the active tab in the urltabs
: custom Tabs component
Additional props are passed to the root component (<div>
).
Tabs
Children of <TabbedShowLayout>
must be <TabbedShowLayout.Tab>
components.
The <TabbedShowLayout.Tab>
component renders tabs headers and the active tab. It manages the tab change, either via the URL, or an internal state.
It accepts the following props:
label
: The string displayed for each tabicon
: The icon to show before the label (optional). Must be a component.path
: The string used for custom urls (optional)count
: the number of items in the tab (dislayed close to the label)
// in src/posts.js
import * as React from "react";
import FavoriteIcon from '@mui/icons-material/Favorite';
import PersonPinIcon from '@mui/icons-material/PersonPin';
import { Show, TabbedShowLayout, TextField } from 'react-admin';
export const PostShow = () => (
<Show>
<TabbedShowLayout>
<TabbedShowLayout.Tab label="Content" icon={<FavoriteIcon />}>
<TextField source="title" />
<TextField source="subtitle" />
</TabbedShowLayout.Tab>
<TabbedShowLayout.Tab label="Metadata" icon={<PersonIcon />} path="metadata">
<TextField source="category" />
</TabbedShowLayout.Tab>
</TabbedShowLayout>
</Show>
);
Tab Fields
<TabbedShowLayout.Tab>
renders each child inside a <Labeled>
component. This component uses the humanized source as label by default. You can customize it by passing a label
prop to the fields:
const PostShow = () => (
<Show>
<TabbedShowLayout>
<TabbedShowLayout.Tab label="main">
<TextField label="My Custom Title" source="title" />
</TabbedShowLayout.Tab>
</TabbedShowLayout>
</Show>
);
The <Labeled label>
uses the humanized source by default. You can customize it by passing a label
prop to the fields:
const PostShow = () => (
<Show>
<TabbedShowLayout>
<TabbedShowLayout.Tab label="main">
<TextField label="My Custom Title" source="title" />
<TextField label="my.custom.translationKey" source="description" />
</TabbedShowLayout.Tab>
</TabbedShowLayout>
</Show>
);
// translates to
const PostShow = () => (
<Show>
<TabbedShowLayout>
<Labeled label="My Custom Title">
<TextField source="title" />
</Labeled>
<Labeled label="my.custom.translationKey">
<TextField source="description" />
</Labeled>
</TabbedShowLayout>
</Show>
);
You can disable the <Labeled>
decoration by passing setting label={false}
on a field:
const PostShow = () => (
<Show>
<TabbedShowLayout>
<TabbedShowLayout.Tab label="main">
<TextField label={false} source="title" />
</TabbedShowLayout.Tab>
</TabbedShowLayout>
</Show>
);
<TabbedShowLayout.Tab>
children can be anything you want. Try passing your own components:
const PostTitle = () => {
const record = useRecordContext();
return <span>Post "{record.title}"</span>;
};
const PostShow = () => (
<Show>
<TabbedShowLayout>
<TabbedShowLayout.Tab label="main">
<PostTitle label="title" />
</TabbedShowLayout.Tab>
</TabbedShowLayout>
</Show>
);
Sync Tabs With Location
To let users come back to a previous tab by using the browser’s back button, <TabbedShowLayout>
stores the active tab in the location by default. You can opt out the location synchronization by passing false
to the syncWithLocation
prop. This allows e.g. to have several <TabbedShowLayout>
components in a page.
import { TabbedShowLayout, Tab } from 'react-admin'
export const PostShow = () => (
<Show>
<TabbedShowLayout syncWithLocation={false}>
<TabbedShowLayout.Tab label="summary">
<TextField label="Id" source="id" />
<TextField source="title" />
<TextField source="teaser" />
</TabbedShowLayout.Tab>
<TabbedShowLayout.Tab label="body" path="body">
<RichTextField source="body" label={false} />
</TabbedShowLayout.Tab>
<TabbedShowLayout.Tab label="Miscellaneous" path="miscellaneous">
<TextField label="Password (if protected post)" source="password" type="password" />
<DateField label="Publication date" source="published_at" />
<NumberField source="average_note" />
<BooleanField label="Allow comments?" source="commentable" defaultValue />
<TextField label="Nb views" source="views" />
</TabbedShowLayout.Tab>
<TabbedShowLayout.Tab label="comments" path="comments">
<ReferenceManyField reference="comments" target="post_id" label={false}>
<Datagrid>
<TextField source="body" />
<DateField source="created_at" />
<EditButton />
</Datagrid>
</ReferenceManyField>
</TabbedShowLayout.Tab>
</TabbedShowLayout>
</Show>
);
Tip: When syncWithLocation
is false
, the path
prop of the <TabbedShowLayout.Tab>
components is ignored.
Spacing
<TabbedShowLayout.Tab>
renders a Material UI <Stack>
. You can customize the spacing of each row by passing a spacing
prop:
const PostShow = () => (
<Show>
<TabbedShowLayout spacing={2}>
<TabbedShowLayout.Tab label="main">
<PostTitle label="title" />
</TabbedShowLayout.Tab>
</TabbedShowLayout>
</Show>
);
The default spacing is 1
.
Divider
<Stack>
accepts an optional divider
prop - a component rendered between each row. <TabbedShowLayout>
also accepts this props, and passes it to the <Stack>
component.
import { Divider } from '@mui/material';
const PostShow = () => (
<Show>
<TabbedShowLayout divider={<Divider flexItem />}>
<TabbedShowLayout.Tab label="main">
<PostTitle label="title" />
</TabbedShowLayout.Tab>
</TabbedShowLayout>
</Show>
);
Custom Tab Component
By default, <TabbedShowLayout>
renders its tabs using <TabbedShowLayoutTabs>
, an internal react-admin component. You can pass a custom component as the tabs
prop to override that default. Also, props passed to <TabbedShowLayoutTabs>
are passed to the Material UI’s <Tabs>
component inside <TabbedShowLayoutTabs>
. That means you can create a custom tabs
component without copying several components from the react-admin source.
For instance, to make use of scrollable <Tabs>
, you can pass variant="scrollable"
and scrollButtons="auto"
props to <TabbedShowLayoutTabs>
and use it in the tabs
prop from <TabbedShowLayout>
as follows:
import {
Show,
TabbedShowLayout,
TabbedShowLayoutTabs,
} from 'react-admin';
const ScrollableTabbedShowLayout = props => (
<Show {...props}>
<TabbedShowLayout tabs={<TabbedShowLayoutTabs variant="scrollable" scrollButtons="auto" {...props} />}>
...
</TabbedShowLayout>
</Show>
);
export default ScrollableTabbedShowLayout;
Controlled Mode
By default, <TabbedShowLayout>
reads the record from the RecordContext
. But by passing a record
prop, you can render the component outside a RecordContext
.
const StaticPostShow = () => (
<TabbedShowLayout record={{ id: 123, title: 'Hello world' }}>
<TabbedShowLayout.Tab label="main">
<TextField source="title" />
</TabbedShowLayout.Tab>
</TabbedShowLayout>
);
When passed a record
, <TabbedShowLayout>
creates a RecordContext
with the given record.
sx
: CSS API
The <TabbedShowLayout>
component accepts the usual className
prop but you can override many class names injected to the inner components by React-admin thanks to the sx
property (see the sx
documentation for syntax and examples). This property accepts the following subclasses:
Rule name | Description |
---|---|
& .RaTabbedShowLayout-content |
Applied to the content zone (under the tabs) |
To override the style of all instances of <TabbedShowLayout>
using the application-wide style overrides, use the RaTabbedShowLayout
key.
To style the tabs, the <TabbedShowLayout.Tab>
component accepts two props:
className
is passed to the tab headercontentClassName
is passed to the tab content
See Also
- Field components
- Show Guesser guesses the fields based on the record type
- SimpleShowLayout provides a simpler layout with no tabs