Skip to contentnotionic
Docs menu

Examples

Headings

Headings 1–4, toggleable headings and the table of contents.

Each example below is a real Notion block, rendered by notionic's built-in components, followed by a recipe to change it. The example headings also appear in this page's outline.

Headings 1–4

In Notion: type /h1, /h2, /h3 or /h4, or start a line with #, ##, ### or ####.

A heading 1

A heading 2

A heading 3

A heading 4

Renders as: <h2> to <h5>, one level down, so the page title stays the only <h1>. Each gets an anchor id from its text. See Supported blocks.

TypeScript
import { RichText, type BlockProps } from "notionic"
// Keep the anchor id from context.headings, and add a link to it.export function Heading2({ block, context }: BlockProps<"heading_2">) {  const id = context.headings.find((heading) => heading.blockId === block.id)?.id  return (    <h2 id={id} className="group scroll-mt-20 text-2xl font-semibold">      <RichText text={block.heading_2.rich_text} context={context} />      {id ? (        <a href={`#${id}`} className="ms-2 text-muted-foreground opacity-0 group-hover:opacity-100">          #        </a>      ) : null}    </h2>  )}
<NotionRenderer blocks={blocks} components={{ heading_2: Heading2 }} />
Customize · heading.tsx

Toggleable headings

In Notion: type /toggle heading, or turn a heading into a toggle from its ⋮⋮ menu.

A toggleable heading

Its content stays in the HTML while closed, so search engines and Cmd+F find it.

Renders as: a <details> whose summary is the heading. It opens without JavaScript.

TypeScript
import { NotionToggle } from "@/components/notion-toggle"
// shadcn/ui's Collapsible, from the registry, for toggles. Toggleable headings keep the built-in <details>.<NotionRenderer blocks={blocks} components={{ toggle: NotionToggle }} />
Customize · toggle.tsx

Table of contents

In Notion: type /table of contents.

Renders as: a list of links to every heading on the page, indented by level.

TypeScript
import { collectHeadings, type NotionBlock } from "notionic"
// The same headings, as a sidebar outline outside the page.export function Outline({ blocks }: { blocks: NotionBlock[] }) {  return (    <nav aria-label="On this page" className="flex flex-col gap-1 text-sm">      {collectHeadings(blocks).map((heading) => (        <a key={heading.id} href={`#${heading.id}`} style={{ paddingInlineStart: (heading.level - 1) * 12 }}>          {heading.text}        </a>      ))}    </nav>  )}
Customize · outline.tsx