Radio
One option. Everything it does not decide, the group decides for it.
import { Radio } from "@dede-style/ui/radio", then <Radio value="standard" label="Standard" /> inside a RadioGroup. It takes the form name, the selected value and the handler from its parent — so what is left here is what one option owns.
The controls below move the first option. Its neighbour is there because a radio cannot stand on its own — and the fact that it does not move is the point.
| Prop | Description | Default | Control |
|---|---|---|---|
| label | the visible label and the accessible name. Required | ||
| description | an optional second line under the label | ||
| size | the circle: 16, 20 (default) or 24px456 | 5 |
|
| control | the circle before the label (start) or after it (end)startend | start | |
| full | spread the row across its container. Off, the row fits its content | false | |
| is | disables this option only; disable the whole set on the RadioGroup | false | |
| hide | hide the label visually but keep it for screen readers | false |
Tokens
What a theme can move, where the props above are what an instance can move.
Radio has none, and that is a decision rather than an omission. Every value it renders already resolves through a foundation token or a role, so a theme moves it by moving those. A component token earns its place only when a theme needs to change one component without changing the role beneath it.
These are public and overridable — there is no private custom property, because anything on :root is reachable by any stylesheet. What replaces privacy is a stability contract: primitives may move, roles are the guarantee, and these are the per-component escape from both.