Snippets
Automated Block Layouts
Use block flags and wrapBlock to keep layout rules out of every block
Use this when the page layout should automatically wrap blocks based on block metadata, rather than making every block render its own page grid.
For the underlying APIs, see Block Flags, Querying Blocks From Views, and Nested Blocks.
Put Layout Hints In Block Metadata
Keep flags small. They are copied into the block payload and are available to ContentBlocks.
import { defineBlock, EditableText, InnerBlocks } from "eddev/blocks"
export const meta: BlockMeta = {
title: "Accordion",
icon: "info",
tags: ["#subpage"],
flags: {
contentWidth: true,
marginRule: "long-card",
},
}
export default defineBlock("content/accordion", () => {
return (
<section>
<EditableText as="h3" store="title" defaultValue="Enter a title" plainText />
<InnerBlocks allowedBlocks={["core/paragraph", "core/list", "content/button-row"]} />
</section>
)
})import { defineBlock, InnerBlocks } from "eddev/blocks"
export const meta: BlockMeta = {
title: "Card Row",
category: "layouts",
icon: "slides",
tags: ["#subpage"],
flags: {
fullWidth: true,
marginRule: "featured-card",
},
}
export default defineBlock("content/card-row", () => {
return <InnerBlocks allowedBlocks={["content/card-row-item"]} />
})Wrap Blocks In One Place
Use wrapBlock on a shared ContentBlocks wrapper so page grid rules live in one component.
import { BlocksContext, ContentBlocks } from "eddev/blocks"
import { ComponentProps, ReactNode } from "react"
function wrapBlock(children: ReactNode, ctx: BlocksContext) {
const marginClass = ctx.current.flags?.marginRule
? `block-margins-${ctx.current.flags.marginRule}`
: ""
if (ctx.current.blockName === "core/rich-text" || ctx.current.flags?.contentWidth) {
return <div className={`col-subpage-content ${marginClass}`}>{children}</div>
}
if (ctx.current.flags?.fullWidth) {
return <div className={`full-width-block ${marginClass}`}>{children}</div>
}
return <div className={marginClass}>{children}</div>
}
type Props = Omit<ComponentProps<typeof ContentBlocks>, "wrapBlock">
export function SubpageContentBlocks(props: Props) {
return <ContentBlocks {...props} wrapBlock={wrapBlock} />
}Use The Wrapper In Views
import { SubpageContentBlocks } from "@features/layout/SubpageContentBlocks"
import { defineView } from "eddev/views"
export default defineView("page", (props) => {
return <SubpageContentBlocks blocks={props.page?.contentBlocks} />
})This works well when blocks need to stay reusable across different views, but each view has its own layout rules.