JGuang

分段选择

SegmentedControl · Astryx

交互预览
npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0

分段选择 · SegmentedControl

分段选择用于操作场景。下面的官方示例展示原生用法与状态,属性名保持上游 API。

安装与前置条件

npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0

需要 React 19+,按顺序导入基础 CSS 和主题,并设置 Theme Provider。参见开始使用。

示例与使用方式

  • 分段选择 · 综合展示 1:首先体验这个示例,再查看代码理解组件的组合方式。
  • 分段选择 · 综合展示 2:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 分段选择 · 禁用状态 3:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 分段选择 · 交互示例 4:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 分段选择 · 交互示例 5:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 分段选择 · 基础用法 6:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 分段选择 · 包含图标 7:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。

API 与上游详细参考

优先使用 0.7.1 官方中文说明;上游尚未提供中文的条目保留英文。属性名、类型及默认值保持原生 API,不把示例状态名称当成组件属性。

Segmented Control

A segmented button group that allows users to make a single selection from a small set of mutually exclusive options. Use SegmentedControl when all options should be visible at once and the selection controls a value or mode, not page navigation.

属性类型默认值说明
value *stringThe currently selected value (controlled).
onChange *(value: string) => voidCallback fired when a segment is selected.
label *stringAccessible label for the radio group (used as aria-label, never rendered visually).
size'sm' | 'md' | 'lg''md'Size variant for the control.
layout'hug' | 'fill''hug'Layout mode. hug (default) sizes segments to content, capped at the container width (segment labels truncate when it is too narrow); fill stretches them equally to fill the container.
isDisabledbooleanfalseWhether the entire control is disabled.
disabledMessagestringExplains why the control is disabled. Applies to the whole-group disabled state (isDisabled), not per segment. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the control focusable via aria-disabled (selection stays blocked). Use this instead of wrapping a disabled SegmentedControl in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.
children *ReactNodeSegmentedControlItem children.
xstyleStyleXStylesStyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value: not an inline style object like style={{}}.

使用建议

  • Use for switching between 2–5 mutually exclusive views or modes where all options should be visible.
  • Provide a descriptive label for the control to ensure the group is accessible to screen readers.
  • 避免:Use for page-level navigation; use TabList instead. TabList is a navigation component, while SegmentedControl is an input that always has exactly one selected option.
  • 避免:Use for simple on/off states; use ToggleButton instead. ToggleButton can be toggled on or off independently, while SegmentedControl enforces a single selection from a group.
  • 避免:Wrap a disabled SegmentedControl in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.

In a narrow card

import {useState} from 'react';
import {Card} from '@astryxdesign/core/Card';
import {Heading} from '@astryxdesign/core/Heading';
import {
  SegmentedControl,
  SegmentedControlItem,
} from '@astryxdesign/core/SegmentedControl';
import {Text} from '@astryxdesign/core/Text';
import {VStack} from '@astryxdesign/core/VStack';

const SUMMARY = {
  overview: '4 projects, 2 due this week.',
  activity: '18 updates since Monday.',
  members: '12 members, 3 pending invites.',
  billing: 'Next invoice on October 1.',
};

// Inside a VStack the default hug layout keeps its content width; it does not
// stretch to the card. When the card is narrower than the control (a 320px
// phone column), the control caps at the card width and each label truncates
// with an ellipsis instead of running past the card edge. The full label stays
// each segment's accessible name. Keep labels short for phone widths.
function WorkspaceCard() {
  const [view, setView] = useState('overview');
  return (
    <Card maxWidth={480}>
      <VStack gap={3}>
        <Heading level={3}>Team workspace</Heading>
        <SegmentedControl label="Workspace view" value={view} onChange={setView}>
          <SegmentedControlItem value="overview" label="Overview" />
          <SegmentedControlItem value="activity" label="Activity" />
          <SegmentedControlItem value="members" label="Members" />
          <SegmentedControlItem value="billing" label="Billing" />
        </SegmentedControl>
        <Text color="secondary">{SUMMARY[view]}</Text>
      </VStack>
    </Card>
  );
}

主题 API

{
  "targets": [
    {
      "className": "astryx-segmented-control",
      "visualProps": [
        "size"
      ]
    },
    {
      "className": "astryx-segmented-control-item",
      "visualProps": [
        "size"
      ],
      "states": [
        "selected",
        "disabled"
      ]
    }
  ],
  "vars": [
    {
      "name": "--_segmented-control-radius",
      "description": "Border radius of the segmented control",
      "default": "var(--radius-element)",
      "private": true
    },
    {
      "name": "--_segmented-control-padding",
      "description": "Inner padding of the segmented control",
      "default": "var(--spacing-0-5)",
      "private": true
    }
  ],
  "derived": [
    {
      "property": "borderRadius",
      "vars": [
        "--_segmented-control-radius"
      ]
    },
    {
      "property": "padding",
      "vars": [
        "--_segmented-control-padding"
      ]
    }
  ]
}

SegmentedControlItem

无障碍

  • Text label: Each label must have at least 4.5:1 contrast with its segment background. Check unselected, Hover, Pointer down, and selected colors as they appear on screen. For Hover and Pointer down, measure the final background after the overlay is applied. — 4.5:1
  • Essential icon: When a segment has no visible label, its icon must have at least 3:1 contrast with the segment background. An icon beside a visible label does not need its own check. — 3:1
  • Selected state indicator: The selected background must reach 3:1 only when users need it to tell selected from unselected. Label color and weight also show selection. — 3:1 if relied upon
  • Visible control boundary: The control edge or segment borders need at least 3:1 contrast when users need them to see the choices. — 3:1 if needed
  • Keyboard focus indicator: The focus outline must have at least 3:1 contrast with the area around the segment. Check it on the track and selected background. — 3:1
  • Disabled appearance: Disabled controls do not need to meet these contrast ratios. — Not required

组件结构

  • Control: Container for the mutually exclusive segment choices.
  • Segment: Individual choice within the control.
  • Label: Visible text identifying a segment when its label is not hidden.
  • Icon: Optional caller-supplied icon shown inside a segment.

Segmented Control Item

单个分段项,在分段控件中渲染为单选按钮。

属性类型默认值说明
value *string该分段的唯一值,与父组件的 value 匹配。
label *string该分段的无障碍标签。除非 isLabelHidden 为 true,否则渲染为可见文本。
isLabelHiddenbooleanfalse是否在视觉上隐藏标签。为 true 时仅显示图标,label 用作 aria-label。
iconReactNode显示在标签前的图标元素。
isDisabledbooleanfalse是否禁用该单个项。