@gemboss/ui 0.12.0 → 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 +33 -0
- package/README.md +74 -0
- package/catalog/index.html +2138 -10
- package/gemboss-ui.css +19 -3
- package/package.json +2 -1
- package/src/collections.css +350 -0
- package/src/collections.tsx +414 -0
- package/src/index-table.tsx +216 -0
- package/src/index.ts +11 -0
- package/src/kit-plain.css +18 -2
- package/src/kit-plain.js +136 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
Versions up to 0.9.0 are described in the README, each in the section that introduced it.
|
|
4
4
|
|
|
5
|
+
## 0.13.0 (06/10/2026)
|
|
6
|
+
|
|
7
|
+
**Collections: six patterns for tables, lists, grids and boards** (Chris 05/10/2026), each with its states. The CSS is
|
|
8
|
+
a NEW entry, `@gemboss/ui/collections.css`, outside `gemboss-ui.css` and outside the admin's sheets. One part did go
|
|
9
|
+
into `gemboss-ui.css`: the media card's own pieces (below, kit-plain.css), because the card has one owner. README
|
|
10
|
+
"Collections".
|
|
11
|
+
|
|
12
|
+
Changed
|
|
13
|
+
- `ui-card--media` (kit-plain.css) is `position: relative`, and gains `__link` (the title, its overlay covers the card),
|
|
14
|
+
`__menu` (⋯ in the picture's corner; the card stops clipping so the menu is not cut off), `__meta`, `data-ratio="4/3"`.
|
|
15
|
+
Admin not affected (it does not load kit-plain.css).
|
|
16
|
+
- `ui-chip[aria-current="true"]` draws like a current chip (a sort chip is not a page).
|
|
17
|
+
|
|
18
|
+
Added
|
|
19
|
+
- `collections.css`: Data table modifiers (`ui-table--sticky-first`, `--compact`, totals, footer, sort with
|
|
20
|
+
`aria-sort`), Index table (`ui-index`, `ui-table--index`: Polaris IndexTable's 12/550 header on #f7f7f7, 6px cells;
|
|
21
|
+
selected #f1f1f1; the bulk bar over the header; folds into a list below 768 of its container), Resource list
|
|
22
|
+
(`ui-list`, 12px padding, a 64px two-line row, the title link covers the row), Compact list (`ui-list--compact`,
|
|
23
|
+
36 / 44 under a finger) and `ui-list--activity` (one timeline), Card grid (`ui-cardgrid`, auto-fill at 200 / 240 /
|
|
24
|
+
320, gap 16, `ui-card__link`), Board (`ui-board`, 12 a column then nested "Show 24 more"), thumbnails (`ui-thumb`),
|
|
25
|
+
states (`ui-empty--no-match`, `ui-coll-error`, `aria-busy`, skeletons per pattern, `ui-trunc`, `ui-clamp-2`).
|
|
26
|
+
- React: `DataTable`, `ResourceList`, `ResourceItem`, `CompactList`, `CardGrid`, `MediaCard`, `Board`,
|
|
27
|
+
`CollectionState`, `CollectionSkeleton` (plain module, server-safe) and `IndexTable` (client: whole-row links,
|
|
28
|
+
selection + bulk actions, Shift range, Escape, sort links or `onSort`).
|
|
29
|
+
- `kit-plain.js` `initCollections()` (runs by itself): `[data-href]` rows open on a click that is not on a control;
|
|
30
|
+
`.ui-index` selection, bulk bar, `gembossUI.selection()`, `gb:selection`; client sort and `gb:sort`, only in a table marked `data-gb-sort` (a React table owns its own sort buttons).
|
|
31
|
+
- `packages/ui/scripts/collections-gate.mjs`: the ruled-out combinations (uppercase header, zebra, card per row, more than one
|
|
32
|
+
visible button, hover-only actions, checkboxes without bulk actions, a linked row over two editors, media cards in a
|
|
33
|
+
per-viewport grid, a table scrolling at 1280), with a page that breaks each rule in `collections.test.ts`.
|
|
34
|
+
- Density gate: eleven new roles from Polaris 13.9.5 rendered (`polaris-reference.json`); `tableHead` / `tableCell`
|
|
35
|
+
now leave the index table to its own roles.
|
|
36
|
+
- Catalog: section "Bảng, list, lưới, board", every pattern and state, with 390px frames where the shape changes.
|
|
37
|
+
|
|
5
38
|
## 0.12.0 (05/10/2026)
|
|
6
39
|
|
|
7
40
|
**A change you SEE on every surface, and on the admin's /admin console.** The kit now draws the admin's (Polaris')
|
package/README.md
CHANGED
|
@@ -731,6 +731,79 @@ surface computes every number and ratio; the kit only draws. Markup for each is
|
|
|
731
731
|
- `ui-grid--2` / `--3`: card grid that drops to one column; `ui-section-head`: an `h2` + note between page head and
|
|
732
732
|
card titles.
|
|
733
733
|
|
|
734
|
+
## Collections (0.13.0): tables, lists, grids, boards
|
|
735
|
+
|
|
736
|
+
Chris settled these on 05/10/2026 after an inventory of 136 hand-made collections on 11 surfaces (86 tables scrolling
|
|
737
|
+
sideways, 7 of them at 1280; 0 sticky first columns; 12 kinds of empty state; checkboxes that selected nothing). Load
|
|
738
|
+
`@gemboss/ui/collections.css` beside `gemboss-ui.css` (its own entry, like `editor.css`: the export had ~1.4 KB of room
|
|
739
|
+
left under its 90 KB, and the admin, which draws tables with Polaris, never loads it). Plain-HTML surfaces also load
|
|
740
|
+
`kit-plain.js` (row links, selection, client sort). Every pattern is in the catalog with its states, at 1280 and 390.
|
|
741
|
+
|
|
742
|
+
### Which pattern
|
|
743
|
+
|
|
744
|
+
```
|
|
745
|
+
Is the picture what people look at to choose? → 5 Card grid
|
|
746
|
+
Do items move through states, and do people move them? → 6 Board
|
|
747
|
+
Is the frame narrower than 480 (a rail, a popup, a drawer)? → 4 Compact list (3 if it needs media)
|
|
748
|
+
Are there 3+ attributes to compare across items?
|
|
749
|
+
├─ each row is an entity to open / select in bulk? → 2 Index table
|
|
750
|
+
└─ read-only figures → 1 Data table
|
|
751
|
+
One line per item? → 4 Compact list
|
|
752
|
+
Otherwise → 3 Resource list
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
More than 50 items: paginate (`ui-pager`, position in the URL; a feed or a board column: `ui-more`). Never cut a list
|
|
756
|
+
silently: a `slice` prints "+N more" or "See all N". A table renders at most 100 rows at a time.
|
|
757
|
+
|
|
758
|
+
| # | Pattern | React | HTML | Polaris |
|
|
759
|
+
|---|---|---|---|---|
|
|
760
|
+
| 1 | Data table | `DataTable` | `ui-table-wrap > table.ui-table(.ui-table--sticky-first, --compact)`; `tfoot.ui-table__totals`, `.ui-table__footer` | DataTable |
|
|
761
|
+
| 2 | Index table | `IndexTable` (client) | `div.ui-index > [div.ui-index__sortbar] + [div.ui-bulkbar] + ui-table-wrap > table.ui-table.ui-table--index`; `tr[data-href]`, `td.ui-table__check`, `td.ui-table__primary > a.ui-table__title + span.ui-sub`, `td.ui-table__actions` | IndexTable |
|
|
762
|
+
| 3 | Resource list | `ResourceList` + `ResourceItem` | `ul.ui-list > li.ui-list__item > .ui-list__media + .ui-list__body(a.ui-list__title, p.ui-list__sub, p.ui-list__meta, .ui-list__badges) + .ui-list__aside + .ui-list__actions` | ResourceList |
|
|
763
|
+
| 4 | Compact list | `CompactList` (`variant="activity"`) | `ul.ui-list.ui-list--compact > li.ui-list__item > a/button/div.ui-list__row`; timeline: `ui-list--activity`, `.ui-list__dot(--tone)`, `.ui-list__detail`, `time` | ActionList |
|
|
764
|
+
| 5 | Card grid | `CardGrid min={200 \| 240 \| 320}` + `MediaCard` | `div.ui-cardgrid[data-min] > article.ui-card.ui-card--media > a.ui-card__media + .ui-card__menu + .ui-card__body > a.ui-card__link` | InlineGrid + Card |
|
|
765
|
+
| 6 | Board | `Board` | `div.ui-board > section.ui-board__col > header.ui-board__head + ol.ui-board__list + details.ui-board__more` | none |
|
|
766
|
+
| | States | `CollectionState kind="empty \| no-match \| error"`, `CollectionSkeleton pattern=…`, `state="busy"` | `ui-empty(--no-match)`, `ui-coll-error`, `ui-skeleton--table/--list/--compact/--grid/--board`, `aria-busy="true"` | EmptyState, EmptySearchResult |
|
|
767
|
+
|
|
768
|
+
`./collections` is a plain module (a server component renders it, render functions and all); `IndexTable` is a client
|
|
769
|
+
module. Its props are plain data (rows of rendered cells, `sortHref` strings) so a server page can still render it;
|
|
770
|
+
the callbacks (`onSort`, `onSelectionChange`, a bulk action's `onAction`) need a client parent. Neither module reaches
|
|
771
|
+
the admin's first load (`kit-plain-bundles.test.ts` checks the shell import carries none of their code).
|
|
772
|
+
|
|
773
|
+
### The rules, and what checks them
|
|
774
|
+
|
|
775
|
+
- **The whole row opens the item; the title stays a real link** (Cmd-click, a screen reader). A click on a checkbox, a
|
|
776
|
+
button, the ⋯ menu, a select or a second link does only that; so does a click that ends a text selection. A row with
|
|
777
|
+
two or more in-place editors is not linked (only its title is). HTML: `tr[data-href]` + kit-plain.js; React:
|
|
778
|
+
`IndexTable` rows with `href`; a resource list's title link covers its row (no script).
|
|
779
|
+
- **One visible button per row at most**, the rest in the ⋯ menu (`ui-menu`). **Never shown only on hover.**
|
|
780
|
+
- **Below 768 of its container an index table becomes a list** (title line; the other cells on one caption line,
|
|
781
|
+
`data-label` prefixes, `data-condensed="hide"` drops; checkbox and actions kept; rows ≥ 44); sort moves to the chips
|
|
782
|
+
of `ui-index__sortbar`. **A data table never folds:** it scrolls in its frame with `--sticky-first`.
|
|
783
|
+
- **At 1280 a table fits its page frame.** Fix in this order: a `canvas` page if the content really is wide; move
|
|
784
|
+
low-priority columns to the detail page; fold attributes into the `ui-sub` line.
|
|
785
|
+
- **No zebra, no uppercase header, no card per row, no grid that changes its column count per viewport** (auto-fill
|
|
786
|
+
with one of 200 / 240 / 320).
|
|
787
|
+
- **A checkbox column only with bulk actions.** The bulk bar covers the header (the table does not move), carries its
|
|
788
|
+
own select-all, Shift+click takes a range, Escape clears. HTML: `input[data-gb-select]` / `[data-gb-select-all]`,
|
|
789
|
+
`gembossUI.selection(root)`, event `gb:selection`.
|
|
790
|
+
- **Sort lives in the URL** (`th[aria-sort] > a.ui-table__sort`); `button.ui-table__sort` sorts a small table in place
|
|
791
|
+
(`table[data-gb-sort="client"]`, by `data-sort-value`) or fires `gb:sort` for the page (`data-gb-sort="event"`); a React table owns its buttons and kit-plain.js leaves them alone.
|
|
792
|
+
- **States** (Gems/CLAUDE.md 9.2): empty (one main action) · no match (filters and header stay, "Clear filters") ·
|
|
793
|
+
loading (a skeleton in the pattern's shape: a table keeps its real header, rows keep their height) · reloading
|
|
794
|
+
(`aria-busy`: the old rows stay, dimmed) · error (a banner in the frame + Retry, "as of HH:MM" with old data; never an
|
|
795
|
+
empty list) · selected · sort · filter (`ui-toolbar` + `ui-chip` + `ui-coll-count`) · pagination · long content
|
|
796
|
+
(`ui-trunc`, `ui-clamp-2`, the full text in `title`) · hover · focus-visible (a ring on the row) · reduced motion.
|
|
797
|
+
|
|
798
|
+
Checks: `packages/ui/src/collections.test.ts` (behaviour in Chromium, both the HTML and the React table), the density gate
|
|
799
|
+
(`polaris-reference.json` roles `dataRow`, `indexHead`, `indexCell`, `indexRow`, `bulkBar`, `resourceItem`,
|
|
800
|
+
`resourceItemTwoLine`, `resourceTitle`, `compactRow`, `skeletonBar`, `thumbnail`) and `packages/ui/scripts/collections-gate.mjs`,
|
|
801
|
+
which reports the ruled-out combinations on any page (each rule has a page built to break it in the test):
|
|
802
|
+
|
|
803
|
+
```bash
|
|
804
|
+
node packages/ui/scripts/collections-gate.mjs --url https://partner-radar.ops.gemboss.ai/companies --width 1280
|
|
805
|
+
```
|
|
806
|
+
|
|
734
807
|
## Long lists: pages or "load more" (0.7.3)
|
|
735
808
|
|
|
736
809
|
*Recommendation, not a rule: Claude, 04/10/2026, after Chris asked it to decide for GemFactory.*
|
|
@@ -803,6 +876,7 @@ something the base cannot express, add a token or a prop here, and every surface
|
|
|
803
876
|
| `packages/ui/src/shell.css` | the SHARED SHELL (rail, topbar, main, mobile drawer, the assistant's thread rail, popover surface, account chip). The admin's `gemboss-shell.css` @imports it on line 2; the export refuses a shared-shell rule in the admin's sheet or an admin-only rule here (one owner). |
|
|
804
877
|
| `packages/ui/src/kit-plain.css` | primitives for surfaces that render plain HTML, not React (0.2.1): menu, key/value list, icon button; 0.3.0 adds `ui-link` / `ui-prose`, the media card (`ui-card--media`, `__media`, `__body`, `__foot`) and the popup's `ui-modal__body` / `__foot`. Shipped inside `gemboss-ui.css`; the admin does not import it (its first-load CSS budget has ~0.1 KB headroom).; (0.4.0) report pages: delta, large KPI grid, bar list, column chart, legend, funnel, card grid, section head. |
|
|
805
878
|
| `packages/ui/src/kit-plain.js` | 0.3.0: the behaviour those surfaces each wrote by hand: `gembossUI.openModal` (Escape, backdrop, Tab trap, stacking, ask-before-close, focus back), `toast` (text, error tone), `initMenus` (outside click, item, blur, Escape closes the menu before the popup); 0.5.0: `confirm`, `initShell`, `initPasswordFields` / `resetPasswordFields`. A classic script: inline it or `<script src>`; see "Plain-HTML behaviour" above. |
|
|
879
|
+
| `packages/ui/src/collections.css` | 0.13.0: tables, lists, grids, boards and their states (see "Collections"). A separate entry, NOT inside `gemboss-ui.css`; the admin does not load it. |
|
|
806
880
|
| `packages/ui/src/editor.css` | 0.9.0: the editors (frame, top bar, preview, Configure dock, inspector and controls, Layers, settings drawer, page picker, menus). A separate entry, NOT inside `gemboss-ui.css`; the admin imports it from the editor components, never from a layout. See "Editor CSS" above. |
|
|
807
881
|
| `packages/ui/src/chat.css`, `chat-composer.css`, `assistant.css`, `auth.css`, `app-shell.css` | the chat body, the composer, the assistant frame, the sign-in screen, the topbar slots + base text + the page width tiers (`ui-page`, 0.8.1). All inside `gemboss-ui.css`; the admin @imports `chat.css` and `chat-composer.css` itself. |
|
|
808
882
|
| `packages/ui/src/icon.svg` | 0.5.0: the GemBoss app icon, for `<link rel="icon" type="image/svg+xml">`. Must stay byte-identical to `apps/admin/src/app/icon.svg` (`kit-look.test.ts` checks). |
|