gray
radius
Overview

A design system in three layers

Built in three layers, so a decision lives in one of them rather than in all of them. Color is settled in the tokens, behavior in the base, appearance here.

Every decision here is one of three kinds: what a value is, how a thing behaves, how it looks. One layer answers each, so changing a color does not mean opening the file that traps focus. There are four packages, because base-react is built on Radix and the behavior Radix does not cover is kept separately in behavior-react.

Values
style-tokens

Color, spacing, radius, type, shadow and motion. One source, four outputs: CSS variables, TypeScript objects, utility classes, and a Tailwind v4 theme.

Behavior
base-react

Eighteen headless components: seventeen wrapping a Radix package each, and Button, which is ours. Keyboard, focus and ARIA, and no styling at all.

behavior-react

Interaction Radix does not cover. usePress, so a link or a div styled as a button still answers the keyboard.

Appearance
components-react

Twenty-three components plus Theme. The only layer that decides what anything looks like.

Components

Compound where the parts need shared state or layout, flat where they do not. The ones marked compound expose their parts; the rest take props, because a Button.Label would be ceremony.

Installation

pnpm add @minuk-hwang-design-system/components-react

Usage

One stylesheet at the root, then a component where it is used.

// Once, at the root of the app. It imports the token stylesheet in turn.
import '@minuk-hwang-design-system/components-react/styles.css';
// Per component, and only the JavaScript is per component.
import { Button } from '@minuk-hwang-design-system/components-react/button';
export default function App() {
return <Button>Publish</Button>;
}
styles.css carries a reset, so it belongs before any stylesheet of your own. Import it from the top of one, where the order cannot be rearranged.

Theme

Theme paints the page and is where the dials live: appearance, accentColor, neutralColor, radius. Every one of them is optional, and left alone the appearance follows the operating system.

import { Theme } from '@minuk-hwang-design-system/components-react/theme';
<Theme appearance="dark" accentColor="purple" neutralColor="slate" radius="large">
<App />
</Theme>