@xferops/design-guide 0.2.1

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.
@@ -0,0 +1,96 @@
1
+ ---
2
+ id: primitives/layout-content
3
+ title: Layout and Content Primitives
4
+ summary: Compose Box, Stack, Text, Card, List, and Avatar into token-driven page sections.
5
+ category: primitives
6
+ slug: layout-content
7
+ tags:
8
+ - primitives
9
+ - layout
10
+ - content
11
+ - box
12
+ - stack
13
+ - text
14
+ - card
15
+ sourcePath: apps/docs/src/App.tsx
16
+ relatedPaths:
17
+ - packages/ui/src/components/Box
18
+ - packages/ui/src/components/Stack
19
+ - packages/ui/src/components/Text
20
+ - packages/ui/src/components/Card
21
+ - packages/ui/src/components/List
22
+ - packages/ui/src/components/Avatar
23
+ ---
24
+
25
+ # Layout and Content Primitives
26
+
27
+ Use the low-level primitives in `@xferops/ui` to build structure before introducing more specialized components.
28
+
29
+ ## Import the Core Primitives
30
+
31
+ ```tsx
32
+ import { Avatar, Box, Card, List, Stack, Text } from "@xferops/ui";
33
+ ```
34
+
35
+ ## Use `Box` for Token-Aligned Containers
36
+
37
+ `Box` is the base surface primitive for padding, border, radius, background, and shadow.
38
+
39
+ ```tsx
40
+ <Box padding="lg" background="surface" border="subtle" radius="lg">
41
+ <Stack gap="sm">
42
+ <Text as="span" weight="semibold">
43
+ Tenant summary
44
+ </Text>
45
+ <Text as="span" size="sm" tone="muted">
46
+ Shared shell container with semantic surface styling.
47
+ </Text>
48
+ </Stack>
49
+ </Box>
50
+ ```
51
+
52
+ ## Use `Stack` for Spacing and Alignment
53
+
54
+ Keep layout logic in `Stack` rather than custom wrappers for every screen.
55
+
56
+ ```tsx
57
+ <Stack gap="lg">
58
+ <Stack direction="row" gap="sm" align="center" wrap>
59
+ <Avatar name="Ada Lovelace" />
60
+ <Avatar name="Grace Hopper" />
61
+ <Avatar fallbackText="+4" />
62
+ </Stack>
63
+
64
+ <Card padding="md" tone="elevated">
65
+ <Stack gap="xs">
66
+ <Text as="span" size="sm" weight="semibold">
67
+ Elevated card
68
+ </Text>
69
+ <Text as="span" size="sm" tone="muted">
70
+ Use cards for grouped content and secondary emphasis.
71
+ </Text>
72
+ </Stack>
73
+ </Card>
74
+ </Stack>
75
+ ```
76
+
77
+ ## Use `Text` and `List` for Readable Content
78
+
79
+ ```tsx
80
+ <Stack gap="xs">
81
+ <Text as="span" size="sm" weight="medium">
82
+ Feature checklist
83
+ </Text>
84
+ <List size="sm" spacing="sm">
85
+ <li>Export invoices as CSV</li>
86
+ <li>Apply partner theme overrides</li>
87
+ <li>Invite finance teammates</li>
88
+ </List>
89
+ </Stack>
90
+ ```
91
+
92
+ ## Notes
93
+
94
+ - `Box` is polymorphic, so switch the `as` prop when the container should be a `section`, `article`, or `aside`.
95
+ - `Text` should carry semantic meaning through `as`, while size, weight, and tone stay visual.
96
+ - `Stack` is the default spacing primitive for rows, columns, and wrapped action groups.
@@ -0,0 +1,156 @@
1
+ ---
2
+ id: table/sorting
3
+ title: Sortable Table Setup
4
+ summary: Set up a sortable table using TableSortButton and useTableSort.
5
+ category: table
6
+ slug: sorting
7
+ tags:
8
+ - table
9
+ - sorting
10
+ - accessibility
11
+ - react
12
+ - docs
13
+ sourcePath: apps/docs/src/App.tsx
14
+ relatedPaths:
15
+ - packages/ui/src/components/Table
16
+ - packages/ui/src/hooks/useTableSort.ts
17
+ ---
18
+
19
+ # Sortable Table Setup
20
+
21
+ This guide shows how to build a sortable table using the same pattern used in `apps/docs/src/App.tsx`.
22
+
23
+ ## Imports
24
+
25
+ Import the table primitives and the sorting hook from `@xferops/ui`.
26
+
27
+ ```tsx
28
+ import {
29
+ Table,
30
+ TableBody,
31
+ TableCaption,
32
+ TableCell,
33
+ TableHead,
34
+ TableHeaderCell,
35
+ TableRow,
36
+ TableSortButton,
37
+ useTableSort
38
+ } from "@xferops/ui";
39
+ ```
40
+
41
+ ## 1. Define Your Row Type
42
+
43
+ Your row type should describe the raw data in the table. Define a separate union for the columns you want to sort.
44
+
45
+ ```tsx
46
+ type InvoiceRow = {
47
+ customer: string;
48
+ status: string;
49
+ totalCents: number;
50
+ };
51
+
52
+ type SortColumn = "customer" | "status" | "totalCents";
53
+
54
+ const rows: InvoiceRow[] = [
55
+ { customer: "Northwind", status: "Paid", totalCents: 120000 },
56
+ { customer: "Stark Industries", status: "Overdue", totalCents: 489000 },
57
+ { customer: "Wayne Enterprises", status: "Draft", totalCents: 53000 }
58
+ ];
59
+ ```
60
+
61
+ ## 2. Initialize `useTableSort`
62
+
63
+ The hook stores the current sort state and returns a sorted copy of your rows.
64
+
65
+ ```tsx
66
+ const {
67
+ sort,
68
+ sortedRows,
69
+ requestSort,
70
+ getAriaSort
71
+ } = useTableSort<InvoiceRow, SortColumn>({
72
+ rows,
73
+ initialSort: {
74
+ column: "customer",
75
+ direction: "asc"
76
+ }
77
+ });
78
+ ```
79
+
80
+ What it gives you:
81
+
82
+ - `sort`: the active sort state, including `column` and `direction`
83
+ - `sortedRows`: a sorted copy of the input rows
84
+ - `requestSort(column)`: toggles sort direction when clicking the active column, or switches to a new column in ascending order
85
+ - `getAriaSort(column)`: returns `"ascending"`, `"descending"`, or `"none"` for accessibility
86
+
87
+ ## 3. Build the Table Header
88
+
89
+ Put `aria-sort` on each `TableHeaderCell`. Inside each header cell, render a `TableSortButton`.
90
+
91
+ ```tsx
92
+ <Table striped>
93
+ <TableCaption>Recent invoices</TableCaption>
94
+ <TableHead>
95
+ <TableRow>
96
+ <TableHeaderCell aria-sort={getAriaSort("customer")}>
97
+ <TableSortButton
98
+ active={sort.column === "customer"}
99
+ direction={sort.direction}
100
+ onClick={() => requestSort("customer")}
101
+ >
102
+ Customer
103
+ </TableSortButton>
104
+ </TableHeaderCell>
105
+
106
+ <TableHeaderCell aria-sort={getAriaSort("status")}>
107
+ <TableSortButton
108
+ active={sort.column === "status"}
109
+ direction={sort.direction}
110
+ onClick={() => requestSort("status")}
111
+ >
112
+ Status
113
+ </TableSortButton>
114
+ </TableHeaderCell>
115
+
116
+ <TableHeaderCell aria-sort={getAriaSort("totalCents")}>
117
+ <TableSortButton
118
+ active={sort.column === "totalCents"}
119
+ direction={sort.direction}
120
+ onClick={() => requestSort("totalCents")}
121
+ >
122
+ Total
123
+ </TableSortButton>
124
+ </TableHeaderCell>
125
+ </TableRow>
126
+ </TableHead>
127
+ ```
128
+
129
+ `TableSortButton` displays:
130
+
131
+ - `↕` when the column is not active
132
+ - `↑` when the active column is ascending
133
+ - `↓` when the active column is descending
134
+
135
+ ## 4. Render `sortedRows`
136
+
137
+ Render the rows returned by the hook instead of the original array.
138
+
139
+ ```tsx
140
+ <TableBody>
141
+ {sortedRows.map((invoice) => (
142
+ <TableRow key={invoice.customer}>
143
+ <TableCell>{invoice.customer}</TableCell>
144
+ <TableCell>{invoice.status}</TableCell>
145
+ <TableCell>{formatCurrency(invoice.totalCents)}</TableCell>
146
+ </TableRow>
147
+ ))}
148
+ </TableBody>
149
+ </Table>
150
+ ```
151
+
152
+ ## Notes
153
+
154
+ - `useTableSort` supports `string`, `number`, `boolean`, `Date`, `null`, and `undefined`.
155
+ - When values are `null` or `undefined`, they sort to the bottom in ascending order.
156
+ - If your displayed value differs from the value you want to sort on, use the hook's `getSortValue` option.
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@xferops/design-guide",
3
+ "version": "0.2.1",
4
+ "private": false,
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "xferops-design-guide-mcp": "dist/server.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "guides"
14
+ ],
15
+ "publishConfig": {
16
+ "access": "public",
17
+ "registry": "https://registry.npmjs.org/"
18
+ },
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "default": "./dist/index.js"
23
+ },
24
+ "./server": {
25
+ "types": "./dist/server.d.ts",
26
+ "default": "./dist/server.js"
27
+ }
28
+ },
29
+ "scripts": {
30
+ "build": "tsup",
31
+ "typecheck": "tsc -p tsconfig.json --noEmit",
32
+ "test": "vitest run"
33
+ },
34
+ "dependencies": {
35
+ "@modelcontextprotocol/sdk": "^1.20.2",
36
+ "zod": "^4.1.11"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^24.5.2",
40
+ "tsx": "^4.20.6"
41
+ }
42
+ }