UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

433 lines (379 loc) 12.7 kB
--- title: 'Radio' description: 'Use Radio when people must choose one option from a set.' version: 11.8.2 generatedAt: 2026-07-03T14:39:18.885Z checksum: 0ff62ef4dc4f9902fb7503d2aff5efc2bb72d942d5a55d0a119bedfac85af14d --- # Radio ## Import ```tsx import { Radio } from '@dnb/eufemia' ``` ## Description The Radio component is displayed as a circle that is filled (checked) when activated. Radio buttons let users select one option from a limited number of choices within a group. It is recommended to use radio buttons in a group. You can use either the React component `<Radio.Group>` or the property `group="NAME"` to define the group. ## When to use Radio vs Eufemia Forms # When to use Eufemia Forms Classic form components like this one are presentational controls. They handle the styling, sizing, icons, and basic events, while you manage their value, validation, and error handling yourself. For most data input and forms situations, use [Eufemia Forms](/uilib/extensions/forms/) fields instead. They build on these same components, but add data handling, validation, and error messages through the surrounding [Form.Handler](/uilib/extensions/forms/Form/Handler/). Browse the [field components](/uilib/extensions/forms/all-fields/) to find the one that matches your data. Reach for a classic component when you need it standalone outside of a form context, or when you handle the value and validation yourself. The Eufemia Forms equivalent of `Radio` is [Field.Selection](/uilib/extensions/forms/base-fields/Selection/) with the radio variant (`variant="radio"`). ## Relevant links - [Figma](https://www.figma.com/design/cdtwQD8IJ7pTeE45U148r1/%F0%9F%92%BB-Eufemia---Web?node-id=4243-1493) - [Source code](https://github.com/dnbexperience/eufemia/tree/main/packages/dnb-eufemia/src/components/radio) - [Docs code](https://github.com/dnbexperience/eufemia/tree/main/packages/dnb-design-system-portal/src/docs/uilib/components/radio) ## Accessibility Radio buttons use semantic `<input type="radio">` elements grouped by the `name` attribute. Arrow keys navigate between options within a group, and Space selects an option. Screen readers announce the group label, current selection, and number of options. ## Related components Radio is part of the [Input](/uilib/components/overview/#input) category. Other components for similar needs: - [Autocomplete](/uilib/components/autocomplete/) – to help people find and choose from matching suggestions as they type. - [Checkbox](/uilib/components/checkbox/) – when people can turn one or more options on or off. - [DatePicker](/uilib/components/date-picker/) – when people need to choose one date or a date range. - [Dropdown](/uilib/components/dropdown/) – when people need to choose one option from a list. - [Filter](/uilib/components/filter/) – to help people narrow down a list or data set. - [FormLabel](/uilib/components/form-label/) – to name an input, control, or form-related field. [See all in Input](/uilib/components/overview/#input) ## Demos ### Radio group ```tsx render( <Radio.Group label="Radio Group" onChange={({ value }) => { console.log('onChange', value) }} value="first" > <Radio label="First" value="first" /> <Radio label="Second" value="second" /> <Radio label="Third" value="third" /> </Radio.Group> ) ``` ### Vertical aligned Radio group ```tsx render( <Radio.Group label="Vertical Group" layoutDirection="column" onChange={({ value }) => { console.log('onChange', value) }} > <Radio label="First" value="first" /> <Radio label="Second" value="second" /> <Radio label="Third" value="third" checked /> </Radio.Group> ) ``` ### Radio group with label above ```tsx render( <Radio.Group vertical label="Vertical Group" layoutDirection="column" onChange={({ value }) => { console.log('onChange', value) }} > <Radio label="First" value="first" /> <Radio label="Second" value="second" /> <Radio label="Third" value="third" checked /> </Radio.Group> ) ``` ### Radio group with status messages ```tsx render( <Radio.Group label="Radio Group with status" layoutDirection="column" onChange={({ value }) => { console.log('onChange', value) }} > <Radio label="First" value="first" status="error" /> <Radio label="Second" value="second" status="Error message" /> <Radio label="Third" value="third" checked status="Info message" statusState="information" /> </Radio.Group> ) ``` ### Plain Radio group Without `<Radio.Group>`. It is recommended to use the `<Radio.Group>` if you are using **React**. ```tsx render( <FieldBlock label="Plain Radio group" layout="horizontal" labelHeight="small" > <Radio value="first" label="First" group="MyRadioGroup" onChange={({ value, checked }) => { console.log('onChange', value, checked) }} right /> <Radio value="second" label="Second" group="MyRadioGroup" onChange={({ value, checked }) => { console.log('onChange', value, checked) }} right /> <Radio checked value="third" label="Third" group="MyRadioGroup" onChange={({ value, checked }) => { console.log('onChange', value, checked) }} right /> </FieldBlock> ) ``` ### With different sizes As for now, there are two sizes. `medium` is the default size. ```tsx <Radio size="medium" label="Medium" right="large" checked /> <Radio size="large" label="Large" checked /> ``` ### Disabled Radio Group With `labelPosition` set to left. ```tsx render( <Radio.Group label="Disabled Group" disabled labelPosition="left" name="MyGroup" > <Radio label="First" value="first" /> <Radio label="Second" value="second" /> <Radio label="Third" value="third" checked /> </Radio.Group> ) ``` ### Radio Buttons with a suffix ```tsx render( <Radio.Group label="With suffixes" labelPosition="left"> <Radio label="First" value="first" /> <Radio label="Second" value="second" suffix={<HelpButton title="Modal Title">Modal content</HelpButton>} /> <Radio label="Third" value="third" status="Error message" suffix={<HelpButton title="Modal Title">Modal content</HelpButton>} checked /> </Radio.Group> ) ``` ```tsx <ComponentBox data-visual-test="radio-error-unchecked"> <Radio label="Unchecked" status="error" /> </ComponentBox> <ComponentBox data-visual-test="radio-error-checked"> <Radio label="Checked" status="error" checked /> </ComponentBox> ``` ```tsx <ComponentBox data-visual-test="radio-default"> <Radio label="Single Radio" /> </ComponentBox> <ComponentBox data-visual-test="radio-checked"> <Radio label="Checked Radio" checked onChange={({ checked }) => console.log(checked)} /> </ComponentBox> ``` ```tsx render( <ShowBoundingArea> <ComponentBox data-visual-test="radio-bounding"> <Radio label="Radio button" checked /> </ComponentBox> </ShowBoundingArea> ) ``` ## `Radio` properties ```json { "props": { "value": { "doc": "Defines the `value` as a string. Use it to get the value during the `onChange` event listener callback in the **RadioGroup**.", "type": "string", "status": "optional" }, "checked": { "doc": "Determine whether the radio is checked or not. Default will be `false`.", "type": "boolean", "status": "optional" }, "group": { "doc": "Use a unique group identifier to define the Radio buttons that belong together.", "type": "string", "status": "optional" }, "size": { "doc": "The size of the Radio button. For now there are `medium` (default) and `large`.", "type": ["\"default\"", "\"medium\"", "\"large\""], "status": "optional" }, "label": { "doc": "Use either the `label` property or provide a custom one.", "type": "React.ReactNode", "status": "optional" }, "labelPosition": { "doc": "Defines the position of the `label`. Use either `left` or `right`. Defaults to `right`.", "type": ["\"left\"", "\"right\""], "status": "optional" }, "labelSrOnly": { "doc": "Use `true` to make the label only readable by screen readers.", "type": "boolean", "status": "optional" }, "status": { "doc": "Text with a status message. The style defaults to an error message. You can use `true` to only get the status color, without a message.", "type": ["\"error\"", "\"information\"", "boolean"], "status": "optional" }, "statusState": { "doc": "Defines the state of the status. Currently, there are two statuses `[error, information]`. Defaults to `error`.", "type": ["\"error\"", "\"information\""], "status": "optional" }, "statusProps": { "doc": "Use an object to define additional FormStatus properties.", "type": "Various", "status": "optional" }, "globalStatus": { "doc": "The [configuration](/uilib/components/global-status/properties/#configuration-object) used for the target [GlobalStatus](/uilib/components/global-status).", "type": "Various", "status": "optional" }, "ref": { "doc": "By providing a `React.Ref` we can get the internally used input element (DOM), e.g. `ref={myRef}` by using `React.useRef(null)`.", "type": "React.RefObject", "status": "optional" } } } ``` ## `Radio.Group` properties ```json { "props": { "value": { "doc": "Defines the pre-selected Radio button. The value has to match the one provided in the Radio button. Use a string value.", "type": "string", "status": "optional" }, "name": { "doc": "Custom grouping name. Defaults to a random name.", "type": "string", "status": "optional" }, "layoutDirection": { "doc": "Define the layout direction of the Radio buttons. Can be either `column` or `row`. Defaults to `row`.", "type": ["\"column\"", "\"row\""], "status": "optional" }, "size": { "doc": "The size of the Radio button. For now there are `medium` (default) and `large`.", "type": ["\"default\"", "\"medium\"", "\"large\""], "status": "optional" }, "status": { "doc": "Uses the `form-status` component to show failure messages.", "type": ["string", "boolean"], "status": "optional" }, "statusState": { "doc": "Defines the state of the status. Currently, there are two statuses `[error, information]`. Defaults to `error`.", "type": ["\"error\"", "\"information\""], "status": "optional" }, "statusProps": { "doc": "Use an object to define additional FormStatus properties.", "type": "Various", "status": "optional" }, "globalStatus": { "doc": "The [configuration](/uilib/components/global-status/properties/#configuration-object) used for the target [GlobalStatus](/uilib/components/global-status).", "type": "Various", "status": "optional" }, "label": { "doc": "Use either the `label` property or provide a custom one.", "type": "React.ReactNode", "status": "optional" }, "labelDirection": { "doc": "To define the `label` layout direction on how the next element should be placed on. Can be either `vertical` or `horizontal`. Defaults to `vertical`.", "type": ["\"vertical\"", "\"horizontal\""], "status": "optional" }, "labelSrOnly": { "doc": "Use `true` to make the label only readable by screen readers.", "type": "boolean", "status": "optional" }, "vertical": { "doc": "Will force both `direction` and `labelDirection` to be `vertical` if set to `true`.", "type": "boolean", "status": "optional" } } } ``` ### Radio group Context You can also pass through `labelPosition` and some more **Radio button** properties to the Group. This way all nested Radio buttons will get the properties. ## `Radio` events ```json { "props": { "onChange": { "doc": "Will be called on state changes made by the user. Returns an object `{ checked, value, event }`.", "type": "function", "status": "optional" } } } ``` ## `Radio.Group` events ```json { "props": { "onChange": { "doc": "Will be called once a Radio button changes the state. Returns an object `{ value, event }`.", "type": "function", "status": "optional" } } } ```