内容项 · Item
内容项用于表格与列表场景。下面的官方示例展示原生用法与状态,属性名保持上游 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:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
API 与上游详细参考
优先使用 0.7.1 官方中文说明;上游尚未提供中文的条目保留英文。属性名、类型及默认值保持原生 API,不把示例状态名称当成组件属性。
Item
通用项目原语,统一 Astryx 中 "起始内容 + 标签 + 描述 + 结束内容" 的布局模式。适用于下拉菜单、选择器、联系人列表、通知、文件浏览器和活动流等场景。
使用建议
- 使用命名插槽(startContent、label、description、endContent)处理常见布局。
- 菜单和密集列表使用 density="compact",标准行使用 "balanced",宽松布局使用 "spacious"。
- 设置 labelLines 和 descriptionLines 控制内容长度不定时的截断。
- 当起始或结束内容高于单行文本时使用 align="start"。
- 避免:不要在交互式 Item 内嵌套交互元素(按钮、链接)。
- 避免:不要使用 Item 进行视图间导航:使用适当的导航组件。
- 避免:不要直接添加已读/未读行为:组合一个薄包装器如 PreviewItem。
主题 API
{
"targets": [
{
"className": "astryx-item",
"visualProps": [
"density",
"align"
]
},
{
"className": "astryx-item-swipe-panel",
"visualProps": [
"side"
]
},
{
"className": "astryx-item-swipe-action",
"visualProps": [
"variant"
]
}
],
"vars": [
{
"name": "--_item-label-color",
"description": "Color of the label line. Unset by default (the label uses the primary text token); a parent sets it to recolor the label it renders, as the destructive dropdown/context menu item does.",
"default": "var(--color-text-primary)",
"private": true
},
{
"name": "--_item-description-color",
"description": "Companion to --_item-label-color for the secondary description line.",
"default": "var(--color-text-secondary)",
"private": true
},
{
"name": "--_item-inset-inline",
"description": "Inline inset of the row. Item derives its paddingInline from this variable, and List reads it to cancel the inset when edgeCompensation=\"inline\". Set paddingInline on `item` in a theme and both stay in sync.",
"default": "var(--spacing-2) (var(--spacing-3) for density=\"spacious\")",
"private": true
}
],
"derived": [
{
"property": "paddingInline",
"vars": [
"--_item-inset-inline"
]
}
]
}
Item
通用项目原语,统一 "起始内容 + 标签 + 描述 + 结束内容" 布局模式。用作列表项、菜单项、联系人行、通知等的构建块。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| label * | ReactNode | 标识此项目的主要文本。接受字符串(自动截断)或 ReactNode(用于富内容)。 | |
| marker | ReactNode | 在 startContent 之前渲染的标记,作为直接 flex 子元素。用于需要自定义基线对齐的列表项目符号/计数器。 | |
| startContent | ReactNode | 在标签/描述区域之前渲染的内容,例如图标、头像或复选框。 | |
| description | ReactNode | 次要文本:副标题、描述或辅助信息。 | |
| endContent | ReactNode | 在标签/描述区域之后渲染的内容,例如徽章、元数据、时间戳或操作按钮。 | |
| as | 'div' | 'li' | 'span' | ElementType | 'div' | 根元素的 HTML 元素。 |
| align | 'center' | 'start' | 'center' | 起始/结束内容插槽的垂直对齐方式。 |
| density | 'compact' | 'balanced' | 'spacious' | 'balanced' | 间距密度。"compact" 使用 4px 块内距,"balanced" 使用 8px,"spacious" 使用 12px 块内距和内联内距。 |
| labelLines | number | 标签截断前的最大行数。 | |
| descriptionLines | number | 描述截断前的最大行数。 | |
| layout | 'stacked' | 'inline' | 'stacked' | How the label and description sit together. stacked puts the description on its own line below the label; inline keeps both on one line, description ellipsizing first, so the row fits a fixed-height host. |
| onClick | (event: MouseEvent) => void | 点击处理函数。使项目可点击,具有按钮语义。 | |
| interactiveRef | RefObject<HTMLElement | null> | 指向嵌套控件(如 startContent 中的复选框)的 ref,该控件承载项目的键盘访问和操作。行成为更大的点击/触摸目标,将表面点击委托给该控件(useClickableContainer),且不渲染不可见按钮/锚点,因此行不会增加第二个 Tab 停留点(WCAG 4.1.2)。与 onClick/href 互斥——设置后二者将被忽略。 | |
| href | string | 链接 URL。通过不可见锚点元素使项目成为链接。 | |
| target | '_blank' | '_self' | 链接目标。仅与 href 一起使用。target="_blank" 会自动添加 noopener noreferrer。 | |
| rel | string | 链接关系标记。target="_blank" 会自动合并 noopener noreferrer。 | |
| isHighlighted | boolean | false | 高亮状态(悬停/键盘焦点外观)。 |
| isSelected | boolean | false | 选中状态。 |
| isDisabled | boolean | false | 禁用状态。 |
| swipeActions | {leading?: ItemSwipeAction[]; trailing?: ItemSwipeAction[]} | Swipe actions for touch: the verbs a sideways drag uncovers on each side, outermost last, each {id?, label, icon?, onActivate, isDisabled?, variant?: 'neutral' | 'accent' | 'destructive', hasRemoval?}. leading is uncovered by a drag toward the inline end, trailing toward the inline start. A mouse never starts the drag and a mostly vertical drag stays the scroller's. The gesture is a touch accelerator and never a row's only path to a verb: a verb reachable only by swipe is unreachable by keyboard and by mouse, so every entry must also be reachable through the row's own content. Served on a row whose role permits interactive descendants (a listitem, a row with no role) and not on an option, a menu item, or a row that is the enlarged target of a native radio. The element containing the rows clips in the inline axis with overflow-inline: clip — List does; any other host does it once. hasRemoval only says the row holds out after the action fires instead of springing back. The gesture and its panels are loaded on demand the first time a row has swipe actions, so a row without them ships none of it. | |
| swipeBehavior | 'reveal' | 'commit' | 'reveal' | What a swipe does. reveal rests the row open with every entry a real button and fires the outermost on a long drag or a fling; commit slides the row out and fires the outermost on release, with nothing resting and a presentational panel. commit fits one entry per side. |
| ref | React.Ref<HTMLDivElement> | 转发到根元素的引用。 | |
| xstyle | StyleXStyles | StyleX 样式,用于布局自定义。必须是 stylex.create() 的值。 | |
| data-testid | string | 自动化测试的选择器。 |
组件结构
- 标记: 在起始内容之前渲染的可选列表项目符号/计数器。
- 起始内容: 前导视觉:头像、图标、图片或复选框。
- 标签: 标识项目的主要文本。
- 描述: 标签下方的次要辅助文本。
- 结束内容: 末端对齐内容:徽章、时间戳或操作按钮。
完整示例的额外依赖
部分示例使用独立图标包。示例清单中的每条安装命令包含该示例实际需要的依赖;若要运行本页全部示例,还需安装:
npm install @heroicons/react@2.2.0
示例的 StyleX 编译要求
ItemDocumentTabs 包含 stylex.create,需要配置 StyleX 源码编译流程。仅引入 Core 预编译 CSS 不足以运行这些示例样式,复制前请阅读样式与 Tailwind。