@gemboss/ui 0.21.0 → 0.30.2
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 +328 -0
- package/README.md +433 -24
- package/catalog/editor.html +426 -10
- package/catalog/index.html +907 -33
- package/gemboss-ui.css +3 -3
- package/package.json +23 -3
- package/parts/components.css +5 -0
- package/parts/core.css +5 -0
- package/parts/shell.css +5 -0
- package/src/action-card.css +1 -0
- package/src/action-card.tsx +149 -0
- package/src/app-shell.css +1 -1
- package/src/assistant/chat-markdown.ts +279 -0
- package/src/assistant/chat-turns.ts +120 -0
- package/src/assistant/chat.tsx +871 -0
- package/src/assistant/engine-mark-art.ts +45 -0
- package/src/assistant/engine-mark.tsx +39 -0
- package/src/assistant/engine.tsx +697 -0
- package/src/assistant/host.tsx +3 -1
- package/src/assistant/index.ts +6 -0
- package/src/assistant-chat.css +1 -0
- package/src/assistant-engine.css +1 -0
- package/src/auth.css +1 -1
- package/src/auth.tsx +18 -2
- package/src/chat-composer.css +1 -1
- package/src/chat-plain.js +6 -0
- package/src/chat.css +1 -1
- package/src/collections.tsx +1 -0
- package/src/dialog.tsx +3 -135
- package/src/editor/controls.tsx +1 -0
- package/src/editor/frame.tsx +12 -4
- package/src/editor/index.ts +10 -1
- package/src/editor/layers.tsx +136 -0
- package/src/editor/panel.tsx +1 -0
- package/src/editor/panes.tsx +4 -3
- package/src/editor/sortable.tsx +79 -0
- package/src/editor/tree.tsx +61 -0
- package/src/editor-layers-plain.js +1 -0
- package/src/editor.css +1 -1
- package/src/engine-plain.js +1 -0
- package/src/index-table.tsx +1 -0
- package/src/index.ts +8 -3
- package/src/kit-plain.css +1 -1
- package/src/kit-plain.js +1 -1
- package/src/launcher.tsx +1 -0
- package/src/menu-layer.ts +9 -2
- package/src/minichart.css +1 -0
- package/src/minichart.tsx +165 -0
- package/src/portal.tsx +1 -0
- package/src/reactions.tsx +1 -0
- package/src/resource-list-select.tsx +1 -0
- package/src/search-dialog.tsx +146 -0
- package/src/selection.tsx +1 -0
- package/src/setup-guide.css +1 -0
- package/src/setup-guide.tsx +116 -0
- package/src/theme-script.ts +10 -0
- package/src/theme.tsx +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,329 @@
|
|
|
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.30.2 (09/10/2026)
|
|
6
|
+
|
|
7
|
+
The admin's chat moves onto the package's composer and engine picker (gemboss admin, assistant sync).
|
|
8
|
+
|
|
9
|
+
- `ChatComposer` `canSend`: overrides the empty-box rule for the action. The admin sends a reference picture with no words,
|
|
10
|
+
and holds send while an upload runs, without disabling the text box. React only: `chat-plain.js` sits at its weight
|
|
11
|
+
ceiling (8698 B gzip) and no plain-HTML surface needs it yet.
|
|
12
|
+
- `ChatComposer` `stopDisabled`: Stop stays in the slot, disabled, while a stop is on its way (the admin's turn can take
|
|
13
|
+
seconds to abort; a second press was a silent no-op).
|
|
14
|
+
- chat-composer.css / chat.css: the admin's own engine chip rules are deleted (`.gemboss-ec-enginepick`, `-enginepick-btn`,
|
|
15
|
+
`-chiplabel`, `-chipsub`, `-chipmark` and their density and 44px-target rules). The admin now draws `EnginePicker` like
|
|
16
|
+
every surface (`gb-engine-*`, assistant-engine.css); nothing in the fleet wears those classes any more.
|
|
17
|
+
|
|
18
|
+
## 0.30.1 (09/10/2026)
|
|
19
|
+
|
|
20
|
+
- `LayerList` / `SortableLayerList` under a finger (`pointer: coarse`): the row's action buttons are 44x44 (were 26x26,
|
|
21
|
+
the mouse size) and the row's pick button is at least 44px tall. Where the name and the buttons do not fit side by side
|
|
22
|
+
(the 300px Layers drawer), the row wraps and the buttons take a line of their own, so a name is never drawn under them.
|
|
23
|
+
Measured on the funnel canvas's section list at 768 with touch. Mouse sizes are unchanged.
|
|
24
|
+
|
|
25
|
+
## 0.30.0 (09/10/2026)
|
|
26
|
+
|
|
27
|
+
**What gemform had and the package did not** (Chris 08/10/2026: "cái page login của gemform cái background bên dưới logo
|
|
28
|
+
cũng đẹp… trong gemform có cái gì mà gemboss ui không có thì chuẩn hoá đăng ký vào gemboss ui"). gemform
|
|
29
|
+
(gemlabs `toolkits/gemform`) was inventoried screen by screen; three things in it were shared patterns the package lacked.
|
|
30
|
+
Everything else it draws (shell, KPIs, cards, tables with bulk actions, filters, pager, switches, banners, key-value
|
|
31
|
+
lists, skeletons) the package already has, and gemform moves onto those. README "The sign-in screen", "Mini charts",
|
|
32
|
+
"Setup guide".
|
|
33
|
+
|
|
34
|
+
Added
|
|
35
|
+
- `AuthLayout backdrop`: `"facet"` (default, the markup and pixels of 0.29.2), `"grid"` (gemform's ground: a 34px iris
|
|
36
|
+
grid fading out from the panel's top-left corner, on an ink gradient), `"none"`. Tokens `--gb-panel-grid-bg`,
|
|
37
|
+
`--gb-panel-grid-line`, `--gb-panel-grid-size`, `--gb-panel-grid-fade` on `.gb-auth`; classes `gb-auth-panel--grid` /
|
|
38
|
+
`--none` for a page that writes the markup. Drawn only where the panel is (900 wide AND 520 tall).
|
|
39
|
+
- `Sparkline` + `sparklinePaths` and `ShareBar`, a new entry `minichart.css` (0.5 KB gzip). Six hand-drawn sparklines in
|
|
40
|
+
the fleet (admin x3, talent-radar, search-radar, gemwatcher, gemform); the baseline is 0 for counts unless fixed.
|
|
41
|
+
- `SetupGuide`, a new entry `setup-guide.css` (0.9 KB gzip): the admin's Setup guide (StoreChecklistCard,
|
|
42
|
+
`gemboss-setup-*`) with the kit's tokens, all native `<details>` (no script for plain HTML). The admin keeps its own
|
|
43
|
+
until it moves onto this one in a PR of its own.
|
|
44
|
+
- The catalog draws the sign-in screens at 1280 (at the catalog's column width the panel never showed), the grid beside
|
|
45
|
+
the facet, the mini charts in "Báo cáo", and a "Hướng dẫn thiết lập" section.
|
|
46
|
+
|
|
47
|
+
Neither new entry is in `gemboss-ui.css` or the core (parts gate); the admin imports none of them. The grid's rules are
|
|
48
|
+
in auth.css (+0.2 KB gzip there and in the bundle). `apps/admin/scripts/check-token-fallbacks-agree.mjs` now reads
|
|
49
|
+
minichart.css and setup-guide.css too.
|
|
50
|
+
|
|
51
|
+
Review #3925 (in this version): class names are written out (no `ui-sharebar__seg--${tone}` stem: the admin's orphan-rule
|
|
52
|
+
gate went red on it); ShareBar grows by share, so fractions fill the track; a sparse array's holes are gaps; SetupGuide
|
|
53
|
+
decides the open step once, draws a step without a body as a plain row, fills a `<progress>` instead of a styled width,
|
|
54
|
+
renders nothing for no steps, remembers a fold (`rememberKey`), takes a `group` name; the reduced-motion block names the
|
|
55
|
+
head's chevron with its own selector (`setup-guide-browser.test.tsx` reads the computed transition, with the weak
|
|
56
|
+
selector as negative control); the specificity test computes specificity instead of matching strings.
|
|
57
|
+
|
|
58
|
+
## 0.29.2 (08/10/2026)
|
|
59
|
+
|
|
60
|
+
Fixes the rollout to search-radar (gemlabs #943) and content-radar (#944) found in the chat body. `chat-plain.js` does the
|
|
61
|
+
same as the components, held to them by chat-plain.test.ts.
|
|
62
|
+
|
|
63
|
+
- `ChatMarkdown` / `parseInline`: a bare `https://…` (and `<https://…>`) is a link again, as the surfaces' own renderers
|
|
64
|
+
drew it. GitHub's reading of where it ends: trailing `. , : ; ! ? _ ~ ' "` and a `)` or `]` with no partner inside the
|
|
65
|
+
URL go back to the sentence (linear time: a URL followed by 50 000 `)` parses in milliseconds). It also ends at `*`,
|
|
66
|
+
CJK text and full-width / typographic punctuation, and one glued to a word (`foohttps://…`) is not a link. Same
|
|
67
|
+
allowlist as a written link (`linkTarget`, then `new URL`: http(s) with a host), so `https://.`, `ftp:`, `javascript:`
|
|
68
|
+
stay text. New export `bareUrl`.
|
|
69
|
+
- `ChatMarkdown` / `parseBlocks`: `####` to `######` are headings at the bubble's lowest step (`level: 3`, an `h5` with
|
|
70
|
+
`gemboss-md-h3`) instead of four hashes in front of a sentence. `#######` and `#tag` stay text; a heading line with no
|
|
71
|
+
words (`#### `) is dropped instead of drawing an empty heading.
|
|
72
|
+
- `ImageHost.host` is optional: an entry with no host is the page's OWN origin (`imageHosts={[{ path: "/api/img/" }]}`),
|
|
73
|
+
for a root-relative picture (content-radar's `/api/img/…`). Checked after the browser's normalisation: the resolved
|
|
74
|
+
path must start with `path`; `../`, `%2e%2e`, `\`, an encoded slash or backslash, a double encoding (`%25`), a `;` path
|
|
75
|
+
parameter (`..;/`), `//host` and `/\host` are refused, and the src drawn is the resolved path. `path` must be a
|
|
76
|
+
directory below the root (`/x/`; `/` and `/x` are ignored). An entry WITH a host never opens relative paths.
|
|
77
|
+
- chat.css: the send circle is `.gemboss-ec-toolbar > button[type="submit"]` (the toolbar's own child, same specificity).
|
|
78
|
+
`.gemboss-ec-input button[type="submit"]` also reached the engine popup, a DOM descendant of the composer even in the
|
|
79
|
+
top layer, and drew a surface's Pair button there as the 44px filled circle (five surfaces wrote `type="button"` to
|
|
80
|
+
dodge it). Test of the forbidden combination in chat.test.tsx, and the popup measured in Chromium against the same
|
|
81
|
+
button outside the composer (chat-browser.test.tsx, chat-plain.test.ts), each with the old selector as its negative.
|
|
82
|
+
|
|
83
|
+
## 0.29.1 (08/10/2026)
|
|
84
|
+
|
|
85
|
+
- `ChatThread` and plain `chat.thread`: keep following when a native scroll event from their own write-to-end arrives
|
|
86
|
+
after new content. The increased content gap no longer masquerades as the reader scrolling up. Wheel, key, touch and
|
|
87
|
+
direct programmatic moves up still unpin the thread.
|
|
88
|
+
|
|
89
|
+
## 0.29.0 (08/10/2026)
|
|
90
|
+
|
|
91
|
+
**The assistant's chat body as components** (Chris 08/10/2026: "đồng bộ hết giao diện của AI assistant… mọi service có
|
|
92
|
+
panel này đồng bộ style + code dùng gemboss ui"). Until now the package drew the frame, the conversation list and the
|
|
93
|
+
engine picker; every surface wrote the bubbles, steps, starters and composer by hand on chat.css's classes, with its own
|
|
94
|
+
markdown renderer (five of them). The surface now hands in data and actions. README "The chat body".
|
|
95
|
+
|
|
96
|
+
Added
|
|
97
|
+
- `@gemboss/ui/assistant`: `AssistantChat` (thread + empty state + composer, from `messages`), and its pieces
|
|
98
|
+
`ChatThread` (role=log, follows the end only while the reader is there, aria-busy), `ChatMessage`, `ChatBubble`,
|
|
99
|
+
`ChatMarkdown` (the admin's parser and renderer: tables, headings demoted, fenced code that folds, safe links, pictures
|
|
100
|
+
only from fleet hosts, no raw HTML; `ownLink` / `renderLink` for a surface's own scheme), `ChatSteps` (rows print and
|
|
101
|
+
stop; kinds step / thinking / trace / steer), `ChatPending` (the one heartbeat; says its label once to a screen
|
|
102
|
+
reader), `ChatStarters` (they wrap), `ChatMeta` (Copy · engine · seconds · cost), `ChatError` (a fix: sentence,
|
|
103
|
+
command, Copy, the original folded), `ChatNote`, `ChatComposer` (a DIV, not a form; Enter sends, Shift+Enter and an IME's
|
|
104
|
+
Enter do not; one 44px slot that is send or stop; grows to 84px; `data-density` full → compact → icon → tight, measured),
|
|
105
|
+
`ChatAttach`, `PaperclipIcon`, `useComposerDensity`, `ChatLabelsProvider`, `CHAT_EN`.
|
|
106
|
+
- `useChatTurns()`: the conversation's state with an id per message; a turn is written BY ITS ID (`start`, `write`,
|
|
107
|
+
`step`, `finish`, `fail`, `note`), so a note landing mid-turn or the next turn opening cannot take its text (the
|
|
108
|
+
"patch the last element" bug of partner-radar #929 / content-radar #937). `bridgeTurnError(e)` + `atBridge(e, status)`:
|
|
109
|
+
only a failure AT the bridge (its call threw, or it answered 401: pairing code rejected) is the bridge's; its 400 / 503
|
|
110
|
+
and failures on the way to the server are the turn's.
|
|
111
|
+
- `parseBlocks`, `parseInline`, `linkTarget`, `imageSource`, `FLEET_IMAGE_HOSTS`: the markdown, testable without React.
|
|
112
|
+
- `EngineMark`, `ENGINE_MARK_ART`, `isEngineMarkId`: each engine's mark (from the admin).
|
|
113
|
+
- `EnginePicker`: `EngineChoice.mark` (the chip shows the engine's mark instead of its name when the composer is too
|
|
114
|
+
narrow), `EngineChoice.models` + `onPick(engine, model)` (every engine with its own models, one click picks both: the
|
|
115
|
+
admin's popup), `problem` (a red line on the Engine tab), `disabled` (the chip itself, while a switch is in flight).
|
|
116
|
+
- `assistant-chat.css`, a new entry (0.9 KB gzip), imported by the chat components; not in `gemboss-ui.css`.
|
|
117
|
+
chat.tsx imports chat.css and chat-composer.css too (they were "the surface links it").
|
|
118
|
+
- `chat-plain.js` (after `kit-plain.js`, and `engine-plain.js` when the page has the picker): `gembossUI.chat` with
|
|
119
|
+
`markdown`, `message`, `render`, `thread`, `steps`, `pending`, `starters`, `meta`, `error`, `note`, `composer`, `attach`,
|
|
120
|
+
`turnError`, `atBridge`, and `gembossUI.engineMark`. Same markup as the components, element by element (chat-plain.test.ts).
|
|
121
|
+
- `AssistantChat` `title` / `subtitle`: the chat's own heading where the frame has no title bar (full screen).
|
|
122
|
+
- `useFullChromeRoom(ref)`: how far full screen's floated buttons reach into an element (`--gb-chat-chrome-w` / `-h`,
|
|
123
|
+
`data-chrome`), for a surface arranging the pieces itself; `AssistantChat` uses it.
|
|
124
|
+
- Exports `./assistant/markdown` (the parser) and `./assistant/engine-mark-art` (the artwork): no JSX, no CSS, so a node
|
|
125
|
+
test or a server module imports them. The admin's `components/chat/markdown-blocks.ts` and `lib/engine-mark-art.ts`
|
|
126
|
+
now re-export these (one owner; the admin's tests read the package's code). A fence with a tag like `c#`, `c++`,
|
|
127
|
+
`objective-c` is a fence (it opened nothing, and its closing fence swallowed the rest of the answer as code).
|
|
128
|
+
|
|
129
|
+
Fixed
|
|
130
|
+
- Full screen: the frame's floated buttons (Back to the popup and a surface's `fullActions`) covered the first message of
|
|
131
|
+
a chat with no heading (content-radar /v2/assistant at 1280). `AssistantChat` measures how far they reach into it and
|
|
132
|
+
makes room (`data-gb-dock-chrome` on the host's button row is what it measures).
|
|
133
|
+
- On a phone, a `fullActions` button with no icon lost its words and showed an empty circle (assistant-chat.css).
|
|
134
|
+
- `BridgeNotice`'s "Open setup" was a 16px box with a 24px overlay, which a measuring tool reads as 16: its own box is now
|
|
135
|
+
24px with a mouse and 44px under touch / at phone width (negative margins keep the line 16px). A long sentence no longer
|
|
136
|
+
wraps away from its dot (dot | sentence, the action under the sentence).
|
|
137
|
+
- `engine-plain.js`: the chip carries the engine's mark (`mark`) when chat-plain.js is on the page.
|
|
138
|
+
|
|
139
|
+
Review #3910 (all in this version): the log unpins at the reader's first move up (wheel, finger, keys), not 24px later, and
|
|
140
|
+
goes back to the end on a send or another conversation (`ChatThread pinKey`; plain: `log.toEnd()` / composer `thread`);
|
|
141
|
+
`turns.step` keeps a field an update leaves out; a bridge `TimeoutError` is the bridge's; clicking the pick already in
|
|
142
|
+
force changes nothing; a step for an engine with no mark keeps its ✓ / ✕; message keys never mix ids and positions;
|
|
143
|
+
plain `render()` keeps a message's element when its look did not change, the heartbeat's clock, and the folds the reader
|
|
144
|
+
opened; the full-screen room is measured again when the buttons themselves change size.
|
|
145
|
+
|
|
146
|
+
## 0.28.0 (08/10/2026)
|
|
147
|
+
|
|
148
|
+
**Action card: an assistant proposes, a person applies.** The look of GemFeedback's merge and board-action cards (Chris
|
|
149
|
+
08/10/2026, "follow theo gemboss ui"), so every assistant in the fleet asks before a change the same way. README "Action card".
|
|
150
|
+
|
|
151
|
+
Added
|
|
152
|
+
- `ActionCard`, `ActionCardSection`, `ActionCardItem`, `ActionChange` (React), `action-card.css` (its own entry
|
|
153
|
+
`./action-card.css`, loaded by the component; `gemboss-ui.css` unchanged).
|
|
154
|
+
- Catalog section "Thẻ hành động".
|
|
155
|
+
- `packages/ui/weight-budget.json`: a ceiling for `packages/ui/src/action-card.css`.
|
|
156
|
+
## 0.27.0 (08/10/2026)
|
|
157
|
+
|
|
158
|
+
**The engine picker for plain HTML**, for gemcare's two assistants (inbox, Reports), which have no React.
|
|
159
|
+
|
|
160
|
+
Added
|
|
161
|
+
- `engine-plain.js` (new entry, after `kit-plain.js`): `gembossUI.enginePicker(host, options)` → `{ update, openTab, open,
|
|
162
|
+
close, isOpen, destroy, element, panel }` and `gembossUI.bridgeNotice(options)`. Same markup as `EnginePicker` (one
|
|
163
|
+
stylesheet, `assistant-engine.css`), same behaviour; a redraw patches in place. README "Plain HTML:
|
|
164
|
+
`gembossUI.enginePicker()`". 5.3 KB gzip minified, its own ceiling.
|
|
165
|
+
- `gembossUI.placeFloating(layer, anchor, end)` in kit-plain.js: the menus' placement, one plain copy (floatMenu and
|
|
166
|
+
engine-plain.js use it).
|
|
167
|
+
|
|
168
|
+
Changed
|
|
169
|
+
- `EnginePicker`: an Escape that closes the panel is marked handled (`preventDefault`) also when focus is outside the
|
|
170
|
+
panel. A surface whose Escape hides the assistant and checks `defaultPrevented` waits for the next one; the
|
|
171
|
+
window-capture markers the surfaces added (gemlabs #922, gemfeedback #66) are no longer needed. Not an Escape it does
|
|
172
|
+
not own: an IME composition (keyCode 229), or one in a modal opened from the panel; and focus entering such a modal
|
|
173
|
+
closes the panel, which would otherwise sit above it in the top layer.
|
|
174
|
+
|
|
175
|
+
## 0.26.0 (08/10/2026)
|
|
176
|
+
|
|
177
|
+
**A tablet glyph to draw with** (the funnel canvas's "All sizes": each page at desktop, tablet and phone widths).
|
|
178
|
+
|
|
179
|
+
Added
|
|
180
|
+
- `TabletGlyph` in `@gemboss/ui/editor`, beside `MonitorGlyph` and `PhoneGlyph`. `DeviceToggle` draws it for its Tablet
|
|
181
|
+
button (it carried the same SVG inline), so there is one tablet.
|
|
182
|
+
|
|
183
|
+
## 0.25.0 (07/10/2026)
|
|
184
|
+
|
|
185
|
+
**The assistant's engine picker** (Chris 07/10/2026): a chip in the composer row, as in the admin, that opens a popup
|
|
186
|
+
with Engine · Setup · Status tabs. Engine, model, effort, the bridge's status and its install command leave the chat.
|
|
187
|
+
|
|
188
|
+
Added
|
|
189
|
+
- `EnginePicker`, `EnginePanel`, `BridgeNotice`, `useEnginePicker` (+ types `EngineChoice`, `Choice`, `BridgeStatus`,
|
|
190
|
+
`BridgeSetup`, `BridgeState`, `EnginePickerTab`) in `@gemboss/ui/assistant`. README "The engine picker".
|
|
191
|
+
- `assistant-engine.css`, a new entry (1.9 KB gzip), imported by the component; not in `gemboss-ui.css`.
|
|
192
|
+
- `placeFloating(layer, anchor, end)` in `menu-layer.ts`: the menus' placement, now shared with the picker's panel
|
|
193
|
+
(`floatMenu` calls it; same geometry).
|
|
194
|
+
|
|
195
|
+
## 0.24.0 (07/10/2026)
|
|
196
|
+
|
|
197
|
+
**The Studio canvas in the editors' frame** (gemboss #3856): the pieces the admin's Studio needed from the editor kit.
|
|
198
|
+
|
|
199
|
+
Added
|
|
200
|
+
- `EditorChatToggle` takes a `name` ("Hide <name>"; default "chat panel"): a column that is not a chat says so.
|
|
201
|
+
|
|
202
|
+
Changed
|
|
203
|
+
- A folded editor column (`.is-chat-collapsed`) is `visibility: hidden`: at width 0 its fields stayed in the Tab order.
|
|
204
|
+
|
|
205
|
+
Removed
|
|
206
|
+
- `.gemboss-pageedit-status` and `.gemboss-pageedit-kind` looks: the page editor draws Polaris' Badge, as the funnel beside it does
|
|
207
|
+
(`.gemboss-pageedit-status` stays on a wrapper as a hook, `data-status`, with no look).
|
|
208
|
+
|
|
209
|
+
## 0.23.0 (07/10/2026)
|
|
210
|
+
|
|
211
|
+
**The CSS comes in parts: a core every surface loads, and entries that come with the components that draw them.**
|
|
212
|
+
README "Load only what you use" has the table and the imports for Next and for plain HTML.
|
|
213
|
+
|
|
214
|
+
Added
|
|
215
|
+
- `@gemboss/ui/core.css` (reset + tokens, 1.0 KB gzip), `@gemboss/ui/components.css` (the kit, the field look,
|
|
216
|
+
kit-plain.css; 8.2 KB), `@gemboss/ui/shell.css` (the shell + app-shell.css; 5.5 KB): built into `parts/` from the
|
|
217
|
+
same sections as `gemboss-ui.css`, each opening with a header that names the gemboss commit (kept through minify).
|
|
218
|
+
The core is 14.7 KB against 21.7 for the bundle. Like `gemboss-ui.css`, the parts exist after `build-css.mjs` (the
|
|
219
|
+
tarball has them; in this repo, build first).
|
|
220
|
+
- Components import their own entry: `AuthLayout` & co. → `auth.css`; `AssistantHost`, the launcher → `assistant.css`;
|
|
221
|
+
`TopbarNav`, `SearchDialog`, `Avatar`, `Leaderboard`, `Podium`, `ThemeToggle` → `portal.css`; `ThemeToggle` /
|
|
222
|
+
`themeScript` (now in `theme-script.ts`, so a root layout with only the script does not take portal.css) → `theme-dark.css`; the collections components → `collections.css`; the editor components → `editor.css`.
|
|
223
|
+
A component a surface never imports takes its CSS out of the build with it (`sideEffects`).
|
|
224
|
+
- The editor kit's step 4 (#3850: `LayerList`, `SortableLayerList`, `LayerTree` in `layers.tsx`, `sortable.tsx`, `tree.tsx`)
|
|
225
|
+
imports `editor.css` like the rest of the editor; `editor-layers-plain.js` is minified and weighed like the other plain
|
|
226
|
+
scripts (1.8 KB gzip).
|
|
227
|
+
- `Reactions` (#3861, born an entry) imports `reactions.css` itself too; the parts gate found it unclassified on the
|
|
228
|
+
rebase, which is the gate doing its job.
|
|
229
|
+
|
|
230
|
+
Changed
|
|
231
|
+
- `@gemboss/ui/shell.css` is the built shell PART (was `packages/ui/src/shell.css`, which only the admin imported). The source is
|
|
232
|
+
`@gemboss/ui/shell-source.css`; the admin's `gemboss-shell.css` imports that, same file as before.
|
|
233
|
+
- `SearchDialog` moved to its own module (`search-dialog.tsx`, same export from `@gemboss/ui`), so a surface that only
|
|
234
|
+
opens a `Dialog` does not get `portal.css`.
|
|
235
|
+
- kit-plain.css → app-shell.css: `.ui-menu__item { display: flex … }` and the thread rail's 44px buttons at phone width
|
|
236
|
+
(`.gemboss-assistant-collapse`, `-newchat`). Both override a shell.css rule by coming after it; kit-plain.css sat
|
|
237
|
+
after shell.css in `gemboss-ui.css` but is in `components.css` now, which loads before it. Same rules, same weight.
|
|
238
|
+
- `gemboss-ui.css` holds the same parts as 0.19.0, in the parts' order (kit-plain.css now sits before the shell).
|
|
239
|
+
Computed style of every element of both catalogs at 1280 and 390, 0.19.0 bundle vs 0.23.0 bundle: 0 differences.
|
|
240
|
+
|
|
241
|
+
Measured on surfaces (tarball installed locally, nothing committed there), gzip of the package's CSS a page loads:
|
|
242
|
+
- content-radar (Next 16): `/v2` 38.5 KB on 0.19.0 → 32.3 with the core; `/login` 31.2 → 25.4; `/v2/accounts` 43.1 →
|
|
243
|
+
36.9. Keeping `gemboss-ui.css` on 0.23.0 instead costs +1.9 KB (`/v2` 40.4): the launcher brings assistant.css twice.
|
|
244
|
+
- taskdesk (plain HTML): 22.2 KB (the minified bundle) → 15.0 with the core; every element's computed style the same and
|
|
245
|
+
screenshots byte-identical at 1280 and 390.
|
|
246
|
+
- GemFactory sign-in (plain HTML): 22.2 KB → 17.7 with the core + auth.css; screenshots byte-identical at 1280 and 390.
|
|
247
|
+
|
|
248
|
+
Upgrading
|
|
249
|
+
- A surface that bundles the package with esbuild needs a CSS loader (`loader: { ".css": "empty" }` if it links the CSS
|
|
250
|
+
itself): esbuild stops at a component's own `import "./auth.css"` without one. GemFactory's gbui.mjs has it already.
|
|
251
|
+
|
|
252
|
+
The compatibility bundle, and the road out
|
|
253
|
+
- `gemboss-ui.css` stays, minified, FROZEN at the 0.19.0 set: a surface that links it does not break, and a new
|
|
254
|
+
component never goes into it (`parts-gate.mjs`, CI).
|
|
255
|
+
- 1. Now: every surface moves to the core + entries on its next bump (Next and Vite: three imports in the root layout and
|
|
256
|
+
drop `gemboss-ui.css` in the same bump; plain HTML: link the core and the entries each page draws).
|
|
257
|
+
2. A search across the fleet's repos for `gemboss-ui.css` shows who still loads it (06/10/2026: content-radar,
|
|
258
|
+
partner-radar, search-radar, talent-radar, GemCommunity admin, GemFeedback, gemwatcher, GemFactory, taskdesk).
|
|
259
|
+
3. When nobody does, it is removed in its own release, with this note pointing at it. Not before.
|
|
260
|
+
|
|
261
|
+
Checks
|
|
262
|
+
- `packages/ui/scripts/parts-gate.mjs` (CI, with `--selftest`): the core and the bundle frozen; every stylesheet in `src/`
|
|
263
|
+
classified; every entry exported; a component that draws an entry's class imports it; the built bundle holds exactly
|
|
264
|
+
the frozen sections.
|
|
265
|
+
- `parts-cascade.test.ts` (`test:ui-browser`): the catalog with the parts (the core first, then the entries in order and
|
|
266
|
+
reversed, collections.css and editor.css included) paints what the bundle paints, element for element, at 1280 and
|
|
267
|
+
390; two planted entries that only agree by order turn it red. The core loads first by contract (README "Order"):
|
|
268
|
+
an entry before it loses its modifiers (`.ui-empty--no-match`), measured.
|
|
269
|
+
- Ceilings for the three parts in `weight-budget.json`.
|
|
270
|
+
|
|
271
|
+
## 0.22.0 (07/10/2026)
|
|
272
|
+
|
|
273
|
+
**The layers, the element outline and the drawer as components (editor kit, step 4 of 5).** Nothing changes on screen
|
|
274
|
+
or in behaviour in the admin: its page editor's Layers, Page settings and Edit content drawers and its element
|
|
275
|
+
inspector's Elements outline now render these, measured equal on a production build (below). README "Layers and
|
|
276
|
+
drawer".
|
|
277
|
+
|
|
278
|
+
Added
|
|
279
|
+
- `@gemboss/ui/editor`, three more modules behind the entry: `layers` (`LayerList`, `EditorDrawer`), `sortable`
|
|
280
|
+
("use client": `SortableLayerList`) and `tree` (`LayerTree`).
|
|
281
|
+
- `LayerList`: the page's sections as rows (34px, 50 with a subtitle); select (`aria-current`), the caller's actions,
|
|
282
|
+
an empty line; off until asked: an eye to hide / show (`onToggleHidden`, `aria-pressed`), indent per `depth`.
|
|
283
|
+
- `SortableLayerList`: the same rows, reordered by drag (a grip, the dragged row faded, a drop line) and Alt+↑ / Alt+↓
|
|
284
|
+
(the focus kept on the moved row, also when `onMove` answers after a server write); the drag is kept by id. Its own
|
|
285
|
+
module, so the admin's Layers (no reordering) do not carry it. For GemFactory's Builder (step 5).
|
|
286
|
+
- `LayerTree`: an indented outline, `role="tree"` of `treeitem`s with level, position and selection.
|
|
287
|
+
- `EditorDrawer`: backdrop + a side panel (`right`: `.gemboss-settings`, `left`: `.gemboss-layers`), head with ✕,
|
|
288
|
+
`before`, body, `footer`.
|
|
289
|
+
- `editor-layers-plain.js` (its own file and its own weight ceiling, 2,315 B gzip; editor-plain.js is unchanged):
|
|
290
|
+
`gembossUI.initEditorLayers()`: select, hide, drag and Alt+↑/↓ (the row moves in the document),
|
|
291
|
+
outline select / clear, drawers opened by `data-gb-drawer` and closed by ✕ and the backdrop; an event for each.
|
|
292
|
+
- editor.css: the optional pieces (`.gemboss-layer-grip`, `.is-dragging`, `[data-drop]`, `.is-hidden`,
|
|
293
|
+
`.gemboss-layer-eye`) and `[hidden]` for a drawer a plain page keeps in the document.
|
|
294
|
+
- `catalog/editor.html`: Layers (drag, hide, select, indent), Page settings and the outline, running, at 1280 and 390.
|
|
295
|
+
|
|
296
|
+
Measured in the admin (two production builds, before = main f23a60729 with the #3848 fixes (0.20.1) and after, pinned SENTRY_RELEASE /
|
|
297
|
+
GIT_COMMIT_SHA / GEMBOSS_BUILD_STAMP, served by `next start` on the same local data; every write the harness could cause
|
|
298
|
+
was held)
|
|
299
|
+
- DOM and computed style (+ ::before / ::after, box, control values) of every element, and :hover / :focus-visible /
|
|
300
|
+
:active forced on every control of the editor's columns and drawers, for 13 states (page editor: Layers open, a layer
|
|
301
|
+
selected, focus on a row's actions, closed with ✕, closed from the backdrop, ↓ pressed with the write held; Edit
|
|
302
|
+
content drawer; Page settings drawer, typing in it; theme editor inspector, Elements: the outline, a node picked, "Add
|
|
303
|
+
inside" open, a node picked and cleared) at 320, 390, 768 (touch), 1280, 1366, 1920: 78 captures, 22,888 element
|
|
304
|
+
renders, 10,620 forced-state checks. 0 differences in computed style or box. In markup, the intended ones only (720):
|
|
305
|
+
`data-id` on each layer row and outline node, `type="button"` on the buttons the components draw (no form around
|
|
306
|
+
them), `aria-current="true"` on the selected layer's button. Not the change: inline styles serialised by the server or
|
|
307
|
+
by the client (computed equal), the logo's per-port URL, the canvas's loading spinner (four states re-captured with
|
|
308
|
+
the canvas settled: equal), and the forced states of the chat column's work-mode select, which differ between two
|
|
309
|
+
captures of the SAME base build too. Negative controls (one declaration laid over the after build: the layer button's
|
|
310
|
+
padding, the outline name's, the drawer head's) are reported in 3 of 3 states.
|
|
311
|
+
- Re-checked after rebasing onto main with 0.20.0 (#3846) and 0.20.1 (#3848): the 13 states at 1280 and 390, 26 captures,
|
|
312
|
+
7,612 element renders, 3,540 forced-state checks: again 0 differences in computed style or box, markup as above.
|
|
313
|
+
- First load (brotli), against main with 0.20.1: the shell 239,674 → 239,655 B (−19); page editor +693 (LayerList and
|
|
314
|
+
EditorDrawer; SortableLayerList is not in it), campaign editor +327, theme editor +314, product studio +198, section
|
|
315
|
+
editor +125, plugin editor −12. Package weight gate: editor.css 8.1 / 8.4 KB gzip, editor-plain.js unchanged,
|
|
316
|
+
editor-layers-plain.js 1.8 / 2.3 KB.
|
|
317
|
+
- Behaviour the admin does not use (drag, Alt+↑/↓, the eye, indent) and the plain-HTML side are asserted in Chromium:
|
|
318
|
+
editor-layers-browser.test.tsx (React and `initEditorLayers()`, with negative controls).
|
|
319
|
+
|
|
320
|
+
Known, kept as it was (this step moves markup, not behaviour)
|
|
321
|
+
- The admin's Layers do not drag and have no eye: they move with ↑ / ↓ buttons, which also work on touch (HTML drag and
|
|
322
|
+
drop does not start from a touch). Using `onMove` there is a change of its own.
|
|
323
|
+
- The drawers have no Escape, and do not move the focus into themselves or back to their opener.
|
|
324
|
+
- `DesignControls` (the inspector's Design tab body) is not moved: moving it changes how it looks.
|
|
325
|
+
- The theme editor's "Sections on this page" list (ThemeSectionList) keeps its own bordered rows (inline styles); drawn
|
|
326
|
+
as a LayerList it would look different.
|
|
327
|
+
|
|
5
328
|
## 0.21.0 (07/10/2026)
|
|
6
329
|
|
|
7
330
|
**Reactions: one emoji set and one chip for the fleet.** GemCare's team chat reactions, moved into the kit so GemFeedback
|
|
@@ -68,8 +391,13 @@ Fixed
|
|
|
68
391
|
- `.ui-seg svg` filled a stroke icon solid (`fill: currentColor` over `fill="none"`): the monitor and phone glyphs drew
|
|
69
392
|
as blocks. A `fill="none"` svg keeps its outline.
|
|
70
393
|
|
|
394
|
+
- A folded editor column (`.is-chat-collapsed`) is `visibility: hidden`: at width 0 its fields stayed in the Tab order.
|
|
395
|
+
- `EditorChatToggle` takes a `name` ("Hide <name>"; default "chat panel"): a column that is not a chat says so.
|
|
396
|
+
|
|
71
397
|
Removed
|
|
72
398
|
- The `.gemboss-ei-seg` look from `editor.css`.
|
|
399
|
+
- `.gemboss-pageedit-status` and `.gemboss-pageedit-kind` (the page editor draws Polaris' Badge, as the funnel beside it does).
|
|
400
|
+
|
|
73
401
|
## 0.19.0 (06/10/2026)
|
|
74
402
|
|
|
75
403
|
**The published CSS and plain scripts are minified, and each file has a wire-weight ceiling.** README "Minified on
|