Skip to main content

Custom layouts

With slots and directives you have all the tools you need to:

  • render into specific areas of the layout using slots
  • control any aspect of your app using directives

Slots and directives lets you decouple content from the layout, so you can use any layout you want, even have multiple layouts for different parts of your app.

1. Any HTML can be your layout

Take any HTML, set where content should be rendered using the slot targets, connect directives to control any aspect of your app (layout, theme, etc.) and you have a custom layout.

my-custom-layout.tsx
import { DropdownContentContainerProvider } from "@contember/admin"
import {
commonSlotTargets,
CommonSlotTargets,
useDocumentTitle,
useLayoutSlotRegistryContext,
} from "@contember/layout"
import { useDirectives } from "./components/Directives"
import { SlotTargets, slotTargets } from "./components/Slots"

export function MyCustomLayout() {
const { activeSlots } = useLayoutSlotRegistryContext()
const directives = useDirectives()

useDocumentTitle(directives.title)

return (
<div className="layout">
<header className="layout__header">
{activeSlots.has(commonSlotTargets.Back) ? <CommonSlotTargets.Back /> : null}
{activeSlots.has(commonSlotTargets.Logo) ? <CommonSlotTargets.Logo /> : null}
{activeSlots.has(commonSlotTargets.Actions) ? <CommonSlotTargets.Actions /> : null}
</header>
<main className="layout__main">
<h1>{directives.title}</h1>
{activeSlots.has(slotTargets.Subtitle) ? <SlotTargets.Subtitle /> : null}
{activeSlots.has(commonSlotTargets.Content) ? <CommonSlotTargets.Content /> : null}
</main>
<aside className="layout__aside">
{activeSlots.has(commonSlotTargets.Navigation) ? <CommonSlotTargets.Navigation /> : null}
{activeSlots.has(commonSlotTargets.Sidebar) ? <CommonSlotTargets.Sidebar /> : null}
</aside>
<footer className="layout__footer">
</footer>
<DropdownContentContainerProvider />
<div id="portal-root" />
</div>
)
}

2. Using your custom layout

Now that we have a layout, we need to connect it with Contember, swap it anytime you need.

admin/components/Layout.tsx
import * as React from 'react'
import { MyCustomLayout } from '../my-custom-layout'

export const Layout = ({
children: pages,
}: React.PropsWithChildren) => (
<>
<MyCustomLayout />
{pages}
</>
)