Skip to content
Principles

Vocabulary

You never write a raw HTML tag. Semantic elements come from a typed menu on the primitives, and the menu is short on purpose.

When a layout primitive needs to be a landmark or a list item, it takes an as prop typed as a closed union of allowed elements, not a raw <section> or <li>. Ask for an element that is not on the menu, such as as="button", and it does not compile: the answer to a button is the Button component.

Raw tags fail the lint. The no-naked-element gate runs at error on every build, so an ordinary element in application code breaks the build. Between the typed union and the gate, the set of elements you can use is finite and known.

Replacements

Each raw tag maps to one replacement. Using the tag itself fails the lint.

36 raw elements.
Raw elementWhat you write instead
<a>Anchor
<article>Box as="article"
<aside>Box as="aside"
<button>Button
<code>Code
<dd>Text as="dd"
<div>Box (decorative) / Stack | Flex | Grid (layout)
<dt>Text as="dt"
<figcaption>Text as="figcaption"
<figure>Box as="figure"
<footer>Box as="footer"
<form>Form
<h1>Heading level={1}
<h2>Heading level={2}
<h3>Heading level={3}
<h4>Heading level={4}
<h5>Heading level={5}
<h6>Heading level={6}
<header>Box as="header"
<iframe>MediaFrameEmbed
<img>GalleryImage
<input>Input
<label>Label
<legend>Text as="legend"
<li>Box as="li" / Text as="li"
<main>Container as="main" / Box as="main"
<nav>Box as="nav"
<ol>Stack as="ol"
<p>Text
<pre>Code block
<section>Box as="section" / Section
<select>Select
<span>Box as="span" (decorative) / Text as="span" (textual)
<svg>Icon
<textarea>Textarea
<ul>Stack as="ul"

Icons

Raw glyphs take whatever size and stroke the author types. Icon takes a size token and renders at a fixed stroke of 1.5.

Raw Lucide

Size and stroke set at each call site.

<ArrowRight className="size-6 stroke-2" />

Icon

One size token in, 18px with stroke 1.5 out.

<Icon icon={ArrowRight} size="sm" />

The one escape hatch

Primitives still take className, so one-off layout is never blocked. The tokens-only gate rejects raw hex, colour functions and arbitrary values in class strings, so even a bespoke tweak is written in the design language. The rules behind both are on the principles page.