Skip to main content

Slots

Layout slots are React components that can be used to render content in predefined places of the layout. Each Slot will append its content to the target as createPortal() would do.

This is useful when you want to render a button in the footer, header, sidebar or any other place of the layout that is not directly accessible from within rendered page.

You can use any of already available common slots that are typical for all Contember layouts and layout specific slots. Common slots are:

  • Title - Slot for rendering page title (usually in the header)
  • Actions – Slot for rendering page actions (usually in the header)
  • Back – Slot for rendering back button (usually in the header near title)
  • Logo – Slot for rendering logo (usually in the header)
  • Navigation – Slot for rendering navigation (usually in the sidebar)
  • Content – Slot for rendering page content in the main area of the layout
  • Sidebar – Slot for rendering sidebar (usually in the right side of the layout)

You can even create your own layout with custom slots and use them in your pages just like the built-in ones.

1. Rendering content to slot from the page

admin/pages/example.tsx
import { Slots } from '../components/Slots'

export default () => (
<Slots.Subtitle>This is a subtitle</Slots.Subtitle>
)

2. Creating your own slots

To create your slot you need to create two components:

  • Slot – React component that will be used to render content from pages
  • SlotTarget – React component that will be used in place where you want to render content
tip

Using the activeSlots from the context you can check if there is any content to render.

admin/components/Slots.tsx
import {
createLayoutSlotComponent,
createLayoutSlotTargetComponent,
} from '@contember/layout'

export const slotTargets = Object.freeze({
Subtitle: 'subtitle',
})

export type SlotsMapType = Record<keyof typeof slotTargets, ReturnType<typeof createLayoutSlotComponent>>

export const Slots: SlotsMapType = {
Subtitle: createLayoutSlotComponent(slotTargets.Subtitle, 'Subtitle'),
}

export type SlotTargetsMapType = Record<keyof typeof slotTargets, ReturnType<typeof createLayoutSlotTargetComponent>>

export const SlotTargets: SlotTargetsMapType = {
Subtitle: createLayoutSlotTargetComponent(slotTargets.Subtitle, 'Subtitle'),
}

3. Placing slots in the layout

admin/components/Layout.tsx
import { slotTargets, SlotTargets } from '../components/Slots'

export const Layout = ({ children: pages }: React.PropsWithChildren) => {
const { activeSlots } = useLayoutSlotRegistryContext()

return (
<>
<div className="layout">
{activeSlots.has(slotTargets.Subtitle) ? <SlotTargets.Subtitle /> : null}
</div>

{pages}
</>
)
}