# Token reference (/docs/token-reference)





`vars` is Luke UI's typed public token contract. Each path resolves to a stable `--luke-*` CSS
variable. For example, `vars.color.background.danger.solid.hover` resolves to
`var(--luke-color-background-danger-solid-hover)`.

Use these variables when a component API or layout utility cannot express a custom element. Some
values vary by theme identity or colour mode, while others remain fixed. The token paths stay the
same across bundled and custom themes.

## Use semantic variables [#use-semantic-variables]

apps/docs/src/examples/theming/semantic-variables.tsx

```tsx
import { Box } from '@luke-ui/react/box';
import { Text } from '@luke-ui/react/text';
import { vars } from '@luke-ui/react/theme';

export default () => {
	return (
		<Box
			display="grid"
			gap="sp12"
			style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(14rem, 1fr))' }}
		>
			<SemanticSurface mode="light" />
			<SemanticSurface mode="dark" />
		</Box>
	);
};

function SemanticSurface({ mode }: { mode: 'light' | 'dark' }) {
	return (
		<Box
			data-color-mode={mode}
			padding="sp16"
			style={{
				backgroundColor: vars.color.surface.floating,
				color: vars.color.text.primary,
			}}
		>
			<Text>{mode === 'light' ? 'Light' : 'Dark'}</Text>
		</Box>
	);
}
```

Choose the token whose name matches the element's role. A card might use `surface.floating`,
`radius.surface`, and `depth.resting`. A warning message might use the warning role's subtle
background and foreground.

## Choosing a scale [#choosing-a-scale]

Token families use different naming models. Spacing uses value-based keys such as `sp16` and `sp24`.
Radius and depth use semantic roles. Use the public variable instead of copying its resolved CSS
value.

### Spacing [#spacing]

Spacing provides one scale for `gap`, `padding`, and `margin`. Each key matches its pixel value, so
`sp16` is 16px.

apps/docs/src/examples/overview/spacing-scale.tsx

```tsx
import { Box } from '@luke-ui/react/box';
import { Text } from '@luke-ui/react/text';
import { spaceScale, vars } from '@luke-ui/react/theme';
import { Fragment } from 'react';

export default () => {
	return (
		<Box
			alignItems="center"
			columnGap="sp16"
			display="grid"
			overflowX="auto"
			rowGap="sp12"
			style={{ gridTemplateColumns: 'auto 1fr', inlineSize: '100%' }}
		>
			{spaceScale.map(([step, value]) => (
				<Fragment key={step}>
					<Text elementType="span" fontVariantNumeric="tabular-nums" typography="caption">
						{step} ({value})
					</Text>
					<Box
						style={{
							backgroundColor: vars.color.background.accent.solid.rest,
							blockSize: '1.5rem',
							borderRadius: vars.radius.detail,
							inlineSize: vars.space[step],
							minInlineSize: vars.space[step],
						}}
					/>
				</Fragment>
			))}
		</Box>
	);
};
```

