Skip to content

Heading

Semantics only: turns a level into the matching tag. It emits no classes — text styling lives in the base layer (h1–h6 in global.css), so there is one source of truth a brand or client can restyle in CSS.

import { Heading } from "@evolve-storefront/ui/heading";
Design notes

A feature cannot know its own document level (that depends on where the consumer composes it), and a depth-counting context cannot work because context is unreadable in Server Components. Hence an explicit level prop, derived downward with subLevel().

⚠️ This component must never regain a size/variant prop and must never emit a class. That re-creates two competing sources of truth for text styling, where the winner comes down to specificity — exactly what this replaced.

Preview

DefaultOpen in Storybook ↗

Usage

<Heading level={2}>{t("recentOrders")}</Heading>;

Props

PropTypeDescription
levelHeadingLevel

Semantic heading level (h1–h6) — the document outline, not a size.

Any other props go to the root element, like on a plain HTML element.

Examples

LevelsEvery level, styled entirely by the base layer.
// The level is the document outline; the base layer decides the size.
<Heading level={1}>{t("account")}</Heading>
<Heading level={2}>{t("addresses")}</Heading>
<Heading level={3}>{t("defaultAddress")}</Heading>
Open in Storybook ↗
Base ElementsOther element defaults the base layer sets.
// Body text needs no component: write the element.
<Heading level={2}>{t("delivery")}</Heading>
<p>{t("deliveryBody")}</p>
<small>{t("deliveryFinePrint")}</small>
Open in Storybook ↗
Derived Levels
function OrderSummary({ headingLevel = 2 }: { headingLevel?: HeadingLevel }) {
return (
<section>
<Heading level={headingLevel}>{t("summary")}</Heading>
<OrderLines headingLevel={subLevel(headingLevel)} />
</section>
);
}
Open in Storybook ↗