table · glass-apple · 灵感来源:GOV.UK table / Polaris data-table
横向放不下时整块滚动,区域可聚焦
| 组件 | 类型 | 材质数 | 浏览量 | 更新 |
|---|---|---|---|---|
| 玻璃按钮 | 按钮 | 3 | 1 284 | 2026-10-24 |
| 玻璃输入框 | 输入 | 3 | 963 | 2026-10-30 |
| 玻璃抽屉 | 抽屉 | 3 | 12 407 | 2026-10-31 |
| 极简通知 | 通知 | 3 | 77 | 2026-10-19 |
| 拟态骨架屏 | 骨架 | 3 | 5 | 2026-10-12 |
Data Table · 玻璃数据表 · 表格 / Glass
做一个 Data Table(玻璃数据表):
- table + caption(视觉隐藏);表头 scope=col,首列当行头 scope=row
- 文本左对齐、数字右对齐 + tabular-nums,表头跟数据同向;不居中
- 内容换行不截断;放不下时容器横向滚动(role=region + aria-label + tabindex=0)
- 半透明底 + 模糊 + 发丝分隔线,悬停让整行陷进背景色
- 只读版没有排序 / 筛选 / 选择 / 固定列;空表换成空态组件
用这些 CSS 变量:--color-text --color-text-muted --color-text-subtle --glass-bg --glass-border --glass-inset --glass-recess --text-2xs
灵感参考:GOV.UK table / Polaris data-table--color-text --color-text-muted --color-text-subtle --glass-bg --glass-border --glass-inset --glass-recess --text-2xs
悬停 / 焦点
/r/table--glass-apple.json
免外壳的 markdown 版:/llms/components/table--glass-apple.mdframed=false:只留滚动容器,材质底不重复画import { type ReactNode } from 'react';
export interface TableColumn {
key: string;
header: string;
/** end = 数字列:表头与数值一起右对齐(GOV / Polaris 同一条) */
align?: 'start' | 'end';
/** 列宽只写 Tailwind 宽度类,不写 px 字面量 */
width?: string;
}
export interface TableRow {
id: string;
cells: Record<string, ReactNode>;
}
interface Props {
caption: string;
columns: TableColumn[];
rows: TableRow[];
/** false = 只留滚动容器,材质底交给外层面板(嵌在卡片里时不再套一层卡) */
framed?: boolean;
className?: string;
}
/** 玻璃数据表:半透明底 + 模糊 + 发丝分隔线;首列当行头,悬停让整行陷进背景 */
export function GlassAppleTable({ caption, columns, rows, framed = true, className = '' }: Props) {
return (
<div
role="region"
aria-label={caption}
tabIndex={0}
className={`
overflow-x-auto outline-offset-2
${framed
? 'rounded-xl bg-[var(--glass-bg)] border border-[var(--glass-border)] backdrop-blur-xl shadow-[var(--glass-inset)]'
: ''}
${className}
`}
>
<table className="w-full min-w-[34rem] border-collapse text-sm">
<caption className="sr-only">{caption}</caption>
<thead>
<tr className="border-b border-[var(--glass-border)]">
{columns.map((c) => (
<th
key={c.key}
scope="col"
className={`
px-4 py-3 text-[length:var(--text-2xs)] font-medium uppercase tracking-[0.14em]
text-[var(--color-text-subtle)] whitespace-nowrap
${c.align === 'end' ? 'text-right' : 'text-left'}
${c.width ?? ''}
`}
>
{c.header}
</th>
))}
</tr>
</thead>
<tbody>
{rows.map((row) => (
<tr
key={row.id}
className="border-b border-[var(--glass-border)] last:border-b-0 transition-colors hover:bg-[var(--glass-recess)]"
>
{columns.map((c, i) =>
i === 0 ? (
<th
key={c.key}
scope="row"
className="px-4 py-3 text-left font-medium text-[var(--color-text)] break-words"
>
{row.cells[c.key]}
</th>
) : (
<td
key={c.key}
className={`
px-4 py-3 text-[var(--color-text-muted)] break-words
${c.align === 'end' ? 'text-right tabular-nums whitespace-nowrap' : ''}
`}
>
{row.cells[c.key]}
</td>
),
)}
</tr>
))}
</tbody>
</table>
</div>
);
}
src/components/table/glass-apple/