Section heading in the display face, Hanken Grotesk through the --font-display variable, at four sizes that step up with the Section container. Renders an h2 by default; the tag can be swapped.
import { mergeProps } from "@base-ui/react/merge-props"
import { useRender } from "@base-ui/react/use-render"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "cn"
const headingVariants = cva(
"font-display font-normal tracking-tight text-balance",
{
variants: {
/**
* The type size. Each size steps up once the nearest
* `@container/section`, such as a `Section`, is at least 42rem wide:
* `sm` from 32px to 40px, `md` (the default) from 32px to 48px, `lg`
* from 36px to 72px and `xl` from 64px to 96px. Outside such a
* container it keeps the smaller size.
*/
size: {
sm: "text-[2rem]/10 @2xl/section:text-[2.5rem]/10",
md: "text-[2rem]/10 @2xl/section:text-5xl/14",
lg: "text-4xl/10 @2xl/section:text-7xl/20",
xl: "text-[4rem]/16 @2xl/section:text-8xl/24",
},
},
defaultVariants: { size: "md" },
}
)
/**
* A section heading in the display font, rendered as an `<h2>`. Pass
* `render` to use another heading level. Its lines are balanced when it
* wraps.
*
* `size` picks the scale, and each size steps up once the nearest
* `@container/section`, such as a `Section`, is at least 42rem wide: `sm`
* from 32px to 40px, `md` (the default) from 32px to 48px, `lg` from 36px
* to 72px and `xl` from 64px to 96px. Without that container it keeps the
* smaller size.
*/
function Heading({
className,
size = "md",
render,
...props
}: useRender.ComponentProps<"h2"> & VariantProps<typeof headingVariants>) {
return useRender({
defaultTagName: "h2",
render,
state: { slot: "heading", size },
props: mergeProps<"h2">(
{ className: cn(headingVariants({ size }), className) },
props
),
})
}
export { Heading }
pnpm dlx shadcn add @01orbital/headingnpx shadcn add @01orbital/headingyarn shadcn add @01orbital/headingbunx --bun shadcn add @01orbital/headingFree under the MIT license. Add the @01orbital registry to components.json once (install guide), then run the command.
It lands at components/editorial/heading.tsx, as source you own and edit.
The example also uses section. Install it too:
pnpm dlx shadcn add @01orbital/sectionnpx shadcn add @01orbital/sectionyarn shadcn add @01orbital/sectionbunx --bun shadcn add @01orbital/sectionimport { Heading } from "@/components/editorial/heading"
import {
Section,
SectionContent,
} from "@/components/editorial/section"
const COPY = {
text: "A strong start. Room to make it yours.",
}
export default function HeadingDemo() {
return (
<Section className="py-0">
<SectionContent className="px-0 @5xl/section:px-0">
<Heading>{COPY.text}</Heading>
</SectionContent>
</Section>
)
}Prop
Type
It also accepts the props of the Base UI part it wraps, and the HTML attributes of the element it renders.
npm: @base-ui/react, class-variance-authority, cn. The CLI installs them for you.
Registry pieces it installs with it:
font-hanken-groteskFeatures
Feature list parts: a Grid rendered as a list in one to four columns or a divided single column, with feature, title and description parts and an outline item that rules its left edge.
Logo
Logo cloud parts: a labelled list laid out as a centred grid, a single wrapping baseline, two columns or muted tiles. Each logo takes an img, svg or text wordmark at three sizes, with a greyscale muted variant.