Foundations

Radius, borders & shadows.

Quiet structure. Clear depth.

Contextual corners, semantic edges and restrained depth connect the controls to the surfaces around them.

The middle ground

Use compact controls, gently rounded panels, clear 1px edges, and restrained depth. The default control remains 10px; cards use 12px and overlays 16px. This is Dixy’s web interpretation of the references below, not a copy of any platform’s pixel or dp values.

ReferencePrincipleDixy decision
Radix Themes ↗Contextual radius settings let controls become pills while content panels keep usable geometry.Keep a Theme preset and map it to separate control, card and overlay roles.
Radix shadows ↗A six-step shadow scale distinguishes inset, content panels, small overlays and large overlays.Use five named roles including none, with two restrained layers for elevated surfaces.
Material 3 shape ↗The current ten-style scale ranges from square through fully rounded. It also describes optical roundness for nested shapes.Use a smaller everyday web scale, keeping 10px controls and 12/16px panel defaults rather than adopting the full expressive range.
Material elevation ↗Six elevation levels make depth an intentional hierarchy rather than arbitrary decoration.Use semantic depth roles; do not imply that box-shadow sets z-index.
Apple materials ↗Material and depth distinguish functional layers from content while protecting legibility.Keep opaque content surfaces and visible borders; glass and blur are not prerequisites for depth.
Apple concentric corners ↗Related nested corners share a center; the inner radius accounts for the distance from its container.Use outer radius minus inset, clamp at zero, and account for the outer border.

Radix’s small scale gives us practical restraint; Material’s roles give depth a purpose; Apple’s nested geometry keeps corners coherent. The flat/default case stays quiet. Border colors continue to come from the existing semantic color foundation.

Try a surface and its overlay

A place for the details

Borders define the edge. Corners give it character. Shadows explain depth.

No changes saved.

surface-example.tsx
import "@dixy-ui/react/styles.css";
import { Theme } from "@dixy-ui/react";
import { useState, type CSSProperties } from "react";
import {
  Button,
  Dialog,
  Field,
  Heading,
  Inline,
  Stack,
  Text,
  TextField,
  Theme as SurfaceScope,
} from "@dixy-ui/react";
import {

The selected shadow and border apply to the example card. Inspect overlay opens a real Base UI dialog: it always uses the overlay radius and shadow roles. Nested Theme settings and inline token overrides are preserved through its portal. Reset also restores the input and action feedback.

Radius: values and relationships

radius.00px · 0rem
radius.22px · 0.125rem
radius.44px · 0.25rem
radius.66px · 0.375rem
radius.88px · 0.5rem
radius.1010px · 0.625rem
radius.1212px · 0.75rem
radius.1616px · 1rem
radius.2424px · 1.5rem
radius.fullCapsule
Theme preset → primitive at a 16px root
PresetControlCardOverlay
none0px0px0px
sm4px8px12px
md10px12px16px
lg16px16px24px
fullfull16px24px

Numeric primitive values remain fixed across theme presets, appearances and density. The full primitive is a large CSS radius sentinel; browsers clamp it to the element’s dimensions. The full Theme preset only rounds controls fully. Panels cap at 16px and overlays at 24px to avoid elliptical text containers. None makes every role square, including Dialog.

Nested corners share a center

24px outer8px padding + 1px border → 15px inner
nested-corners.css
.outer {
  border: var(--dixy-border-default);
  border-radius: var(--dixy-radius-24);
  padding: var(--dixy-space-100);
}
.inner {
  border-radius: max(0px, calc(var(--dixy-radius-24) - var(--dixy-space-100) - var(--dixy-border-width-1)));
}

This derived 15px inner radius is a geometric relationship, not another primitive. Compare border-box edges: padding alone omits the outer border’s width. Clamp negative results to zero. Density can change padding, so recompute related inner corners from the actual inset rather than freezing an optical correction.

Borders: quiet structure, explicit state

border.width.00px
border.width.11px
border.width.22px
RoleWidthStyleExisting color role
subtle1pxsolidborder.subtle
default1pxsolidborder.default
strong2pxsolidborder.strong
danger1pxsolidborder.danger
Dashed: a deliberate placeholder boundary.

Use 1px for ordinary edges and dividers, 2px for strong emphasis, and zero only when the surrounding context supplies a clear boundary. Solid is the default; dashed is available for deliberate placeholders. Danger communicates an actual error and needs accompanying text. The spinner’s 1.5px stroke remains an optical exception, separate from container borders.

Focus is an independent accessibility contract: a 2px outline with a 3px offset. Decorative border or shadow choices never remove it. Border and focus widths use CSS pixels, preserving crisp edges when text size changes. A border alone does not establish sufficient contrast; keep the semantic color and interaction context aligned.

Shadows: a small depth vocabulary

noneFlat content
insetRecessed region
raisedResting card
floatingSmall floating panel
overlayModal layer
light-shadow.css
/* none */
--dixy-shadow-none: none;

/* inset */
--dixy-shadow-inset: inset 0px 1px 2px 0px rgb(0 0 0 / 0.06);

/* raised */
--dixy-shadow-raised: 0px 1px 2px 0px rgb(0 0 0 / 0.06), 0px 2px 6px -1px rgb(0 0 0 / 0.08);

/* floating */
--dixy-shadow-floating: 0px 4px 8px -2px rgb(0 0 0 / 0.08), 0px 12px 24px -4px rgb(0 0 0 / 0.12);

/* overlay */
--dixy-shadow-overlay: 0px 8px 16px -4px rgb(0 0 0 / 0.12), 0px 24px 48px -8px rgb(0 0 0 / 0.18);

Shadow geometry is shared between light and dark appearances; dark mode increases the neutral occlusion opacity. Borders and surface colors still carry separation when shadows are difficult to see. Shadows do not establish DOM stacking order, modality, or keyboard behavior. Forced colors maps all shadow tokens to none; keep a visible border and focus outline. No radius, border, or shadow animation is added.

Framework-independent usage

surface.css
@import "@dixy-ui/tokens/color.css";
@import "@dixy-ui/tokens/radius.css";
@import "@dixy-ui/tokens/border.css";
@import "@dixy-ui/tokens/shadow.css";

.panel {
  border: var(--dixy-border-default);
  border-radius: var(--dixy-radius-card);
  box-shadow: var(--dixy-shadow-raised);
}
surface-tokens.ts
import { radius, surfaceRadius, borderWidth, border, shadow } from "@dixy-ui/tokens";

radius("12"); // var(--dixy-radius-12), fixed primitive
surfaceRadius("card"); // contextual Theme role
borderWidth("1"); // 1 CSS px
border("default"); // width + style + semantic color
shadow("floating"); // appearance-aware CSS reference

Component integration and migration

Button and TextField use control radius aliases; Dialog uses the overlay alias. Components consume generated border widths, and Dialog uses the overlay shadow. Existing --dixy-radius and --dixy-shadow overrides remain supported for controls and Dialog shadow, respectively. For panel geometry, override --dixy-card-radius or --dixy-dialog-radius explicitly. Put overrides on Theme’s style when they must cross a portal.

The default Dialog corner is now 16px instead of the previous computed 18px; Theme radius="none" now produces a square Dialog instead of leaving an 8px corner. Existing sm/md/lg control radii stay 4/10/16px. Appearance, focus, refs, events and Base UI composition retain their contracts. Live previews and scale tables are generated from local definitions; the reference systems inform our decisions rather than becoming dependencies.