Skip to content

Shape

One base radius drives every corner in the system. Change a single variable and the whole interface re-proportions, from sharp and technical to soft and friendly.

prfct's corners come from a single variable, --radius (8px by default). Every step of the radius scale is that value times a fixed factor, from 0.25 for xs to 4 for 4xl, so a change to the base keeps every relationship intact — including 0 for a fully sharp system.

2px

Focus-ring insets, tiny indicators

4px

Keyboard keys, chip controls, inline focus rings

6px

Badges, tooltips, extra-small buttons, tab pills

8px

Buttons, inputs, selects, menu items

12px

Cards, popovers, menus

16px

Dialogs, floating sheets, the command palette

24px

Marketing tiles

32px

Hero media

:root {
  --radius: 0.5rem; /* try 0, 0.25rem or 0.75rem */
}

Concentric corners

When one rounded shape sits inside another, the inner radius should equal the outer radius minus the padding between them. Equal radii make the inner shape look like it's bulging; concentric radii look machined.

12px
✓ inner = outer − padding
24px
✕ same radius inside and out
function Nested({
  outer,
  inner,
  label,
  good,
}: {
  outer: number
  inner: number
  label: string
  good: boolean
}) {
  return (
    <figure className="flex flex-col items-center gap-3">
      <div
        className="border-2 border-foreground/80 bg-surface p-3"
        style={{ borderRadius: outer }}
      >
        <div
          className="flex size-24 items-center justify-center bg-brand-4 font-mono text-xs text-brand-12"
          style={{ borderRadius: inner }}
        >
          {inner}px
        </div>
      </div>
      <figcaption className="text-center text-xs text-muted-foreground">
        <span className={good ? "text-success-11" : "text-danger-11"}>
          {good ? "✓" : "✕"}
        </span>{" "}
        {label}
      </figcaption>
    </figure>
  )
}

export default function ConcentricRadius() {
  return (
    <div className="flex flex-wrap items-start justify-center gap-10">
      <Nested outer={24} inner={12} label="inner = outer − padding" good />
      <Nested
        outer={24}
        inner={24}
        label="same radius inside and out"
        good={false}
      />
    </div>
  )
}

prfct's components are already concentric: a 12px menu with 4px padding holds 8px items. When the padding is larger than the outer radius — a 16px dialog with 24px padding — the inner shapes are too far away to compete, and keep their own radius.

Choosing a radius

ElementStep
Checkboxes, kbdsm
Badges, extra-small buttons, tooltipsmd
Buttons, inputs, selects, menu itemslg
Cards, popovers, menusxl
Dialogs, floating sheets2xl
People (avatars)full
Organizations and appsrounded-[25%] via Avatar shape="square"
Draft
DoRadius grows with the size of the surface.
Draft
Don’tPills everywhere flatten hierarchy and waste horizontal space.