Styling contract
Style against documented radio state hooks and semantic tokens rather than relying on wrapper markup that your app does not own.
| Selector | Applied on | Purpose |
|---|---|---|
[data-state="checked"] | Primitive input | Checked visual treatment. |
[data-checked], [data-unchecked] | Primitive input | Convenience hooks for checked or unchecked states. |
[data-invalid], [data-disabled], [data-readonly] | Primitive input | Validation and non-editable state styling. |
[data-focused], [data-focus-visible] | Primitive input | Generic focus and keyboard focus-visible styling. |
State selectors
radio.states.css
css
input[tngRadio][data-state="checked"] {
accent-color: var(--tng-semantic-accent-brand, #2563eb);
}
input[tngRadio][data-invalid] {
outline: 2px solid color-mix(in srgb, var(--tng-semantic-accent-danger, #dc2626) 55%, white);
outline-offset: 2px;
}
input[tngRadio][data-focus-visible] {
outline: 2px solid color-mix(in srgb, var(--tng-semantic-accent-brand, #2563eb) 70%, white);
outline-offset: 2px;
}
radio.shell.css
css
.radio-filter-card {
display: grid;
gap: 0.75rem;
inline-size: min(100%, 26rem);
margin-inline: auto;
padding: 1rem;
border: 1px solid var(--tng-semantic-border-subtle, #cbd5e1);
border-radius: 0.9rem;
background: var(--tng-semantic-background-base, #ffffff);
}
.radio-filter-card__row {
display: inline-flex;
align-items: center;
gap: 0.65rem;
color: var(--tng-semantic-foreground-primary, #0f172a);
}
Example shells
The primitive stays native while your wrapper card and label rows carry the visual language.