Customizing
Since version 0.3.0New components. Scaffold a component of your own that gets a directive, validation and a manifest entry for free.
When Postkit doesn't have what you need, define it yourself. This is rung 8 of the customization ladder. Your component is defined the same way Postkit's built-in ones are, so it gets a Markdown directive, validation, theming and a manifest entry for free, and Prismark can offer it to writers.
Scaffold it
npx postkit new showcase --category media✓ src/postkit/showcase/showcase.definition.ts
✓ src/postkit/showcase/showcase.tsx
✓ src/postkit/showcase/showcase.css
Register it with createPostkit({ components }) in lib/postkit.ts:
import { Showcase } from '../src/postkit/showcase/showcase';
import { showcaseDefinition } from '../src/postkit/showcase/showcase.definition';
export const postkit = createPostkit({
// …your renderer and kits
components: [{ definition: showcaseDefinition, view: Showcase }],
});
Use it as <Showcase /> in MDX or :::postkit-showcase in Markdown.
Import showcase.css from your global stylesheet for the headless view.You get a definition, a headless view and its styles, as a starting point
that wraps authored content (children: 'mdx'), with a title prop and
root, title and body parts. --chakra adds a
Chakra view (showcase.chakra.tsx) and slot recipe (showcase.recipe.ts), and
--spec adds a spec per view. The CSS targets the anatomy attributes; import
it from your global stylesheet. See CLI for every
flag.
In an Nx workspace, the generator writes the same files from the same templates:
nx g @postkit/nx:component showcase --category=media --directory=libs/site/src/postkitDefine it
The definition is the contract: the component's name, directive, props and named parts. It's framework-free, so the manifest and editors can read it without React. See definePostkitComponent for every field.
The example frames a screenshot in a browser or app window. (Postkit's own Device already does iPhone, iPad and Mac frames.)
// showcase/showcase.definition.ts
import {
definePostkitComponent,
prop,
presentation,
} from '@postkit/core/components';
export const showcaseDefinition = definePostkitComponent({
name: 'Showcase',
directive: 'postkit-showcase',
category: 'media',
description: 'A screenshot framed in a browser or app window.',
runtime: 'static',
stability: 'experimental',
props: {
...presentation,
kind: prop.enum(['browser', 'window'], {
description: 'The showcase frame.',
default: 'browser',
themeVariant: true,
}),
src: prop.string('The screenshot URL.', { required: true }),
alt: prop.string('Text alternative for the screenshot.', {
required: true,
}),
caption: prop.string('An optional caption.'),
},
slots: ['root', 'frame', 'screen', 'caption'],
keywords: ['showcase', 'screenshot', 'mockup'],
example: {
props: { kind: 'browser', src: '/shots/home.png', alt: 'The home page' },
},
});- Required props take
{ required: true }. A directive without them fails validation, an MDX element without them gets a console warning in development, and the view receives them as non-optional. childrencan be left out, as here: it defaults to'none'. Setchildren: 'mdx'when the component wraps authored content.categoryis one of Postkit's six:article-structure,technical-content,media,discovery,engagementorpublishing. Pick the closest; it groups the component in the manifest and in editors.
Write the view
Build the view with postkitView, so it emits the anatomy and picks up
defaults, slot overrides and part styles like any other component:
// showcase/showcase.tsx
import { postkitView } from '@postkit/react';
import { showcaseDefinition } from './showcase.definition';
export const Showcase = postkitView(showcaseDefinition, ({ props, part }) => (
<figure {...part('root')}>
<div {...part('frame')}>
<img {...part('screen')} src={props.src} alt={props.alt} />
</div>
{props.caption && (
<figcaption {...part('caption')}>{props.caption}</figcaption>
)}
</figure>
));Register it
Add the definition and view to components, next to your kits:
// lib/postkit.ts
import { createPostkit } from '@postkit/react';
import { article, media } from '@postkit/react/kits';
import { Showcase } from './showcase/showcase';
import { showcaseDefinition } from './showcase/showcase.definition';
export const postkit = createPostkit({
kits: [article, media],
components: [{ definition: showcaseDefinition, view: Showcase }],
});Writers can now use it in either syntax:
<Showcase
kind="window"
src="/shots/editor.png"
alt="The editor with a post open"
/>::postkit-showcase{kind="window" src="/shots/editor.png" alt="The editor with a post open"}What you get
From the one definition:
- Typed props for your view, with
PostkitPropsOf<typeof showcaseDefinition>. - A directive, validated like Postkit's own (see Validation).
- An entry in
postkit.manifest(), so editors like Prismark can offer it. - Slot and variant types derived from its parts and theme-variant props, and
the recipe key
postkitShowcaseif you write a Chakra view and recipe for it withpostkitChakraView. - Anatomy attributes on every part, so part styles work the same as for built-in components.
Share it
A component package exports { definition, view } pairs and a manifest,
written with createPostkitComponentManifest from @postkit/core/components
(see Manifest). A site turns the components on by adding
those pairs to components, and editors read the manifest. A component that
proves itself can be proposed upstream to Postkit.