Import
import { Layout } from '@contentful/f36-components';// orimport { Layout } from '@contentful/f36-layout';
Layout Compound Components
The Layout exports the following compound components
Compound Component | Description | Typical Usage Area |
|---|---|---|
Layout.Header | Should contain a | header |
Layout.Sidebar | Allows for variants | leftSidebar, rightSidebar |
Layout.Body | Wrapper around all children, this compound component is essential for proper overflow and scrolling behaviors. | wrapper around all children of Layout |
Examples
Basic Layout with body only
function BasicLayoutExample() {const [submitting, setSubmitting] = useState(false);const submitForm = () => {setSubmitting(true);setTimeout(() => setSubmitting(false), 1000);};return (<Layout><Layout.Body><Box padding="none" marginBottom="spacingXl"><Form onSubmit={submitForm}><FormControl><FormControl.Label isRequired>Name</FormControl.Label><TextInput /><FormControl.HelpText>Please enter your first name</FormControl.HelpText></FormControl><FormControl><FormControl.Label>Description</FormControl.Label><Textarea /><FormControl.HelpText>Tell me about yourself</FormControl.HelpText></FormControl><Button variant="primary" type="submit" isDisabled={submitting}>{submitting ? 'Submitted' : 'Click me to submit'}</Button></Form></Box></Layout.Body></Layout>);}
Layout with header
function BasicLayoutExample() {const [submitting, setSubmitting] = useState(false);const submitForm = () => {setSubmitting(true);setTimeout(() => setSubmitting(false), 1000);};return (<Layoutheader={<Layout.Header><Header title="Your Details" /></Layout.Header>}><Layout.Body><Box padding="none" marginBottom="spacingXl"><Form onSubmit={submitForm}><FormControl><FormControl.Label isRequired>Name</FormControl.Label><TextInput /><FormControl.HelpText>Please enter your first name</FormControl.HelpText></FormControl><FormControl><FormControl.Label>Description</FormControl.Label><Textarea /><FormControl.HelpText>Tell me about yourself</FormControl.HelpText></FormControl><Button variant="primary" type="submit" isDisabled={submitting}>{submitting ? 'Submitted' : 'Click me to submit'}</Button></Form></Box></Layout.Body></Layout>);}
Layout with left sidebar
function BasicLayoutExample() {const [submitting, setSubmitting] = useState(false);const submitForm = () => {setSubmitting(true);setTimeout(() => setSubmitting(false), 1000);};return (<LayoutleftSidebar={<Layout.Sidebar><Box padding="none" marginBottom="spacingXl"><Paragraph>Sidebar Content</Paragraph></Box></Layout.Sidebar>}><Layout.Body><Box padding="none" marginBottom="spacingXl"><Form onSubmit={submitForm}><FormControl><FormControl.Label isRequired>Name</FormControl.Label><TextInput /><FormControl.HelpText>Please enter your first name</FormControl.HelpText></FormControl><FormControl><FormControl.Label>Description</FormControl.Label><Textarea /><FormControl.HelpText>Tell me about yourself</FormControl.HelpText></FormControl><Button variant="primary" type="submit" isDisabled={submitting}>{submitting ? 'Submitted' : 'Click me to submit'}</Button></Form></Box></Layout.Body></Layout>);}
Layout with right sidebar
function BasicLayoutExample() {const [submitting, setSubmitting] = useState(false);const submitForm = () => {setSubmitting(true);setTimeout(() => setSubmitting(false), 1000);};return (<LayoutrightSidebar={<Layout.Sidebar><Box padding="none" marginBottom="spacingXl"><Paragraph>Sidebar Content</Paragraph></Box></Layout.Sidebar>}><Layout.Body><Box padding="none" marginBottom="spacingXl"><Form onSubmit={submitForm}><FormControl><FormControl.Label isRequired>Name</FormControl.Label><TextInput /><FormControl.HelpText>Please enter your first name</FormControl.HelpText></FormControl><FormControl><FormControl.Label>Description</FormControl.Label><Textarea /><FormControl.HelpText>Tell me about yourself</FormControl.HelpText></FormControl><Button variant="primary" type="submit" isDisabled={submitting}>{submitting ? 'Submitted' : 'Click me to submit'}</Button></Form></Box></Layout.Body></Layout>);}
Layout with header and sidebars
function BasicLayoutExample() {const [submitting, setSubmitting] = useState(false);const submitForm = () => {setSubmitting(true);setTimeout(() => setSubmitting(false), 1000);};return (<Layoutheader={<Layout.Header><Header title="Your Details" /></Layout.Header>}leftSidebar={<Layout.Sidebar><Box padding="none" marginBottom="spacingXl"><Paragraph>Sidebar Content</Paragraph></Box></Layout.Sidebar>}rightSidebar={<Layout.Sidebar><Box padding="none" marginBottom="spacingXl"><Paragraph>Sidebar Content</Paragraph></Box></Layout.Sidebar>}><Layout.Body><Box padding="none" marginBottom="spacingXl"><Form onSubmit={submitForm}><FormControl><FormControl.Label isRequired>Name</FormControl.Label><TextInput /><FormControl.HelpText>Please enter your first name</FormControl.HelpText></FormControl><FormControl><FormControl.Label>Description</FormControl.Label><Textarea /><FormControl.HelpText>Tell me about yourself</FormControl.HelpText></FormControl><Button variant="primary" type="submit" isDisabled={submitting}>{submitting ? 'Submitted' : 'Click me to submit'}</Button></Form></Box></Layout.Body></Layout>);}
Full Screen Layout with header and sidebars
function BasicLayoutExample() {const [submitting, setSubmitting] = useState(false);const submitForm = () => {setSubmitting(true);setTimeout(() => setSubmitting(false), 1000);};return (<Layoutvariant="fullscreen"header={<Layout.Header><Header title="Your Details" /></Layout.Header>}leftSidebar={<Layout.Sidebar><Box padding="none" marginBottom="spacingXl"><Paragraph>Sidebar Content</Paragraph></Box></Layout.Sidebar>}rightSidebar={<Layout.Sidebar><Box padding="none" marginBottom="spacingXl"><Paragraph>Sidebar Content</Paragraph></Box></Layout.Sidebar>}><Layout.Body><Box padding="none" marginBottom="spacingXl"><Form onSubmit={submitForm}><FormControl><FormControl.Label isRequired>Name</FormControl.Label><TextInput /><FormControl.HelpText>Please enter your first name</FormControl.HelpText></FormControl><FormControl><FormControl.Label>Description</FormControl.Label><Textarea /><FormControl.HelpText>Tell me about yourself</FormControl.HelpText></FormControl><Button variant="primary" type="submit" isDisabled={submitting}>{submitting ? 'Submitted' : 'Click me to submit'}</Button></Form></Box></Layout.Body></Layout>);}
Layout areas
The Layout component offers 4 individual areas, which can be set via the props header, leftSidebar, rightSidebar, and as children (for the main content area).
| Prop | Description | Recommended Child components |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| children | Elements handed over as children to the Layout component render as the Layout's body. Ideally, all children should be wrapped inside Layout.Body | Layout.Body |
| header | Elements in the header overarch the whole width of the layout component. Child components should be wrapped inside Layout.Header. It is also recommended to use Header as the only child of Layout.Header | Layout.Header with Header as a child |
| leftSidebar | rightSidebar | These child-components render on the left and right side of the body content. They should be wrapped in Layout.Sidebar | Layout.Sidebar |
** Note ** When passing at least one sidebar, a divider is added underneath the header. There is no divider otherwise.
Accessibility
- The Layout component renders a
<section>by default. If you use multiple layouts or want to improve landmark navigation, provide a unique aria-label Layout.Sidebarrenders as a semantic<aside>by defaultLayout.Headerrenders as a semantic<header>by default- Keyboard navigation and focus management for interactive content inside the layout should be implemented by the consumer.
Props (API reference)
Open in StorybookLayout
Name | Type | Default |
|---|---|---|
| children | ReactNode The body of the layout. | |
| className | string CSS class to be appended to the root element | |
| contentClassName | string Classname that will be passed to the main content div, which holds the sidebars and children div | |
| contentTestId | string | |
| header | string number bigint false true ReactElement<unknown, string | JSXElementConstructor<any>> Iterable<ReactNode> ReactPortal Promise<AwaitedReactNode> | |
| leftSidebar | string number bigint false true ReactElement<unknown, string | JSXElementConstructor<any>> Iterable<ReactNode> ReactPortal Promise<AwaitedReactNode> | |
| leftSidebarVariant | "narrow" "wide" Defines the width of the layout left sidebar. | 'narrow' (280px) |
| offsetTop | number Offset for layout heights calculation. Set to `0` for layout usage without navbar. | 60 (= navbar height) |
| rightSidebar | string number bigint false true ReactElement<unknown, string | JSXElementConstructor<any>> Iterable<ReactNode> ReactPortal Promise<AwaitedReactNode> | |
| rightSidebarVariant | "narrow" "wide" Defines the width of the layout right sidebar. | 'wide' (340px) |
| testId | string A [data-test-id] attribute used for testing purposes | |
| variant | "narrow" "wide" "fullscreen" Defines the width of the layout and its content. | 'wide' |
| withBoxShadow | false true |