@tanishqkancharla/maui 0.0.13 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,20 +1,29 @@
1
- import type React from "react";
2
- export declare function Table(props: {
3
- children: React.ReactNode;
4
- }): React.JSX.Element;
5
- export declare function TableHead(props: {
6
- children: React.ReactNode;
7
- }): React.JSX.Element;
8
- export declare function TableBody(props: {
9
- children: React.ReactNode;
10
- }): React.JSX.Element;
11
- export declare function TableRow(props: {
12
- children: React.ReactNode;
13
- }): React.JSX.Element;
14
- export declare function TableHeaderCell(props: {
15
- children: React.ReactNode;
16
- }): React.JSX.Element;
17
- export declare function TableCell(props: {
18
- children: React.ReactNode;
19
- align?: "top" | "middle";
20
- }): React.JSX.Element;
1
+ import type { ReactNode } from "react";
2
+ import { type CellProps as AriaCellProps, type ColumnProps as AriaColumnProps, type RowProps as AriaRowProps, type TableBodyProps as AriaTableBodyProps, type TableFooterProps as AriaTableFooterProps, type TableHeaderProps as AriaTableHeaderProps, type TableProps as AriaTableProps } from "react-aria-components";
3
+ export type TableAlign = "start" | "center" | "end";
4
+ export interface TableProps extends Omit<AriaTableProps, "className"> {
5
+ }
6
+ export declare function Table(props: TableProps): import("react").JSX.Element;
7
+ export interface TableHeaderProps<T> extends Omit<AriaTableHeaderProps<T>, "className"> {
8
+ }
9
+ export declare function TableHeader<T extends object = object>(props: TableHeaderProps<T>): import("react").JSX.Element;
10
+ export interface TableHeadProps extends Omit<AriaColumnProps, "className"> {
11
+ align?: TableAlign;
12
+ }
13
+ export declare function TableHead({ align, ...props }: TableHeadProps): import("react").JSX.Element;
14
+ export interface TableBodyProps<T> extends Omit<AriaTableBodyProps<T>, "className"> {
15
+ }
16
+ export declare function TableBody<T extends object = object>(props: TableBodyProps<T>): import("react").JSX.Element;
17
+ export interface TableFooterProps<T> extends Omit<AriaTableFooterProps<T>, "className"> {
18
+ }
19
+ export declare function TableFooter<T extends object = object>(props: TableFooterProps<T>): import("react").JSX.Element;
20
+ export interface TableRowProps<T> extends Omit<AriaRowProps<T>, "className"> {
21
+ }
22
+ export declare function TableRow<T extends object = object>(props: TableRowProps<T>): import("react").JSX.Element;
23
+ export interface TableCellProps extends Omit<AriaCellProps, "className"> {
24
+ align?: TableAlign;
25
+ }
26
+ export declare function TableCell({ align, ...props }: TableCellProps): import("react").JSX.Element;
27
+ export declare function TableCaption(props: {
28
+ children: ReactNode;
29
+ }): import("react").JSX.Element;
@@ -1,42 +1,116 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Cell as AriaCell, Column as AriaColumn, Row as AriaRow, Table as AriaTable, TableBody as AriaTableBody, TableFooter as AriaTableFooter, TableHeader as AriaTableHeader, } from "react-aria-components";
2
3
  import { style, useStyles } from "purse-styles";
3
- import { border } from "../tokens/borders";
4
+ import { backgroundColor } from "../tokens/background";
5
+ import { border, borderColor } from "../tokens/borders";
6
+ import { colors } from "../tokens/colors";
7
+ import { focusRing } from "../tokens/focusRing";
8
+ import { spacing } from "../tokens/spacing";
4
9
  import { text } from "../tokens/text";
