@nexub/mcp 6.2.0 → 6.4.0

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,48 @@
1
+ # Action Bar
2
+
3
+ Save and cancel that stay in view at the bottom of a long form.
4
+
5
+ - Package: `@nexub/react` · Category: Form & Input · Status: beta
6
+ - Import: `import { ActionBar } from '@nexub/react';`
7
+ - Docs: https://nexub-ds-docs.pages.dev/components/action-bar
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ | --- | --- | --- | --- |
13
+ | `message` | `ReactNode` | | Status on the start side, e.g. "Unsaved changes"; announced politely and names the region. |
14
+ | `children` (required) | `ReactNode` | | The actions, primary last. |
15
+
16
+ ## Example: Unsaved changes
17
+
18
+ ```tsx
19
+ 'use client';
20
+
21
+ import * as React from 'react';
22
+ import { ActionBar, Button, Input, useUnsavedChanges } from '@nexub/react';
23
+
24
+ export default function Example() {
25
+ const [saved, setSaved] = React.useState('Acme');
26
+ const [name, setName] = React.useState('Acme');
27
+ const dirty = name !== saved;
28
+ useUnsavedChanges(dirty);
29
+ return (
30
+ <div className="flex w-full max-w-lg flex-col gap-4">
31
+ <Input aria-label="Company name" value={name} onChange={(e) => setName(e.target.value)} />
32
+ {dirty && (
33
+ <ActionBar message="Unsaved changes">
34
+ <Button variant="text" onClick={() => setName(saved)}>Discard</Button>
35
+ <Button onClick={() => setSaved(name)}>Save</Button>
36
+ </ActionBar>
37
+ )}
38
+ </div>
39
+ );
40
+ }
41
+ ```
42
+
43
+ ## Accessibility
44
+
45
+ - A region named by its message. Sticky at the bottom of its scrolling parent, so put it last in the form.
46
+ - Pair with `useUnsavedChanges(dirty)` to warn before leaving the page.
47
+
48
+ Related: [form](form.md), [data-table](data-table.md)
@@ -12,6 +12,8 @@ Feature-rich data table with sorting and row selection powered by TanStack Table
12
12
  | --- | --- | --- | --- |
13
13
  | `columns` (required) | `DataTableColumn<TData>[]` | | TanStack Table column definitions (`DataTableColumn` is exported from @nexub/react). Set `meta: { align: 'end' }` for numeric columns; headers, sort buttons and cells follow it. |
14
14
  | `data` (required) | `TData[]` | | Array of row data objects to render. |
15
+ | `getSubRows` | `(row, index) => TData[] \| undefined` | | Nested rows (a tree table). The first column gets an expand toggle (`aria-expanded`) and indents each level; sorting sorts within each level. |
16
+ | `expanded / defaultExpanded / onExpandedChange` | `ExpandedState` | | Expanded rows by row id (see `getRowId`), or `true` for all. |
15
17
  | `caption` | `ReactNode` | | Names the table for assistive tech (and its scroll region). Shown below the table; add `captionHidden` to keep it screen-reader only. |
16
18
  | `enableSorting` | `boolean` | `false` | Click a header to sort; Shift+click adds more columns, numbered 1, 2… (5.3). |
17
19
  | `enableRowSelection` | `boolean` | `false` | Turns on row selection state. |
@@ -242,6 +244,56 @@ export default function Example() {
242
244
  }
