apx-dsv0.1Local renderer · live
K
Foundations4
  • Getting started
  • Theming
  • Templates
  • Icons
  • Avatar
  • Badge
  • DataGrid
  • Scheduler
  • Stat
  • Table
  • Timeline
  • TreeView
  • Accordion
  • Alert
  • EmptyState
  • Progress
  • Skeleton
  • Spinner
  • SplashScreen
  • Toast
  • ColorPicker
  • FileUpload
  • Form
  • Rating
  • TagsInput
  • Combobox
  • Field
  • Select
  • Toggle
  • Button
  • Calendar
  • Checkbox
  • DatePicker
  • Input
  • NumberInput
  • Radio
  • Slider
  • Switch
  • Textarea
  • AppShell
  • Div
  • Divider
  • Marquee
  • Parallax
  • Reveal
  • Section
  • SectionHeading
  • Sidebar
  • Stack
  • Surface
  • Typography
  • Image
  • Breadcrumbs
  • Carousel
  • NavigationMenu
  • Pagination
  • Stepper
  • Tabs
  • Toolbar
  • CommandPalette
  • Confirm
  • Drawer
  • HoverCard
  • Menu
  • Modal
  • Popover
  • Tooltip
  • Icon
  • Card
  • PricingCard
66 componentsapx-ds/renderer
Div
Variant↳ other

Layout

Div

