Borders & radii

Edges and corners are presets in the theme, static or stepping at breakpoints; a component names the preset.

Shared engine playground

Actual viewport: 0px. Resize the browser to test transitions. The preview uses the active theme and shared engine defaults. Edits below are scoped to this demo and do not save source JSON.

Border presets

Border 0
border: border(0);
none
Border 1
border: border(1);
1px solid var(--uxdsl__color__gray-300)
Border 2
border: border(2);
var(--uxdsl__space__1) solid var(--uxdsl__color__gray-300)
Border 3
border: border(3);
var(--uxdsl__space__2) solid var(--uxdsl__color__gray-400)
Border 4
border: border(4);
var(--uxdsl__space__3) solid var(--uxdsl__color__gray-500)
Border 5
border: border(5);
var(--uxdsl__space__4) solid var(--uxdsl__color__gray-600)

Radius presets

Radius 0
border-radius: radius(0);
0
Radius 1
border-radius: radius(1);
var(--uxdsl__space__1)
Radius 2
border-radius: radius(2);
var(--uxdsl__space__2)
Radius 3
border-radius: radius(3);
var(--uxdsl__space__3)
Radius 4
border-radius: radius(4);
var(--uxdsl__space__4)
Radius 5
border-radius: radius(5);
var(--uxdsl__space__6)

Built-in shapes

pill
radius(pill) → 9999px
circle
radius(circle) → 50%

Theme uxdsl.theme.json, merged over the base theme

{
  "borders": {
    "1": "xs(1px solid palette(divider.main)) md(2px solid palette(divider.main))"
  },
  "radii": {
    "2": "xs(space(2)) md(space(3))"
  }
}

UXDSL you write example.uxdsl

.card {
  border: border(1);
  border-radius: radius(2);
}
.chip { border-radius: radius(pill); }
.avatar { border-radius: radius(circle); }

CSS you get compiled by uxdsl; :root shows only these tokens

:root {
  --uxdsl__border__1: 1px solid var(--uxdsl__palette__divider-main);
  --uxdsl__radius__2: var(--uxdsl__space__2);
}
@media (min-width: 768px) {
  :root {
    --uxdsl__border__1: 2px solid var(--uxdsl__palette__divider-main);
    --uxdsl__radius__2: var(--uxdsl__space__3);
  }
}
.card {
  border: var(--uxdsl__border__1);
  border-radius: var(--uxdsl__radius__2);
}
.chip { border-radius: 9999px; }
.avatar { border-radius: 50%; }

Rules

  • border(k) is a whole edge — width, style and color — and radius(k) a corner. Either preset can be static or a responsive expression; the component names it once.
  • border() takes the key only: border(1, red, dashed) is UXD_EDGE_ARGUMENT. For one component, write border: border(1) and then the longhand you change (border-style: dashed); it persists across the preset’s breakpoints.
  • radius(pill) is 9999px and radius(circle) is 50% (a circle needs equal width and height). They are built in, not presets; radius(full) and rounded() are UXD_SYNTAX_REMOVED.
  • Every numbered family has an explicit zero: border(0) is none, radius(0) a square corner. An unknown key is UXD_EDGE_REFERENCE, listing the keys that exist.
  • A preset can reference the theme: "1px solid palette(divider.main)" follows the palette and dark mode; "xs(space(2)) md(space(3))" follows the spacing scale. A border radius does not clip children; add overflow when it must.
.card--selected {
  border: border(1);
  border-style: dashed;
  border-color: palette(primary.main);
}
.tag { border-radius: radius(full); }  /* UXD_SYNTAX_REMOVED: write radius(pill) */

The guides for coding agents are on For AI agents.