Heading
h1…h6 by level, sized by the base layer.
Picks the element, nothing else. level rendersh1…h6, and the appearance comes from the base layer, which already maps each level to a Utopia step, a weight and its rhythm. Separating the two is the point: a section that needs to sit ath3 in the document outline can say so without anybody arguing about how large it should look.
Which is why almost every block takes a headingLevel prop and passes it straight through. The host owns the outline, because only the host knows what the page above the block looks like.
Because it has no <style> of its own, a parent's scoped rule does not reach the element it renders — a passed classarrives, the scope hash does not. Use :global() under a scoped ancestor, or a class from the components layer such as.section-h. This is the most expensive gotcha in the repo and it looks exactly like a specificity bug.
The six levels
Every home comes with a garden
Every home comes with a garden
Every home comes with a garden
Every home comes with a garden
Every home comes with a garden
Every home comes with a garden
Size held, level changed
All three are .section-h from the components layer, ath2, h3 and h4. They look identical and the outline reads correctly — that is the separation working.
A section heading at level 2
A section heading at level 3
A section heading at level 4
Props
| Prop | Type | Required |
|---|---|---|
| level | 1 | 2 | 3 | 4 | 5 | 6 | — |
| class | string | — |