Skip to content

Commit 9ca3050

Browse files
committed
update/radio_button
1 parent ce063fd commit 9ca3050

1 file changed

Lines changed: 330 additions & 0 deletions

File tree

Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
# Guideline
2+
3+
## Intro 👈🤖
4+
5+
A radio button enables users to select exactly one option from a predefined set of mutually exclusive choices.
6+
7+
---
8+
9+
## Definition
10+
11+
A radio button is a user interface element that allows users to select a single option from a set of mutually exclusive choices, typically displayed as a circular input with a label that becomes filled when selected.
12+
13+
This component family is available in two variants:
14+
**Radio-button:** In this template, the component does not display any text or icon. This layout provides greater flexibility when creating other components that require a radio-button to be displayed.
15+
**Radio-button item:** In this template, the component displays multiple additional text elements and icon assets.
16+
17+
---
18+
19+
## Best for 👈🤔
20+
21+
✅ Single selection from a small set of 2–7 mutually exclusive options
22+
23+
✅ Settings or preferences where only one choice applies at a time
24+
25+
✅ Forms requiring explicit user commitment to one option
26+
27+
✅ Yes/No or binary choice questions on a page
28+
29+
✅ Filter controls where one category must be active
30+
31+
✅ Survey questions with predefined answer choices
32+
33+
✅ Configuration panels with exclusive mode selections
34+
35+
✅ Checkout flows for shipping or payment method selection
36+
37+
✅ User onboarding where one path must be chosen
38+
39+
✅ Legal or compliance forms requiring explicit single selection
40+
41+
---
42+
43+
## Anatomy 👈🤖
44+
45+
| # | Element | Purpose | Optional |
46+
|---|---------|---------|----------|
47+
| 1 | Radio indicator | Circular input showing selected/unselected state via fill or empty circle | N |
48+
| 2 | Label | Primary text describing the selectable option | N |
49+
| 3 | Extra label | Strong accompanying text providing additional emphasis for the label | Y |
50+
| 4 | Description | Supporting text providing context or clarification for the option | Y |
51+
| 5 | Icon | Visual element to enhance recognition or categorization of the option | Y |
52+
| 6 | Error message | Text displayed when validation fails, explaining the error condition | Y |
53+
| 7 | Divider | Horizontal line separating radio button items in a list | Y |
54+
| 8 | Container (combined) | Interactive area encompassing indicator and label for click/tap targets; includes outlined variant for emphasis | N |
55+
56+
---
57+
58+
## Selected
59+
60+
Typically, a radio button has two main states: Selected and Unselected.
61+
62+
**`False`** The radio button is unselected. Used by default or when the user chooses another option in the group.
63+
64+
**`True`** The radio button is selected. Indicates the user's current active choice within the group.
65+
66+
---
67+
68+
## selected_do_&_dont 👈🤔
69+
70+
**Do:** Pre-select a default option when a recommended or most common choice exists to reduce user effort
71+
**Don't:** Pre-select an option that could commit users to unwanted actions like subscriptions or agreements
72+
73+
**Do:** Ensure the selected state is visually distinct with a filled indicator and sufficient color contrast
74+
**Don't:** Use subtle visual differences that make it difficult to distinguish selected from unselected states
75+
76+
**Do:** Allow users to change their selection freely before form submission
77+
**Don't:** Lock selections or require page refresh to change a radio button choice
78+
79+
**Do:** Provide a "None" or "Not applicable" option if no selection should be a valid user choice
80+
**Don't:** Force users to select an option when the question may not apply to them
81+
82+
**Do:** Automatically deselect the previous option when a new one is selected within the group
83+
**Don't:** Allow multiple radio buttons in the same group to be selected simultaneously
84+
85+
---
86+
87+
## Error
88+
89+
**`False`** The field is required but not selected. Example: the "I accept the terms" checkbox is not checked — user action is required.
90+
91+
**`True`** The field is selected but still invalid. Example: the user selects "Subscribe to newsletter" but doesn't provide an email — logical condition not met.
92+
93+
---
94+
95+
## error_do_&_dont 👈🤔
96+
97+
**Do:** Display error messages directly below the radio group with clear, actionable language like "Select an option"
98+
**Don't:** Use generic error messages like "Invalid input" that don't explain what action is required
99+
100+
**Do:** Use a distinct error color (typically red) for the indicator border and error message text
101+
**Don't:** Rely solely on color to indicate errors—include text and icons for accessibility
102+
103+
**Do:** Associate error messages programmatically with the radio group using `aria-describedby`
104+
**Don't:** Place error messages far from the radio group where users may miss the connection
105+
106+
**Do:** Clear error states immediately when the user makes a valid selection
107+
**Don't:** Keep error indicators visible after the user has corrected the issue
108+
109+
**Do:** Validate on blur or form submission rather than on every interaction to avoid premature errors
110+
**Don't:** Show error states before the user has had a chance to interact with the radio group
111+
112+
---
113+
114+
## Outlined
115+
116+
**`False`** This is the default layout of the component.
117+
118+
**`True`** Outlined radio buttons are designed to stand out and draw the user's attention. They are often used to emphasize significant or impactful options that require careful consideration in the interface.
119+
120+
---
121+
122+
## outlined_do_&_dont 👈🤔
123+
124+
**Do:** Use outlined variants sparingly for high-importance decisions like pricing plans or subscription tiers
125+
**Don't:** Apply outlined styling to every radio group, which diminishes its emphasis effect
126+
127+
**Do:** Maintain consistent padding and border styling across all outlined radio buttons in a group
128+
**Don't:** Mix outlined and non-outlined radio buttons within the same selection group
129+
130+
**Do:** Ensure outlined borders have sufficient contrast against the background (minimum 3:1 ratio)
131+
**Don't:** Use light gray borders on white backgrounds that fail accessibility contrast requirements
132+
133+
**Do:** Increase touch target size when using outlined variants to accommodate the larger visual footprint
134+
**Don't:** Reduce clickable areas to match only the visible border boundaries
135+
136+
**Do:** Use outlined variants when radio options contain rich content like descriptions or icons
137+
**Don't:** Use outlined variants for simple binary choices where standard radio buttons suffice
138+
139+
---
140+
141+
## Reverse
142+
143+
**`False`** This is the default layout of the component. From left to right, the order of the elements is as follows: radio button / text / icon.
144+
145+
**`True`** As its name suggests, this layout is the reversed mirror of the "Default" template. From left to right, the order of the elements is as follows: icon / text / radio button. This variant is necessary for RTL mode and certain mobile use cases.
146+
147+
---
148+
149+
## reverse_do_&_dont 👈🤔
150+
151+
**Do:** Use reverse layout for right-to-left (RTL) languages like Arabic and Hebrew
152+
**Don't:** Use reverse layout arbitrarily without considering reading direction conventions
153+
154+
**Do:** Apply reverse layout consistently across all radio buttons when supporting RTL interfaces
155+
**Don't:** Mix LTR and RTL radio button layouts on the same page or within the same form
156+
157+
**Do:** Position the radio indicator on the trailing edge (right side for LTR, left for RTL) for mobile list interfaces
158+
**Don't:** Place indicators in inconsistent positions across different screen sizes
159+
160+
**Do:** Ensure tab order and focus management work correctly regardless of visual layout direction
161+
**Don't:** Assume visual order equals DOM order—verify keyboard navigation flows logically
162+
163+
**Do:** Test reverse layouts with screen readers to confirm proper announcement order
164+
**Don't:** Rely solely on visual testing when implementing layout variants
165+
166+
---
167+
168+
## Other boolean options
169+
170+
**`Extra label`** It is possible to display or hide strong accompanying text for the main label.
171+
172+
**`Description`** It is possible to display or hide accompanying text for the main label.
173+
174+
**`Icon`** It is possible to display or hide an icon. If displayed, this option includes functionality to choose any Solaris icon.
175+
176+
**`Divider`** It is possible to display or hide a dividing element (line).
177+
178+
**`Error message`** In the context where the component is in its "Error" true option, the error message can be displayed.
179+
180+
---
181+
182+
## other_boolean_options_do_&_dont 👈🤔
183+
184+
**Do:** Use descriptions to provide helpful context that aids decision-making between options
185+
**Don't:** Add descriptions to every radio button when options are already self-explanatory
186+
187+
**Do:** Use icons that clearly represent the option and are recognizable at small sizes
188+
**Don't:** Use decorative icons that don't add meaningful information to the selection
189+
190+
**Do:** Use dividers to create visual separation in long lists of radio button items
191+
**Don't:** Add dividers to groups with only 2–3 options where separation isn't needed
192+
193+
**Do:** Keep extra labels concise and complementary to the main label text
194+
**Don't:** Duplicate information between the main label and extra label
195+
196+
**Do:** Show error messages only when validation has failed and hide them upon correction
197+
**Don't:** Display placeholder error message space when no error exists
198+
199+
---
200+
201+
# Specs
202+
203+
## States
204+
205+
**`Enabled`** The default active state where the radio button is functional and selectable. It may show an unselected or selected style, with a label and helper text visible.
206+
207+
**`Hover`** When a user places a pointing device over a radio button, but has not yet taken action on it. This includes a subtle visual indicator (highlighted background or color change) to show interactivity.
208+
209+
**`Focus`** When a user selects a radio button via keyboard or voice command, but has not yet taken action on it. Mirrors the "Hover" state but includes an additional border.
210+
211+
**`Pressed`** An intermediate state that communicates a user has taken action on a radio button, and that it is in the process of navigating to a destination, triggering logic, or transmitting data.
212+
213+
**`Read only`** The radio button is displayed in a specific state (selected or unselected), but the user cannot modify it with a label and helper text visible.
214+
215+
**`Disabled`** The radio button is non-interactive and grayed out to indicate it cannot be selected or changed. The label and helper text are muted.
216+
217+
**`Skeleton`** Improves the perceived loading time by providing a visual cue of where radio button will appear once fully loaded. Uses the "Skeleton" component, variant "Security marge=True".
218+
219+
---
220+
221+
## Layout and spacing
222+
223+
🚧 Content to be added
224+
225+
---
226+
227+
# Accessibility 👈🤖
228+
229+
## Accessibility intro
230+
231+
Radio buttons must meet WCAG 2.2 Level AA standards, ensuring keyboard operability, proper labeling, and clear state communication for all users including those using assistive technologies. For comprehensive accessibility guidance, see the [Orange Unified Design System Accessibility Overview](https://unified-design-system.orange.com/472794e18/p/88ebab-accessibility-and-sustainability).
232+
233+
---
234+
235+
## Accessibility Challenges
236+
237+
Radio buttons present unique accessibility challenges because they operate as groups where only one option can be selected, requiring proper grouping semantics, clear state indication, and coordinated keyboard navigation across multiple interactive elements.
238+
239+
### Key Challenges
240+
- Communicating mutual exclusivity to screen reader users who cannot see visual relationships
241+
- Managing roving tabindex for efficient keyboard navigation within groups
242+
- Ensuring error states are announced and associated with the correct group
243+
- Maintaining visible focus indicators across all interaction states
244+
245+
### Critical Success Factors
246+
1. Group radio buttons using `<fieldset>` with `<legend>` or `role="radiogroup"` with `aria-labelledby` (WCAG 1.3.1)
247+
2. Ensure each radio button has an accessible name via `<label>` or `aria-label` (WCAG 4.1.2)
248+
3. Provide visible focus indicators with ≥3:1 contrast ratio (WCAG 2.4.7)
249+
4. Associate error messages with the group using `aria-describedby` (WCAG 3.3.1)
250+
251+
---
252+
253+
## Design Requirements
254+
255+
### Structure & Labels
256+
- [ ] **Group labeling**: Use `<fieldset>` and `<legend>` to provide group context ([Orange label guidelines](https://a11y-guidelines.orange.com/en/web/components-examples/))
257+
- [ ] **Individual labels**: Every radio button has a visible `<label>` associated via `for`/`id`
258+
- [ ] **Required indication**: Mark required groups with "(required)" in legend, use `aria-required="true"`
259+
260+
### Visual Design
261+
- [ ] **Focus indicator**: 3:1 minimum contrast, visible on all backgrounds ([Focus guidelines](https://a11y-guidelines.orange.com/en/web/design/focus-visible/))
262+
- [ ] **State contrast**: Selected/unselected states distinguishable without relying on color alone
263+
- [ ] **Touch target**: Minimum 44×44px interactive area for radio button and label combined
264+
265+
### Content
266+
- [ ] **Error messages**: ❌ "Error" / ✅ "Select your preferred contact method" ([Error guidelines](https://a11y-guidelines.orange.com/en/web/components-examples/forms/))
267+
- [ ] **Concise labels**: Use clear, scannable option text under 3–4 words per label
268+
269+
---
270+
271+
## Testing Checklist
272+
273+
### Screen Reader Testing
274+
- [ ] Test with NVDA (Windows), JAWS (Windows), VoiceOver (macOS/iOS), TalkBack (Android)
275+
- [ ] Verify group label announced, option labels read, selected state communicated, error messages associated
276+
277+
### Keyboard Testing
278+
- [ ] Tab moves focus to group, Arrow keys navigate between options, Space selects focused option
279+
- [ ] Verify focus indicator visible with ≥3:1 contrast throughout all states
280+
281+
### Visual Testing
282+
- [ ] Confirm selected/unselected states distinguishable by shape, not just color
283+
- [ ] Verify error indicators include icon or text in addition to color change
284+
285+
Resources: [Orange Accessibility Testing Guide](https://a11y-guidelines.orange.com/en/web/toolbox/)
286+
287+
---
288+
289+
## Key WCAG Criteria
290+
291+
- **1.3.1 Info and Relationships** (A): Radio groups use proper `<fieldset>`/`<legend>` or ARIA grouping semantics
292+
- **2.1.1 Keyboard** (A): All radio buttons operable via Tab and Arrow keys without mouse
293+
- **2.4.7 Focus Visible** (AA): Visible focus indicator on active radio button with ≥3:1 contrast
294+
- **3.3.1 Error Identification** (A): Errors identified in text and associated with radio group via `aria-describedby`
295+
- **4.1.2 Name, Role, Value** (A): Radio button role, checked state, and accessible name exposed to assistive technology
296+
297+
For complete reference: [Orange Accessibility Guidelines - Form Components](https://a11y-guidelines.orange.com/en/web/components-examples/forms/)
298+
299+
---
300+
301+
## Additional Resources
302+
303+
- [Orange Accessibility Guidelines - Radio Buttons](https://a11y-guidelines.orange.com/en/web/components-examples/)
304+
- [WCAG 2.2 Understanding 1.3.1 Info and Relationships](https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships)
305+
- [WAI-ARIA Radio Group Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/radio/)
306+
- [Orange Design System - Accessibility & Sustainability](https://unified-design-system.orange.com/472794e18/p/88ebab-accessibility-and-sustainability)
307+
308+
---
309+
310+
# Changelog
311+
312+
| Date | Number | Notes | Designer |
313+
|------|--------|-------|----------|
314+
| Nov 7, 2025 | 1.4.0 | • A new Read-only variant has been added for the .Radiobutton.Indicator component, supporting two boolean variants — Selected = True/False. This variant introduces two new color tokens: | Anton Astafev |
315+
| | | ‎ ‎ ‎ • ouds/color/action/read-only-primary — used for the indicator (shape) | |
316+
| | | ‎ ‎ ‎ • ouds/color/action/read-only-secondary — used for the stroke | |
317+
| | | • The new Read-only variant has been integrated into the Read-only variant of both the Radio button and Radio button Item components. | |
318+
| | | • We replaced the token in Error text container ouds-control-text-input-space-padding-block-top-helper-text with ouds-control-control-item-space-padding-block-top-error-text. | |
319+
| | | • "Helper text" is now called "Description". | |
320+
| | | • "Additional label" is now called "Extra label". | |
321+
| Oct 20, 2025 | 1.3.0 | • The Radio button item has been split into two boolean variants: → Error = True/False → Selected = True/False | Anton Astafev |
322+
| | | • The divider color is now functional in the Error state — it changes dynamically according to the component status. | |
323+
| | | • The icon in the Error state is fixed to .Component/alert/important; its color changes together with the divider depending on the component's status. → The new token $control-control-item-size-error-icon is used for the icon size. → The new token $control-text-input-space-padding-inline-error-icon is used for the error icon container. 🆕 Both tokens are now available in the latest release of the Token Library 2.1.0. | |
324+
| | | • Added Error text (from the Input component) — it follows the same padding-inline as control-item (16px) and uses → $control-text-input-space-padding-block-top-helper-text for block padding. By default, the Error text adapts automatically to match the component status: → Selected → displays the corresponding default error message for the selected state. → Unselected → displays the corresponding default error message for the unselected state. | |
325+
| | | • The "Read only" state has been updated to replace control items (in their disabled states) — both selected and unselected — with the Tag → Text only → Muted component: → Positive with label "Selected" if selected = True → Negative with label "Unselected" if selected = False | |
326+
| | | • Harmonisation of spacing across the control-item family We've unified sizing tokens across the entire control-item family (previously they were defined per component) to align spacing with other control items such as Text input. Replacement note: instead of the single token padding inset 12, use the following tokens: → ouds/_control/control-item/space/padding-inline → 16 → ouds/_control/control-item/space/padding-block → 12 Additionally, for the control-item family: → ouds/_control/control-item/space/column-gap → 12 → ouds/_control/control-item/size/max-width → 480 | |
327+
| Sep 19, 2025 | 1.2.0 | • In the initial settings, the 'Divider' variant is now hidden. | Maxime Tonnerre |
328+
| Jul 21, 2025 | 1.1.0 | • The name of the family to which this component belongs is changing: Input → Control. As a result, the token naming convention is being updated. | Maxime Tonnerre |
329+
| | | • Following the renaming of the 'Control' category, the name of the token sub-family 'control-item' is now becoming 'item'." | |
330+
| Jan 22, 2025 | 1.0.0 | • Component creation | Maxime Tonnerre |

0 commit comments

Comments
 (0)