Skip to content
Primitiv home
Framework
Consumption mode

Box

stableSource Figma

The escape hatch — a bare polymorphic element with no visual opinion. Exists so a consumer has something to attach a custom property or a one-off style to without reaching for a raw <div>.

Playground

Density

Preview

A plain box you style yourself
import { Box } from "@/components/ui/box";
<Box  style={{    padding: "var(--primitiv-space-space-16)",    border: "1px dashed var(--primitiv-border-default)",    borderRadius: "var(--primitiv-radii-8)",  }}>  A plain box you style yourself</Box>

Density is set by a data-density ancestor — the Context system, not a Box prop.

Installation

npx primitiv add box

Import

import { Box } from "@/components/ui/box";

No headless primitive — this one ships only as a copied styled surface, so primitiv add is the only way in, whichever mode you are reading.

Props

Box

Extends HTMLDivElement — every native attribute of that element is accepted and forwarded.

PropTypeDefaultDescription
asChildbooleanRender the single child element instead of a wrapping <div>, merging the box class onto it — e.g. <Box asChild><section>...</section></Box>.

Styling contract

Accessibility

  • Box renders a plain <div> with no role, label or semantics of its own — correct for a pure styling wrapper, which should be invisible to assistive tech.
  • When the wrapper should mean something, use asChild to render a real element (<section>, <nav>, <article>) rather than nesting a bare <div>: a landmark a screen-reader user can navigate to beats an anonymous box.
  • Any role or aria-* you pass forwards to the rendered element — Box adds none of its own, so it never fights or duplicates the semantics you give it.

Examples

As your own element

asChild renders the child element instead of a wrapping <div>, merging Box onto it. Reach for it when the wrapper should carry meaning — a <section>, <article> or <nav> — so you get a real landmark rather than an anonymous <div> that adds nothing to the accessibility tree.

Density
A real <section> landmark
import { Box } from "@/components/ui/box";
<Box asChild>  <section aria-label="Account summary">{/* ... */}</section></Box>

Scoping a design token

Because a design token is a CSS custom property, setting one on a Box re-points it for everything inside — the token cascades, so descendants that resolve --primitiv-space-space-16 inherit the new value here without prop-drilling. This is the canonical Box use: a subtree-scoped override with somewhere to attach it that is not a raw <div>.

Density
Padded by the token this Box re-points.
import { Box } from "@/components/ui/box";
<Box style={{ "--primitiv-space-space-16": "2.5rem" }}>  {/* Descendants resolving the token pick up the scoped value. */}  <article style={{ padding: "var(--primitiv-space-space-16)" }}>    {/* ... */}  </article></Box>