标签页 · TabList
标签页用于导航场景。下面的官方示例展示原生用法与状态,属性名保持上游 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:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 标签页 · 交互示例 8:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 标签页 · 状态 9:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 标签页 · 基础用法 10:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 标签页 · 交互示例 11:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
API 与上游详细参考
优先使用 0.7.1 官方中文说明;上游尚未提供中文的条目保留英文。属性名、类型及默认值保持原生 API,不把示例状态名称当成组件属性。
Tab
单个标签项,渲染为按钮或锚点链接,具有选中状态样式和可选图标。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| value * | string | 此标签的唯一值,与 TabListContext.value 进行匹配。 | |
| label * | string | 此标签的无障碍标签。默认作为可见文本使用;当 isLabelHidden 为 true 时用作 aria-label。 | |
| isLabelHidden | boolean | false | 是否在视觉上隐藏标签。为 true 时,仅显示图标和 endContent,并将 label 用作无障碍 aria-label。 |
| href | string | 要导航到的 URL;提供时,标签渲染为锚点元素。 | |
| panelId | string | Id of the panel this tab controls, wired up as aria-controls where the TabList speaks the tabs pattern. Put the same id on the panel element. No effect under the navigation pattern, and a development warning says so. | |
| as | LinkComponentType | 用于替代 <a> 渲染链接标签的自定义组件。覆盖 LinkProvider 的默认值。仅在提供 href 时生效。 | |
| icon | ReactNode | 标签未选中时显示的图标元素。 | |
| selectedIcon | ReactNode | 标签选中时显示的图标元素;未提供时回退到 icon。 | |
| endContent | ReactNode | 在标签文本之后渲染的内容,例如徽章计数或状态点。 | |
| xstyle | StyleXStyles | StyleX 样式,用于布局自定义(边距、定位、尺寸)。必须是 stylex.create() 的值,而非内联样式对象如 style={{}}。 |
Tab List
TabList provides tab-style navigation for organizing content into categorized sections. Use it to let users switch between related views without leaving the page, with overflow items handled by a built-in "more" menu.
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| value * | string | The currently selected tab value. | |
| onChange * | (value: string) => void | Callback fired when a tab is selected. | |
| size | 'sm' | 'md' | 'lg' | 'md' | Size variant applied to all child tabs. |
| layout | 'hug' | 'fill' | 'hug' | Layout mode for tab sizing. 'hug': each tab hugs its content width. 'fill': tabs stretch equally to fill the container width. |
| hasDivider | boolean | false | Whether to show a bottom border divider under the tab list. |
| isFullBleed | boolean | false | Makes the tab strip escape its parent's container padding, extending to the container's content edges (cancels the nearest padded Layout container's --container-padding-* custom properties with negative margins). The inner strip pads back by the portion of the container inset that is not already supplied by the first or last tab stop, keeping edge labels aligned while a hasDivider underline spans the full content width. Matches Divider's isFullBleed: inline (start/end) edges only; block-edge docking stays with the surrounding layout. |
| role | AriaRole | ARIA role for the strip. 'tablist' asks for the WAI-ARIA tabs pattern: role="tablist" / role="tab" and aria-selected, with each tab pointing at the panel it controls via its panelId; only tabs may live in a tablist strip, and an href on a tab is ignored there. Left unset, the strip is a nav landmark marking the current tab with aria-current. Any other value is passed through to the element unchanged. | |
| overflow | 'auto' | 'scroll' | 'visible' | 'auto' | What happens when the tabs are wider than the strip. 'auto' lets the component choose, which today always scrolls. 'scroll' scrolls the tabs horizontally, with edge fades and arrow affordances for pointers that can hover. 'visible' turns overflow handling off and lets the tabs spill out of the strip. The selected tab is always scrolled back into view. |
| children * | ReactNode | Tab and TabMenu items to render inside the strip. | |
| xstyle | StyleXStyles | StyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value: not an inline style object like style={{}}. |
使用建议
- Keep tab labels short and descriptive so users can quickly scan available sections.
- Leave overflow handling on: a strip narrower than its tabs scrolls, and the selected tab is kept in view. Use TabMenu when you want a curated group of extra options rather than a scrolling strip.
- When using hasDivider with action buttons alongside tabs, match the Button size to the TabList size (both md, both sm); the divided tab strip reserves space so tabs and same-size buttons align to a shared baseline above the rail.
- Reach for role="tablist" when the strip switches panels in place, and give each tab a panelId pointing at the panel it opens: that link is how a screen reader gets from a tab to its content. Leave it off for navigation between views.
- Set isFullBleed to stretch a tab bar inside a padded LayoutHeader, Card, or Section to the container's inline content edges, instead of reaching for negative-margin CSS.
- 避免:Use tabs for sequential steps or workflows; use a stepper or wizard pattern instead.
- 避免:Place more than 6–8 visible tabs before the overflow menu; prioritize the most important categories.
- 避免:Confuse TabList with SegmentedControl or ToggleButton. TabList is for navigation between views. SegmentedControl and ToggleButton are input controls: SegmentedControl always has exactly one selected option, while ToggleButton can be toggled on or off.
主题 API
{
"targets": [
{
"className": "astryx-tab-list",
"visualProps": [
"size"
]
},
{
"className": "astryx-tab-strip"
},
{
"className": "astryx-tab-scroll-button"
},
{
"className": "astryx-tab",
"states": [
"selected"
]
},
{
"className": "astryx-tab-indicator",
"states": [
"selected"
]
},
{
"className": "astryx-tab-menu"
},
{
"className": "astryx-tab-menu-dropdown"
},
{
"className": "astryx-tab-menu-item"
}
],
"vars": [
{
"name": "--_tab-indicator-bottom",
"description": "Vertical offset of the selected-tab indicator from the tab bottom edge. A host that draws its own bottom divider (Toolbar) sets this so the indicator sits on the divider instead of above it.",
"default": "-1px",
"private": true
}
]
}
Tab
TabMenu
无障碍
- Tab label: Each label must have at least 4.5:1 contrast with the tab surface behind it. For Hover and Pointer down, measure the final background after the overlay layer is applied. — 4.5:1
组件结构
- Left Content: Most important area; hugs content width.
- Center-Fill Content: Stretches to fill available space.
- Right Content: Hugs content width.
Tab Menu
溢出菜单触发器,打开包含额外标签选项的下拉菜单,将选中选项的标签显示为触发器文本。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| label * | string | 触发器按钮的标签(无选项选中时显示)以及下拉菜单标题分隔线的文本。 | |
| options * | TabMenuOption[] | 在下拉菜单中渲染的菜单选项数组。 |