@gemboss/ui 0.40.0 → 0.42.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 +110 -0
- package/README.md +98 -2
- package/catalog/editor.html +9 -7
- package/catalog/index.html +394 -235
- package/gemboss-ui.css +3 -3
- package/package.json +6 -2
- package/parts/components.css +1 -1
- package/parts/core.css +1 -1
- package/parts/shell.css +2 -2
- package/src/editor/controls.tsx +52 -8
- package/src/editor/index.ts +2 -2
- package/src/editor/repeater.tsx +27 -19
- package/src/editor/swatch.ts +133 -9
- package/src/editor-plain.js +1 -1
- package/src/editor.css +1 -1
- package/src/index.ts +3 -2
- package/src/portal.tsx +12 -6
- package/src/reactions-data.ts +13 -0
- package/src/reactions.tsx +5 -5
- package/src/reader-dialog.css +1 -0
- package/src/reader-dialog.tsx +26 -0
- package/src/shell.css +1 -1
- package/src/team-chat-data.ts +46 -13
- package/src/team-chat-plain.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,108 @@
|
|
|
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.42.0 (21/10/2026)
|
|
6
|
+
|
|
7
|
+
**The editor's colour field offers the page's theme colours and this store's recent colours** (gemboss #4888, Chris "bấm
|
|
8
|
+
trước gõ sau").
|
|
9
|
+
|
|
10
|
+
Added
|
|
11
|
+
- `ColorControl` takes `choices` (`ColorChoice { value, label, swatch }`): chips under the field while it is in use; a chip
|
|
12
|
+
writes its `value` (a theme chip writes `var(--gem-color-<role>)`). `themeColorChoices(palette)` lists the theme's roles in
|
|
13
|
+
`TOKEN_NAMES` order. No new CSS: `.gemboss-ei-swatches` / `.gemboss-ei-sw`.
|
|
14
|
+
|
|
15
|
+
**Team chat days in a given time zone; leaderboard words in the page's language** (follow-ups of GemCommunity's UX audit,
|
|
16
|
+
20–21/10/2026: /chat threw React #418 because the server (UTC) and a browser in Hanoi drew different day separators, and the
|
|
17
|
+
app had to feed the rules shifted dates; the podium's screen-reader words were English on vi and zh pages).
|
|
18
|
+
|
|
19
|
+
Added
|
|
20
|
+
- `timeZone` (IANA name) on `teamChatRows` options and as a last argument of `chatDayKey` and `chatDayWord`: days are that
|
|
21
|
+
zone's calendar days. An unknown name or an invalid date falls back to the local day, as without it.
|
|
22
|
+
- `chatDayISO(at, timeZone?)`: the day as "2026-10-21", for a `DaySeparator`'s `dateTime`.
|
|
23
|
+
- Plain script: `gembossUI.teamChat.rows` reads `opts.timeZone`; `dayKey`, `dayWord` take it last; `dayISO` is new. Held to
|
|
24
|
+
the TypeScript by `team-chat-plain-data.test.ts` under four zones (one unknown).
|
|
25
|
+
- `Podium`: `label` (the list's name, default "Top three") and `rankLabel` (default `(n) => "Rank " + n`); `Leaderboard`:
|
|
26
|
+
`rankLabel`. Defaults keep the markup as it was.
|
|
27
|
+
|
|
28
|
+
**"Frequently used" in the reaction picker always holds nine** (Chris 20/10/2026: GemCare's row held nine; the package's showed
|
|
29
|
+
only what this browser had used, one or two for a new person, which read as empty).
|
|
30
|
+
|
|
31
|
+
Changed
|
|
32
|
+
- `ReactionPicker` (React) and `gembossUI.teamChat.reactionPicker` (plain): "Frequently used" is what this browser used, most
|
|
33
|
+
recent first, then the `SUGGESTED_REACTIONS` it has not used (👍 ✅ 🙏 🎉 😂 ❤️ 👀 🙌 🔥), nine in all.
|
|
34
|
+
- `reactions-data.ts` exports `SUGGESTED_REACTIONS`, `FREQUENT_MAX` and `frequentReactions(recent)`. The plain script carries
|
|
35
|
+
the list in its data block and the same function in ES5, held to the TypeScript by `team-chat-plain-data.test.ts`.
|
|
36
|
+
|
|
37
|
+
## 0.41.0 (20/10/2026)
|
|
38
|
+
|
|
39
|
+
**A document read over its list** (Chris 20/10/2026, after GemMedia's and partner-radar's Docs drew the same popup with
|
|
40
|
+
their own CSS: "làm đi").
|
|
41
|
+
|
|
42
|
+
Added
|
|
43
|
+
- `ReaderDialog`: the kit popup sized for reading, `min(1440px, 94vw)` × `min(92dvh, 1200px)`, the whole screen under
|
|
44
|
+
768px with the head's actions on their own line. It is `Dialog` with `ui-reader` (same props, less `wide`). The body has
|
|
45
|
+
no padding and is a column the document fills: `ui-reader__frame` (an iframe) or `ui-reader__scroll` (a padded scroller
|
|
46
|
+
of the surface's own). README "ReaderDialog", catalog "Hộp đọc tài liệu".
|
|
47
|
+
- `packages/ui/src/reader-dialog.css` (`@gemboss/ui/reader-dialog.css`): its own entry, imported by the component; every
|
|
48
|
+
selector `dialog.ui-modal.ui-reader…`. Nothing moves into the core or the bundle.
|
|
49
|
+
- `reader-dialog.test.tsx` (markup, every class styled, selectors), `reader-dialog-browser.test.tsx` (Chromium: size,
|
|
50
|
+
fill, scroll, phone head, page lock, Escape; negative control without the entry finds the 460px popup).
|
|
51
|
+
|
|
52
|
+
**A colour field reads every colour, not only a 6-digit hex** (A4, 21/10/2026). Measured on 169 element pages: of 3,283 colour
|
|
53
|
+
values, 66% are `rgb()`, 17% `rgba()`, 9% a 6-digit hex, ~3% `oklch()`. Only the hex 9% had a swatch: nine colours in ten showed a
|
|
54
|
+
locked black square.
|
|
55
|
+
|
|
56
|
+
Changed
|
|
57
|
+
- `swatchState` shows any one colour (`parseColor`: hex of 3, 4, 6 or 8 digits, `rgb`/`rgba`, `hsl`/`hsla`, `oklch`). A token, a
|
|
58
|
+
gradient, a scheme id or a padded value is still not a colour the swatch can stand for: off, with the reason.
|
|
59
|
+
- `ColorControl`: a pick on the swatch keeps the value's transparency and way of writing (`pickSwatch`: a hex stays a hex, else
|
|
60
|
+
`rgb()`, `rgba()` with an alpha), so turning the swatch on can never drop an alpha. A colour's opacity sits beside it in a `%`
|
|
61
|
+
box (`input[data-alpha]`, `withOpacity`); a value that is not one colour has none. No CSS change (the box's width is inline).
|
|
62
|
+
- `swatchWhy`: "Type a color to use your own"; the kept-as-written reason names what the swatch reads.
|
|
63
|
+
- `editor-plain.js`: the same swatch and `%` box on a page without React, for a hex and `rgb()`/`rgba()` (92% of the colours
|
|
64
|
+
measured); `hsl()` and `oklch()` stay a locked swatch there (named in editor-panel.test.tsx). Exposes `gembossUI.colorOf`,
|
|
65
|
+
`pickSwatch`, `withOpacity`.
|
|
66
|
+
|
|
67
|
+
Added
|
|
68
|
+
- `parseColor`, `pickSwatch`, `opacityOf`, `withOpacity`, type `Rgba` (from `@gemboss/ui/editor`).
|
|
69
|
+
|
|
70
|
+
**A colour field offers colours to click before one to type** (A4b, 21/10/2026; Chris: "bấm trước gõ sau").
|
|
71
|
+
|
|
72
|
+
Added
|
|
73
|
+
- `ColorControl` `choices`: chips under the field while it is in use (focus inside it), each a `ColorChoice` `{ value, label,
|
|
74
|
+
swatch }`: the value written on a click, its name, the colour it paints. A token value painted by a chip shows that colour on the
|
|
75
|
+
swatch, and a pick on the swatch then starts from it. None drawn in SSR or when `choices` is empty.
|
|
76
|
+
- `themeColorChoices(palette)`: the theme's colour roles as choices (`var(--gem-color-<role>)`, in `TOKEN_NAMES` order), painted
|
|
77
|
+
with the colour the page draws for each; a role the palette does not paint is left out. Type `ColorChoice`.
|
|
78
|
+
|
|
79
|
+
**The team chat's rows for a plain page, from the package: `gembossUI.teamChat`** (Chris 20/10/2026: the markup in ONE place,
|
|
80
|
+
so GemCare stops writing it by hand and a change to it is made once).
|
|
81
|
+
|
|
82
|
+
Added
|
|
83
|
+
- `packages/ui/src/team-chat-plain.js` (`@gemboss/ui/team-chat-plain.js`, its own entry): builders that RETURN elements with
|
|
84
|
+
the components' markup for the same props: `message` (`Message`, every prop; plus `picking` / `reactionsPicking` /
|
|
85
|
+
`onPickingChange` for a page that redraws its list), `daySeparator`, `newMessagesLine`, `jumpToLatest` + `updateJump`,
|
|
86
|
+
`readReceipt`, `channelSection`, `channelItem`, `peopleSection`, `personRow`, `reactions`, `reactionPicker` (the package's
|
|
87
|
+
picker and its keys, "Frequently used" under the React picker's storage key), `avatar`, `icon`, and `rows` / `dayKey` /
|
|
88
|
+
`dayWord` (`teamChatRows`, `chatDayKey`, `chatDayWord`). Labels are `TEAM_CHAT_LABELS` (`LABELS`), any subset overridable.
|
|
89
|
+
Strings are text; callbacks are click listeners. A classic script, ES5, after `kit-plain.js` when the page has it.
|
|
90
|
+
8,208 B gzip minified (ceiling 8,714 in `weight-budget.json`; a page that draws no team chat never loads it).
|
|
91
|
+
- `team-chat-plain-browser.test.ts` (Chromium, `test:ui-browser`): every builder, in every state, against
|
|
92
|
+
`renderToStaticMarkup` of its component as one tree (attributes, classes, text, SVG in full); the same clicks and keys on
|
|
93
|
+
the mounted components and on the plain rows leave the same DOM (the pickers, search, Escape and focus); callbacks,
|
|
94
|
+
escaping, toolbar and picker keys, `updateJump`, the load-order warning. `team-chat-plain-data.test.ts` (node): the
|
|
95
|
+
generated block (icons, emoji set; `UPDATE_PLAIN_TEAM_CHAT=1` writes it) and the ES5 copies (labels, initials, tone,
|
|
96
|
+
reaction helpers, row rules) held to the TypeScript.
|
|
97
|
+
- `team-chat.test.fixtures.tsx`: the contract test's data, now shared with the plain parity test (the README is unchanged).
|
|
98
|
+
- The catalog's "Chat đội" section has a live plain-HTML frame built with `gembossUI.teamChat`.
|
|
99
|
+
|
|
100
|
+
**A list whose items come from elsewhere** (item management IM2, 21/10/2026: a list that shows a content type).
|
|
101
|
+
|
|
102
|
+
Changed
|
|
103
|
+
- `RepeaterList` `onMove` and `onRemove` are optional. Without `onMove` the rows keep their order: no grip, no ↑ ↓, no
|
|
104
|
+
Alt+arrows, no drop. Without `onRemove`, no ✕. A row still opens (inline or in the popover) and still says it was picked
|
|
105
|
+
(`onActive`). The admin draws a list read from Content this way: its order and its rows are Content's. No CSS change.
|
|
106
|
+
|
|
5
107
|
## 0.40.0 (20/10/2026)
|
|
6
108
|
|
|
7
109
|
**A list's item edits in a popover** (item management IM1a, Chris 20/10/2026; GemPages 7.5's "Item management" read in its code).
|
|
@@ -17,6 +119,14 @@ Added
|
|
|
17
119
|
- `packages/ui/src/editor-repeater.css`: the popover's placement and header, the picked row's outline, the picture (+220 B gzip,
|
|
18
120
|
1,096 of its 1,384 B ceiling). The surface is the fleet's `gemboss-popover-surface`.
|
|
19
121
|
|
|
122
|
+
**An inspector's tabs stand on the fields' edge** (Chris 20/10/2026: "cùng là tabs mà chỗ to chỗ nhỏ").
|
|
123
|
+
|
|
124
|
+
Fixed
|
|
125
|
+
- `packages/ui/src/editor.css`: `.gemboss-ei-tabs` inside a settings body or the column's dock drop their 12px side margin
|
|
126
|
+
(`:is(.gemboss-settings-body,.gemboss-ec-dock-body)`), so the Settings · Advanced track lines up with the fields under it (the
|
|
127
|
+
canvas's element and section panels measured 34–360 and 316px over fields at 22–372). A docked inspector keeps its own, more
|
|
128
|
+
specific rule; a floating inspector keeps 12px. +15 B gzip (8,680 of 8,690).
|
|
129
|
+
|
|
20
130
|
**A phone pays for the topbar once, and the full-screen assistant gets the whole width** (measured on the admin at 390×844,
|
|
21
131
|
19/10/2026).
|
|
22
132
|
|
package/README.md
CHANGED
|
@@ -71,6 +71,7 @@ its CSS out of the build with it (`sideEffects`). gzip of the minified file, as
|
|
|
71
71
|
| assistant-chat | `@gemboss/ui/assistant-chat.css` | `packages/ui/src/assistant-chat.css` | the chat pieces the package draws (0.29.0): column, starters that wrap, meta, errors, notes, paperclip | 0.9 KB | `AssistantChat` and its pieces import it |
|
|
72
72
|
| minichart | `@gemboss/ui/minichart.css` | `packages/ui/src/minichart.css` | `Sparkline`, `ShareBar` (0.30.0) | 0.5 KB | those components import it |
|
|
73
73
|
| setup-guide | `@gemboss/ui/setup-guide.css` | `packages/ui/src/setup-guide.css` | `SetupGuide` (0.30.0) | 0.9 KB | `SetupGuide` imports it |
|
|
74
|
+
| reader-dialog | `@gemboss/ui/reader-dialog.css` | `packages/ui/src/reader-dialog.css` | `ReaderDialog`: the popup sized for reading a document (0.41.0) | 0.4 KB | `ReaderDialog` imports it |
|
|
74
75
|
| service-switcher | `@gemboss/ui/service-switcher.css` | `packages/ui/src/service-switcher.css` | `ServiceSwitcher` and `Switcher`: the button after the brand and its panel (0.36.0; any list, illustrated tiles 0.40.0) | 2.2 KB | `ServiceSwitcher` imports it, and `BrandLockup` through it (README "ServiceSwitcher") |
|
|
75
76
|
| team-chat | `@gemboss/ui/team-chat.css` | `packages/ui/src/team-chat.css` | the team chat layer (20/10/2026): rail, messages, composer, thread and people panels, the screen's layout | 3.6 KB | `TeamChat` and its pieces import it (with `Avatar`'s portal.css and `Reactions`' reactions.css); a plain-HTML page links it (README "The team chat layer") |
|
|
76
77
|
| bundle | `@gemboss/ui/gemboss-ui.css` | `gemboss-ui.css` | core + components + shell + auth + assistant + chat + portal + theme-dark | 21.9 KB | compatibility only (see CHANGELOG 0.23.0) |
|
|
@@ -1177,6 +1178,40 @@ The body scrolls under a head that stays, and scrolling past its end does not sc
|
|
|
1177
1178
|
contain`). `packages/ui/src/sheet-browser.test.tsx` measures it in Chromium; its negative control runs the same probe
|
|
1178
1179
|
without `sheet.css` and finds the centred popup. Catalog section "Ngăn trượt cạnh phải".
|
|
1179
1180
|
|
|
1181
|
+
## ReaderDialog (0.41.0): a document read over its list
|
|
1182
|
+
|
|
1183
|
+
Two surfaces drew the same popup with their own CSS the same week, because `Dialog`'s widths (460, `wide` 620) are a
|
|
1184
|
+
form's: GemMedia's admin Docs (gemmedia #76) and partner-radar's Docs (gemlabs #1122) open a long document over the list
|
|
1185
|
+
of documents, nearly the whole window, the whole screen on a phone. Chris 20/10/2026: put it in the kit. `ReaderDialog`
|
|
1186
|
+
is that popup:
|
|
1187
|
+
|
|
1188
|
+
```tsx
|
|
1189
|
+
import { ReaderDialog } from "@gemboss/ui";
|
|
1190
|
+
|
|
1191
|
+
<ReaderDialog open onClose={close} title={doc.title} subtitle={`v${doc.version} · updated ${doc.updated}`}
|
|
1192
|
+
actions={<><CopyLink slug={doc.slug} /><a className="ui-btn ui-btn--sm" href={doc.src} target="_blank">Open in a new tab</a></>}>
|
|
1193
|
+
<iframe className="ui-reader__frame" src={doc.src} title={doc.title} />
|
|
1194
|
+
</ReaderDialog>
|
|
1195
|
+
```
|
|
1196
|
+
|
|
1197
|
+
The body is the document's. Give it one child that fills it: `iframe.ui-reader__frame` for a self-contained HTML
|
|
1198
|
+
document, or a scroller of your own with `ui-reader__scroll` (padded 24/32/48, 16/16/40 on a phone; it scrolls, keeps
|
|
1199
|
+
its overscroll, and takes `tabIndex={-1}` and focus so the arrow keys and Space read the document). Keys pressed inside
|
|
1200
|
+
an iframe do not reach the `<dialog>`: a surface that wants Escape there forwards it (`frame.contentWindow` keydown →
|
|
1201
|
+
`dialog.close()`, same-origin). A route that draws it (Next's intercepting route) leaves `open` true and goes back in
|
|
1202
|
+
`onClose`, as with `Sheet`.
|
|
1203
|
+
|
|
1204
|
+
| | |
|
|
1205
|
+
| --- | --- |
|
|
1206
|
+
| Markup | `<dialog class="ui-modal ui-reader">` with the popup's own `ui-modal__head` (title, `__subtitle`, `__actions`, ✕), `__body`, `__foot` |
|
|
1207
|
+
| Behaviour | It is `Dialog` with `ui-reader` on it (one render tree, one hook, `useModalDialog`): Escape, ✕ and a press that started on the backdrop close it, `onClose` hears each once, the page behind is inert and holds still (`html:has(dialog.ui-modal:modal)`), focus goes back to the opener. On open focus goes to the first control, as `Dialog`'s; move it to your document |
|
|
1208
|
+
| Size | `min(1440px, 94vw)` × `min(92dvh, 1200px)`, centred, from 768px up; the whole screen below that, where the actions take their own line under the title and ✕ stays beside it |
|
|
1209
|
+
| CSS | `reader-dialog.css`, its own entry, loaded by the component. Every selector is `dialog.ui-modal.ui-reader…` ((0,2,1)). It lays itself out (no padding, border-box, a column the document fills), so it works on a surface that loads `ui.css` alone. A plain-HTML surface links `@gemboss/ui/reader-dialog.css` beside `gemboss-ui.css` and opens the markup with `showModal()` |
|
|
1210
|
+
|
|
1211
|
+
`packages/ui/src/reader-dialog-browser.test.tsx` measures it in Chromium (size at four windows and three phones, the
|
|
1212
|
+
iframe flush under the head, the scroller scrolling under a head that stays, the phone's head, the page lock, Escape);
|
|
1213
|
+
its negative control runs without `reader-dialog.css` and finds the 460px popup. Catalog section "Hộp đọc tài liệu".
|
|
1214
|
+
|
|
1180
1215
|
## SettingsDialog (0.35.0): settings as one popup
|
|
1181
1216
|
|
|
1182
1217
|
The admin's Settings (apps/admin `SettingsDialog`): one popup over the app, the sections in a rail on the left with a
|
|
@@ -1554,7 +1589,8 @@ import { Avatar, Dialog, Leaderboard, Podium, SearchDialog, ThemeToggle, themeSc
|
|
|
1554
1589
|
Opt-in: a surface without it (the admin) stays light.
|
|
1555
1590
|
- `Avatar` (24 · 32 · 40 · 56): picture or initials on one of eight tones picked from the name.
|
|
1556
1591
|
- `Leaderboard`: 🥇 🥈 🥉 then the rank, avatar, name, count; the leader's count in gold; nothing at
|
|
1557
|
-
all when empty. `Podium`: the first three, second · first · third.
|
|
1592
|
+
all when empty. `Podium`: the first three, second · first · third. Screen readers hear "Rank 1: " before each
|
|
1593
|
+
name and "Top three" for the podium; pass `rankLabel={(n) => …}` (both) and `label` (Podium) in the page's language.
|
|
1558
1594
|
- `initialsOf` moved to `initials.ts` (plain, not "use client") so server components can call it; it is
|
|
1559
1595
|
still exported from the package and from account.tsx.
|
|
1560
1596
|
- **Without the whole kit (0.7.2):** a surface with its own skin (GemCommunity) takes only these pieces'
|
|
@@ -1679,7 +1715,10 @@ own state (the reaction picker a message opened, the composer's text when the ap
|
|
|
1679
1715
|
write themselves is in `TEAM_CHAT_LABELS`; pass `labels` (any subset) to translate. `teamChatRows(messages, { meId,
|
|
1680
1716
|
isUnread })` (plain TS, `team-chat-data.ts`) says where the day separators and the "New messages" line go and which
|
|
1681
1717
|
messages are `grouped`: same author, same day, under 5 minutes apart, not a reply, and not the first new one (GemCare's
|
|
1682
|
-
rules). `chatDayWord` gives "Today" / "Yesterday"; older days the app formats in its own locale.
|
|
1718
|
+
rules). `chatDayWord` gives "Today" / "Yesterday"; older days the app formats in its own locale. Days are the viewer's
|
|
1719
|
+
local days unless `timeZone` (an IANA name) is given to `teamChatRows`, `chatDayKey`, `chatDayWord` and `chatDayISO` (the day
|
|
1720
|
+
as "2026-10-21", for a `DaySeparator`'s `dateTime`): give it on a screen the server renders first, or the server's zone and
|
|
1721
|
+
the browser's draw different day separators (React #418). Format the times with the same zone.
|
|
1683
1722
|
|
|
1684
1723
|
**The layout.** `.gb-tc` is a CSS grid and a size container: it decides by its OWN width (in an app shell the chat is the
|
|
1685
1724
|
window minus the shell's rail), with container queries. `TEAM_CHAT_DRAWER_MAX` (1100) and `TEAM_CHAT_PHONE_MAX` (760) are the
|
|
@@ -2101,6 +2140,62 @@ closes a drawer, focus moves into it and back, the rail and the conversation are
|
|
|
2101
2140
|
open state (`gb-tc-msg--active`, `aria-expanded` on its button); arrow keys along `div.gb-tc-acts[role=toolbar]`; when to
|
|
2102
2141
|
show `.gb-tc-jump` and its count.
|
|
2103
2142
|
|
|
2143
|
+
### Plain HTML: `gembossUI.teamChat` (20/10/2026)
|
|
2144
|
+
|
|
2145
|
+
So a plain page does not write the markup above by hand. `team-chat-plain.js` builds the rows from data and RETURNS
|
|
2146
|
+
elements whose markup is the component's for the same props: tags, classes, every attribute, the text, the icons' SVG.
|
|
2147
|
+
`team-chat-plain-browser.test.ts` draws every piece in every state both ways in Chromium (the contract's data,
|
|
2148
|
+
`team-chat.test.fixtures.tsx`, and the states beyond it) and holds them to one tree, so the markup is written once, in
|
|
2149
|
+
`team-chat.tsx`, and a plain page follows a change to it with a version bump. A classic script, no imports, inlinable:
|
|
2150
|
+
after `kit-plain.js` when the page has it (it adds `gembossUI.teamChat`; loaded first it says so in the console).
|
|
2151
|
+
|
|
2152
|
+
| Builder | Draws what this draws |
|
|
2153
|
+
|---|---|
|
|
2154
|
+
| `message(props)` | `Message`, every prop by the same name; plus `picking` / `reactionsPicking` (a picker drawn open) and `onPickingChange(which, open)` (`"bar"` or `"reactions"`) for a page that redraws its whole list |
|
|
2155
|
+
| `daySeparator(label, dateTime)`, `newMessagesLine(labels)` | `DaySeparator`, `NewMessagesLine` |
|
|
2156
|
+
| `jumpToLatest({ count, visible, onJump, labels })`, `updateJump(button, { count, visible, labels })` | `JumpToLatest`; `updateJump` redraws the same button (a scroll handler keeps its focus) |
|
|
2157
|
+
| `readReceipt({ read, of, label })` | `ReadReceipt` (`null` when `of` ≤ 0) |
|
|
2158
|
+
| `channelSection({ label, id, items })`, `channelItem(props)` | `ChannelSection`, `ChannelItem` (`href`: a link, else a button); `items` are rows or their props |
|
|
2159
|
+
| `peopleSection({ label, count, id, items })`, `personRow(props)` | `PeopleSection`, `PersonRow` (a link, a button with `onSelect`, else a `div`) |
|
|
2160
|
+
| `reactions(props)`, `reactionPicker(props)` | `Reactions` (plus `open` / `onOpenChange`), `ReactionPicker` |
|
|
2161
|
+
| `avatar({ name, src, size, className })`, `icon(name, size)` | `Avatar` (portal.tsx's initials and tone), `Icon` (the icons the builders draw, and `more`) |
|
|
2162
|
+
| `rows(messages, opts)`, `dayKey(at, timeZone)`, `dayISO(at, timeZone)`, `dayWord(at, now, timeZone)` | `teamChatRows`, `chatDayKey`, `chatDayISO`, `chatDayWord` |
|
|
2163
|
+
| `LABELS` | `TEAM_CHAT_LABELS`; `labels` (any subset) translates, functions included |
|
|
2164
|
+
|
|
2165
|
+
```html
|
|
2166
|
+
<link rel="stylesheet" href="/ui/portal.css"><link rel="stylesheet" href="/ui/reactions.css"><link rel="stylesheet" href="/ui/team-chat.css">
|
|
2167
|
+
<script src="/ui/kit-plain.js"></script><script src="/ui/team-chat-plain.js"></script>
|
|
2168
|
+
```
|
|
2169
|
+
|
|
2170
|
+
```js
|
|
2171
|
+
const tc = gembossUI.teamChat;
|
|
2172
|
+
list.replaceChildren(...tc.rows(messages, { meId: me.id, isUnread: (m) => m.id > readUpTo }).map((r) =>
|
|
2173
|
+
r.kind === "day" ? tc.daySeparator(dayLabel(r.date), isoDay(r.date))
|
|
2174
|
+
: r.kind === "new" ? tc.newMessagesLine()
|
|
2175
|
+
: tc.message({ author: r.message.authorName, time: hhmm(r.message.at), dateTime: r.message.at, body: r.message.text,
|
|
2176
|
+
grouped: r.grouped, messageId: r.message.id, reactions: r.message.reactions, edited: Boolean(r.message.editedAt),
|
|
2177
|
+
receipt: tc.readReceipt({ read: 2, of: 3, label: "Read by Linh, Quan. Not yet: Bo" }),
|
|
2178
|
+
onReact: (emoji) => react(r.message.id, emoji), onReply: () => startReply(r.message), onOpenThread: (e) => openThread(r.message.id, e.currentTarget),
|
|
2179
|
+
moreActions: myMoreButton(r.message), picking: view.picking === r.message.id,
|
|
2180
|
+
onPickingChange: (which, open) => { if (which === "bar") view.picking = open ? r.message.id : null; } })));
|
|
2181
|
+
```
|
|
2182
|
+
|
|
2183
|
+
Strings are TEXT (a body `"<img onerror=…>"` shows those characters); a slot that takes a node (`avatar`, `badges`,
|
|
2184
|
+
`attachments`, `extra`, `receipt`, `moreActions`, `editor`, a rich `time` or `body`) takes a DOM node as given. Callbacks are
|
|
2185
|
+
click listeners and get what React's `onClick` gets (the event; `onReact` the emoji). The behaviour is the components': the
|
|
2186
|
+
action bar is a toolbar (arrows, Home / End), "More reactions" opens the package's picker under the body and the reaction
|
|
2187
|
+
row's "Add reaction" one under the row (search, this browser's "Frequently used" under the React picker's own storage key,
|
|
2188
|
+
arrows, Enter picks the first match, Escape closes and gives focus back), a chip's click remembers its emoji. A row drawn
|
|
2189
|
+
with `picking` takes no focus: after a redraw the page puts focus back, as it does for anything it redraws.
|
|
2190
|
+
|
|
2191
|
+
Not built here: the screen's shell (`TeamChat`, `ChannelRail`, `ChatHeader`, `MessageList`, `Composer`, `ThreadPanel`,
|
|
2192
|
+
`PeoplePanel`) is markup a page writes once (the blocks above), with the behaviour listed just above.
|
|
2193
|
+
|
|
2194
|
+
The script carries two kinds of copy, both held by `team-chat-plain-data.test.ts`: the icons' drawing (icons.tsx) and the
|
|
2195
|
+
emoji set (reactions-data.ts) as a generated block (`UPDATE_PLAIN_TEAM_CHAT=1` on that test writes it), and the labels, the
|
|
2196
|
+
avatar's initials and tone, the reaction helpers and `teamChatRows` in ES5, called with the TypeScript's inputs and held to
|
|
2197
|
+
its answers.
|
|
2198
|
+
|
|
2104
2199
|
## Action card (0.28.0): an assistant proposes, a person applies
|
|
2105
2200
|
|
|
2106
2201
|
Chris 08/10/2026: the Feedback Assistant lists likely duplicates and merges them, and carries out status, owner, label
|
|
@@ -2405,6 +2500,7 @@ something the base cannot express, add a token or a prop here, and every surface
|
|
|
2405
2500
|
| `packages/ui/src/editor-plain.js` | 0.14.0: `gembossUI.initEditorFrame()`, the frame's behaviour for plain HTML; 0.17.0: `gembossUI.initEditorPanel()`, the settings panel's. Load after `kit-plain.js`. |
|
|
2406
2501
|
| `packages/ui/src/editor-layers-plain.js` | 0.22.0: `gembossUI.initEditorLayers()`, the layers', the outline's and the drawers' behaviour for plain HTML. Load after `kit-plain.js`. |
|
|
2407
2502
|
| `packages/ui/src/service-switcher-plain.js` | 0.36.0: `gembossUI.initServiceSwitcher()`, the ServiceSwitcher drawn and driven for plain HTML (`@gemboss/ui/service-switcher-plain.js`). After `kit-plain.js` when the page has it; works alone. See "ServiceSwitcher". |
|
|
2503
|
+
| `packages/ui/src/team-chat-plain.js` | 20/10/2026: `gembossUI.teamChat`, builders that return the team chat's rows (messages, day separators, "New messages", jump, receipt, rail rows, people rows, reactions and the picker) with the components' markup, for plain HTML (`@gemboss/ui/team-chat-plain.js`). After `kit-plain.js` when the page has it; works alone. See "The team chat layer". |
|
|
2408
2504
|
| `catalog/editor.html` | 0.14.0: the frame rendered from the components and running (`packages/ui/scripts/build-catalog-editor.mjs`), linked from `catalog/index.html`. |
|
|
2409
2505
|
| `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. |
|
|
2410
2506
|
| `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. |
|
package/catalog/editor.html
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
.cat-code summary{padding:10px 16px;font-size:13px;cursor:pointer;color:var(--gemboss-text-muted);border-top:1px solid var(--gemboss-divider);min-height:24px}
|
|
9
9
|
.cat-code pre,.cat-api{margin:0;padding:12px 16px;overflow:auto;background:#0f1012;color:#e8e8e6;font-size:12px;line-height:1.5;border-radius:0}
|
|
10
10
|
.cat-api{border-radius:12px;margin:0 0 16px}</style></head><body><div class="cat">
|
|
11
|
-
<h1>@gemboss/ui 0.
|
|
11
|
+
<h1>@gemboss/ui 0.42.0 · Editor</h1>
|
|
12
12
|
<p>Khung của mọi editor: <code>EditorFrame</code> (cột trái · khe kéo · preview · cột phải dock trên mép phải preview) và <code>EditorTopbar</code> (← · tiêu đề · cụm giữa · cụm phải · dòng trạng thái). Là đúng khung của theme / page / section editor trong admin. Gói chỉ vẽ KHUNG; chat, Configure, canvas, page picker, menu, Publish là của editor, đi vào bằng slot. Trang HTML thuần nạp <code>editor.css</code> + <code>editor-plain.js</code> rồi gọi <code>gembossUI.initEditorFrame()</code>: kéo khe (chuột, chạm, phím mũi tên / Home / End), đổi thiết bị, mở ⋯ và Publish ▾, ẩn cột trái, Chat | Preview trên điện thoại. <a href="index.html">← Catalog</a></p>
|
|
13
13
|
<h2>React</h2><pre class="cat-api"><code>import "@gemboss/ui/editor.css";
|
|
14
14
|
import { EditorFrame, EditorTopbar, EditorBack, EditorChatToggle, EditorPaneTabs, EditorSaveState, DeviceToggle } from "@gemboss/ui/editor";
|
|
@@ -319,7 +319,7 @@ import { EditorFrame, EditorTopbar, EditorBack, EditorChatToggle, EditorPaneTabs
|
|
|
319
319
|
<Field label="Padding"><EdgeBox label="Padding" values={pad} onChange={(side, raw) => …} onCommit={save} /></Field>
|
|
320
320
|
<Field label="Image" htmlFor="img"><ImageControl id="img" value={url} onChange={setUrl} /></Field>
|
|
321
321
|
</InspectorGroup></code></pre>
|
|
322
|
-
<figure class="cat-demo"><figcaption>1280 (chuột): cột Configure 360px, đủ control, nhóm Motion đang gập</figcaption><div class="cat-wide"><iframe title="1280 (chuột): cột Configure 360px, đủ control, nhóm Motion đang gập" style="width:1280px;height:1120px" srcdoc="<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="../gemboss-ui.css"><link rel="stylesheet" href="../src/editor.css"></head><body><div class="gemboss-ec" style="width:360px;height:1040px"><div class="gemboss-ec-tabs" role="tablist" aria-label="Editor panels"><button type="button" role="tab" data-value="configure" class="gemboss-ec-tab" aria-selected="true">Settings</button><button type="button" role="tab" data-value="chat" class="gemboss-ec-tab" aria-selected="false">Chat</button></div><div class="gemboss-ec-dock-body" style="padding:0"><aside class="gemboss-ei gemboss-ei--docked" role="region" aria-label="Settings — Hero"><header class="gemboss-ei-head"><span class="gemboss-ei-title">Hero<small>hero-banner.default.v1</small></span><button type="button" class="gemboss-ei-act" title="Duplicate section" aria-label="Duplicate section">⧉</button><button type="button" class="gemboss-ei-act" title="Restore this section to its previous version" aria-label="Restore this section">↺</button></header><div class="gemboss-ei-tabs" role="tablist"><button type="button" role="tab" data-value="content" class="gemboss-ei-tab" aria-selected="false" tabindex="-1">Content</button><button type="button" role="tab" data-value="design" class="gemboss-ei-tab on" aria-selected="true" tabindex="0">Design</button><button type="button" role="tab" data-value="advanced" class="gemboss-ei-tab" aria-selected="false" tabindex="-1">Advanced</button></div><div class="gemboss-ei-body"><div class="gemboss-ei-pane"><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Layout<small class="gemboss-ei-gh-note">· all screens</small></button><div class="gemboss-ei-fld"><label>Content width</label><div class="ui-seg ui-seg--fill gemboss-ei-seg" role="group" aria-label="Content width"><button type="button" data-value="full" aria-pressed="false" class="is-text">Full</button><button type="button" data-value="contained" aria-pressed="true" class="is-text active">Contained</button><button type="button" data-value="narrow" aria-pressed="false" class="is-text">Narrow</button></div></div><div class="gemboss-ei-fld"><div class="gemboss-ei-lbl"><label>Columns</label><button type="button" class="gemboss-ei-help" aria-label="About Columns" aria-describedby=":R18u:" aria-expanded="false">?</button></div><div class="ui-seg ui-seg--fill gemboss-ei-seg" role="group" aria-label="Columns"><button type="button" data-value="2" disabled="" aria-pressed="false" class="is-text">2</button><button type="button" data-value="3" disabled="" aria-pressed="true" class="is-text active">3</button><button type="button" data-value="4" disabled="" aria-pressed="false" class="is-text">4</button></div><p class="gemboss-ei-hint gemboss-ei-help-text" id=":R18u:">Disabled while a change is applied.</p></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Spacing</button><div class="gemboss-ei-fld"><label>Padding</label><div class="gemboss-ei-edgebox"><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding top" value="24"/><span>T</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding right" value=""/><span>R</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding bottom" value="24"/><span>B</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding left" value=""/><span>L</span></div></div></div><div class="gemboss-ei-fld"><div class="gemboss-ei-lbl"><label>Margin</label><button type="button" class="gemboss-ei-help" aria-label="About Margin" aria-describedby=":R19e:" aria-expanded="false">?</button></div><div class="gemboss-ei-edgebox"><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="16" aria-label="Margin top" value=""/><span>T</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Margin right" value=""/><span>R</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="16" aria-label="Margin bottom" value=""/><span>B</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Margin left" value=""/><span>L</span></div></div><p class="gemboss-ei-hint gemboss-ei-help-text" id=":R19e:">Empty edges follow desktop.</p></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Color</button><div class="gemboss-ei-fld"><label for="cat-bg">Background</label><div class="gemboss-ei-color"><input type="color" class="gemboss-ei-swatch" aria-label="Background swatch" value="#f4efe6"/><input id="cat-bg" class="gemboss-field gemboss-ei-inp" placeholder="Not set" value="#f4efe6"/></div></div><div class="gemboss-ei-fld"><div class="gemboss-ei-lbl"><label for="cat-ov">Overlay</label><button type="button" class="gemboss-ei-help" aria-label="About Overlay" aria-describedby=":R19u:" aria-expanded="false">?</button></div><div class="gemboss-ei-color"><input type="color" class="gemboss-ei-swatch" aria-label="Overlay swatch" disabled="" title="Kept as written: the swatch picks 6-digit hex colors only." aria-describedby=":Rb9u:" value="#000000"/><input id="cat-ov" class="gemboss-field gemboss-ei-inp" placeholder="Not set" value="linear-gradient(90deg,#000,#0000)"/><p id=":Rb9u:" class="gemboss-ei-color-why">Kept as written: the swatch picks 6-digit hex colors only.</p></div><p class="gemboss-ei-hint gemboss-ei-help-text" id=":R19u:">A gradient: the swatch cannot show it, so it is off.</p></div><div class="gemboss-ei-fld"><label for="cat-op">Opacity<span class="gemboss-ei-rangeval" data-suffix="%">80%</span></label><input id="cat-op" type="range" class="gemboss-ei-range" min="0" max="100" step="1" value="80"/></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Media</button><div class="gemboss-ei-fld"><label for="cat-img">Image</label><div class="gemboss-ei-img"><div class="gemboss-ei-img-thumb" aria-hidden="true">—</div><div class="gemboss-ei-img-ctl"><input id="cat-img" class="gemboss-field gemboss-ei-inp" placeholder="Paste image URL…" value=""/><div class="gemboss-ei-img-actions"><button type="button" class="ui-btn" aria-expanded="false">Library</button><button type="button" class="ui-btn" data-gb-image-clear>Clear</button></div></div></div></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="closed" aria-expanded="false"><span class="gemboss-ei-chev" aria-hidden="true">▸</span>Motion</button><div class="gemboss-ei-fld"><label>Reveal</label><div class="ui-seg ui-seg--fill gemboss-ei-seg" role="group" aria-label="Reveal"><button type="button" data-value="none" aria-pressed="true" class="is-text active">None</button><button type="button" data-value="fade" aria-pressed="false" class="is-text">Fade</button></div></div></div></div></div></aside></div></div><script src="../src/kit-plain.js"></script><script src="../src/editor-plain.js"></script><script>gembossUI.initEditorFrame()</script><script>gembossUI.initEditorPanel()</script><script src="../src/editor-layers-plain.js"></script><script>gembossUI.initEditorLayers()</script></body></html>"></iframe></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="gemboss-ec" style="width:360px;height:1040px">
|
|
322
|
+
<figure class="cat-demo"><figcaption>1280 (chuột): cột Configure 360px, đủ control, nhóm Motion đang gập</figcaption><div class="cat-wide"><iframe title="1280 (chuột): cột Configure 360px, đủ control, nhóm Motion đang gập" style="width:1280px;height:1120px" srcdoc="<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="../gemboss-ui.css"><link rel="stylesheet" href="../src/editor.css"></head><body><div class="gemboss-ec" style="width:360px;height:1040px"><div class="gemboss-ec-tabs" role="tablist" aria-label="Editor panels"><button type="button" role="tab" data-value="configure" class="gemboss-ec-tab" aria-selected="true">Settings</button><button type="button" role="tab" data-value="chat" class="gemboss-ec-tab" aria-selected="false">Chat</button></div><div class="gemboss-ec-dock-body" style="padding:0"><aside class="gemboss-ei gemboss-ei--docked" role="region" aria-label="Settings — Hero"><header class="gemboss-ei-head"><span class="gemboss-ei-title">Hero<small>hero-banner.default.v1</small></span><button type="button" class="gemboss-ei-act" title="Duplicate section" aria-label="Duplicate section">⧉</button><button type="button" class="gemboss-ei-act" title="Restore this section to its previous version" aria-label="Restore this section">↺</button></header><div class="gemboss-ei-tabs" role="tablist"><button type="button" role="tab" data-value="content" class="gemboss-ei-tab" aria-selected="false" tabindex="-1">Content</button><button type="button" role="tab" data-value="design" class="gemboss-ei-tab on" aria-selected="true" tabindex="0">Design</button><button type="button" role="tab" data-value="advanced" class="gemboss-ei-tab" aria-selected="false" tabindex="-1">Advanced</button></div><div class="gemboss-ei-body"><div class="gemboss-ei-pane"><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Layout<small class="gemboss-ei-gh-note">· all screens</small></button><div class="gemboss-ei-fld"><label>Content width</label><div class="ui-seg ui-seg--fill gemboss-ei-seg" role="group" aria-label="Content width"><button type="button" data-value="full" aria-pressed="false" class="is-text">Full</button><button type="button" data-value="contained" aria-pressed="true" class="is-text active">Contained</button><button type="button" data-value="narrow" aria-pressed="false" class="is-text">Narrow</button></div></div><div class="gemboss-ei-fld"><div class="gemboss-ei-lbl"><label>Columns</label><button type="button" class="gemboss-ei-help" aria-label="About Columns" aria-describedby=":R18u:" aria-expanded="false">?</button></div><div class="ui-seg ui-seg--fill gemboss-ei-seg" role="group" aria-label="Columns"><button type="button" data-value="2" disabled="" aria-pressed="false" class="is-text">2</button><button type="button" data-value="3" disabled="" aria-pressed="true" class="is-text active">3</button><button type="button" data-value="4" disabled="" aria-pressed="false" class="is-text">4</button></div><p class="gemboss-ei-hint gemboss-ei-help-text" id=":R18u:">Disabled while a change is applied.</p></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Spacing</button><div class="gemboss-ei-fld"><label>Padding</label><div class="gemboss-ei-edgebox"><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding top" value="24"/><span>T</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding right" value=""/><span>R</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding bottom" value="24"/><span>B</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding left" value=""/><span>L</span></div></div></div><div class="gemboss-ei-fld"><div class="gemboss-ei-lbl"><label>Margin</label><button type="button" class="gemboss-ei-help" aria-label="About Margin" aria-describedby=":R19e:" aria-expanded="false">?</button></div><div class="gemboss-ei-edgebox"><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="16" aria-label="Margin top" value=""/><span>T</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Margin right" value=""/><span>R</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="16" aria-label="Margin bottom" value=""/><span>B</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Margin left" value=""/><span>L</span></div></div><p class="gemboss-ei-hint gemboss-ei-help-text" id=":R19e:">Empty edges follow desktop.</p></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Color</button><div class="gemboss-ei-fld"><label for="cat-bg">Background</label><div class="gemboss-ei-color"><input type="color" class="gemboss-ei-swatch" aria-label="Background swatch" value="#f4efe6"/><input id="cat-bg" class="gemboss-field gemboss-ei-inp" placeholder="Not set" value="#f4efe6"/><input class="gemboss-field gemboss-ei-inp" data-alpha="" aria-label="Background opacity" inputMode="numeric" style="flex:0 0 64px" value="100%"/></div></div><div class="gemboss-ei-fld"><div class="gemboss-ei-lbl"><label for="cat-ov">Overlay</label><button type="button" class="gemboss-ei-help" aria-label="About Overlay" aria-describedby=":R19u:" aria-expanded="false">?</button></div><div class="gemboss-ei-color"><input type="color" class="gemboss-ei-swatch" aria-label="Overlay swatch" disabled="" title="Kept as written: the swatch shows one color (hex, rgb, hsl or oklch), not a gradient or a name." aria-describedby=":Rb9u:" value="#000000"/><input id="cat-ov" class="gemboss-field gemboss-ei-inp" placeholder="Not set" value="linear-gradient(90deg,#000,#0000)"/><p id=":Rb9u:" class="gemboss-ei-color-why">Kept as written: the swatch shows one color (hex, rgb, hsl or oklch), not a gradient or a name.</p></div><p class="gemboss-ei-hint gemboss-ei-help-text" id=":R19u:">A gradient: the swatch cannot show it, so it is off.</p></div><div class="gemboss-ei-fld"><label for="cat-op">Opacity<span class="gemboss-ei-rangeval" data-suffix="%">80%</span></label><input id="cat-op" type="range" class="gemboss-ei-range" min="0" max="100" step="1" value="80"/></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Media</button><div class="gemboss-ei-fld"><label for="cat-img">Image</label><div class="gemboss-ei-img"><div class="gemboss-ei-img-thumb" aria-hidden="true">—</div><div class="gemboss-ei-img-ctl"><input id="cat-img" class="gemboss-field gemboss-ei-inp" placeholder="Paste image URL…" value=""/><div class="gemboss-ei-img-actions"><button type="button" class="ui-btn" aria-expanded="false">Library</button><button type="button" class="ui-btn" data-gb-image-clear>Clear</button></div></div></div></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="closed" aria-expanded="false"><span class="gemboss-ei-chev" aria-hidden="true">▸</span>Motion</button><div class="gemboss-ei-fld"><label>Reveal</label><div class="ui-seg ui-seg--fill gemboss-ei-seg" role="group" aria-label="Reveal"><button type="button" data-value="none" aria-pressed="true" class="is-text active">None</button><button type="button" data-value="fade" aria-pressed="false" class="is-text">Fade</button></div></div></div></div></div></aside></div></div><script src="../src/kit-plain.js"></script><script src="../src/editor-plain.js"></script><script>gembossUI.initEditorFrame()</script><script>gembossUI.initEditorPanel()</script><script src="../src/editor-layers-plain.js"></script><script>gembossUI.initEditorLayers()</script></body></html>"></iframe></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="gemboss-ec" style="width:360px;height:1040px">
|
|
323
323
|
<div class="gemboss-ec-tabs" role="tablist" aria-label="Editor panels">
|
|
324
324
|
<button type="button" role="tab" data-value="configure" class="gemboss-ec-tab" aria-selected="true">Settings</button>
|
|
325
325
|
<button type="button" role="tab" data-value="chat" class="gemboss-ec-tab" aria-selected="false">Chat</button>
|
|
@@ -422,6 +422,7 @@ import { EditorFrame, EditorTopbar, EditorBack, EditorChatToggle, EditorPaneTabs
|
|
|
422
422
|
<div class="gemboss-ei-color">
|
|
423
423
|
<input type="color" class="gemboss-ei-swatch" aria-label="Background swatch" value="#f4efe6"/>
|
|
424
424
|
<input id="cat-bg" class="gemboss-field gemboss-ei-inp" placeholder="Not set" value="#f4efe6"/>
|
|
425
|
+
<input class="gemboss-field gemboss-ei-inp" data-alpha="" aria-label="Background opacity" inputMode="numeric" style="flex:0 0 64px" value="100%"/>
|
|
425
426
|
</div>
|
|
426
427
|
</div>
|
|
427
428
|
<div class="gemboss-ei-fld">
|
|
@@ -430,9 +431,9 @@ import { EditorFrame, EditorTopbar, EditorBack, EditorChatToggle, EditorPaneTabs
|
|
|
430
431
|
<button type="button" class="gemboss-ei-help" aria-label="About Overlay" aria-describedby=":R19u:" aria-expanded="false">?</button>
|
|
431
432
|
</div>
|
|
432
433
|
<div class="gemboss-ei-color">
|
|
433
|
-
<input type="color" class="gemboss-ei-swatch" aria-label="Overlay swatch" disabled="" title="Kept as written: the swatch
|
|
434
|
+
<input type="color" class="gemboss-ei-swatch" aria-label="Overlay swatch" disabled="" title="Kept as written: the swatch shows one color (hex, rgb, hsl or oklch), not a gradient or a name." aria-describedby=":Rb9u:" value="#000000"/>
|
|
434
435
|
<input id="cat-ov" class="gemboss-field gemboss-ei-inp" placeholder="Not set" value="linear-gradient(90deg,#000,#0000)"/>
|
|
435
|
-
<p id=":Rb9u:" class="gemboss-ei-color-why">Kept as written: the swatch
|
|
436
|
+
<p id=":Rb9u:" class="gemboss-ei-color-why">Kept as written: the swatch shows one color (hex, rgb, hsl or oklch), not a gradient or a name.</p>
|
|
436
437
|
</div>
|
|
437
438
|
<p class="gemboss-ei-hint gemboss-ei-help-text" id=":R19u:">A gradient: the swatch cannot show it, so it is off.</p>
|
|
438
439
|
</div>
|
|
@@ -475,7 +476,7 @@ import { EditorFrame, EditorTopbar, EditorBack, EditorChatToggle, EditorPaneTabs
|
|
|
475
476
|
</aside>
|
|
476
477
|
</div>
|
|
477
478
|
</div></code></pre></details></figure>
|
|
478
|
-
<figure class="cat-demo"><figcaption>390 (điện thoại): ô nhập 16px, control 44px</figcaption><div class="cat-wide"><iframe title="390 (điện thoại): ô nhập 16px, control 44px" style="width:390px;height:1240px" srcdoc="<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="../gemboss-ui.css"><link rel="stylesheet" href="../src/editor.css"></head><body><div class="gemboss-ec" style="width:360px;height:1040px"><div class="gemboss-ec-tabs" role="tablist" aria-label="Editor panels"><button type="button" role="tab" data-value="configure" class="gemboss-ec-tab" aria-selected="true">Settings</button><button type="button" role="tab" data-value="chat" class="gemboss-ec-tab" aria-selected="false">Chat</button></div><div class="gemboss-ec-dock-body" style="padding:0"><aside class="gemboss-ei gemboss-ei--docked" role="region" aria-label="Settings — Hero"><header class="gemboss-ei-head"><span class="gemboss-ei-title">Hero<small>hero-banner.default.v1</small></span><button type="button" class="gemboss-ei-act" title="Duplicate section" aria-label="Duplicate section">⧉</button><button type="button" class="gemboss-ei-act" title="Restore this section to its previous version" aria-label="Restore this section">↺</button></header><div class="gemboss-ei-tabs" role="tablist"><button type="button" role="tab" data-value="content" class="gemboss-ei-tab" aria-selected="false" tabindex="-1">Content</button><button type="button" role="tab" data-value="design" class="gemboss-ei-tab on" aria-selected="true" tabindex="0">Design</button><button type="button" role="tab" data-value="advanced" class="gemboss-ei-tab" aria-selected="false" tabindex="-1">Advanced</button></div><div class="gemboss-ei-body"><div class="gemboss-ei-pane"><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Layout<small class="gemboss-ei-gh-note">· all screens</small></button><div class="gemboss-ei-fld"><label>Content width</label><div class="ui-seg ui-seg--fill gemboss-ei-seg" role="group" aria-label="Content width"><button type="button" data-value="full" aria-pressed="false" class="is-text">Full</button><button type="button" data-value="contained" aria-pressed="true" class="is-text active">Contained</button><button type="button" data-value="narrow" aria-pressed="false" class="is-text">Narrow</button></div></div><div class="gemboss-ei-fld"><div class="gemboss-ei-lbl"><label>Columns</label><button type="button" class="gemboss-ei-help" aria-label="About Columns" aria-describedby=":R18u:" aria-expanded="false">?</button></div><div class="ui-seg ui-seg--fill gemboss-ei-seg" role="group" aria-label="Columns"><button type="button" data-value="2" disabled="" aria-pressed="false" class="is-text">2</button><button type="button" data-value="3" disabled="" aria-pressed="true" class="is-text active">3</button><button type="button" data-value="4" disabled="" aria-pressed="false" class="is-text">4</button></div><p class="gemboss-ei-hint gemboss-ei-help-text" id=":R18u:">Disabled while a change is applied.</p></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Spacing</button><div class="gemboss-ei-fld"><label>Padding</label><div class="gemboss-ei-edgebox"><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding top" value="24"/><span>T</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding right" value=""/><span>R</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding bottom" value="24"/><span>B</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding left" value=""/><span>L</span></div></div></div><div class="gemboss-ei-fld"><div class="gemboss-ei-lbl"><label>Margin</label><button type="button" class="gemboss-ei-help" aria-label="About Margin" aria-describedby=":R19e:" aria-expanded="false">?</button></div><div class="gemboss-ei-edgebox"><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="16" aria-label="Margin top" value=""/><span>T</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Margin right" value=""/><span>R</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="16" aria-label="Margin bottom" value=""/><span>B</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Margin left" value=""/><span>L</span></div></div><p class="gemboss-ei-hint gemboss-ei-help-text" id=":R19e:">Empty edges follow desktop.</p></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Color</button><div class="gemboss-ei-fld"><label for="cat-bg">Background</label><div class="gemboss-ei-color"><input type="color" class="gemboss-ei-swatch" aria-label="Background swatch" value="#f4efe6"/><input id="cat-bg" class="gemboss-field gemboss-ei-inp" placeholder="Not set" value="#f4efe6"/></div></div><div class="gemboss-ei-fld"><div class="gemboss-ei-lbl"><label for="cat-ov">Overlay</label><button type="button" class="gemboss-ei-help" aria-label="About Overlay" aria-describedby=":R19u:" aria-expanded="false">?</button></div><div class="gemboss-ei-color"><input type="color" class="gemboss-ei-swatch" aria-label="Overlay swatch" disabled="" title="Kept as written: the swatch picks 6-digit hex colors only." aria-describedby=":Rb9u:" value="#000000"/><input id="cat-ov" class="gemboss-field gemboss-ei-inp" placeholder="Not set" value="linear-gradient(90deg,#000,#0000)"/><p id=":Rb9u:" class="gemboss-ei-color-why">Kept as written: the swatch picks 6-digit hex colors only.</p></div><p class="gemboss-ei-hint gemboss-ei-help-text" id=":R19u:">A gradient: the swatch cannot show it, so it is off.</p></div><div class="gemboss-ei-fld"><label for="cat-op">Opacity<span class="gemboss-ei-rangeval" data-suffix="%">80%</span></label><input id="cat-op" type="range" class="gemboss-ei-range" min="0" max="100" step="1" value="80"/></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Media</button><div class="gemboss-ei-fld"><label for="cat-img">Image</label><div class="gemboss-ei-img"><div class="gemboss-ei-img-thumb" aria-hidden="true">—</div><div class="gemboss-ei-img-ctl"><input id="cat-img" class="gemboss-field gemboss-ei-inp" placeholder="Paste image URL…" value=""/><div class="gemboss-ei-img-actions"><button type="button" class="ui-btn" aria-expanded="false">Library</button><button type="button" class="ui-btn" data-gb-image-clear>Clear</button></div></div></div></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="closed" aria-expanded="false"><span class="gemboss-ei-chev" aria-hidden="true">▸</span>Motion</button><div class="gemboss-ei-fld"><label>Reveal</label><div class="ui-seg ui-seg--fill gemboss-ei-seg" role="group" aria-label="Reveal"><button type="button" data-value="none" aria-pressed="true" class="is-text active">None</button><button type="button" data-value="fade" aria-pressed="false" class="is-text">Fade</button></div></div></div></div></div></aside></div></div><script src="../src/kit-plain.js"></script><script src="../src/editor-plain.js"></script><script>gembossUI.initEditorFrame()</script><script>gembossUI.initEditorPanel()</script><script src="../src/editor-layers-plain.js"></script><script>gembossUI.initEditorLayers()</script></body></html>"></iframe></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="gemboss-ec" style="width:360px;height:1040px">
|
|
479
|
+
<figure class="cat-demo"><figcaption>390 (điện thoại): ô nhập 16px, control 44px</figcaption><div class="cat-wide"><iframe title="390 (điện thoại): ô nhập 16px, control 44px" style="width:390px;height:1240px" srcdoc="<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="../gemboss-ui.css"><link rel="stylesheet" href="../src/editor.css"></head><body><div class="gemboss-ec" style="width:360px;height:1040px"><div class="gemboss-ec-tabs" role="tablist" aria-label="Editor panels"><button type="button" role="tab" data-value="configure" class="gemboss-ec-tab" aria-selected="true">Settings</button><button type="button" role="tab" data-value="chat" class="gemboss-ec-tab" aria-selected="false">Chat</button></div><div class="gemboss-ec-dock-body" style="padding:0"><aside class="gemboss-ei gemboss-ei--docked" role="region" aria-label="Settings — Hero"><header class="gemboss-ei-head"><span class="gemboss-ei-title">Hero<small>hero-banner.default.v1</small></span><button type="button" class="gemboss-ei-act" title="Duplicate section" aria-label="Duplicate section">⧉</button><button type="button" class="gemboss-ei-act" title="Restore this section to its previous version" aria-label="Restore this section">↺</button></header><div class="gemboss-ei-tabs" role="tablist"><button type="button" role="tab" data-value="content" class="gemboss-ei-tab" aria-selected="false" tabindex="-1">Content</button><button type="button" role="tab" data-value="design" class="gemboss-ei-tab on" aria-selected="true" tabindex="0">Design</button><button type="button" role="tab" data-value="advanced" class="gemboss-ei-tab" aria-selected="false" tabindex="-1">Advanced</button></div><div class="gemboss-ei-body"><div class="gemboss-ei-pane"><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Layout<small class="gemboss-ei-gh-note">· all screens</small></button><div class="gemboss-ei-fld"><label>Content width</label><div class="ui-seg ui-seg--fill gemboss-ei-seg" role="group" aria-label="Content width"><button type="button" data-value="full" aria-pressed="false" class="is-text">Full</button><button type="button" data-value="contained" aria-pressed="true" class="is-text active">Contained</button><button type="button" data-value="narrow" aria-pressed="false" class="is-text">Narrow</button></div></div><div class="gemboss-ei-fld"><div class="gemboss-ei-lbl"><label>Columns</label><button type="button" class="gemboss-ei-help" aria-label="About Columns" aria-describedby=":R18u:" aria-expanded="false">?</button></div><div class="ui-seg ui-seg--fill gemboss-ei-seg" role="group" aria-label="Columns"><button type="button" data-value="2" disabled="" aria-pressed="false" class="is-text">2</button><button type="button" data-value="3" disabled="" aria-pressed="true" class="is-text active">3</button><button type="button" data-value="4" disabled="" aria-pressed="false" class="is-text">4</button></div><p class="gemboss-ei-hint gemboss-ei-help-text" id=":R18u:">Disabled while a change is applied.</p></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Spacing</button><div class="gemboss-ei-fld"><label>Padding</label><div class="gemboss-ei-edgebox"><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding top" value="24"/><span>T</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding right" value=""/><span>R</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding bottom" value="24"/><span>B</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Padding left" value=""/><span>L</span></div></div></div><div class="gemboss-ei-fld"><div class="gemboss-ei-lbl"><label>Margin</label><button type="button" class="gemboss-ei-help" aria-label="About Margin" aria-describedby=":R19e:" aria-expanded="false">?</button></div><div class="gemboss-ei-edgebox"><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="16" aria-label="Margin top" value=""/><span>T</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Margin right" value=""/><span>R</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="16" aria-label="Margin bottom" value=""/><span>B</span></div><div class="gemboss-ei-edge"><input class="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode="numeric" placeholder="0" aria-label="Margin left" value=""/><span>L</span></div></div><p class="gemboss-ei-hint gemboss-ei-help-text" id=":R19e:">Empty edges follow desktop.</p></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Color</button><div class="gemboss-ei-fld"><label for="cat-bg">Background</label><div class="gemboss-ei-color"><input type="color" class="gemboss-ei-swatch" aria-label="Background swatch" value="#f4efe6"/><input id="cat-bg" class="gemboss-field gemboss-ei-inp" placeholder="Not set" value="#f4efe6"/><input class="gemboss-field gemboss-ei-inp" data-alpha="" aria-label="Background opacity" inputMode="numeric" style="flex:0 0 64px" value="100%"/></div></div><div class="gemboss-ei-fld"><div class="gemboss-ei-lbl"><label for="cat-ov">Overlay</label><button type="button" class="gemboss-ei-help" aria-label="About Overlay" aria-describedby=":R19u:" aria-expanded="false">?</button></div><div class="gemboss-ei-color"><input type="color" class="gemboss-ei-swatch" aria-label="Overlay swatch" disabled="" title="Kept as written: the swatch shows one color (hex, rgb, hsl or oklch), not a gradient or a name." aria-describedby=":Rb9u:" value="#000000"/><input id="cat-ov" class="gemboss-field gemboss-ei-inp" placeholder="Not set" value="linear-gradient(90deg,#000,#0000)"/><p id=":Rb9u:" class="gemboss-ei-color-why">Kept as written: the swatch shows one color (hex, rgb, hsl or oklch), not a gradient or a name.</p></div><p class="gemboss-ei-hint gemboss-ei-help-text" id=":R19u:">A gradient: the swatch cannot show it, so it is off.</p></div><div class="gemboss-ei-fld"><label for="cat-op">Opacity<span class="gemboss-ei-rangeval" data-suffix="%">80%</span></label><input id="cat-op" type="range" class="gemboss-ei-range" min="0" max="100" step="1" value="80"/></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="open" aria-expanded="true"><span class="gemboss-ei-chev" aria-hidden="true">▾</span>Media</button><div class="gemboss-ei-fld"><label for="cat-img">Image</label><div class="gemboss-ei-img"><div class="gemboss-ei-img-thumb" aria-hidden="true">—</div><div class="gemboss-ei-img-ctl"><input id="cat-img" class="gemboss-field gemboss-ei-inp" placeholder="Paste image URL…" value=""/><div class="gemboss-ei-img-actions"><button type="button" class="ui-btn" aria-expanded="false">Library</button><button type="button" class="ui-btn" data-gb-image-clear>Clear</button></div></div></div></div></div><div class="gemboss-ei-grp"><button type="button" class="gemboss-ei-gh" data-open="closed" aria-expanded="false"><span class="gemboss-ei-chev" aria-hidden="true">▸</span>Motion</button><div class="gemboss-ei-fld"><label>Reveal</label><div class="ui-seg ui-seg--fill gemboss-ei-seg" role="group" aria-label="Reveal"><button type="button" data-value="none" aria-pressed="true" class="is-text active">None</button><button type="button" data-value="fade" aria-pressed="false" class="is-text">Fade</button></div></div></div></div></div></aside></div></div><script src="../src/kit-plain.js"></script><script src="../src/editor-plain.js"></script><script>gembossUI.initEditorFrame()</script><script>gembossUI.initEditorPanel()</script><script src="../src/editor-layers-plain.js"></script><script>gembossUI.initEditorLayers()</script></body></html>"></iframe></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="gemboss-ec" style="width:360px;height:1040px">
|
|
479
480
|
<div class="gemboss-ec-tabs" role="tablist" aria-label="Editor panels">
|
|
480
481
|
<button type="button" role="tab" data-value="configure" class="gemboss-ec-tab" aria-selected="true">Settings</button>
|
|
481
482
|
<button type="button" role="tab" data-value="chat" class="gemboss-ec-tab" aria-selected="false">Chat</button>
|
|
@@ -578,6 +579,7 @@ import { EditorFrame, EditorTopbar, EditorBack, EditorChatToggle, EditorPaneTabs
|
|
|
578
579
|
<div class="gemboss-ei-color">
|
|
579
580
|
<input type="color" class="gemboss-ei-swatch" aria-label="Background swatch" value="#f4efe6"/>
|
|
580
581
|
<input id="cat-bg" class="gemboss-field gemboss-ei-inp" placeholder="Not set" value="#f4efe6"/>
|
|
582
|
+
<input class="gemboss-field gemboss-ei-inp" data-alpha="" aria-label="Background opacity" inputMode="numeric" style="flex:0 0 64px" value="100%"/>
|
|
581
583
|
</div>
|
|
582
584
|
</div>
|
|
583
585
|
<div class="gemboss-ei-fld">
|
|
@@ -586,9 +588,9 @@ import { EditorFrame, EditorTopbar, EditorBack, EditorChatToggle, EditorPaneTabs
|
|
|
586
588
|
<button type="button" class="gemboss-ei-help" aria-label="About Overlay" aria-describedby=":R19u:" aria-expanded="false">?</button>
|
|
587
589
|
</div>
|
|
588
590
|
<div class="gemboss-ei-color">
|
|
589
|
-
<input type="color" class="gemboss-ei-swatch" aria-label="Overlay swatch" disabled="" title="Kept as written: the swatch
|
|
591
|
+
<input type="color" class="gemboss-ei-swatch" aria-label="Overlay swatch" disabled="" title="Kept as written: the swatch shows one color (hex, rgb, hsl or oklch), not a gradient or a name." aria-describedby=":Rb9u:" value="#000000"/>
|
|
590
592
|
<input id="cat-ov" class="gemboss-field gemboss-ei-inp" placeholder="Not set" value="linear-gradient(90deg,#000,#0000)"/>
|
|
591
|
-
<p id=":Rb9u:" class="gemboss-ei-color-why">Kept as written: the swatch
|
|
593
|
+
<p id=":Rb9u:" class="gemboss-ei-color-why">Kept as written: the swatch shows one color (hex, rgb, hsl or oklch), not a gradient or a name.</p>
|
|
592
594
|
</div>
|
|
593
595
|
<p class="gemboss-ei-hint gemboss-ei-help-text" id=":R19u:">A gradient: the swatch cannot show it, so it is off.</p>
|
|
594
596
|
</div>
|