Skip to main content

Interface 1.2+ Directives

Use directives to to pass values to upper contexts using JSX components.

Directives are React components that can be used to pass values to upper contexts just by rendering <Directive> components and specifying the name and content.

Similar to slots that give you a way to escape from the tied page layout, directives give you a way to escape from the tied page behavior.

In most cases you can use it to control your app from within the page to direct it what to do (hence the name), e.g. when you need some pages to stretch to the full width of the screen.

Creating Directives

To create a directive, you need to use the createDirectiveContext factory function.

admin/components/Directives.tsx
import { Directives } from '@contember/layout';

export type DirectivesType = {
'full-width': boolean
}

export const initialDirectives: DirectivesType = {
'full-width': false,
}

// Local export with current DirectivesType specific to the project
export const Directive = Directives.Directive as unknown as Directives.DirectiveComponentType<DirectivesType>

// Local export with current DirectivesType specific to the project
export const useDirectives = Directives.useDirectives<DirectivesType>
tip

To make the usage of directives easier, you can create a shorthand component. For example, you can create a FullWidth component that will render the Directive that will set the full width directive to true.

admin/components/FullWidth.tsx
import { Directive } from './Directives'

export function FullWidth() {
return <Directive name={'full-width'} content={true} />
}

Setting values with a directive in the page

To use a directive that will push value to the parent context just render the Directive component with the name and content props.

admin/pages/example.tsx
import * as React from 'react'
import { CommonSlots } from '@contember/layout'
import { Directive } from '../components/Directives'

export default () => (
<>
<Directive name="full-width" content={true} />
<p>Some content</p>
</>
)

Accessing the directive values

To use the directives in the layout, you need to use the useDirectives hook.

admin/components/Layout.tsx
import { useDirectives } from "../Directives"

export const Layout = ({ children: pages }: React.PropsWithChildren) => {
const directives = useDirectives()

return (
<div className={directives['full-width']
? "full-width"
: undefined
}>
{pages}
</div>
)
}

Caveats

You can use directives to control any aspect of your page at any nesting depth and you can render as many directives as you want, the last one rendered wins. This principle ensures the ability to override the value of a directive from within any nested component.

admin/pages/example.tsx
import * as React from 'react'
import { CommonSlots } from '@contember/layout'
import { Directive } from '../components/Directives'

export default () => (
<>
<Directive name="full-width" content={true} />
<p>Some content</p>
<div>
<p>Nested component</p>
<Directive name="full-width" content={false} />
</div>
</>
)
admin/components/Layout.tsx
import { useDirectives } from "../Directives"

export const Layout = ({ children: pages }: React.PropsWithChildren) => {
const directives = useDirectives()

return (
<div className={directives['full-width']
? "full-width"
: undefined
}>
{pages}
</div>
)
}

The result is that the page will not be full width, because the directive from the nested component overrides the directive from the page.

Context Providers

Using directives is optional. Their respective providers are included in our project templates in the application entry point. Once you decide to go your own way just remove the <Directives.Provider> from the index.tsx file.