Raft 设计系统

组件 · 导航

SegmentedControl

2 to 4 segments in a gray track that switch how the same content is shown, in place; the selected segment is a yellow sticker.

稳定也叫 Segmented button
import { SegmentedControl } from "@botiverse/raft-ui";
本页尚未翻译
译文完成之前,这里显示英文原文。 阅读英文版

A segmented control switches between 2 to 4 views of the same content, in place: a board or a list of the same tasks, a light or a dark appearance. The segments sit in a gray track, and the selected one is a yellow sticker.

segmented-control/compositions/view-mode

When to use

SituationUse
Another view of the same content: Board / List, Light / Dark / SystemSegmentedControl
Sections of one page, each with its own contentTabs
An answer submitted with a formRadioGroup
More options than fit as segmentsSelect

The full table is in Choosing a component. Where Board / List goes on a task list is in Tasks.

Anatomy

  • SegmentedControl: the track, in fill-muted.
  • SegmentedControlItem: one 32px segment, with an optional icon before its label.
  • SegmentedControlLabel: the segment's text. It truncates.
  • SegmentedControlCount: a count after the label, in Space Mono.
segmented-control/compositions/filters

States

  • Selected: a yellow sticker with a bold label. It doesn't change on hover, like a selected tab; a press lays sticker-medium (Hover and press).
  • The other segments are foreground-muted, with the medium tier, fill-medium, on hover and press.
  • Disabled: set on the whole control, as in States.
segmented-control/compositions/disabled

Behavior

  • The segments sit 3px inside the track and 3px apart, so the gap between two of them is the gap to the track (Spacing).
  • The track hugs its segments. Don't stretch it to fill its container: a stretched track leaves an empty run of gray beside the segments.
  • The control never shrinks below its segments. When the row is too narrow, its neighbors give way first, then the segments show only their icons (Responsive layout).
  • To let the segments show only their icons, mark the row with @container and set iconsOnlyBelow on the control to the row width below which the labels no longer fit: xs (20rem), sm (24rem), md (28rem), lg (32rem), xl (36rem) or 2xl (42rem). Below it, every segment becomes a 32px square that shows only its icon: its label and its count stay its accessible name, and its label shows in a tooltip on hover and on keyboard focus. The control keeps its 32px height and its text size. Set iconsOnlyBelow only when every segment has an icon: a segment without one would be left empty.
  • Pick the width from the row, not the window: the same row sits in columns of different widths, and a container query follows the column.
  • Stretch it only when it is the only choice in a form. Then give it the full width (w-full) on its own line, not in a row beside other controls, and let the segments share it equally: in a row, a full-width track that can't shrink pushes past its neighbors.
  • On a phone, use at most 4 segments and show only their icons when they don't fit, with iconsOnlyBelow (Responsive layout).
segmented-control/compositions/narrow-row

Content

  • Label each segment with 1 or 2 words in Title Case: Board, List; Relevant, Recent (Typography).
  • Put a count in SegmentedControlCount, never in the label's text.

Accessibility

  • SegmentedControl wraps the Base UI RadioGroup, and each SegmentedControlItem is a Base UI Radio rendered as a button: the control is one tab stop, and the arrow keys move the selection.
  • Name the control with aria-label after what it switches: "Task view", "Time format".
  • Give every icon-only segment an aria-label. A segment that shows only its icon because of iconsOnlyBelow needs none: its label is still in it, hidden from sight but not from assistive technology.

API

SegmentedControl

Prop类型默认值
iconsOnlyBelowWhen the nearest `@container` ancestor (the row the control sits in) is narrower than this width, every segment shows only its icon (give each one). Its label stays the accessible name and shows in a tooltip.SegmentedControlIconsOnlyBelow
defaultValueThe uncontrolled value of the radio button that should be initially selected.T
disabledWhether the component should ignore user interaction.booleanfalse
formIdentifies the form that owns the radio inputs. Useful when the radio group is rendered outside the form.string
inputRefA ref to access the hidden input element.((instance: HTMLInputElement | null) => void | (() => void | { [UNDEFINED_VOID_ONLY]: never; }) | DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | RefObject<HTMLInputElement | null>
nameIdentifies the field when a form is submitted.string
onValueChangeCallback fired when the value changes.(value: T, eventDetails: BaseRadioGroup.ChangeEventDetails) => void
readOnlyWhether the user should be unable to select a different radio button in the group.booleanfalse
renderAllows you to replace the component's HTML element with a different tag, or compose it with another component.ReactElement | ((props, state) => ReactElement)
requiredWhether the user must choose a value before submitting a form.booleanfalse
valueThe controlled value of the radio item that should be currently selected.T

Also takes the attributes of its element.

SegmentedControlCount

接受其元素的全部属性。

SegmentedControlItem

Prop类型默认值
disabledWhether the component should ignore user interaction.boolean
inputRefA ref to access the hidden input element.((instance: HTMLInputElement | null) => void | (() => void | { [UNDEFINED_VOID_ONLY]: never; }) | DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | RefObject<HTMLInputElement | null>
nativeButtonWhether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `true` if the rendered element is a native button.booleanfalse
readOnlyWhether the user should be unable to select the radio button.boolean
renderAllows you to replace the component's HTML element with a different tag, or compose it with another component.ReactElement | ((props, state) => ReactElement)
requiredWhether the user must choose a value before submitting a form.boolean
value (required)The unique identifying value of the radio in a group.T

Also takes the attributes of its element.

SegmentedControlLabel

接受其元素的全部属性。

改动

  • 0.9.0 · AddedSegmentedControl takes iconsOnlyBelow ("xs" to "2xl", Tailwind's container sizes; type SegmentedControlIconsOnlyBelow). Mark the row @container; below that width each segment shows only its icon as a 32px square, its label and count stay the accessible name, and a tooltip shows the label. Use it only when every segment has an icon.
  • 0.8.0 · Breaking ChangesSegmentedControl no longer shrinks with max-w-full; it keeps its width (shrink-0). In a narrow row, give it room or let the row degrade as responsive.md says, or it overflows.
  • 0.8.0 · FixedSegmentedControl keeps its width and no longer gets squeezed by a neighbor in the same row.