@ai-matrx/design-system 0.12.1 → 0.13.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,42 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.13.0 — 2026-09-09
4
+
5
+ ### `ArchiveFilter` — THE ARCHIVED-ITEMS LAW made a control
6
+
7
+ Arman ruled on 2026-09-09 that archived rows of every entity are treated
8
+ identically everywhere: every list carries an archive filter, the default hides
9
+ archived, and revealing them is one or two clicks
10
+ (`common-docs/policies/archived-items.md`). Before this release each host
11
+ invented its own answer — a boolean `includeArchived` that nothing ever passed,
12
+ a badge that showed archived rows mixed in, or nothing at all — so the reveal
13
+ the platform intended was unreachable in most clients.
14
+
15
+ `ArchiveFilter` is that control, once: a three-state segmented toggle over
16
+ `active` (default) / `archived` / `all`, speaking the same words the Next.js
17
+ app already uses (`lib/entity-list`'s "Active only" / "Archived only" /
18
+ "Active + archived"). Shipped alongside it: `ARCHIVE_FILTER_VALUES`,
19
+ `DEFAULT_ARCHIVE_FILTER`, `ARCHIVE_FILTER_LABELS`, the `ArchiveFilterValue`
20
+ type, and `toArchiveFilter()` — which narrows an untrusted value (URL param,
21
+ stored preference, API echo) to the tri-state and falls back to `active`, so a
22
+ bad value can never silently widen a list to archived rows.
23
+
24
+ Optional `counts` render a per-state number beside each label. Pass a count
25
+ only when it describes what the list would actually render: a screen never
26
+ lies.
27
+
28
+ The control is a REQUEST, not a client-side sieve. Hand its value to the reader
29
+ (an RPC's `p_archived`, an endpoint's `archived=`) so counts, badges and
30
+ pagination agree with the rows on screen.
31
+
32
+ ### Consumer action
33
+
34
+ Any list over an entity with `is_archived` / `archived_at` / an archived status
35
+ must render `<ArchiveFilter>` and pass its value through to the server-side
36
+ reader. Delete local `showArchived` booleans and hardcoded archive predicates —
37
+ a boolean cannot express "archived only", which is why the law names three
38
+ states.
39
+
3
40
  ## 0.12.1 — 2026-09-09
4
41
 
5
42
  Dialog, AlertDialog, Drawer, Sheet, and BottomSheet footer actions now carry a
package/README.md CHANGED
@@ -5,7 +5,7 @@ The small, semantic UI foundation shared by AI Matrx React applications — prim
5
5
  **Controls:** Button, Badge, Label, Separator, the Input family, the Textarea family, Checkbox, Switch, RadioGroup, Slider, Toggle + ToggleGroup, Avatar, Progress.
6
6
  **Surfaces:** Card, Table, Tabs, Accordion, Collapsible, ScrollArea, Popover, Tooltip, HoverCard, Sheet, Dialog, AlertDialog, Drawer, BottomSheet + TabbedBottomSheet, Alert, Resizable, Skeleton.
7
7
  **Menus:** DropdownMenu, ContextMenu, Command / CommandDialog, Select, CreatablePicker.
8
- **Composed:** EditableLabel, SegmentedControl, ScoreRing, OverflowToolbar, ConfirmDialog + ConfirmDialogHost.
8
+ **Composed:** EditableLabel, SegmentedControl, ArchiveFilter, ScoreRing, OverflowToolbar, ConfirmDialog + ConfirmDialogHost.
9
9
  **Hooks + utilities:** `useScrollFade`, `useIsMobile`, `usePortalContainer`, `useDialogContainer`, `useDrawerDirection`, `cn`.
10
10
 
11
11
  **The confirm dialog lives here; the imperative `confirm()` lives in `@ai-matrx/kit`.** Since 0.11.0 / kit 0.9.0 the surface is one implementation, in the package that owns AlertDialog, the motion layer and the overlay scrim token. Mount the host once near your provider root and call `confirm()` from anywhere — they share one registry through a `globalThis` slot:
@@ -29,6 +29,19 @@ Use the declarative `<ConfirmDialog open … busy />` inline instead when the di
29
29
 
30
30
  **Footer actions stay touch-sized through portals.** Dialog, AlertDialog, Drawer, Sheet, and BottomSheet footers apply a 44px action floor on coarse pointers or below 1024px. Import the package stylesheet; no host subtree class is required. Fine-pointer desktop keeps its declared density. State controls and prose links retain their sizing; exceptional compact actions can use `data-touch-exempt` with a call-site reason.
31
31
 
32
+ **Every list over an archivable entity uses `ArchiveFilter`.** THE ARCHIVED-ITEMS LAW (Arman, 2026-09-09 — `common-docs/policies/archived-items.md`): an archive filter on every list, the default hides archived rows, and seeing them is one click. `ArchiveFilter` is the one control — `active` (default) / `archived` / `all`, in the same words the Next.js app uses.
33
+
34
+ ```tsx
35
+ import { ArchiveFilter, DEFAULT_ARCHIVE_FILTER, type ArchiveFilterValue } from "@ai-matrx/design-system";
36
+
37
+ const [archived, setArchived] = React.useState<ArchiveFilterValue>(DEFAULT_ARCHIVE_FILTER);
38
+ const rows = useRows({ archived }); // the SERVER applies the predicate
39
+
40
+ <ArchiveFilter value={archived} onValueChange={setArchived} counts={{ active: rows.activeCount }} />
41
+ ```
42
+
43
+ Pass the value to the reader, never filter the already-fetched page: counts, badges and pagination must describe what the list renders. `toArchiveFilter()` narrows an untrusted value (URL param, stored preference) back to the tri-state, defaulting to `active` so nothing silently widens.
44
+
32
45
  **The Tooltip lives here, and only here.** `@ai-matrx/tap-target` used to ship its own copy; since design-system 0.7.0 / tap-target 0.2.0 it consumes this one and re-exports nothing.
33
46
 
34
47
  Where hosts had forked a primitive over DENSITY, density is a prop, not a fork: `Card size="sm|md|lg"`, `Table size="sm|md"`, `Accordion size="sm|md"`, `Switch`/`Avatar`/`Checkbox`/`Slider`/`RadioGroup`/`Toggle` `size`, `ResizableHandle size="xs".."4xl"`. It is declared once on the root and every item reads it from context, so a card cannot mix paddings and a radio group cannot mix control sizes.