Styling primitive (

Div

<Div /> is the DS's canonical styling primitive — the equivalent of MUI's Box or Chakra's Box. A single <div> (or any other element via actLike / as / asChild) with a flat, token-aware CSS shorthand prop surface plus responsive show/hide, opt-in motion presets, a centered shortcut, full HTML pass-through, and pseudo-state className hooks.

Reach for <Div> whenever you'd otherwise write <div className="flex items-center p-4 bg-bg-paper">…</div> — it reads better and resolves theme tokens (primary.main, md, …) into CSS variables for free.

Anatomy

tsx
import { Div } from 'apx-ds';

<Div p={4} bg="primary.50" fg="primary.contrast" radius="md">
  A token-aware box.
</Div>

<Div display="flex" gap={12} alignItems="center">
  <Div flex={1}>Left</Div>
  <Div flex={2}>Right</Div>
</Div>

<Div hideOn="md">Mobile-only content</Div>
<Div displayOn="lg">Desktop-only content</Div>

<Div centered h={200}>
  <Spinner />
</Div>

<Div actLike="button" type="button" onClick={open} onHover="bg-primary-100" onFocusVisible="ring-2 ring-primary-500">
  Click me
</Div>

<Div animation="fadeIn">Fades in on mount</Div>
import { Div } from 'apx-ds';

<Div p={4} bg="primary.50" fg="primary.contrast" radius="md">
  A token-aware box.
</Div>

<Div display="flex" gap={12} alignItems="center">
  <Div flex={1}>Left</Div>
  <Div flex={2}>Right</Div>
</Div>

<Div hideOn="md">Mobile-only content</Div>
<Div displayOn="lg">Desktop-only content</Div>

<Div centered h={200}>
  <Spinner />
</Div>

<Div actLike="button" type="button" onClick={open} onHover="bg-primary-100" onFocusVisible="ring-2 ring-primary-500">
  Click me
</Div>

<Div animation="fadeIn">Fades in on mount</Div>

Prop surface

Styling shorthand

Every value flows through the engine's sxToStyle resolver — palette / radius / shadow / spacing token strings (e.g. bg="primary.main", radius="md") become var(--sds-…), plain CSS values pass through untouched. Scalars only in v1 (no { base, sm, md } shape on these props — use hideOn / displayOn / className for responsive layout).

GroupProps
Aliasesm mt mr mb ml mx my p pt pr pb pl px py w h radius shadow z bg fg
Layoutdisplay position top right bottom left inset zIndex overflow overflowX overflowY visibility
Flex / Gridflex flexDirection flexWrap flexBasis flexGrow flexShrink alignItems alignContent alignSelf justifyContent justifyItems justifySelf gap rowGap columnGap order + grid*
Sizingwidth height minWidth maxWidth minHeight maxHeight boxSizing aspectRatio
Spacingmargin padding + every directional variant including the logical marginInline / paddingBlock family
Color / bgcolor backgroundColor background backgroundImage
Borderborder borderRadius borderWidth borderStyle borderColor borderTop borderRight borderBottom borderLeft
TypographyfontSize fontWeight fontFamily lineHeight letterSpacing textAlign textTransform textDecoration whiteSpace textOverflow wordBreak
EffectsboxShadow opacity cursor transition transform pointerEvents userSelect filter backdropFilter

Responsive show / hide

PropTypeBehavior
hideOn'sm' | 'md' | 'lg' | 'xl' | '2xl'Adds ${bp}:hidden — hides from that breakpoint upward.
displayOn'sm' | 'md' | 'lg' | 'xl' | '2xl'Adds hidden ${bp}:block — start hidden, reveal at that breakpoint.

Both use Tailwind's mobile-first "from breakpoint upward" semantics, so each emits a single utility class that the JIT scanner picks up at build time.

Animation

PropTypeBehavior
animation'fadeIn' | 'scaleIn' | 'slideInFromBottom' | 'slideInFromTop' | 'slideInFromLeft' | 'slideInFromRight' | 'riseIn' | 'blurIn' | 'zoomIn'Wraps the element via motion.create(...) and applies the matching engine preset. useReducedMotion() short-circuits to a plain element.
animateOnViewboolean | { once?, amount?, margin? }Defer the animation until the element scrolls into view. true uses the DS defaults (once: true, amount: 0.25, -64px bottom margin).
animationDelaynumberSeconds before this element starts.
animationDurationnumber | 'fast' | 'normal' | 'slow'Token names resolve through @apx-ui/tokens, so a theme motion change reaches here.
animationEase'standard' | 'emphasized' | 'decelerate' | 'accelerate' | 'linear' | stringToken name or any raw CSS easing string.
staggernumberCascade descendant animated <Div>s, this many seconds apart. Children opt in just by having an animation.
staggerDelaynumberSeconds before the first staggered child starts. Requires stagger.

The pressScale preset is not exposed here — it's a whileTap interaction that belongs on a trigger element (<Button>) instead.

Scroll reveal

Without animateOnView the animation runs on mount — so everything below the fold finishes animating before the user ever scrolls to it, and a long page reads as static. animateOnView moves the trigger to the viewport:

tsx
<Div animation="riseIn" animateOnView>
  Reveals as it enters
</Div>

<Div animation="fadeIn" animateOnView={{ once: false, amount: 0.5 }}>
  Re-reveals every time, once half-visible
</Div>
<Div animation="riseIn" animateOnView>
  Reveals as it enters
</Div>

<Div animation="fadeIn" animateOnView={{ once: false, amount: 0.5 }}>
  Re-reveals every time, once half-visible
</Div>

Stagger

A stagger parent cascades its animated descendants. The children need no extra props — having an animation is the opt-in:

tsx
<Div stagger={0.08} staggerDelay={0.1} animateOnView>
  {features.map((f) => (
    <Div key={f.id} animation="riseIn">
      <FeatureCard {...f} />
    </Div>
  ))}
</Div>
<Div stagger={0.08} staggerDelay={0.1} animateOnView>
  {features.map((f) => (
    <Div key={f.id} animation="riseIn">
      <FeatureCard {...f} />
    </Div>
  ))}
</Div>

This works through ordinary wrapper markup — the cascade travels by React context, not by DOM adjacency, so grid wrappers and layout <div>s in between don't break it. Groups also nest: an inner stagger both inherits its start from the outer group and sequences its own children.

The mechanism matters if you write custom children: a stagger participant declares Motion variants and deliberately omits initial / animate, because an explicit animate prop outranks the inherited variant label and would silently detach the child from the parent's timeline — making stagger look like it does nothing.

Reduced motion

Every path above is gated on useReducedMotion(). When it's on, <Div> renders a plain element with no motion props at all — which is the only safe answer for a scroll reveal, since a viewport trigger that never fires would otherwise leave content pinned at opacity: 0. A stagger parent also stops publishing its orchestration context, so its children fall back to plain elements too.

Shortcuts

PropBehavior
centeredInjects display: flex; align-items: center; justify-content: center; at the lowest style priority, so any explicit value wins.
decorativeInjects position: absolute; inset: 0; pointer-events: none; and adds aria-hidden="true" so screen readers skip the purely visual layer. Pair with gradient for the soft-backdrop pattern, or use it standalone with a custom backgroundImage / className.
gradientResolves to a background-image value. Accepts true (default theme-aware radial primary.subtle → transparent), a DivGradientConfig (type, from, to, position, size, fromStop, toStop), or a raw CSS string (radial-gradient(...), linear-gradient(...), url(...)). Palette token paths in from / to resolve to var(--sds-palette-…) so the gradient tracks the active theme variant.
tsx
// the verbose className recipe…
<Div className="absolute inset-0 pointer-events-none bg-[radial-gradient(80%_80%_at_0%_50%,var(--sds-palette-primary-subtle)_0%,transparent_70%)]" aria-hidden />

// …becomes a single composed shortcut.
<Div decorative gradient={{ position: 'left' }} />
// the verbose className recipe…
<Div className="absolute inset-0 pointer-events-none bg-[radial-gradient(80%_80%_at_0%_50%,var(--sds-palette-primary-subtle)_0%,transparent_70%)]" aria-hidden />

// …becomes a single composed shortcut.
<Div decorative gradient={{ position: 'left' }} />

Polymorphism

PropBehavior
asSwap the rendered element (<Div as="section">).
actLikeAlias of as — provided for the requested ergonomic reading <Div actLike="button">. Wins over as when both are set (dev warning).
asChildRadix-style — merges Div's props onto the single child element. Mutually exclusive with as / actLike; asChild wins (dev warning). Animation is skipped here.

Pseudo-state className hooks

Each prop accepts a Tailwind className string. Every whitespace-separated token is automatically prefixed with the corresponding state variant via the engine's prefixClasses helper.

PropPrefixNotes
onHoverhover:Mouse / pen hover.
onFocusVisiblefocus-visible:Use this for focus rings — keyboard-focus-only is the a11y default.
onActiveactive:Pressed (mouse-down / Enter).
onDisableddisabled:Disabled form control.
onCheckedaria-checked:Triggered by aria-checked="true".
onGroupHovergroup-hover:Pair with a parent that has the group class.
onDataStatedata-[state=open]:Radix-style state hook.

onFocus is intentionally absent because it would collide with React's native focus event handler. Use onFocusVisible (the a11y-correct choice for focus rings) or compose focus:* classes via the standard className prop.

HTML pass-through

id, role, aria-*, data-*, every event handler, plus the common element-specific attributes (href, type, target, rel, download, src, alt, name, value, htmlFor, disabled, checked) flow to the rendered element untouched. Use actLike to swap the element type and the matching attributes "just work":

tsx
<Div actLike="a" href="/docs" target="_blank" rel="noreferrer">Open docs</Div>
<Div actLike="button" type="submit" disabled={isSubmitting}>Save</Div>
<Div actLike="a" href="/docs" target="_blank" rel="noreferrer">Open docs</Div>
<Div actLike="button" type="submit" disabled={isSubmitting}>Save</Div>

Style resolution order

Lowest → highest priority:

  1. centered defaults (display: flex; align-items: center; justify-content: center;)
  2. decorative defaults (position: absolute; inset: 0; pointer-events: none;)
  3. gradient (background-image: …)
  4. sx (theme-aware object)
  5. Curated style shorthand props (p={4}, bg="primary.50", display="grid", …)
  6. Consumer style prop (escape hatch)

Classes layer the same way:

  1. Recipe (hideOn / displayOn)
  2. theme.components.Div.styleOverrides.root (theme override)
  3. Consumer className
  4. Pseudo-state hooks (hover: / focus-visible: / …)

tailwind-merge handles utility-class conflict resolution (last wins).

Examples

Basic — token-aware padding + bg + radius

Loading preview…
Basic.tsx

Flex — display='flex' + flex={n} on children

Loading preview…
Flex.tsx

Centered — the centered shortcut

Loading preview…
Centered.tsx

HideOn — hide from breakpoint upward

Loading preview…
HideOn.tsx

DisplayOn — reveal from breakpoint upward

Loading preview…
DisplayOn.tsx

Animation — opt-in motion presets

Loading preview…
Animation.tsx

ScrollReveal — animateOnView + stagger

Loading preview…
ScrollReveal.tsx

Gradient — theme-aware backdrop via the `decorative` + `gradient` shortcuts

Loading preview…
Gradient.tsx

ActLike button — real <button> with onClick + pseudo hooks

Loading preview…
ActLikeButton.tsx

ActLike anchor — real <a> with href

Loading preview…
ActLikeAnchor.tsx

OnHover — hover-state Tailwind classes

Loading preview…
OnHover.tsx

OnFocusVisible — keyboard-only focus ring

Loading preview…
OnFocus.tsx

TokenStyles — palette tokens across colors

Loading preview…
TokenStyles.tsx

Accessibility

  • <Div> is a layout primitive — no implicit role, no implicit ARIA, no focus management of its own.
  • When you swap the element with actLike (e.g. actLike="button"), the rendered intrinsic element carries its own semantics. Pair with type="button" and let the native element handle keyboard activation; no extra role is needed.
  • hideOn / displayOn use display: none, which removes the node from the accessibility tree at the matching breakpoint — that's almost always what you want for purely decorative or duplicate content. For content you want to keep announced but hide visually, prefer a Tailwind utility like sr-only via className.

RTL

  • No RTL-specific code. The aliases mx / my / px / py map to logical properties (marginInline, paddingBlock, …) so they flip automatically under dir="rtl".
  • Pseudo-state classes (hover:, focus-visible:, …) are direction-agnostic.

Theming

  • <Div> reads from theme.components.Div.styleOverrides.root and theme.components.Div.defaultProps via the standard useThemedClasses hook.
  • Consumer className always wins via tailwind-merge.

Bundle

  • Static cost: a single forwardRef component + two small pure helpers (extractStyleProps, buildPseudoClassName) + the existing engine sxToStyle / cv / prefixClasses / motionPresets.
  • Motion runtime is only pulled in when animation is set on at least one render — and even then useReducedMotion() short-circuits to a plain element.

Do / Don't

  • Do reach for <Div> instead of <div className="…"> when you'd otherwise inline more than one or two Tailwind utilities.
  • Do use <Div centered> for the centered-spinner / centered-empty-state pattern.
  • Do prefer <Div actLike="button"> over <Div role="button" tabIndex={0}> — the real element gets you keyboard activation + focus for free.
  • Don't use <Div> as a substitute for a real DS component when one exists (<Button>, <Card>, <Stack>, <Field>, …). Those carry richer semantics, recipes, and a11y.
  • Don't pass responsive objects to the inline-style shorthand props — they expect scalars in v1. For responsive layout, reach for hideOn / displayOn / className.
  • Don't combine as / actLike with asChild — pick one. A dev warning fires in development if both are set.

Props

PropTypeDefaultDescription
actLikeElementType—Alias of `as`. Provided because the requested API uses `actLike="button"` reading. When both `as` and `actLike` are set, `actLike` wins and a dev warning fires.
alignContentAlignContent——
alignItemsAlignItems——
alignSelfAlignSelf——
altstring—Media `alt`.
animateOnViewboolean | ViewportOptions—Defer `animation` until the element scrolls into view, instead of running it on mount. Without this, every animated element on a page finishes its entrance before the user has scrolled to it — so a long marketing page animates entirely off-screen and reads as static. Pass `true` for the DS defaults (`once: true`, `amount: 0.25`, and a `-64px` bottom margin so the reveal starts just before the element reaches the fold), or an object to tune them. Ignored when `animation` is absent, when `asChild` is set, and under reduced motion — where the element renders plain and fully visible rather than waiting for a trigger it will never receive. @example <Div animation="riseIn" animateOnView /> <Div animation="fadeIn" animateOnView={{ once: false, amount: 0.5 }} />
animationenum—Animation preset (`fadeIn`, `scaleIn`, `slideInFromBottom`, `slideInFromTop`, `pressScale`). When set, the element renders through `motion.create(...)` with the matching variant. `useReducedMotion()` short-circuits the wrapper so reduced-motion users get a plain element. Skipped when `asChild` is true.
animationDelaynumber—Seconds to wait before the animation starts. Composes with `stagger` on an ancestor.
animationDurationnumber | "normal" | "fast" | "slow" | "slower" | "deliberate"—Animation length — seconds, or a motion token name (`'fast'` · `'normal'` · `'slow'`). Token names resolve through `@apx-ui/tokens`, so a theme-level motion change reaches here.
animationEasestring—Easing — a token name (`'standard'` · `'emphasized'` · `'decelerate'` · `'accelerate'` · `'linear'`) or any raw CSS easing string.
asElementType—Render element. Defaults to `'div'`.
asChildboolean—Radix-style polymorphism — merges Div's props onto the single child element. Mutually exclusive with `as` / `actLike`; `asChild` wins on conflict (dev warning fires).
aspectRatioAspectRatio——
backdropFilterBackdropFilter——
backgroundBackground<string | number>——
backgroundColorstring | (string & {})——
backgroundImageBackgroundImage——
bgstring | (string & {})——
borderBorder<string | number>——
borderBottomBorderBottom<string | number>——
borderColorstring | (string & {})——
borderLeftBorderLeft<string | number>——
borderRadiusBorderRadius<string | number>——
borderRightBorderRight<string | number>——
borderStyleBorderStyle——
borderTopBorderTop<string | number>——
borderWidthBorderWidth<string | number>——
bottomBottom<string | number>——
boxShadowstring | (string & {})——
boxSizingenum——
centeredboolean—Shortcut for `display: flex; align-items: center; justify-content: center;`. Explicit style props win — if any of the three keys is also supplied, the consumer value is kept.
checkedboolean—Form control `checked`.
childrenReactNode—Children to render inside the element (or the single child when `asChild` is true).
classNamestring—Standard className. Appended after the recipe + pseudo classes via `tailwind-merge`.
colorstring | (string & {})——
columnGapColumnGap<string | number>——
cursorCursor——
decorativeboolean—Shortcut for the "decorative overlay" pattern — fills the parent (`position: absolute; inset: 0;`), declines pointer events, and adds `aria-hidden="true"` so screen readers skip the purely visual layer. Compose with `gradient` for the soft backdrop pattern, or use it standalone with a custom `backgroundImage` / `className`.
disabledboolean—Form control `disabled`.
displayDisplay——
displayOnenum—Start hidden, reveal the element at the named breakpoint and above.
downloadstring | boolean—Anchor `download`.
fgstring | (string & {})——
filterFilter——
flexFlex<string | number>——
flexBasisFlexBasis<string | number>——
flexDirectionenum——
flexGrowFlexGrow——
flexShrinkFlexShrink——
flexWrapenum——
fontFamilyFontFamily——
fontSizeFontSize<string | number>——
fontWeightFontWeight——
gapGap<string | number>——
gradientDivGradient—Theme-aware background gradient — replaces the verbose `className="bg-[radial-gradient(...)]"` recipe with a single typed prop. - `true` → emit a default radial gradient using the active palette (`primary.subtle` → `transparent`, anchored top-left). Tracks the active theme variant for free. - `DivGradientConfig` object → tweak the gradient (`type`, `from`, `to`, `position`, `size`, `fromStop`, `toStop`). `from` / `to` accept palette token paths (`'success.subtle'`) or any raw CSS color. - `string` → escape hatch — used verbatim as `background-image` (drop in any `radial-gradient(...)` / `linear-gradient(...)` / `url(...)`). Sits in the inline style stack just **above** `sx` and just **below** the curated style props, so explicit `backgroundImage` / `background` overrides still win. Often paired with `decorative` for the "soft backdrop" pattern: <Div decorative gradient /> // theme default <Div decorative gradient={{ position: 'top' }} /> // override one field
gridAreaGridArea——
gridAutoColumnsGridAutoColumns<string | number>——
gridAutoFlowGridAutoFlow——
gridAutoRowsGridAutoRows<string | number>——
gridColumnGridColumn——
gridRowGridRow——
gridTemplateColumnsGridTemplateColumns<string | number>——
gridTemplateRowsGridTemplateRows<string | number>——
hHeight<string | number>——
heightHeight<string | number>——
hideOnenum—Hide the element at the named breakpoint and above (Tailwind "from upward" semantics).
hrefstring—Anchor `href` — narrow when using `as="a"` / `actLike="a"`.
htmlForstring—Label `htmlFor`.
insetInset<string | number>——
justifyContentJustifyContent——
justifyItemsJustifyItems——
justifySelfJustifySelf——
leftLeft<string | number>——
letterSpacingLetterSpacing<string | number>——
lineHeightLineHeight<string | number>——
mMargin<string | number>——
marginMargin<string | number>——
marginBlockMarginBlock<string | number>——
marginBottomMarginBottom<string | number>——
marginInlineMarginInline<string | number>——
marginLeftMarginLeft<string | number>——
marginRightMarginRight<string | number>——
marginTopMarginTop<string | number>——
maxHeightMaxHeight<string | number>——
maxWidthMaxWidth<string | number>——
mbMarginBottom<string | number>——
minHeightMinHeight<string | number>——
minWidthMinWidth<string | number>——
mlMarginLeft<string | number>——
mrMarginRight<string | number>——
mtMarginTop<string | number>——
mxMarginInline<string | number>——
myMarginBlock<string | number>——
namestring—Form field `name`.
onActivestring—Tailwind classes applied on `:active` (pressed). e.g. `"scale-[0.98]"`.
onCheckedstring—Tailwind classes applied when `aria-checked="true"`.
onDataStatestring—Tailwind classes applied when `data-state="open"` is present.
onDisabledstring—Tailwind classes applied on `:disabled`. e.g. `"opacity-50 cursor-not-allowed"`.
onFocusVisiblestring—Tailwind classes applied on `:focus-visible` (keyboard focus). e.g. `"ring-2 ring-primary-500"`.
onGroupHoverstring—Tailwind classes applied when a parent `.group` is hovered.
onHoverstring—Tailwind classes applied on `:hover`. e.g. `"bg-primary-100 scale-[1.02]"`.
opacityOpacity——
orderOrder——
overflowOverflow——
overflowXenum——
overflowYenum——
pPadding<string | number>——
paddingPadding<string | number>——
paddingBlockPaddingBlock<string | number>——
paddingBottomPaddingBottom<string | number>——
paddingInlinePaddingInline<string | number>——
paddingLeftPaddingLeft<string | number>——
paddingRightPaddingRight<string | number>——
paddingTopPaddingTop<string | number>——
pbPaddingBottom<string | number>——
plPaddingLeft<string | number>——
placeContentPlaceContent——
placeItemsPlaceItems——
placeSelfPlaceSelf——
pointerEventsenum——
positionenum——
prPaddingRight<string | number>——
ptPaddingTop<string | number>——
pxPaddingInline<string | number>——
pyPaddingBlock<string | number>——
radiusBorderRadius<string | number>——
refRef<HTMLElement>—Ref to the rendered element. Type depends on `as` / `actLike` / `asChild`. Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see {@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
relstring—Anchor `rel`.
rightRight<string | number>——
rowGapRowGap<string | number>——
shadowstring | (string & {})——
srcstring—Media `src`.
staggernumber—Cascade descendant `<Div animation="…">` elements instead of firing them together: the number of seconds between each one starting. The children need no extra props — they opt in simply by having an `animation`. Combine with `animateOnView` on this element to make the whole group reveal on scroll as one unit, which is the common case for a card grid or a feature list. @example <Div stagger={0.08} animateOnView> {items.map((i) => <Div key={i.id} animation="riseIn">…</Div>)} </Div>
staggerDelaynumber—Seconds to wait before the first staggered child starts. Requires `stagger`.
styleCSSProperties—Inline style override. Wins over `sx`, curated style props, and the `centered` shortcut.
sxSx—Theme-aware inline style (resolves palette / spacing / radius tokens).
targetstring—Anchor `target`.
textAlignenum——
textDecorationTextDecoration<string | number>——
textOverflowTextOverflow——
textTransformTextTransform——
topTop<string | number>——
transformTransform——
transitionTransition<string & {}>——
typestring—Button `type` — narrow when using `as="button"` / `actLike="button"`.
userSelectenum——
valuestring | number | readonly string[]—Form field `value`.
visibilityenum——
wWidth<string | number>——
whiteSpaceWhiteSpace——
widthWidth<string | number>——
wordBreakenum——
zZIndex——
zIndexZIndex——