243
245
  ```
244
246
 
247
+ ## Example: Tree rows
248
+
249
+ `getSubRows` nests rows: the first column gets an expand toggle and indents each level. With pages, a parent and its children stay on one page.
250
+
251
+ ```tsx
252
+ 'use client';
253
+
254
+ import { DataTable, type DataTableColumn } from '@nexub/react';
255
+
256
+ type Account = { name: string; owner: string; arr: number; children?: Account[] };
257
+
258
+ const data: Account[] = [
259
+ {
260
+ name: 'Acme Group',
261
+ owner: 'Ada',
262
+ arr: 420000,
263
+ children: [
264
+ { name: 'Acme EU', owner: 'Grace', arr: 180000, children: [{ name: 'Acme Berlin', owner: 'Grace', arr: 60000 }] },
265
+ { name: 'Acme US', owner: 'Alan', arr: 240000 },
266
+ ],
267
+ },
268
+ { name: 'Globex', owner: 'Linus', arr: 95000 },
269
+ ];
270
+
271
+ const columns: DataTableColumn<Account>[] = [
272
+ { accessorKey: 'name', header: 'Account' },
273
+ { accessorKey: 'owner', header: 'Owner' },
274
+ {
275
+ accessorKey: 'arr',
276
+ header: 'ARR',
277
+ meta: { align: 'end' },
278
+ cell: ({ getValue }) => new Intl.NumberFormat('en', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }).format(getValue<number>()),
279
+ },
280
+ ];
281
+
282
+ export default function Example() {
283
+ return (
284
+ <DataTable
285
+ caption="Accounts by region"
286
+ captionHidden
287
+ columns={columns}
288
+ data={data}
289
+ getSubRows={(row) => row.children}
290
+ getRowId={(row) => row.name}
291
+ defaultExpanded={{ 'Acme Group': true }}
292
+ />
293
+ );
294
+ }
295
+ ```
296
+
245
297
  ## Accessibility
246
298
 
247
299
  - Roles: table (default), grid (with `grid`), columnheader with aria-sort when sortable
@@ -0,0 +1,45 @@
1
+ # Resizable Panels
2
+
3
+ Panels with draggable separators, for list–detail and editor layouts.
4
+
5
+ - Package: `@nexub/react` · Category: Layout · Status: beta
6
+ - Import: `import { ResizablePanels } from '@nexub/react';`
7
+ - Docs: https://nexub-ds-docs.pages.dev/components/resizable-panels
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ | --- | --- | --- | --- |
13
+ | `children` (required) | `ReactNode` | | The panels; a separator goes between each pair. |
14
+ | `direction` | `'horizontal' \| 'vertical'` | `'horizontal'` | Side by side or stacked. |
15
+ | `sizes / defaultSizes / onSizesChange` | `number[]` | | One percentage per panel, adding up to 100. Save them (localStorage, user settings) to restore the layout. |
16
+ | `minSizes` | `number[]` | `10 each` | Smallest size per panel, in percent. |
17
+ | `handleLabel` | `string` | `"Resize panels"` | Names the separators. |
18
+
19
+ ## Example: List and detail
20
+
21
+ ```tsx
22
+ import { ResizablePanels } from '@nexub/react';
23
+
24
+ export default function Example() {
25
+ return (
26
+ <ResizablePanels defaultSizes={[35, 65]} minSizes={[20, 30]} className="h-64 w-full rounded-shape-container border border-[var(--color-outline-variant)]">
27
+ <ul className="flex flex-col gap-2 p-4 text-body-md">
28
+ <li>Quarterly report</li>
29
+ <li>Launch checklist</li>
30
+ <li>Hiring plan</li>
31
+ </ul>
32
+ <div className="p-4 text-body-md">Drag the line, or focus it with Tab and use the arrow keys.</div>
33
+ </ResizablePanels>
34
+ );
35
+ }
36
+ ```
37
+
38
+ ## Accessibility
39
+
40
+ - Roles: separator (focusable, with aria-valuenow / min / max and aria-controls)
41
+ - `Arrow keys`: Move the focused separator by 5%. Mirrored in RTL.
42
+ - `Home / End`: To the smallest or largest size.
43
+ - `Enter`: Back to the default split.
44
+
45
+ Related: [sidebar](sidebar.md), [app-shell](app-shell.md)
@@ -0,0 +1,65 @@
1
+ # Stepper
2
+
3
+ Progress through a multi-step flow, with clickable steps that follow the order you allow.
4
+
5
+ - Package: `@nexub/react` · Category: Navigation · Status: beta
6
+ - Import: `import { Stepper } from '@nexub/react';`
7
+ - Docs: https://nexub-ds-docs.pages.dev/components/stepper
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ | --- | --- | --- | --- |
13
+ | `steps` (required) | `{ id, label, description? }[]` | | The steps in order. |
14
+ | `current` (required) | `number` | | Index of the step being shown. |
15
+ | `completed` | `number[]` | | Finished steps. Defaults to every step before `current`. |
16
+ | `onStepChange` | `(index) => void` | | Makes reachable steps buttons: finished ones and the first unfinished one. |
17
+ | `nonLinear` | `boolean` | | Every step is reachable. |
18
+ | `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Vertical suits side columns and narrow screens. |
19
+ | `aria-label` | `string` | | Names the navigation landmark, e.g. "Setup steps". |
20
+
21
+ ## Example: Wizard with a form per step
22
+
23
+ ```tsx
24
+ 'use client';
25
+
26
+ import * as React from 'react';
27
+ import { Button, Form, FormField, Input, Stepper } from '@nexub/react';
28
+
29
+ const steps = [
30
+ { id: 'account', label: 'Account' },
31
+ { id: 'workspace', label: 'Workspace' },
32
+ { id: 'done', label: 'Done' },
33
+ ];
34
+
35
+ export default function Example() {
36
+ const [current, setCurrent] = React.useState(0);
37
+ return (
38
+ <div className="flex w-full max-w-lg flex-col gap-6">
39
+ <Stepper aria-label="Sign-up steps" steps={steps} current={current} onStepChange={setCurrent} />
40
+ {current < 2 ? (
41
+ <Form key={current} onSubmit={() => setCurrent(current + 1)}>
42
+ <FormField.Root name={current === 0 ? 'email' : 'workspace'} required>
43
+ <FormField.Label>{current === 0 ? 'Work email' : 'Workspace name'}</FormField.Label>
44
+ <FormField.Control>
45
+ <Input type={current === 0 ? 'email' : 'text'} />
46
+ </FormField.Control>
47
+ <FormField.Error />
48
+ </FormField.Root>
49
+ <Button type="submit" className="self-start">Continue</Button>
50
+ </Form>
51
+ ) : (
52
+ <p className="text-body-md">All set.</p>
53
+ )}
54
+ </div>
55
+ );
56
+ }
57
+ ```
58
+
59
+ ## Accessibility
60
+
61
+ - A `nav` with an ordered list; the current step has `aria-current="step"`.
62
+ - Each step reads "Step 2 of 4: Billing", plus "completed" when finished.
63
+ - Validate each step with a Form and move `current` on its submit.
64
+
65
+ Related: [form](form.md), [tabs](tabs.md)
@@ -0,0 +1,106 @@
1
+ # Tree View
2
+
3
+ A keyboard-friendly hierarchy (ARIA tree) with lazy children and tri-state checkboxes.
4
+
5
+ - Package: `@nexub/react` · Category: Navigation · Status: beta
6
+ - Import: `import { TreeView } from '@nexub/react';`
7
+ - Docs: https://nexub-ds-docs.pages.dev/components/tree-view
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ | --- | --- | --- | --- |
13
+ | `nodes` (required) | `TreeNode[]` | | `{ id, label, textValue?, icon?, children?, hasChildren?, disabled? }`. |
14
+ | `aria-label / aria-labelledby` (required) | `string` | | Names the tree. |
15
+ | `expanded / defaultExpanded / onExpandedChange` | `string[]` | | Open node ids. |
16
+ | `selected / defaultSelected / onSelectedChange` | `string \| null` | | Single selection, set by click, Enter or Space. |
17
+ | `checkable` | `boolean` | | Checkboxes instead of selection. A parent is checked when all its children are and mixed when some are. |
18
+ | `checked / defaultChecked / onCheckedChange` | `string[]` | | Every checked id, parents included. |
19
+ | `onLoadChildren` | `(node) => Promise` | | Called when a `hasChildren` node without `children` opens. Load them and pass the new `nodes`; the item is `aria-busy` meanwhile. |
20
+
21
+ ## Example: Lazy loading and selection
22
+
23
+ ```tsx
24
+ 'use client';
25
+
26
+ import * as React from 'react';
27
+ import { TreeView, type TreeNode } from '@nexub/react';
28
+
29
+ export default function Example() {
30
+ const [nodes, setNodes] = React.useState<TreeNode[]>([
31
+ {
32
+ id: 'eng',
33
+ label: 'Engineering',
34
+ children: [
35
+ { id: 'web', label: 'Web', children: [{ id: 'ada', label: 'Ada Lovelace' }, { id: 'alan', label: 'Alan Turing' }] },
36
+ { id: 'mobile', label: 'Mobile', hasChildren: true },
37
+ ],
38
+ },
39
+ { id: 'design', label: 'Design', children: [{ id: 'grace', label: 'Grace Hopper' }] },
40
+ ]);
41
+ const [selected, setSelected] = React.useState<string | null>('ada');
42
+
43
+ // Pretend server call: fills Mobile's children the first time it opens.
44
+ const load = async (node: TreeNode) => {
45
+ await new Promise((r) => setTimeout(r, 700));
46
+ const fill = (list: TreeNode[]): TreeNode[] =>
47
+ list.map((n) =>
48
+ n.id === node.id
49
+ ? { ...n, children: [{ id: 'linus', label: 'Linus Torvalds' }, { id: 'margaret', label: 'Margaret Hamilton' }] }
50
+ : { ...n, children: n.children && fill(n.children) },
51
+ );
52
+ setNodes(fill);
53
+ };
54
+
55
+ return (
56
+ <div className="flex w-full max-w-xs flex-col gap-2">
57
+ <TreeView aria-label="Teams" nodes={nodes} defaultExpanded={['eng', 'web']} selected={selected} onSelectedChange={setSelected} onLoadChildren={load} />
58
+ <p className="text-body-sm text-[var(--color-on-surface-muted)]">Selected: {selected ?? 'none'}</p>
59
+ </div>
60
+ );
61
+ }
62
+ ```
63
+
64
+ ## Example: Checkboxes
65
+
66
+ ```tsx
67
+ 'use client';
68
+
69
+ import * as React from 'react';
70
+ import { TreeView, type TreeNode } from '@nexub/react';
71
+
72
+ const nodes: TreeNode[] = [
73
+ {
74
+ id: 'reports',
75
+ label: 'Reports',
76
+ children: [
77
+ { id: 'revenue', label: 'Revenue' },
78
+ { id: 'churn', label: 'Churn' },
79
+ ],
80
+ },
81
+ { id: 'settings', label: 'Settings', children: [{ id: 'billing', label: 'Billing' }, { id: 'members', label: 'Members' }] },
82
+ ];
83
+
84
+ export default function Example() {
85
+ const [checked, setChecked] = React.useState<string[]>(['revenue']);
86
+ return (
87
+ <div className="flex w-full max-w-xs flex-col gap-2">
88
+ <TreeView aria-label="Permissions" nodes={nodes} checkable defaultExpanded={['reports', 'settings']} checked={checked} onCheckedChange={setChecked} />
89
+ <p className="text-body-sm text-[var(--color-on-surface-muted)]">Granted: {checked.join(', ') || 'nothing'}</p>
90
+ </div>
91
+ );
92
+ }
93
+ ```
94
+
95
+ ## Accessibility
96
+
97
+ - Roles: tree, treeitem with aria-level, aria-setsize, aria-posinset, aria-expanded, group
98
+ - `ArrowDown / ArrowUp`: Next or previous visible item.
99
+ - `ArrowRight`: Opens a closed item, or moves to its first child. Mirrored in RTL.
100
+ - `ArrowLeft`: Closes an open item, or moves to its parent. Mirrored in RTL.
101
+ - `Home / End`: First or last visible item.
102
+ - `Enter / Space`: Selects the item, or toggles its checkbox.
103
+ - `Type a letter`: Moves to the next item starting with the typed text.
104
+ - The tree is one tab stop (roving tabindex); it returns to the last focused or the selected item.
105
+
106
+ Related: [data-table](data-table.md), [sidebar](sidebar.md)
@@ -1,6 +1,6 @@
1
1
  # Component index
