InputsReact
One choice out of a few, drawn as a bar of segments with a pill under the chosen one.
Rendered by React 19.3.1
Loading React…Installation
npm i @hamur/reactNot on npm yet. The package goes out under the chosen name.
Anatomy
Import the component and assemble its parts:
<SegmentGroup.Root>
<SegmentGroup.Indicator />
<SegmentGroup.Item />
</SegmentGroup.Root>Examples
Vertical
A row density choice stacked in a column; the pill moves on the block axis.
Disabled
A billing period whose third segment is disabled; the arrow keys skip it.
Controlled
Icon-only alignment segments named by aria-label, with the value held by the app and a Reset button.
Form
In a Field labelled "Default view", submitted with its form and brought back to Week by a reset.
API reference
17 props across 3 parts, in React syntax. className, style, render are listed once, under Shared props.
IndicatorSegmentGroup.Indicator
A visual indicator that can be styled to match the position of the checked segment. Renders a <span>.
| Prop | Type | Default |
|---|---|---|
renderBeforeHydrationWhether to render itself before React hydrates. | boolean | false |
| Data attribute | Description |
|---|---|
data-orientation | Indicates the layout direction of the segments. |
data-activation-direction | Indicates the direction of the last move (based on the previously checked segment). |
data-resizing | Present from a re-measure that is not a change of value (a resize) until the next animation frame, so a transition can be turned off while it is present. |
| CSS variable | Description |
|---|---|
--active-segment-left | The distance from the left edge of the Root's padding box to the checked segment. |
--active-segment-right | The distance from the checked segment to the right edge of the Root's padding box. |
--active-segment-top | The distance from the top edge of the Root's padding box to the checked segment. |
--active-segment-bottom | The distance from the checked segment to the bottom edge of the Root's padding box. |
--active-segment-width | The width of the checked segment. |
--active-segment-height | The height of the checked segment. |
ItemSegmentGroup.Item
A segment of the group: a radio with its text as its name. and a hidden <input> beside. Renders a <span>.
| Prop | Type | Default |
|---|---|---|
nativeButtonWhether the component renders a native <button> element when replacing it | boolean | false |
valuerequiredThe unique identifying value of the segment in the group. | TValue | — |
disabledWhether the component should ignore user interaction. | boolean | false |
readOnlyWhether the user should be unable to check the segment. | boolean | false |
requiredWhether the user must choose a value before submitting a form. | boolean | false |
inputRefA ref to access the hidden input element. | React.Ref<HTMLInputElement> | — |
| Data attribute | Description |
|---|---|
data-orientation | Indicates the layout direction of the segments. |
data-checked | Present when the segment is checked. |
data-unchecked | Present when the segment is not checked. |
data-disabled | Present when the segment is disabled. |
data-readonly | Present when the segment is readonly. |
data-required | Present when the segment is required. |
data-valid | Present when the segment is in a valid state (when wrapped in Field.Root). |
data-invalid | Present when the segment is in an invalid state (when wrapped in Field.Root). |
data-touched | Present when the segment has been touched (when wrapped in Field.Root). |
data-dirty | Present when the segment's value has changed (when wrapped in Field.Root). |
data-filled | Present when the segment is checked (when wrapped in Field.Root). |
data-focused | Present when the segment is focused (when wrapped in Field.Root). |
RootSegmentGroup.Root
Groups the segments of a single-choice bar and measures the checked one for the Indicator. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
valueThe controlled value of the checked segment, or null for none. | TValue | null | — |
defaultValueThe uncontrolled value of the segment checked when the component is initially rendered, and | TValue | null | — |
onValueChangeCallback fired when the value changes. | ((value: TValue, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void) | — |
orientationThe layout direction of the segments. | SegmentGroupOrientation | 'horizontal' |
disabledWhether the component should ignore user interaction. | boolean | false |
readOnlyWhether the user should be unable to check a different segment. | boolean | false |
requiredWhether the user must choose a value before submitting a form. | boolean | false |
nameIdentifies the field when a form is submitted. | string | — |
formIdentifies the form that owns the hidden inputs. | string | — |
inputRefA ref to access the hidden input element. | React.Ref<HTMLInputElement> | — |
| Data attribute | Description |
|---|---|
data-orientation | Indicates the layout direction of the segments. |
data-disabled | Present when the segment group is disabled. |
data-valid | Present when the segment group is in a valid state (when wrapped in Field.Root). |
data-invalid | Present when the segment group is in an invalid state (when wrapped in Field.Root). |
data-touched | Present when the segment group has been touched (when wrapped in Field.Root). |
data-dirty | Present when the segment group's value has changed (when wrapped in Field.Root). |
data-filled | Present when a segment is checked (when wrapped in Field.Root). |
data-focused | Present when a segment is focused (when wrapped in Field.Root). |
Shared props
Every part that renders an element takes these.
| Prop | Type |
|---|---|
classNameCSS class applied to the element, or a function that
returns a class based on the component's state. | string | ((state: State) => string | undefined) |
styleStyle applied to the element, or a function that
returns a style object based on the component's state. | React.CSSProperties | ((state: State) => React.CSSProperties | undefined) |
renderAllows you to replace the component's HTML element
with a different tag, or compose it with another component. | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, State> |
Keyboard and accessibility
Keyboard
| Keys | Does | Part |
|---|---|---|
| ArrowLeftArrowRightArrowUpArrowDown | Moves to the previous or next segment and checks it, wrapping at the ends, in either layout | Item |
| ArrowRight | Skips a disabled segment | Item |
| Space | Checks the focused segment | Item |
| Enter | Changes nothing and submits nothing | Item |
| HomeEnd | Change nothing | Item |
| Tab | Enters the group on the checked segment, then leaves it in one step | Root |
Accessibility
| Part | Sets | So that |
|---|---|---|
| Root | role="radiogroup" and aria-orientation, named by the Field label, a Fieldset legend, or the app's aria-labelledby or aria-label | the segments are said as one set, with its question |
| Root | aria-disabled, aria-readonly, aria-required from disabled, readOnly and required | the group's constraints are said |
| Item | role="radio" with aria-checked, the roving tabindex, and a hidden radio input beside it | each segment is said as a choice with its state, and submits a value |
| Item | its text as its name; an icon-only Item takes the app's aria-label | every segment has a name |
| Indicator | role="presentation", no text, never focused; hidden until measured | the pill is drawing only, and nothing jumps on the first paint |
Focus order
- The group is one tab stop: the checked segment, or the first enabled one while none is checked.
- The arrow keys move focus and the choice together; disabled segments are skipped.
- Tab leaves the group in one step. Nothing takes focus on mount or on a form reset.