Read [Layout](/docs/layout#responsive-values) for breakpoint keys and how spacing values cascade.

### Radius [#radius]

Radius provides five semantic roles. Choose the role that matches the element being rounded, such as
`control` for an input or `surface` for a card.

apps/docs/src/examples/overview/radius-roles.tsx

```tsx
import { Box } from '@luke-ui/react/box';
import { Text } from '@luke-ui/react/text';
import { vars } from '@luke-ui/react/theme';
import { DecorativeBox } from './decorative-box.js';

const radiusRoles = [
	{ label: 'Detail', value: vars.radius.detail },
	{ label: 'Control', value: vars.radius.control },
	{ label: 'Surface', value: vars.radius.surface },
	{ label: 'Overlay', value: vars.radius.overlay },
	{ label: 'Full', value: vars.radius.full },
] as const;

export default () => {
	return (
		<Box
			display="grid"
			gap="sp16"
			style={{
				gridTemplateColumns: 'repeat(auto-fit, minmax(5rem, 1fr))',
				inlineSize: '100%',
			}}
		>
			{radiusRoles.map((role) => (
				<Box display="grid" gap="sp8" key={role.label}>
					<DecorativeBox
						alignItems="center"
						display="flex"
						flexGrow="1"
						justifyContent="center"
						padding="sp8"
						style={{
							blockSize: '5rem',
							borderRadius: role.value,
						}}
					/>
					<Text typography="caption" style={{ textAlign: 'center' }}>
						{role.label}
					</Text>
				</Box>
			))}
		</Box>
	);
};
```

apps/docs/src/examples/overview/concentric-radius.tsx

```tsx
import { Box } from '@luke-ui/react/box';
import { Text } from '@luke-ui/react/text';
import { deriveConcentricRadius, vars } from '@luke-ui/react/theme';
import { DecorativeBox } from './decorative-box.js';

export default () => {
	const controlGap = vars.space.sp8;

	return (
		<Box display="grid" gap="sp8">
			<DecorativeBox
				display="grid"
				padding="sp8"
				style={{
					borderRadius: deriveConcentricRadius(vars.radius.control, controlGap),
				}}
			>
				<Box
					blockSize="6rem"
					inlineSize="100%"
					style={{
						backgroundColor: vars.color.surface.floating,
						borderRadius: vars.radius.control,
					}}
				/>
			</DecorativeBox>
			<Text typography="caption">Outer radius from inner radius + gap</Text>
		</Box>
	);
};
```

When one rounded surface sits inside another, derive the outer radius from the inner radius and the
space between them, usually the wrapper's padding. This keeps their corners concentric.

```tsx
import { deriveConcentricRadius, vars } from '@luke-ui/react/theme';

const wrapperRadius = deriveConcentricRadius(vars.radius.control, vars.space.sp8);
```

### Depth [#depth]

Depth describes how a surface sits above or within the interface.

apps/docs/src/examples/overview/depth.tsx

```tsx
import { Box } from '@luke-ui/react/box';
import { Text } from '@luke-ui/react/text';
import { vars } from '@luke-ui/react/theme';

export default () => {
	return (
		<Box
			display="grid"
			gap="sp12"
			padding="sp16"
			style={{
				gridTemplateColumns: 'repeat(auto-fit, minmax(6rem, 1fr))',
				inlineSize: '100%',
			}}
		>
			{Object.entries(vars.depth).map(([name, depth]) => (
				<Box display="grid" gap="sp8" key={name}>
					<Box
						style={{
							backgroundColor: vars.color.surface.floating,
							blockSize: '5rem',
							border: `1px solid ${vars.color.border.control}`,
							borderRadius: vars.radius.surface,
							boxShadow: depth,
						}}
					/>
					<Text typography="caption" style={{ textAlign: 'center' }}>
						{name}
					</Text>
				</Box>
			))}
		</Box>
	);
};
```

Pair each depth role with the matching surface role. For example, a menu can use `surface.floating`
with `depth.floating`, while a dialog can use `surface.overlay` with `depth.overlay`.

Components already apply depth to their own states. Use these variables only for custom surfaces.

### Motion [#motion]

Motion provides three durations. Each duration is named for the role the movement plays.

* `feedback` covers an in-place state change, such as hover, focus, or selection.
* `enter` covers an element or an overlay that enters the interface.
* `exit` covers an element or an overlay that leaves the interface.

Pair `easing.standard` with feedback and with entry. Pair `easing.exit` with a dismissal.

## Browse the tokens [#browse-the-tokens]

The explorer lists every public token in the contract. Samples use the active identity and colour
mode.

<TokenExplorer />

## Continue learning [#continue-learning]

<Cards>
  <Card href="/docs/styling" title="Styling">
    Choose when to use vars beside component props and layout utilities.
  </Card>

  <Card href="/docs/layout" title="Layout">
    Apply spacing and breakpoints with Box.
  </Card>

  <Card href="/docs/color" title="Colour">
    Choose semantic surfaces and roles for custom UI.
  </Card>
</Cards>