2
2
 
3
- Nexub DS v6.2.0. Open `components/<slug>.md` for props, examples and accessibility notes.
3
+ Nexub DS v6.4.0. Open `components/<slug>.md` for props, examples and accessibility notes.
4
4
  Never use a component marked deprecated.
5
5
 
6
6
  ## Components — Actions
@@ -66,6 +66,7 @@ Never use a component marked deprecated.
66
66
 
67
67
  ## Components — Form & Input
68
68
 
69
+ - [Action Bar](components/action-bar.md) `@nexub/react`: Save and cancel that stay in view at the bottom of a long form.
69
70
  - [Date Picker](components/date-picker.md) `@nexub/react`: Calendar date picker with text input.
70
71
  - [Date Range Picker](components/date-range-picker.md) `@nexub/react`: Dual-calendar date range selector.
71
72
  - [Date Time Picker](components/date-time-picker.md) `@nexub/react`: A DatePicker and a TimePicker that edit one Date, with an optional time-zone label.
@@ -131,6 +132,7 @@ Never use a component marked deprecated.
131
132
  - [Flex](components/flex.md) `@nexub/react`: Flexbox layout primitive.
132
133
  - [Grid](components/grid.md) `@nexub/react`: CSS Grid layout primitive.
133
134
  - [Media Card](components/media-card.md) `@nexub/react`: An image card with a glass caption over a soft scrim. With `href`, the whole card is one link.
