lensclear design system

The layout primitive. Typed props compile to stylex classes at build time, tokens resolve light and dark on their own, and display defaults to flex.

Overview

Box is the one primitive for layout, spacing, color, borders, radius, shadow, flex, grid, position, and motion.

Every visual concern is a typed prop that takes a token. No class guesswork, no dark mode boilerplate. Any prop also takes an object keyed by base, a breakpoint, or a pseudo-state.

Box is flex by default for block-level elements, so a bare Box is a flex row. Set flexDirection, gap, and alignment directly. Inline elements and li keep their native display.

Layout

Flex layouts from direction, alignment, and token gaps.

Vertical stack

flexDirection column with a rowGap step.

First
Second
Third
<Box flexDirection="column" rowGap="3">
  <Tile>First</Tile>
  <Tile>Second</Tile>
  <Tile>Third</Tile>
</Box>

Centered row

The default flex row, centered, with a columnGap step.

One
Two
Three
<Box alignItems="center" columnGap="3">
  <Tile>One</Tile>
  <Tile>Two</Tile>
  <Tile>Three</Tile>
</Box>

Spacing and color

A surface is radius, background, and padding tokens composed.

Card surface

Card surface

Radius, background, and padding from tokens.

<Box
  borderRadius="lg"
  backgroundColor="card"
  padding="6"
  flexDirection="column"
  rowGap="3"
>
  <Text variant="heading-xs" as="h4">Card surface</Text>
  <Text color="muted">Radius, background, and padding from tokens.</Text>
</Box>

Polymorphism

as picks the element for semantics and accessibility. The style api stays the same.

  • List item rendered as li
  • Keeps the native list-item display
<Box as="nav" alignItems="center" columnGap="3">
  <Text as="span" variant="label">Home</Text>
  <Text as="span" variant="label" color="muted">Docs</Text>
</Box>

<Box as="ul" flexDirection="column" rowGap="2">
  <Box as="li">List item rendered as li</Box>
</Box>

Responsive and pseudo-states

Any style prop takes an object keyed by base, sm, md, lg, xl, 2xl, and the pseudo-states hover, focus, active, focusVisible, focusWithin.

Breakpoints

Resize the window. Base values compile to stylex; the breakpoints go through a scoped style tag.

Stacks below md
Rows from md
Wider gap from md
<Box
  flexDirection={{ base: "column", md: "row" }}
  gap={{ base: "2", md: "4" }}
>
  ...
</Box>

Interactive card

Pair a pseudo-state value with a transition to animate it.

Hover me

Pseudo-state props animate background, shadow, and transform.

<Box
  borderRadius="lg"
  backgroundColor={{ base: "card", hover: "secondary" }}
  boxShadow={{ base: "none", hover: "md" }}
  transform={{ hover: "translateY(-2px)" }}
  transitionProperty="common"
  transitionDuration="fast"
  ease="out"
  cursor="pointer"
  padding="6"
>
  ...
</Box>

Escape hatches

className and style exist for what the system does not model.

A canvas host, a third party class, a keyframe: those are the cases. Never a property that has a typed prop. In app code the lens lint rules block className and style on Box; extend BoxStyleProps instead.

Props

The common props. The full set is BoxStyleProps in packages/lens/src/utils/types.ts.

asEdefault: 'div'

The element. div, span, section, article, aside, main, nav, header, footer, form, fieldset, label, ul, ol, li. Dom props for the chosen element are typed and forwarded.

Flex by default for block-level elements. span, label, and li keep their native display.

Also rowGap and columnGap. The tailwind steps 0 to 24, as strings.

Plus paddingTop, paddingRight, paddingBottom, paddingLeft, paddingHorizontal, paddingVertical, and the aliases p, px, py.

Plus the per-side and axis forms and the aliases m, mx, my. Takes auto and the negative steps ('-0.5' to '-24').

Any semantic color, tint, or status fill.

Any semantic color, tint, or status ink.

Any semantic color or tint.

xs, sm, md, base, lg, xl, 2xl, 3xl, 4xl, full. Plus the per-corner props.

In px. Plus the per-side props.

none, md, 2xl, inset.

Numbers resolve to px. Also height, minWidth, maxWidth, minHeight, maxHeight.

For example '16 / 9'.

Also right, bottom, left, inset, and zIndex. Takes spacing steps (negative too), any css length, and numbers as px.

A keyword expands to a real property list.

instant, fast, base, slow, slower.

Alias for transitionTimingFunction. standard, in, out.

For example 'translateY(-2px)'.

The visual props also include cursor, pointerEvents, userSelect, visibility, and textAlign.

classNamestring

For what the system does not model, such as a canvas host. The lens lint rules block it on Box in app code.