5
- import { labelText } from "./Typography";
6
- const tableClass = style({
10
+ import { memoize } from "../utils/memoize";
11
+ const tableContainerClass = style({
12
+ width: "100%",
13
+ overflowX: "auto",
14
+ });
15
+ const tableClass = style(focusRing("&[data-focus-visible]"), {
7
16
  borderCollapse: "collapse",
17
+ borderSpacing: 0,
8
18
  width: "100%",
19
+ outline: "none",
20
+ });
21
+ const tableHeaderClass = style({
22
+ outline: "none",
23
+ });
24
+ const tableHeadClass = memoize((align = "start") => style(text({ size: "xs", fontWeight: 500, color: "lowContrast" }), spacing.padding({ x: 4, y: 3 }), border(["bottom"], "border"), focusRing("&[data-focus-visible]"), {
25
+ textAlign: align,
26
+ verticalAlign: "middle",
27
+ whiteSpace: "nowrap",
28
+ outline: "none",
29
+ fontWeight: 500,
30
+ }));
31
+ const tableBodyClass = style({
32
+ outline: "none",
33
+ "& tr:last-child td": {
34
+ borderBottom: "none",
35
+ },
36
+ "&[data-empty]": {
37
+ textAlign: "center",
38
+ },
39
+ });
40
+ const tableFooterClass = style(text({ size: "sm", fontWeight: 500, color: "highContrast" }), {
41
+ backgroundColor: colors.gray[2],
42
+ "& td": {
43
+ borderBottom: "none",
44
+ fontWeight: 500,
45
+ backgroundColor: colors.gray[2],
46
+ },
47
+ "& tr:first-child td": {
48
+ borderTop: `1px solid ${borderColor.border}`,
49
+ },
50
+ "& tr:hover td, & tr[data-hovered] td": {
51
+ backgroundColor: colors.gray[2],
52
+ },
9
53
  });
10
- const tableHeaderCellClass = style(labelText, {
11
- padding: "0 12px 8px 0",
12
- textAlign: "left",
13
- verticalAlign: "bottom",
54
+ const tableRowClass = style({
55
+ outline: "none",
56
+ cursor: "default",
57
+ "&:hover td, &[data-hovered] td": {
58
+ backgroundColor: backgroundColor.elementHover,
59
+ },
60
+ "&[data-selected] td": {
61
+ backgroundColor: backgroundColor.elementActive,
62
+ },
63
+ "&[data-disabled]": {
64
+ color: colors.gray[8],
65
+ },
14
66
  });
15
- const tableBodyCellClass = style(text({ size: "sm", fontWeight: 400, color: "lowContrast" }), border(["top"], "border"), {
16
- padding: "10px 12px 10px 0",
17
- verticalAlign: "top",
67
+ const tableCellClass = memoize((align = "start") => style(text({ size: "sm", fontWeight: 400, color: "highContrast" }), spacing.padding({ x: 4, y: 3 }), border(["bottom"], "border"), focusRing("&[data-focus-visible]"), {
68
+ textAlign: align,
69
+ verticalAlign: "middle",
70
+ outline: "none",
71
+ '&[role="rowheader"]': {
72
+ fontWeight: 500,
73
+ },
74
+ }));
75
+ const tableCaptionClass = style(text({ size: "xs", fontWeight: 400, color: "lowContrast" }), {
76
+ margin: 0,
77
+ marginTop: spacing.value(4),
78
+ });
79
+ const emptyStateClass = style(text({ size: "sm", fontWeight: 400, color: "lowContrast" }), spacing.padding({ x: 4, y: 8 }), {
80
+ textAlign: "center",
18
81
  });
19
82
  export function Table(props) {
83
+ const containerClassName = useStyles(tableContainerClass);
20
84
  const className = useStyles(tableClass);
21
- return _jsx("table", { className: className, children: props.children });
85
+ return (_jsx("div", { className: containerClassName, children: _jsx(AriaTable, { ...props, className: className }) }));
86
+ }
87
+ export function TableHeader(props) {
88
+ const className = useStyles(tableHeaderClass);
89
+ return _jsx(AriaTableHeader, { ...props, className: className });
22
90
  }
23
- export function TableHead(props) {
24
- return _jsx("thead", { children: props.children });
91
+ export function TableHead({ align = "start", ...props }) {
92
+ const className = useStyles(tableHeadClass(align));
93
+ return _jsx(AriaColumn, { ...props, className: className });
25
94
  }
26
95
  export function TableBody(props) {
27
- return _jsx("tbody", { children: props.children });
96
+ const className = useStyles(tableBodyClass);
97
+ const emptyClassName = useStyles(emptyStateClass);
98
+ return (_jsx(AriaTableBody, { ...props, className: className, renderEmptyState: props.renderEmptyState ??
99
+ (() => _jsx("div", { className: emptyClassName, children: "No results." })) }));
100
+ }
101
+ export function TableFooter(props) {
102
+ const className = useStyles(tableFooterClass);
103
+ return _jsx(AriaTableFooter, { ...props, className: className });
28
104
  }
29
105
  export function TableRow(props) {
30
- return _jsx("tr", { children: props.children });
106
+ const className = useStyles(tableRowClass);
107
+ return _jsx(AriaRow, { ...props, className: className });
31
108
  }
32
- export function TableHeaderCell(props) {
33
- const className = useStyles(tableHeaderCellClass);
34
- return _jsx("th", { className: className, children: props.children });
109
+ export function TableCell({ align = "start", ...props }) {
110
+ const className = useStyles(tableCellClass(align));
111
+ return _jsx(AriaCell, { ...props, className: className });
35
112
  }
36
- const tableBodyCellMiddleClass = style({
37
- verticalAlign: "middle",
38
- });
39
- export function TableCell(props) {
40
- const className = useStyles(tableBodyCellClass, props.align === "middle" && tableBodyCellMiddleClass);
41
- return _jsx("td", { className: className, children: props.children });
113
+ export function TableCaption(props) {
114
+ const className = useStyles(tableCaptionClass);
115
+ return _jsx("div", { className: className, children: props.children });
42
116
  }
package/dist/maui.d.ts CHANGED
@@ -28,8 +28,7 @@ export { Select, SelectItem, type SelectProps, type SelectItemProps, } from "./c
28
28
  export { Dialog } from "./components/Dialog";
29
29
  export { Tooltip } from "./components/Tooltip";
30
30
  export { Overlay } from "./components/Overlay";
31
- export { Panel } from "./components/Panel";
32
- export { Table, TableHead, TableBody, TableRow, TableHeaderCell, TableCell, } from "./components/Table";
31
+ export { Table, TableHeader, TableHead, TableBody, TableFooter, TableRow, TableCell, TableCaption, type TableAlign, type TableProps, type TableHeaderProps, type TableHeadProps, type TableBodyProps, type TableFooterProps, type TableRowProps, type TableCellProps, } from "./components/Table";
33
32
  export { Prose, useProseSize, proseMaxWidth } from "./components/Prose";
34
33
  export { Editor, type EditorProps } from "./components/Editor";
35
34
  export { Thinking, type ThinkingProps, type ThinkingVariant, } from "./components/Thinking";
package/dist/maui.js CHANGED
@@ -31,8 +31,7 @@ export { Select, SelectItem, } from "./components/Select";
31
31
  export { Dialog } from "./components/Dialog";
32
32
  export { Tooltip } from "./components/Tooltip";
33
33
  export { Overlay } from "./components/Overlay";
34
- export { Panel } from "./components/Panel";
35
- export { Table, TableHead, TableBody, TableRow, TableHeaderCell, TableCell, } from "./components/Table";
34
+ export { Table, TableHeader, TableHead, TableBody, TableFooter, TableRow, TableCell, TableCaption, } from "./components/Table";
36
35
  export { Prose, useProseSize, proseMaxWidth } from "./components/Prose";
37
36
  export { Editor } from "./components/Editor";
38
37
  export { Thinking, } from "./components/Thinking";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanishqkancharla/maui",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "description": "Maui design system",
5
5
  "type": "module",
6
6
  "main": "./dist/maui.js",
@@ -116,14 +116,13 @@ import { Text as TextIcon } from "maui/icons"
116
116
  - `Avatar`
117
117
  - `Badge`
118
118
  - `Code`, `Kbd`, `CodeBlock`
119
- - `Table` / `TableHead` / `TableBody` / `TableRow` / `TableHeaderCell` / `TableCell`
120
- - `Panel` — gallery/demo surface
119
+ - `Table` — React Aria table. `TableHeader` contains `TableHead` columns directly (no `TableRow`). Mark the identifying column with `isRowHeader` (required; usually the name/id column, not a leading checkbox or drag handle). `align` on `TableHead` / `TableCell` is `"start"` | `"center"` | `"end"`. `TableFooter` fills with `colors.gray[2]`. Place `TableCaption` after `Table`. `TableBody` renders “No results.” when empty; pass `renderEmptyState` to replace it.
121
120
  - `FuzzyString` — highlight segments; takes a match result, not a plain string
122
121
  - `Thinking` — 3×3 Game of Life indicator; reseeds when the board dies or loops
123
122
 
124
123
  ## Reference: patterns and apps
125
124
 
126
- Patterns and demo apps are not part of the `"maui"` package barrel. Use the closest one as a reference before inventing new layout (also available via `"maui/src/..."`):
125
+ Patterns, demo apps, and the gallery `Panel` preview surface are not part of the `"maui"` package barrel. Use the closest one as a reference before inventing new layout (also available via `"maui/src/..."`):
127
126
 
128
127
  ### Patterns — `src/patterns/`
129
128
 
@@ -17,7 +17,6 @@ import {
17
17
  import { ListBox, ListBoxItem } from "../../components/ListBox"
18
18
  import { Menu, MenuItem, MenuTrigger } from "../../components/Menu"
19
19
  import { Overlay } from "../../components/Overlay"
20
- import { Panel } from "../../components/Panel"
21
20
  import { Prose } from "../../components/Prose"
22
21
  import { RadioOption, RadioOptionGroup } from "../../components/Radio"
23
22
  import { Select, SelectItem } from "../../components/Select"
@@ -26,9 +25,11 @@ import { Switch } from "../../components/Switch"
26
25
  import {
27
26
  Table,
28
27
  TableBody,
28
+ TableCaption,
29
29
  TableCell,
30
+ TableFooter,
30
31
  TableHead,
31
- TableHeaderCell,
32
+ TableHeader,
32
33
  TableRow,
33
34
  } from "../../components/Table"
34
35
  import { Text } from "../../components/Text"
@@ -264,11 +265,6 @@ export const catalog: CatalogComponent[] = [
264
265
  { name: "className" },
265
266
  ],
266
267
  },
267
- {
268
- name: "Panel",
269
- info: "Raised preview surface.",
270
- attributes: [],
271
- },
272
268
  {
273
269
  name: "Icons",
274
270
  info: "Icon set. Use as <Icons.Plus size=\"sm\" />. The Icons namespace is not tree-shakeable.",
@@ -346,6 +342,53 @@ export const catalog: CatalogComponent[] = [
346
342
  info: "Select option.",
347
343
  attributes: [{ name: "id" }],
348
344
  },
345
+ {
346
+ name: "Table",
347
+ info: "Accessible data table. Pair with TableHeader, TableHead, TableBody, TableRow, and TableCell.",
348
+ attributes: [{ name: "aria-label" }],
349
+ },
350
+ {
351
+ name: "TableHeader",
352
+ info: "Table column header row. Contains TableHead columns directly, not TableRow.",
353
+ attributes: [],
354
+ },
355
+ {
356
+ name: "TableHead",
357
+ info: "Column header. First identifying column should set isRowHeader. align is start, center, or end.",
358
+ attributes: [
359
+ { name: "isRowHeader", boolean: true },
360
+ { name: "align", values: ["start", "center", "end"] },
361
+ { name: "id" },
362
+ ],
363
+ },
364
+ {
365
+ name: "TableBody",
366
+ info: "Table rows. Renders an empty state when there are no rows.",
367
+ attributes: [],
368
+ },
369
+ {
370
+ name: "TableRow",
371
+ info: "Table row.",
372
+ attributes: [{ name: "id" }],
373
+ },
374
+ {
375
+ name: "TableCell",
376
+ info: "Table cell. align is start, center, or end.",
377
+ attributes: [
378
+ { name: "align", values: ["start", "center", "end"] },
379
+ { name: "colSpan" },
380
+ ],
381
+ },
382
+ {
383
+ name: "TableFooter",
384
+ info: "Summary row group below the body.",
385
+ attributes: [],
386
+ },
387
+ {
388
+ name: "TableCaption",
389
+ info: "Caption below the table. Place after Table, often inside a figure.",
390
+ attributes: [],
391
+ },
349
392
  {
350
393
  name: "Tooltip",
351
394
  info: "Hover tooltip.",
@@ -400,7 +443,6 @@ export const previewScope: Record<string, unknown> = {
400
443
  MenuItem,
401
444
  MenuTrigger,
402
445
  Overlay,
403
- Panel,
404
446
  Editor,
405
447
  Prose,
406
448
  RadioOption,
@@ -411,9 +453,11 @@ export const previewScope: Record<string, unknown> = {
411
453
  Switch,
412
454
  Table,
413
455
  TableBody,
456
+ TableCaption,
414
457
  TableCell,
458
+ TableFooter,
415
459
  TableHead,
416
- TableHeaderCell,
460
+ TableHeader,
417
461
  TableRow,
418
462
  Text,
419
463
  Thinking,
@@ -1,61 +1,223 @@
1
+ import type { ReactNode } from "react"
2
+ import {
3
+ Cell as AriaCell,
4
+ Column as AriaColumn,
5
+ Row as AriaRow,
6
+ Table as AriaTable,
7
+ TableBody as AriaTableBody,
8
+ TableFooter as AriaTableFooter,
9
+ TableHeader as AriaTableHeader,
10
+ type CellProps as AriaCellProps,
11
+ type ColumnProps as AriaColumnProps,
12
+ type RowProps as AriaRowProps,
13
+ type TableBodyProps as AriaTableBodyProps,
14
+ type TableFooterProps as AriaTableFooterProps,
15
+ type TableHeaderProps as AriaTableHeaderProps,
16
+ type TableProps as AriaTableProps,
17
+ } from "react-aria-components"
1
18
  import { style, useStyles } from "purse-styles"
2
- import type React from "react"
3
- import { border } from "../tokens/borders"
19
+ import { backgroundColor } from "../tokens/background"
20
+ import { border, borderColor } from "../tokens/borders"
21
+ import { colors } from "../tokens/colors"
22
+ import { focusRing } from "../tokens/focusRing"
23
+ import { spacing } from "../tokens/spacing"
4
24
  import { text } from "../tokens/text"
5
- import { labelText } from "./Typography"
25
+ import { memoize } from "../utils/memoize"
6
26
 
7
- const tableClass = style({
27
+ export type TableAlign = "start" | "center" | "end"
28
+
29
+ const tableContainerClass = style({
30
+ width: "100%",
31
+ overflowX: "auto",
32
+ })
33
+
34
+ const tableClass = style(focusRing("&[data-focus-visible]"), {
8
35
  borderCollapse: "collapse",
36
+ borderSpacing: 0,
9
37
  width: "100%",
38
+ outline: "none",
10
39
  })
11
40
 
12
- const tableHeaderCellClass = style(labelText, {
13
- padding: "0 12px 8px 0",
14
- textAlign: "left",
15
- verticalAlign: "bottom",
41
+ const tableHeaderClass = style({
42
+ outline: "none",
16
43
  })
17
44
 
18
- const tableBodyCellClass = style(text({ size: "sm", fontWeight: 400, color: "lowContrast" }), border(["top"], "border"), {
19
- padding: "10px 12px 10px 0",
20
- verticalAlign: "top",
45
+ const tableHeadClass = memoize((align: TableAlign = "start") =>
46
+ style(
47
+ text({ size: "xs", fontWeight: 500, color: "lowContrast" }),
48
+ spacing.padding({ x: 4, y: 3 }),
49
+ border(["bottom"], "border"),
50
+ focusRing("&[data-focus-visible]"),
51
+ {
52
+ textAlign: align,
53
+ verticalAlign: "middle",
54
+ whiteSpace: "nowrap",
55
+ outline: "none",
56
+ fontWeight: 500,
57
+ },
58
+ ),
59
+ )
60
+
61
+ const tableBodyClass = style({
62
+ outline: "none",
63
+ "& tr:last-child td": {
64
+ borderBottom: "none",
65
+ },
66
+ "&[data-empty]": {
67
+ textAlign: "center",
68
+ },
69
+ })
70
+
71
+ const tableFooterClass = style(
72
+ text({ size: "sm", fontWeight: 500, color: "highContrast" }),
73
+ {
74
+ backgroundColor: colors.gray[2],
75
+ "& td": {
76
+ borderBottom: "none",
77
+ fontWeight: 500,
78
+ backgroundColor: colors.gray[2],
79
+ },
80
+ "& tr:first-child td": {
81
+ borderTop: `1px solid ${borderColor.border}`,
82
+ },
83
+ "& tr:hover td, & tr[data-hovered] td": {
84
+ backgroundColor: colors.gray[2],
85
+ },
86
+ },
87
+ )
88
+
89
+ const tableRowClass = style({
90
+ outline: "none",
91
+ cursor: "default",
92
+ "&:hover td, &[data-hovered] td": {
93
+ backgroundColor: backgroundColor.elementHover,
94
+ },
95
+ "&[data-selected] td": {
96
+ backgroundColor: backgroundColor.elementActive,
97
+ },
98
+ "&[data-disabled]": {
99
+ color: colors.gray[8],
100
+ },
21
101
  })
22
102
 
23
- export function Table(props: { children: React.ReactNode }) {
103
+ const tableCellClass = memoize((align: TableAlign = "start") =>
104
+ style(
105
+ text({ size: "sm", fontWeight: 400, color: "highContrast" }),
106
+ spacing.padding({ x: 4, y: 3 }),
107
+ border(["bottom"], "border"),
108
+ focusRing("&[data-focus-visible]"),
109
+ {
110
+ textAlign: align,
111
+ verticalAlign: "middle",
112
+ outline: "none",
113
+ '&[role="rowheader"]': {
114
+ fontWeight: 500,
115
+ },
116
+ },
117
+ ),
118
+ )
119
+
120
+ const tableCaptionClass = style(
121
+ text({ size: "xs", fontWeight: 400, color: "lowContrast" }),
122
+ {
123
+ margin: 0,
124
+ marginTop: spacing.value(4),
125
+ },
126
+ )
127
+
128
+ const emptyStateClass = style(
129
+ text({ size: "sm", fontWeight: 400, color: "lowContrast" }),
130
+ spacing.padding({ x: 4, y: 8 }),
131
+ {
132
+ textAlign: "center",
133
+ },
134
+ )
135
+
136
+ export interface TableProps extends Omit<AriaTableProps, "className"> {}
137
+
138
+ export function Table(props: TableProps) {
139
+ const containerClassName = useStyles(tableContainerClass)
24
140
  const className = useStyles(tableClass)
25
141
 
26
- return <table className={className}>{props.children}</table>
142
+ return (
143
+ <div className={containerClassName}>
144
+ <AriaTable {...props} className={className} />
145
+ </div>
146
+ )
27
147
  }
28
148
 
29
- export function TableHead(props: { children: React.ReactNode }) {
30
- return <thead>{props.children}</thead>
31
- }
149
+ export interface TableHeaderProps<T>
150
+ extends Omit<AriaTableHeaderProps<T>, "className"> {}
32
151
 
33
- export function TableBody(props: { children: React.ReactNode }) {
34
- return <tbody>{props.children}</tbody>
152
+ export function TableHeader<T extends object = object>(
153
+ props: TableHeaderProps<T>,
154
+ ) {
155
+ const className = useStyles(tableHeaderClass)
156
+
157
+ return <AriaTableHeader {...props} className={className} />
35
158
  }
36
159
 
37
- export function TableRow(props: { children: React.ReactNode }) {
38
- return <tr>{props.children}</tr>
160
+ export interface TableHeadProps extends Omit<AriaColumnProps, "className"> {
161
+ align?: TableAlign
39
162
  }
40
163
 
41
- export function TableHeaderCell(props: { children: React.ReactNode }) {
42
- const className = useStyles(tableHeaderCellClass)
164
+ export function TableHead({ align = "start", ...props }: TableHeadProps) {
165
+ const className = useStyles(tableHeadClass(align))
43
166
 
44
- return <th className={className}>{props.children}</th>
167
+ return <AriaColumn {...props} className={className} />
45
168
  }
46
169
 
47
- const tableBodyCellMiddleClass = style({
48
- verticalAlign: "middle",
49
- })
170
+ export interface TableBodyProps<T>
171
+ extends Omit<AriaTableBodyProps<T>, "className"> {}
50
172
 
51
- export function TableCell(props: {
52
- children: React.ReactNode
53
- align?: "top" | "middle"
54
- }) {
55
- const className = useStyles(
56
- tableBodyCellClass,
57
- props.align === "middle" && tableBodyCellMiddleClass,
173
+ export function TableBody<T extends object = object>(props: TableBodyProps<T>) {
174
+ const className = useStyles(tableBodyClass)
175
+ const emptyClassName = useStyles(emptyStateClass)
176
+
177
+ return (
178
+ <AriaTableBody
179
+ {...props}
180
+ className={className}
181
+ renderEmptyState={
182
+ props.renderEmptyState ??
183
+ (() => <div className={emptyClassName}>No results.</div>)
184
+ }
185
+ />
58
186
  )
187
+ }
188
+
189
+ export interface TableFooterProps<T>
190
+ extends Omit<AriaTableFooterProps<T>, "className"> {}
191
+
192
+ export function TableFooter<T extends object = object>(
193
+ props: TableFooterProps<T>,
194
+ ) {
195
+ const className = useStyles(tableFooterClass)
196
+
197
+ return <AriaTableFooter {...props} className={className} />
198
+ }
199
+
200
+ export interface TableRowProps<T>
201
+ extends Omit<AriaRowProps<T>, "className"> {}
202
+
203
+ export function TableRow<T extends object = object>(props: TableRowProps<T>) {
204
+ const className = useStyles(tableRowClass)
205
+
206
+ return <AriaRow {...props} className={className} />
207
+ }
208
+
209
+ export interface TableCellProps extends Omit<AriaCellProps, "className"> {
210
+ align?: TableAlign
211
+ }
212
+
213
+ export function TableCell({ align = "start", ...props }: TableCellProps) {
214
+ const className = useStyles(tableCellClass(align))
215
+
216
+ return <AriaCell {...props} className={className} />
217
+ }
218
+
219
+ export function TableCaption(props: { children: ReactNode }) {
220
+ const className = useStyles(tableCaptionClass)
59
221
 
60
- return <td className={className}>{props.children}</td>
222
+ return <div className={className}>{props.children}</div>
61
223
  }
package/src/maui.ts CHANGED
@@ -81,14 +81,23 @@ export {
81
81
  export { Dialog } from "./components/Dialog"
82
82
  export { Tooltip } from "./components/Tooltip"
83
83
  export { Overlay } from "./components/Overlay"
84
- export { Panel } from "./components/Panel"
85
84
  export {
86
85
  Table,
86
+ TableHeader,
87
87
  TableHead,
88
88
  TableBody,
89
+ TableFooter,
89
90
  TableRow,
90
- TableHeaderCell,
91
91
  TableCell,
92
+ TableCaption,
93
+ type TableAlign,
94
+ type TableProps,
95
+ type TableHeaderProps,
96
+ type TableHeadProps,
97
+ type TableBodyProps,
98
+ type TableFooterProps,
99
+ type TableRowProps,
100
+ type TableCellProps,
92
101
  } from "./components/Table"
93
102
  export { Prose, useProseSize, proseMaxWidth } from "./components/Prose"
94
103
  export { Editor, type EditorProps } from "./components/Editor"
@@ -2,7 +2,8 @@ import { useStyles } from "purse-styles"
2
2
  import { CodeBlock } from "../components/CodeBlock"
3
3
  import { Panel } from "../components/Panel"
4
4
  import { Prose } from "../components/Prose"
5
- import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "../components/Table"
5
+ import { Table, TableBody, TableCell, TableHead,
6
+ TableHeader, TableRow } from "../components/Table"
6
7
  import { H2, H3, P } from "../components/Typography"
7
8
  import { background } from "../tokens/background"
8
9
  import { border } from "../tokens/borders"
@@ -39,14 +40,12 @@ export function BackgroundColorTokenPage() {
39
40
  </P>
40
41
 
41
42
  <H3>Values</H3>
42
- <Table>
43
- <TableHead>
44
- <TableRow>
45
- <TableHeaderCell>Name</TableHeaderCell>
46
- <TableHeaderCell>Value</TableHeaderCell>
47
- <TableHeaderCell>Use</TableHeaderCell>
48
- </TableRow>
49
- </TableHead>
43
+ <Table aria-label="Background color tokens">
44
+ <TableHeader>
45
+ <TableHead isRowHeader>Name</TableHead>
46
+ <TableHead>Value</TableHead>
47
+ <TableHead>Use</TableHead>
48
+ </TableHeader>
50
49
  <TableBody>
51
50
  <TableRow>
52
51
  <TableCell>
@@ -1,5 +1,6 @@
1
1
  import { style, useStyles, type CSSProperties } from "purse-styles"
2
- import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "../components/Table"
2
+ import { Table, TableBody, TableCell, TableHead,
3
+ TableHeader, TableRow } from "../components/Table"
3
4
  import { CodeBlock } from "../components/CodeBlock"
4
5
  import { Panel } from "../components/Panel"
5
6
  import { Prose } from "../components/Prose"
@@ -54,14 +55,12 @@ export function BordersTokenPage() {
54
55
  </P>
55
56
 
56
57
  <H3>Values</H3>
57
- <Table>
58
- <TableHead>
59
- <TableRow>
60
- <TableHeaderCell>Input</TableHeaderCell>
61
- <TableHeaderCell>Values</TableHeaderCell>
62
- <TableHeaderCell>Use</TableHeaderCell>
63
- </TableRow>
64
- </TableHead>
58
+ <Table aria-label="Border token values">
59
+ <TableHeader>
60
+ <TableHead isRowHeader>Input</TableHead>
61
+ <TableHead>Values</TableHead>
62
+ <TableHead>Use</TableHead>
63
+ </TableHeader>
65
64
  <TableBody>
66
65
  <TableRow>
67
66
  <TableCell>
@@ -102,13 +101,11 @@ export function BordersTokenPage() {
102
101
  </Table>
103
102
 
104
103
  <H3>Examples</H3>
105
- <Table>
106
- <TableHead>
107
- <TableRow>
108
- <TableHeaderCell>Call</TableHeaderCell>
109
- <TableHeaderCell>Use</TableHeaderCell>
110
- </TableRow>
111
- </TableHead>
104
+ <Table aria-label="Border token examples">
105
+ <TableHeader>
106
+ <TableHead isRowHeader>Call</TableHead>
107
+ <TableHead>Use</TableHead>
108
+ </TableHeader>
112
109
  <TableBody>
113
110
  {borderExamples.map((example) => (
114
111
  <TableRow key={example.label}>
@@ -6,7 +6,7 @@ import {
6
6
  TableBody,
7
7
  TableCell,
8
8
  TableHead,
9
- TableHeaderCell,
9
+ TableHeader,
10
10
  TableRow,
11
11
  } from "../components/Table"
12
12
  import { H2, H3, H4, Link, P } from "../components/Typography"
@@ -111,26 +111,24 @@ export function CodePage() {
111
111
  strings use blue in light and green in dark.
112
112
  </P>
113
113
 
114
- <Table>
115
- <TableHead>
116
- <TableRow>
117
- <TableHeaderCell>Role</TableHeaderCell>
118
- <TableHeaderCell>Sublime scope</TableHeaderCell>
119
- <TableHeaderCell>Color</TableHeaderCell>
120
- <TableHeaderCell>Sample</TableHeaderCell>
121
- </TableRow>
122
- </TableHead>
114
+ <Table aria-label="Maui Shiki theme tokens">
115
+ <TableHeader>
116
+ <TableHead isRowHeader>Role</TableHead>
117
+ <TableHead>Sublime scope</TableHead>
118
+ <TableHead>Color</TableHead>
119
+ <TableHead>Sample</TableHead>
120
+ </TableHeader>
123
121
  <TableBody>
124
122
  {themeTokens.map((token) => (
125
123
  <TableRow key={token.role}>
126
- <TableCell align="middle">{token.role}</TableCell>
127
- <TableCell align="middle">
124
+ <TableCell>{token.role}</TableCell>
125
+ <TableCell>
128
126
  <Code>{token.sublime}</Code>
129
127
  </TableCell>
130
- <TableCell align="middle">
128
+ <TableCell>
131
129
  <Code>{token.color}</Code>
132
130
  </TableCell>
133
- <TableCell align="middle">
131
+ <TableCell>
134
132
  <span
135
133
  style={{
136
134
  color: token.color,
@@ -1,7 +1,8 @@
1
1
  import { CodeBlock } from "../components/CodeBlock"
2
2
  import { Panel } from "../components/Panel"
3
3
  import { Prose } from "../components/Prose"
4
- import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "../components/Table"
4
+ import { Table, TableBody, TableCell, TableHead,
5
+ TableHeader, TableRow } from "../components/Table"
5
6
  import { H2, H3, P } from "../components/Typography"
6
7
 
7
8
  import { colors } from "../tokens/colors"
@@ -16,14 +17,12 @@ export function CornerRadiusTokenPage() {
16
17
  </P>
17
18
 
18
19
  <H3>Values</H3>
19
- <Table>
20
- <TableHead>
21
- <TableRow>
22
- <TableHeaderCell>Name</TableHeaderCell>
23
- <TableHeaderCell>Value</TableHeaderCell>
24
- <TableHeaderCell>Use</TableHeaderCell>
25
- </TableRow>
26
- </TableHead>
20
+ <Table aria-label="Corner radius tokens">
21
+ <TableHeader>
22
+ <TableHead isRowHeader>Name</TableHead>
23
+ <TableHead>Value</TableHead>
24
+ <TableHead>Use</TableHead>
25
+ </TableHeader>
27
26
  <TableBody>
28
27
  <TableRow>
29
28
  <TableCell>
@@ -1,7 +1,8 @@
1
1
  import { CodeBlock } from "../components/CodeBlock"
2
2
  import { Panel } from "../components/Panel"
3
3
  import { Prose } from "../components/Prose"
4
- import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "../components/Table"
4
+ import { Table, TableBody, TableCell, TableHead,
5
+ TableHeader, TableRow } from "../components/Table"
5
6
  import { H2, H3, P } from "../components/Typography"
6
7
  import { Flex } from "../components/Utils"
7
8
 
@@ -24,14 +25,12 @@ export function FlexTokenPage() {
24
25
  </P>
25
26
 
26
27
  <H3>Values</H3>
27
- <Table>
28
- <TableHead>
29
- <TableRow>
30
- <TableHeaderCell>Name</TableHeaderCell>
31
- <TableHeaderCell>Value</TableHeaderCell>
32
- <TableHeaderCell>Use</TableHeaderCell>
33
- </TableRow>
34
- </TableHead>
28
+ <Table aria-label="Flex attributes">
29
+ <TableHeader>
30
+ <TableHead isRowHeader>Name</TableHead>
31
+ <TableHead>Value</TableHead>
32
+ <TableHead>Use</TableHead>
33
+ </TableHeader>
35
34
  <TableBody>
36
35
  <TableRow>
37
36
  <TableCell>
@@ -1,5 +1,6 @@
1
1
  import { style, useStyles } from "purse-styles"
2
- import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "../components/Table"
2
+ import { Table, TableBody, TableCell, TableHead,
3
+ TableHeader, TableRow } from "../components/Table"
3
4
  import { CodeBlock } from "../components/CodeBlock"
4
5
  import { Panel } from "../components/Panel"
5
6
  import { Prose } from "../components/Prose"
@@ -28,14 +29,12 @@ export function FocusRingTokenPage() {
28
29
  </P>
29
30
 
30
31
  <H3>Values</H3>
31
- <Table>
32
- <TableHead>
33
- <TableRow>
34
- <TableHeaderCell>Name</TableHeaderCell>
35
- <TableHeaderCell>Value</TableHeaderCell>
36
- <TableHeaderCell>Use</TableHeaderCell>
37
- </TableRow>
38
- </TableHead>
32
+ <Table aria-label="Focus ring tokens">
33
+ <TableHeader>
34
+ <TableHead isRowHeader>Name</TableHead>
35
+ <TableHead>Value</TableHead>
36
+ <TableHead>Use</TableHead>
37
+ </TableHeader>
39
38
  <TableBody>
40
39
  <TableRow>
41
40
  <TableCell>
@@ -1,6 +1,7 @@
1
1
  import { useStyles } from "purse-styles"
2
2
  import { useMemo, useState } from "react"
3
- import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "../components/Table"
3
+ import { Table, TableBody, TableCell, TableHead,
4
+ TableHeader, TableRow } from "../components/Table"
4
5
  import { FuzzyString } from "../components/FuzzyString"
5
6
  import { SearchField } from "../components/Input"
6
7
  import { Panel } from "../components/Panel"
@@ -70,14 +71,12 @@ export function FuzzyStringPage() {
70
71
 
71
72
  <H3>Examples</H3>
72
73
  <Panel>
73
- <Table>
74
- <TableHead>
75
- <TableRow>
76
- <TableHeaderCell>Query</TableHeaderCell>
77
- <TableHeaderCell>Text</TableHeaderCell>
78
- <TableHeaderCell>Result</TableHeaderCell>
79
- </TableRow>
80
- </TableHead>
74
+ <Table aria-label="FuzzyString examples">
75
+ <TableHeader>
76
+ <TableHead isRowHeader>Query</TableHead>
77
+ <TableHead>Text</TableHead>
78
+ <TableHead>Result</TableHead>
79
+ </TableHeader>
81
80
  <TableBody>
82
81
  {staticExamples.map((example) => {
83
82
  const match = fuzzyMatch(example.query, example.text)
@@ -1,5 +1,6 @@
1
1
  import { style, useStyles } from "purse-styles"
2
- import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "../components/Table"
2
+ import { Table, TableBody, TableCell, TableHead,
3
+ TableHeader, TableRow } from "../components/Table"
3
4
  import { CodeBlock } from "../components/CodeBlock"
4
5
  import { Panel } from "../components/Panel"
5
6
  import { Prose } from "../components/Prose"
@@ -32,14 +33,12 @@ export function LayoutTokenPage() {
32
33
  </P>
33
34
 
34
35
  <H3>Values</H3>
35
- <Table>
36
- <TableHead>
37
- <TableRow>
38
- <TableHeaderCell>Name</TableHeaderCell>
39
- <TableHeaderCell>Arguments</TableHeaderCell>
40
- <TableHeaderCell>Use</TableHeaderCell>
41
- </TableRow>
42
- </TableHead>
36
+ <Table aria-label="Layout tokens">
37
+ <TableHeader>
38
+ <TableHead isRowHeader>Name</TableHead>
39
+ <TableHead>Arguments</TableHead>
40
+ <TableHead>Use</TableHead>
41
+ </TableHeader>
43
42
  <TableBody>
44
43
  <TableRow>
45
44
  <TableCell>
@@ -50,6 +50,7 @@ import { SelectPage } from "./SelectPage"
50
50
  import { SpacingTokenPage } from "./SpacingTokenPage"
51
51
  import { TextPage } from "./TextPage"
52
52
  import { TextTokenPage } from "./TextTokenPage"
53
+ import { TablePage } from "./TablePage"
53
54
  import { TooltipPage } from "./TooltipPage"
54
55
 
55
56
  export function Maui() {
@@ -139,6 +140,7 @@ const navigation: NavEntry[] = [
139
140
  path: "/components/list-box",
140
141
  page: ListBoxPage,
141
142
  },
143
+ { label: "Table", path: "/components/table", page: TablePage },
142
144
  { label: "Menu", path: "/components/menu", page: MenuPage },
143
145
  { label: "Tooltip", path: "/components/tooltip", page: TooltipPage },
144
146
  {
@@ -1,5 +1,6 @@
1
1
  import { useState } from "react"
2
- import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "../components/Table"
2
+ import { Table, TableBody, TableCell, TableHead,
3
+ TableHeader, TableRow } from "../components/Table"
3
4
  import { style, useStyles } from "purse-styles"
4
5
  import { Button } from "../components/Button"
5
6
  import { CodeBlock } from "../components/CodeBlock"
@@ -35,14 +36,12 @@ export function MotionTokenPage() {
35
36
  </P>
36
37
 
37
38
  <H3>Values</H3>
38
- <Table>
39
- <TableHead>
40
- <TableRow>
41
- <TableHeaderCell>Name</TableHeaderCell>
42
- <TableHeaderCell>Value</TableHeaderCell>
43
- <TableHeaderCell>Use</TableHeaderCell>
44
- </TableRow>
45
- </TableHead>
39
+ <Table aria-label="Motion tokens">
40
+ <TableHeader>
41
+ <TableHead isRowHeader>Name</TableHead>
42
+ <TableHead>Value</TableHead>
43
+ <TableHead>Use</TableHead>
44
+ </TableHeader>
46
45
  <TableBody>
47
46
  <TableRow>
48
47
  <TableCell>
@@ -7,7 +7,7 @@ import {
7
7
  TableBody,
8
8
  TableCell,
9
9
  TableHead,
10
- TableHeaderCell,
10
+ TableHeader,
11
11
  TableRow,
12
12
  } from "../components/Table"
13
13
  import { H2, H3, P } from "../components/Typography"
@@ -31,14 +31,12 @@ export function ShadowTokenPage() {
31
31
  </P>
32
32
 
33
33
  <H3>Values</H3>
34
- <Table>
35
- <TableHead>
36
- <TableRow>
37
- <TableHeaderCell>Name</TableHeaderCell>
38
- <TableHeaderCell>Value</TableHeaderCell>
39
- <TableHeaderCell>Use</TableHeaderCell>
40
- </TableRow>
41
- </TableHead>
34
+ <Table aria-label="Shadow tokens">
35
+ <TableHeader>
36
+ <TableHead isRowHeader>Name</TableHead>
37
+ <TableHead>Value</TableHead>
38
+ <TableHead>Use</TableHead>
39
+ </TableHeader>
42
40
  <TableBody>
43
41
  <TableRow>
44
42
  <TableCell>
@@ -4,7 +4,7 @@ import {
4
4
  TableBody,
5
5
  TableCell,
6
6
  TableHead,
7
- TableHeaderCell,
7
+ TableHeader,
8
8
  TableRow,
9
9
  } from "../components/Table"
10
10
  import { CodeBlock } from "../components/CodeBlock"
@@ -26,14 +26,12 @@ export function SizingTokenPage() {
26
26
  </P>
27
27
 
28
28
  <H3>Values</H3>
29
- <Table>
30
- <TableHead>
31
- <TableRow>
32
- <TableHeaderCell>Name</TableHeaderCell>
33
- <TableHeaderCell>Value</TableHeaderCell>
34
- <TableHeaderCell>Use</TableHeaderCell>
35
- </TableRow>
36
- </TableHead>
29
+ <Table aria-label="Sizing tokens">
30
+ <TableHeader>
31
+ <TableHead isRowHeader>Name</TableHead>
32
+ <TableHead>Value</TableHead>
33
+ <TableHead>Use</TableHead>
34
+ </TableHeader>
37
35
  <TableBody>
38
36
  <TableRow>
39
37
  <TableCell>
@@ -1,5 +1,6 @@
1
1
  import { useStyles } from "purse-styles"
2
- import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "../components/Table"
2
+ import { Table, TableBody, TableCell, TableHead,
3
+ TableHeader, TableRow } from "../components/Table"
3
4
  import { CodeBlock } from "../components/CodeBlock"
4
5
  import { Panel } from "../components/Panel"
5
6
  import { Prose } from "../components/Prose"
@@ -18,14 +19,12 @@ export function SpacingTokenPage() {
18
19
  </P>
19
20
 
20
21
  <H3>Values</H3>
21
- <Table>
22
- <TableHead>
23
- <TableRow>
24
- <TableHeaderCell>Name</TableHeaderCell>
25
- <TableHeaderCell>Value</TableHeaderCell>
26
- <TableHeaderCell>Use</TableHeaderCell>
27
- </TableRow>
28
- </TableHead>
22
+ <Table aria-label="Spacing tokens">
23
+ <TableHeader>
24
+ <TableHead isRowHeader>Name</TableHead>
25
+ <TableHead>Value</TableHead>
26
+ <TableHead>Use</TableHead>
27
+ </TableHeader>
29
28
  <TableBody>
30
29
  {spacingScale.map((token) => (
31
30
  <TableRow key={token.name}>
@@ -0,0 +1,121 @@
1
+ import { Code } from "../components/Code"
2
+ import { Panel } from "../components/Panel"
3
+ import { Prose } from "../components/Prose"
4
+ import {
5
+ Table,
6
+ TableBody,
7
+ TableCaption,
8
+ TableCell,
9
+ TableFooter,
10
+ TableHead,
11
+ TableHeader,
12
+ TableRow,
13
+ } from "../components/Table"
14
+ import { H2, H3, P } from "../components/Typography"
15
+
16
+ const invoices = [
17
+ {
18
+ invoice: "INV001",
19
+ paymentStatus: "Paid",
20
+ totalAmount: "$250.00",
21
+ paymentMethod: "Credit Card",
22
+ },
23
+ {
24
+ invoice: "INV002",
25
+ paymentStatus: "Pending",
26
+ totalAmount: "$150.00",
27
+ paymentMethod: "PayPal",
28
+ },
29
+ {
30
+ invoice: "INV003",
31
+ paymentStatus: "Unpaid",
32
+ totalAmount: "$350.00",
33
+ paymentMethod: "Bank Transfer",
34
+ },
35
+ {
36
+ invoice: "INV004",
37
+ paymentStatus: "Paid",
38
+ totalAmount: "$450.00",
39
+ paymentMethod: "Credit Card",
40
+ },
41
+ {
42
+ invoice: "INV005",
43
+ paymentStatus: "Paid",
44
+ totalAmount: "$550.00",
45
+ paymentMethod: "PayPal",
46
+ },
47
+ {
48
+ invoice: "INV006",
49
+ paymentStatus: "Pending",
50
+ totalAmount: "$200.00",
51
+ paymentMethod: "Bank Transfer",
52
+ },
53
+ {
54
+ invoice: "INV007",
55
+ paymentStatus: "Unpaid",
56
+ totalAmount: "$300.00",
57
+ paymentMethod: "Credit Card",
58
+ },
59
+ ]
60
+
61
+ export function TablePage() {
62
+ return (
63
+ <Prose style={{ marginBottom: "32px" }}>
64
+ <H2>Table</H2>
65
+ <P>
66
+ A data table with horizontal dividers and cell padding. Columns live
67
+ directly in <Code>TableHeader</Code>. Use <Code>align</Code> on{" "}
68
+ <Code>TableHead</Code> and <Code>TableCell</Code> instead of text
69
+ alignment classes.
70
+ </P>
71
+
72
+ <H3>Invoices</H3>
73
+ <Panel>
74
+ <figure style={{ margin: 0, width: "100%" }}>
75
+ <Table aria-label="Invoices">
76
+ <TableHeader>
77
+ <TableHead isRowHeader>Invoice</TableHead>
78
+ <TableHead>Status</TableHead>
79
+ <TableHead>Method</TableHead>
80
+ <TableHead align="end">Amount</TableHead>
81
+ </TableHeader>
82
+ <TableBody>
83
+ {invoices.map((invoice) => (
84
+ <TableRow key={invoice.invoice} id={invoice.invoice}>
85
+ <TableCell>{invoice.invoice}</TableCell>
86
+ <TableCell>{invoice.paymentStatus}</TableCell>
87
+ <TableCell>{invoice.paymentMethod}</TableCell>
88
+ <TableCell align="end">{invoice.totalAmount}</TableCell>
89
+ </TableRow>
90
+ ))}
91
+ </TableBody>
92
+ <TableFooter>
93
+ <TableRow id="total">
94
+ <TableCell colSpan={3}>Total</TableCell>
95
+ <TableCell align="end">$2,500.00</TableCell>
96
+ </TableRow>
97
+ </TableFooter>
98
+ </Table>
99
+ <TableCaption>A list of your recent invoices.</TableCaption>
100
+ </figure>
101
+ </Panel>
102
+
103
+ <H3>Empty</H3>
104
+ <P>
105
+ Tables need an empty composition. <Code>TableBody</Code> renders “No
106
+ results.” when there are no rows; pass{" "}
107
+ <Code>renderEmptyState</Code> to replace it.
108
+ </P>
109
+ <Panel>
110
+ <Table aria-label="Empty invoices">
111
+ <TableHeader>
112
+ <TableHead isRowHeader>Invoice</TableHead>
113
+ <TableHead>Status</TableHead>
114
+ <TableHead align="end">Amount</TableHead>
115
+ </TableHeader>
116
+ <TableBody />
117
+ </Table>
118
+ </Panel>
119
+ </Prose>
120
+ )
121
+ }
@@ -7,7 +7,7 @@ import {
7
7
  TableBody,
8
8
  TableCell,
9
9
  TableHead,
10
- TableHeaderCell,
10
+ TableHeader,
11
11
  TableRow,
12
12
  } from "../components/Table"
13
13
  import { Text } from "../components/Text"
@@ -28,14 +28,12 @@ export function TextPage() {
28
28
  </P>
29
29
 
30
30
  <H3>Attributes</H3>
31
- <Table>
32
- <TableHead>
33
- <TableRow>
34
- <TableHeaderCell>Attribute</TableHeaderCell>
35
- <TableHeaderCell>Values</TableHeaderCell>
36
- <TableHeaderCell>Default</TableHeaderCell>
37
- </TableRow>
38
- </TableHead>
31
+ <Table aria-label="Text attributes">
32
+ <TableHeader>
33
+ <TableHead isRowHeader>Attribute</TableHead>
34
+ <TableHead>Values</TableHead>
35
+ <TableHead>Default</TableHead>
36
+ </TableHeader>
39
37
  <TableBody>
40
38
  <TableRow>
41
39
  <TableCell>
@@ -1,5 +1,6 @@
1
1
  import { useStyles } from "purse-styles"
2
- import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "../components/Table"
2
+ import { Table, TableBody, TableCell, TableHead,
3
+ TableHeader, TableRow } from "../components/Table"
3
4
  import { CodeBlock } from "../components/CodeBlock"
4
5
  import { Panel } from "../components/Panel"
5
6
  import { Prose } from "../components/Prose"
@@ -22,14 +23,12 @@ export function TextTokenPage() {
22
23
  </P>
23
24
 
24
25
  <H3>Values</H3>
25
- <Table>
26
- <TableHead>
27
- <TableRow>
28
- <TableHeaderCell>Input</TableHeaderCell>
29
- <TableHeaderCell>Values</TableHeaderCell>
30
- <TableHeaderCell>Use</TableHeaderCell>
31
- </TableRow>
32
- </TableHead>
26
+ <Table aria-label="Text token values">
27
+ <TableHeader>
28
+ <TableHead isRowHeader>Input</TableHead>
29
+ <TableHead>Values</TableHead>
30
+ <TableHead>Use</TableHead>
31
+ </TableHeader>
33
32
  <TableBody>
34
33
  <TableRow>
35
34
  <TableCell>
@@ -1,4 +0,0 @@
1
- import type React from "react";
2
- type PanelProps = React.ComponentPropsWithoutRef<"div">;
3
- export declare function Panel({ className, children, ...props }: PanelProps): React.JSX.Element;
4
- export {};
@@ -1,15 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { style, useStyles } from "purse-styles";
3
- import { border } from "../tokens/borders";
4
- import { colors } from "../tokens/colors";
5
- import { radius } from "../tokens/radius";
6
- import { spacing } from "../tokens/spacing";
7
- const panelClass = style(spacing.padding({ all: 16 }), border([], "outline"), radius.lg, {
8
- backgroundColor: colors.gray[1],
9
- backgroundImage: `radial-gradient(${colors.grayAlpha[3]} 1px, transparent 1px)`,
10
- backgroundSize: "12px 12px",
11
- });
12
- export function Panel({ className, children, ...props }) {
13
- const panelClassName = useStyles(panelClass);
14
- return (_jsx("div", { ...props, className: [panelClassName, className].filter(Boolean).join(" "), children: children }));
15
- }