135
+ - [Resizable Panels](components/resizable-panels.md) `@nexub/react`: Panels with draggable separators, for list–detail and editor layouts.
134
136
  - [Stack](components/stack.md) `@nexub/react`: Vertical stack layout with configurable gap.
135
137
 
136
138
  ## Components — Loading States
@@ -156,7 +158,9 @@ Never use a component marked deprecated.
156
158
  - [Navigation Rail](components/navigation-rail.md) `@nexub/react`: Navigation for medium-width windows: icons over labels, with an active pill behind the icon.
157
159
  - [Pagination](components/pagination.md) `@nexub/react`: Page navigation control with prev/next and page number buttons.
158
160
  - [Saved Views](components/saved-views.md) `@nexub/react`: A menu to switch, save, update and delete saved filter views. Your app stores them.
161
+ - [Stepper](components/stepper.md) `@nexub/react`: Progress through a multi-step flow, with clickable steps that follow the order you allow.
159
162
  - [Tabs](components/tabs.md) `@nexub/react`: Layered content panels switched by tab triggers. Built on Radix UI Tabs.
163
+ - [Tree View](components/tree-view.md) `@nexub/react`: A keyboard-friendly hierarchy (ARIA tree) with lazy children and tri-state checkboxes.
160
164
 
161
165
  ## Components — Overlays
162
166
 
@@ -1,6 +1,6 @@
1
1
  # Tokens
2
2
 
3
- Nexub DS v6.2.0. Every token is a CSS custom property from `@nexub/tokens/css` (loaded by `@nexub/themes/base`).
3
+ Nexub DS v6.4.0. Every token is a CSS custom property from `@nexub/tokens/css` (loaded by `@nexub/themes/base`).
4
4
  The Tailwind preset (`@nexub/tokens/tailwind`) maps them to utilities. Never hardcode a hex, px spacing or shadow that a token covers.
5
5
 
6
6
  ## Color roles
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexub/mcp",
3
- "version": "6.2.0",
3
+ "version": "6.4.0",
4
4
  "description": "MCP server for Nexub Design System: gives Claude, Cursor and any MCP client the components, patterns, tokens and design rules of the installed release.",
5
5
  "type": "module",
6
6
  "license": "MIT",