@gemboss/ui 0.4.2 → 0.6.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/README.md +102 -17
- package/catalog/index.html +74 -9
- package/gemboss-ui.css +335 -60
- package/package.json +6 -3
- package/src/app-shell.css +22 -1
- package/src/assistant.css +44 -21
- package/src/auth.tsx +3 -0
- package/src/chat-composer.css +1 -1
- package/src/chat.css +1 -1
- package/src/gemboss-field.css +3 -3
- package/src/gemboss-tokens.css +1 -1
- package/src/icon.svg +1 -0
- package/src/kit-plain.css +223 -4
- package/src/kit-plain.js +115 -7
- package/src/launcher.tsx +16 -7
- package/src/shell.css +1 -0
- package/src/shell.tsx +3 -1
- package/src/ui.css +33 -25
package/README.md
CHANGED
|
@@ -12,10 +12,10 @@ npm install @gemboss/ui
|
|
|
12
12
|
|
|
13
13
|
```tsx
|
|
14
14
|
import "@gemboss/ui/gemboss-ui.css";
|
|
15
|
-
import { AppShell, RailItem, RailGroup, RailHeading,
|
|
15
|
+
import { AppShell, RailItem, RailGroup, RailHeading, BrandLockup } from "@gemboss/ui";
|
|
16
16
|
|
|
17
17
|
<AppShell
|
|
18
|
-
brand={<
|
|
18
|
+
brand={<BrandLockup name="GemWatcher" href="#/" />}
|
|
19
19
|
center={<SearchBox />}
|
|
20
20
|
rail={<>
|
|
21
21
|
<RailHeading>Market</RailHeading>
|
|
@@ -29,6 +29,9 @@ import { AppShell, RailItem, RailGroup, RailHeading, GemMark } from "@gemboss/ui
|
|
|
29
29
|
</AppShell>
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
- The topbar brand is `BrandLockup` (the admin's: gem 20.8×26, name 13.3px/700, 40px box), never a bare
|
|
33
|
+
`GemMark`. `GemMark` is the app TILE (sign-in screen, favicon); at 28px in a topbar it reads as a second app
|
|
34
|
+
icon (this example taught that until 0.5.0, and gemwatcher shipped it).
|
|
32
35
|
- Wrap each item in `RailGroup`: the selected pill only exists inside `.gnav-group`.
|
|
33
36
|
- `RailItem` renders `<a>`; pass `as={Link}` (Next) or `as="button"`. Every other prop is forwarded.
|
|
34
37
|
- No router, no data. The package only emits the markup the CSS was written for.
|
|
@@ -167,11 +170,82 @@ const m = openModal({ title: "Delete #12?", closeLabel: "Đóng", body: '<div cl
|
|
|
167
170
|
onClose: (v) => v && toast("Đã xoá") });
|
|
168
171
|
```
|
|
169
172
|
|
|
170
|
-
|
|
173
|
+
0.5.0 adds three more, each one a hand copy on some surface first:
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
// a delete: red confirm button, focus starts on Cancel; resolves true / false. Strings are TEXT.
|
|
177
|
+
if (await gembossUI.confirm({ title: "Delete #12?", body: "It leaves the board.", confirmLabel: "Delete",
|
|
178
|
+
cancelLabel: "Huỷ", tone: "critical" })) remove(12);
|
|
179
|
+
gembossUI.initShell(); // AppShell markup written by hand: ☰ drawer, backdrop, Escape, followed link
|
|
180
|
+
gembossUI.initPasswordFields(); // the sign-in's reveal button; resetPasswordFields() on sign-out
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
In a bundled app (Next, Vite) load it once with a bare `import "@gemboss/ui/kit-plain.js";` in a client module: the
|
|
184
|
+
package lists the file in `sideEffects`, so the bundler keeps it (before 0.5.0 it dropped it and `gembossUI` was
|
|
185
|
+
undefined in production builds). Use `confirm` instead of `window.confirm()`: the browser's box has no GemBoss look, no critical tone, and its
|
|
186
|
+
buttons cannot be named. For `initShell`, put `data-label-open` / `data-label-close` on the ☰ button to have its
|
|
187
|
+
name follow the state; for `initPasswordFields`, `data-label-show` / `data-label-hide` on the reveal button.
|
|
188
|
+
|
|
189
|
+
`title`, `body` and `foot` of `openModal` are HTML (escape your text); toast text is text. `beforeClose` may return a promise of
|
|
171
190
|
false to keep the popup open (it gets the close value, and a guard that throws keeps it open). Its behaviour is
|
|
172
191
|
asserted in Chromium by `packages/ui/src/kit-plain.test.ts` (`npm run test:ui-browser`, run by the CI job that has
|
|
173
192
|
Chromium; `test:packages` excludes it); the catalog's "Hộp thoại" section runs it live.
|
|
174
193
|
|
|
194
|
+
## Polaris parity (0.5.0)
|
|
195
|
+
|
|
196
|
+
The admin is Polaris; this package is how the rest of the fleet looks like it. Measured on 02/10/2026 across the six
|
|
197
|
+
surfaces on the package, the same gaps were filled six ways. What 0.5.0 settles, so a surface stops patching it:
|
|
198
|
+
|
|
199
|
+
| | Under a mouse | Under a thumb / ≤ 767px wide |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| Control height: `gemboss-field`, `ui-select`, `ui-btn`, `ui-seg` | **32px** (Polaris TextField / Select), `--ui-control-h` | **44px**, `ui-btn--sm` included |
|
|
202
|
+
| `ui-btn--sm` | 28px | 44px |
|
|
203
|
+
| Focus ring, every control | 2px iris `--ui-focus` (= `--gemboss-accent`, the admin's `--p-color-border-focus`) | same |
|
|
204
|
+
| Body text (`html`, `body`, at zero specificity) | 13px / 20px, weight 450, `--gemboss-text`, antialiased (Polaris bodyMd) | same |
|
|
205
|
+
| Kit text (tabs, table, notice, pager, empty, page-head lead) | `--ui-fs-body`, 13px | 16px in fields (iOS zoom) |
|
|
206
|
+
|
|
207
|
+
New primitives, Polaris' shapes on GemBoss tokens (`kit-plain.css`; the admin uses Polaris itself):
|
|
208
|
+
|
|
209
|
+
| Need | Class | Polaris |
|
|
210
|
+
|---|---|---|
|
|
211
|
+
| Delete / revoke | `ui-btn ui-btn--critical`, `ui-btn--primary ui-btn--critical` | Button `tone="critical"` |
|
|
212
|
+
| Status | `ui-badge` (12px/550, radius 8) `--success|--warning|--critical|--info`, `--dot` | Badge `tone` |
|
|
213
|
+
| Something to read or act on | `ui-banner` `__head` `__icon` `__title` `__close` `__body` `__actions`, same tones | Banner |
|
|
214
|
+
| Help / error under a field | `ui-help`, `ui-error`; `aria-invalid="true"` paints the field | Labelled help text, InlineError |
|
|
215
|
+
| Radio group | `fieldset.ui-choices` + `label.ui-check > input[type=radio]` | ChoiceList |
|
|
216
|
+
| On / off that applies at once | `label.ui-check.ui-switch > input[role=switch]` | (admin toggle) |
|
|
217
|
+
| Label for an icon button | `.ui-tooltip > button + .ui-tooltip__bubble[role=tooltip]` | Tooltip |
|
|
218
|
+
| Waiting | `ui-spinner` (20px), `--lg` (44px) | Spinner |
|
|
219
|
+
| Progress | `progress.ui-progress`, `--success|--critical` | ProgressBar small |
|
|
220
|
+
| Two-column form, table in a popup | `openModal({ className: "ui-modal--wide" })`, 620px | Modal default width |
|
|
221
|
+
| A popup in React (no kit-plain.js) | `<dialog class="ui-modal">` + `showModal()`: same head / body / foot, the kit's backdrop; the browser gives Escape and the inert page | Modal |
|
|
222
|
+
| Favicon | `@gemboss/ui/icon.svg` (the admin's `app/icon.svg`, byte for byte) | |
|
|
223
|
+
|
|
224
|
+
0.5.1 adds what the first surfaces on 0.5.0 still drew themselves (GemFactory, content-radar):
|
|
225
|
+
|
|
226
|
+
| Need | Class / API |
|
|
227
|
+
|---|---|
|
|
228
|
+
| Title with buttons on the right | `ui-page-head ui-page-head--actions` > `div` (h1 + p) + `.ui-page-head__actions` |
|
|
229
|
+
| Chips that toggle in place (no URL) | `.ui-chips > button.ui-tag--chip[aria-pressed]` |
|
|
230
|
+
| A long badge label | `ui-badge ui-badge--wrap` |
|
|
231
|
+
| Close the account menu on a static page | `gembossUI.initMenus()` now closes `details.gb-account` as well |
|
|
232
|
+
| ☰ and eye names on a static render | `MobileMenuButton` / `PasswordField` emit `data-label-open/close`, `data-label-show/hide` |
|
|
233
|
+
|
|
234
|
+
And four targets that measured under 44px at phone width are now 44: a compact text button's width, the bare input
|
|
235
|
+
inside `gemboss-field--group`, the brand mark alone (≤460px), a toggle chip. A popup opened by an Escape handler no
|
|
236
|
+
longer catches that same Escape (`openModal` listens from the next task). The rail item and segmented buttons draw the iris focus ring (they had
|
|
237
|
+
none: the browser drew its own), the popup × too (it drew near-black); at phone width the chat composer is 16px (iOS
|
|
238
|
+
zoomed it at 14) and the thread rail's "new chat" / collapse buttons are 44px under a fine pointer as well. Headings carry
|
|
239
|
+
their own line-height (a wrapped 22px title overlapped itself on the 20px body line), a badge is a tint of the ink (it
|
|
240
|
+
vanished on a hovered table row), `ui-seg` reads `aria-pressed`, a `[readonly]` field looks read-only, and a popup may
|
|
241
|
+
wrap body + foot in one `<form>` (`.ui-modal > form` takes no box). A metric that filters the view is a toggle: `button.ui-metric[aria-pressed]` (or
|
|
242
|
+
`a.ui-metric[aria-current="page"]` for a link), drawn with the iris edge when chosen.
|
|
243
|
+
|
|
244
|
+
If your surface still sets any of these itself (a `body { font-size }`, a `min-height: 44px` on `.ui-btn--sm`, a
|
|
245
|
+
`.danger` button, a `confirm()`), delete it on the upgrade: the package draws it now, and a surface rule wins the
|
|
246
|
+
cascade over the package's zero-specificity base. `packages/ui/src/kit-look.test.ts` measures the table above in
|
|
247
|
+
Chromium on the built CSS.
|
|
248
|
+
|
|
175
249
|
## Resizable panels
|
|
176
250
|
|
|
177
251
|
`ui-resizer` is the seam a person drags between two panels; `ui-resizing` on `<body>` is the drag in
|
|
@@ -202,24 +276,33 @@ The surface owns where the seam sits and what it does. Five rules, each paid for
|
|
|
202
276
|
React surfaces: `useResizableChatPanel` in the admin is the reference. Others write the same markup and
|
|
203
277
|
the five rules by hand; the catalog's "Thanh kéo giữa hai cột" shows the markup.
|
|
204
278
|
|
|
205
|
-
## The assistant launcher (0.4.2)
|
|
279
|
+
## The assistant launcher (0.4.2; not floating since 0.6.0)
|
|
206
280
|
|
|
207
|
-
The top-right corner of the topbar is the ACCOUNT (`AccountMenu`). The button
|
|
208
|
-
bottom-right
|
|
209
|
-
|
|
281
|
+
The top-right corner of the topbar is the ACCOUNT (`AccountMenu`). The assistant button is NOT a floating button: 0.4.2
|
|
282
|
+
floated it bottom-right, and a fixed button sits on whatever text scrolls under it (visual-gate `content_covered` red at
|
|
283
|
+
5 of 6 widths on every partner-radar page measured, 03/10/2026; GemCommunity had already dropped its floating buttons for
|
|
284
|
+
the same reason, #239). Chris chose to drop it. Render TWO copies; CSS displays exactly one at any width:
|
|
210
285
|
|
|
211
286
|
```tsx
|
|
212
|
-
import { AssistantLauncher } from "@gemboss/ui";
|
|
287
|
+
import { AppShell, AssistantLauncher } from "@gemboss/ui";
|
|
213
288
|
|
|
214
|
-
|
|
215
|
-
|
|
289
|
+
const open = dock.presentation !== "hidden";
|
|
290
|
+
<AppShell
|
|
291
|
+
actions={<>
|
|
292
|
+
<AssistantLauncher placement="topbar" label="Partner Assistant" shortcut="⌘J" hidden={open} onClick={() => dock.reopen()} />
|
|
293
|
+
<AccountMenu … />
|
|
294
|
+
</>}
|
|
295
|
+
railBottom={<AssistantLauncher label="Partner Assistant" shortcut="⌘J" hidden={open} onClick={() => dock.reopen()} />}
|
|
296
|
+
/>
|
|
216
297
|
```
|
|
217
298
|
|
|
218
|
-
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
299
|
+
- `placement="rail"` (default): the last row of the rail, full width, primary (near-black), label + shortcut. Hidden at
|
|
300
|
+
≤760px, where the rail is a drawer nobody sees until they open it.
|
|
301
|
+
- `placement="topbar"`: a 44×44 icon button, left of the account chip, ≤760px only. The label stays the accessible name.
|
|
302
|
+
- No provider and no state: pass `hidden` while your assistant is open.
|
|
222
303
|
- The shortcut is a hint only: the surface owns the key binding.
|
|
304
|
+
- 0.6.0, not a patch: an existing `<AssistantLauncher>` call changes meaning (no longer fixed; the default copy is the
|
|
305
|
+
rail one, hidden on phones). A surface on `^0.5.x` must move to `^0.6.0` in the same PR that places the two copies.
|
|
223
306
|
|
|
224
307
|
## The topbar kit: lockup, account, icons
|
|
225
308
|
|
|
@@ -307,7 +390,7 @@ the slots and props (`brand`, `center`, `actions`, rail items, icons, headings).
|
|
|
307
390
|
|
|
308
391
|
The base font is one of those tokens. `gemboss-ui.css` sets `html`, `body` and `button` in
|
|
309
392
|
`--gemboss-font-sans`, the admin's own body stack (Polaris `--p-font-family-sans`: Inter, then the
|
|
310
|
-
system UI font). The rule sits at zero specificity (`:where()`), so a surface re-themes with
|
|
393
|
+
system UI font), and since 0.5.0 `html` / `body` at Polaris bodyMd (13px / 20px, 450, `--gemboss-text`). The rule sits at zero specificity (`:where()`), so a surface re-themes with
|
|
311
394
|
`:root { --gemboss-font-sans: … }` and needs no `body { font-family }` patch. A surface that loads
|
|
312
395
|
its own web font does it itself; the package loads none.
|
|
313
396
|
|
|
@@ -319,10 +402,12 @@ something the base cannot express, add a token or a prop here, and every surface
|
|
|
319
402
|
|
|
320
403
|
| Path | What |
|
|
321
404
|
|---|---|
|
|
322
|
-
| `gemboss-ui.css` | built at pack time: `apps/admin/scripts/export-ui-css.mjs` (tokens + kit + field + `packages/ui/src/shell.css`, with Polaris `--p-*` resolved to their fallbacks) + `packages/ui/src/app-shell.css` + `
|
|
405
|
+
| `gemboss-ui.css` | built at pack time: `apps/admin/scripts/export-ui-css.mjs` (tokens + kit + field + `packages/ui/src/shell.css`, with Polaris `--p-*` resolved to their fallbacks) + `packages/ui/src/app-shell.css` + `auth.css` + `assistant.css` + `kit-plain.css` + `chat.css` + `chat-composer.css` (`packages/ui/scripts/build-css.mjs`) |
|
|
323
406
|
| `packages/ui/src/shell.css` | the SHARED SHELL (rail, topbar, main, mobile drawer, the assistant's thread rail, popover surface, account chip). The admin's `gemboss-shell.css` @imports it on line 2; the export refuses a shared-shell rule in the admin's sheet or an admin-only rule here (one owner). |
|
|
324
407
|
| `packages/ui/src/kit-plain.css` | primitives for surfaces that render plain HTML, not React (0.2.1): menu, key/value list, icon button; 0.3.0 adds `ui-link` / `ui-prose`, the media card (`ui-card--media`, `__media`, `__body`, `__foot`) and the popup's `ui-modal__body` / `__foot`. Shipped inside `gemboss-ui.css`; the admin does not import it (its first-load CSS budget has ~0.1 KB headroom).; (0.4.0) report pages: delta, large KPI grid, bar list, column chart, legend, funnel, card grid, section head. |
|
|
325
|
-
| `packages/ui/src/kit-plain.js` | 0.3.0: the behaviour those surfaces each wrote by hand: `gembossUI.openModal` (Escape, backdrop, Tab trap, stacking, ask-before-close, focus back), `toast` (text, error tone), `initMenus` (outside click, item, blur, Escape closes the menu before the popup). A classic script: inline it or `<script src>`; see "Plain-HTML behaviour"
|
|
408
|
+
| `packages/ui/src/kit-plain.js` | 0.3.0: the behaviour those surfaces each wrote by hand: `gembossUI.openModal` (Escape, backdrop, Tab trap, stacking, ask-before-close, focus back), `toast` (text, error tone), `initMenus` (outside click, item, blur, Escape closes the menu before the popup); 0.5.0: `confirm`, `initShell`, `initPasswordFields` / `resetPasswordFields`. A classic script: inline it or `<script src>`; see "Plain-HTML behaviour" above. |
|
|
409
|
+
| `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. All inside `gemboss-ui.css`; the admin @imports `chat.css` and `chat-composer.css` itself. |
|
|
410
|
+
| `packages/ui/src/icon.svg` | 0.5.0: the GemBoss app icon, for `<link rel="icon" type="image/svg+xml">`. Must stay byte-identical to `apps/admin/src/app/icon.svg` (`kit-look.test.ts` checks). |
|
|
326
411
|
| `packages/ui/src/**/*.tsx` | the components, as TypeScript source. Next: add `@gemboss/ui` to `transpilePackages`. Vite compiles it as is. |
|
|
327
412
|
|
|
328
413
|
`gemboss-ui.css` is never committed and never edited. To change a colour or a radius, change
|
package/catalog/index.html
CHANGED
|
@@ -27,15 +27,18 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
|
|
|
27
27
|
@media (max-width:760px){.cat{grid-template-columns:1fr;padding:16px}.cat-nav{position:static;flex-direction:row;flex-wrap:wrap}}
|
|
28
28
|
</style></head><body>
|
|
29
29
|
<div class="cat"><nav class="cat-nav" aria-label="Mục"><a href="#tokens">Token</a><a href="#buttons">Nút</a><a href="#fields">Ô nhập</a><a href="#choice">Tab, nhóm nút, thẻ</a><a href="#surfaces">Thẻ, số liệu, bảng, trạng thái trống</a><a href="#report">Báo cáo</a><a href="#resizer">Thanh kéo giữa hai cột</a><a href="#modal">Hộp thoại, toast, menu (JS thuần)</a><a href="#shell">Khung app</a><a href="#auth">Đăng nhập</a><a href="#chat">Thân chat</a><a href="#assistant">Trợ lý: cột phiên</a><a href="#icons">Icon</a></nav>
|
|
30
|
-
<main><header class="cat-head"><h1>@gemboss/ui 0.
|
|
30
|
+
<main><header class="cat-head"><h1>@gemboss/ui 0.6.0</h1><p>Ngôn ngữ thiết kế chung của các công cụ GemBoss. Markup dưới mỗi ví dụ là đúng thứ package render ra; bề mặt không dùng React (HTML tĩnh, Python) chép markup này và nạp <code>gemboss-ui.css</code>. Dựng từ gemboss <code>47291357064c</code>.</p></header>
|
|
31
31
|
<section id="tokens"><h2>Token</h2><p>Đổi giao diện một bề mặt bằng cách đặt lại token, không viết đè class. Tên và giá trị đọc thẳng từ gemboss-ui.css.</p><div class="cat-swatches"><div class="cat-swatch"><i style="background:var(--gemboss-primary)"></i><code>--gemboss-primary</code><span>#1b1c1e</span></div><div class="cat-swatch"><i style="background:var(--gemboss-primary-dark)"></i><code>--gemboss-primary-dark</code><span>#000000</span></div><div class="cat-swatch"><i style="background:var(--gemboss-primary-soft)"></i><code>--gemboss-primary-soft</code><span>#f2f3f5</span></div><div class="cat-swatch"><i style="background:var(--gemboss-accent)"></i><code>--gemboss-accent</code><span>#5661f5</span></div><div class="cat-swatch"><i style="background:var(--gemboss-accent-strong)"></i><code>--gemboss-accent-strong</code><span>#3a44de</span></div><div class="cat-swatch"><i style="background:var(--gemboss-accent-soft)"></i><code>--gemboss-accent-soft</code><span>#eef0fe</span></div><div class="cat-swatch"><i style="background:var(--gemboss-text-strong)"></i><code>--gemboss-text-strong</code><span>#1b1c1e</span></div><div class="cat-swatch"><i style="background:var(--gemboss-text)"></i><code>--gemboss-text</code><span>#1b1c1e</span></div><div class="cat-swatch"><i style="background:var(--gemboss-text-muted)"></i><code>--gemboss-text-muted</code><span>#686b71</span></div><div class="cat-swatch"><i style="background:var(--gemboss-surface)"></i><code>--gemboss-surface</code><span>#ffffff</span></div><div class="cat-swatch"><i style="background:var(--gemboss-canvas)"></i><code>--gemboss-canvas</code><span>#ffffff</span></div><div class="cat-swatch"><i style="background:var(--gemboss-preview-canvas)"></i><code>--gemboss-preview-canvas</code><span>#eceef1</span></div><div class="cat-swatch"><i style="background:var(--gemboss-rail-bg)"></i><code>--gemboss-rail-bg</code><span>#ffffff</span></div><div class="cat-swatch"><i style="background:var(--gemboss-panel-bg)"></i><code>--gemboss-panel-bg</code><span>#ffffff</span></div><div class="cat-swatch"><i style="background:var(--gemboss-divider)"></i><code>--gemboss-divider</code><span>#e5e7ea</span></div><div class="cat-swatch"><i style="background:var(--gemboss-divider-soft)"></i><code>--gemboss-divider-soft</code><span>#edeff2</span></div><div class="cat-swatch"><i style="background:var(--gemboss-hover)"></i><code>--gemboss-hover</code><span>#eceef2</span></div><div class="cat-swatch"><i style="background:var(--gemboss-active-bg)"></i><code>--gemboss-active-bg</code><span>#f0f1f4</span></div><div class="cat-swatch"><i style="background:var(--gemboss-active-fg)"></i><code>--gemboss-active-fg</code><span>#1b1c1e</span></div><div class="cat-swatch"><i style="background:var(--gemboss-danger)"></i><code>--gemboss-danger</code><span>#d72c0d</span></div><div class="cat-swatch"><i style="background:var(--gemboss-danger-strong)"></i><code>--gemboss-danger-strong</code><span>#b42318</span></div><div class="cat-swatch"><i style="background:var(--gemboss-danger-soft)"></i><code>--gemboss-danger-soft</code><span>#fff0e9</span></div><div class="cat-swatch"><i style="background:var(--gemboss-danger-border)"></i><code>--gemboss-danger-border</code><span>#f5c9bc</span></div><div class="cat-swatch"><i style="background:var(--gemboss-success)"></i><code>--gemboss-success</code><span>#007f5f</span></div><div class="cat-swatch"><i style="background:var(--gemboss-success-strong)"></i><code>--gemboss-success-strong</code><span>#0a6a4c</span></div><div class="cat-swatch"><i style="background:var(--gemboss-success-soft)"></i><code>--gemboss-success-soft</code><span>#e3f1df</span></div><div class="cat-swatch"><i style="background:var(--gemboss-success-border)"></i><code>--gemboss-success-border</code><span>#b7dfcd</span></div><div class="cat-swatch"><i style="background:var(--gemboss-warning)"></i><code>--gemboss-warning</code><span>#9a6700</span></div><div class="cat-swatch"><i style="background:var(--gemboss-warning-soft)"></i><code>--gemboss-warning-soft</code><span>#fff8e0</span></div><div class="cat-swatch"><i style="background:var(--gemboss-warning-border)"></i><code>--gemboss-warning-border</code><span>#f5d569</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-bg)"></i><code>--gemboss-dark-bg</code><span>#0a0a0c</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-rail)"></i><code>--gemboss-dark-rail</code><span>#0e0e11</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-surface)"></i><code>--gemboss-dark-surface</code><span>#16161a</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-surface-2)"></i><code>--gemboss-dark-surface-2</code><span>#1e1e24</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-divider)"></i><code>--gemboss-dark-divider</code><span>#2a2a31</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-text)"></i><code>--gemboss-dark-text</code><span>#ededf0</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-muted)"></i><code>--gemboss-dark-muted</code><span>#9a9aa4</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-bg)"></i><code>--gemboss-field-bg</code><span>#fdfdfd</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-bg-hover)"></i><code>--gemboss-field-bg-hover</code><span>#fafafa</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-ink)"></i><code>--gemboss-field-ink</code><span>#303030</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-placeholder)"></i><code>--gemboss-field-placeholder</code><span>#616161</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-line)"></i><code>--gemboss-field-line</code><span>#8a8a8a</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-line-hover)"></i><code>--gemboss-field-line-hover</code><span>#616161</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-line-active)"></i><code>--gemboss-field-line-active</code><span>#1a1a1a</span></div><div class="cat-swatch"><i style="background:var(--gemboss-chip-ink)"></i><code>--gemboss-chip-ink</code><span>#303633</span></div><div class="cat-swatch"><i style="background:var(--gemboss-chip-line)"></i><code>--gemboss-chip-line</code><span>#cfd6ce</span></div><div class="cat-swatch"><i style="background:var(--gemboss-chip-line-hover)"></i><code>--gemboss-chip-line-hover</code><span>#aab4ad</span></div><div class="cat-swatch"><i style="background:var(--gemboss-chip-bg-hover)"></i><code>--gemboss-chip-bg-hover</code><span>#f6f7f5</span></div><div class="cat-swatch"><i style="background:var(--gemboss-on-primary)"></i><code>--gemboss-on-primary</code><span>#ffffff</span></div><div class="cat-swatch"><i style="background:var(--gemboss-app-bg)"></i><code>--gemboss-app-bg</code><span>#ffffff</span></div></div><table class="ui-table cat-scale"><thead><tr><th>Token</th><th>Giá trị</th><th>Mẫu</th></tr></thead><tbody><tr><td><code>--gemboss-fs-micro</code></td><td>11px</td><td style="font-size:var(--gemboss-fs-micro)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-caption</code></td><td>12px</td><td style="font-size:var(--gemboss-fs-caption)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-body</code></td><td>14px</td><td style="font-size:var(--gemboss-fs-body)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-body-lg</code></td><td>16px</td><td style="font-size:var(--gemboss-fs-body-lg)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-h3</code></td><td>16px</td><td style="font-size:var(--gemboss-fs-h3)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-h2</code></td><td>20px</td><td style="font-size:var(--gemboss-fs-h2)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-h1</code></td><td>24px</td><td style="font-size:var(--gemboss-fs-h1)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-display</code></td><td>30px</td><td style="font-size:var(--gemboss-fs-display)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-radius-xs</code></td><td>4px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-xs)"></i></td></tr><tr><td><code>--gemboss-radius-sm</code></td><td>6px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-sm)"></i></td></tr><tr><td><code>--gemboss-radius-md</code></td><td>8px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-md)"></i></td></tr><tr><td><code>--gemboss-radius-lg</code></td><td>12px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-lg)"></i></td></tr><tr><td><code>--gemboss-radius-xl</code></td><td>16px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-xl)"></i></td></tr><tr><td><code>--gemboss-radius-2xl</code></td><td>20px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-2xl)"></i></td></tr><tr><td><code>--gemboss-radius-full</code></td><td>999px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-full)"></i></td></tr><tr><td><code>--gemboss-shadow-resting</code></td><td class="cat-small">0 1px 2px rgba(31, 30, 29, 0.04), 0 2px 6px rgba(31, 30, 29, 0.06)</td><td><i class="cat-radius" style="box-shadow:var(--gemboss-shadow-resting);border:0"></i></td></tr><tr><td><code>--gemboss-shadow-raised</code></td><td class="cat-small">0 4px 16px rgba(31, 30, 29, 0.10)</td><td><i class="cat-radius" style="box-shadow:var(--gemboss-shadow-raised);border:0"></i></td></tr><tr><td><code>--gemboss-shadow-overlay</code></td><td class="cat-small">0 16px 48px rgba(31, 30, 29, 0.18)</td><td><i class="cat-radius" style="box-shadow:var(--gemboss-shadow-overlay);border:0"></i></td></tr></tbody></table></section>
|
|
32
|
-
<section id="buttons"><h2>Nút</h2><p>Một lớp <code>ui-btn</code>, ba biến thể, một cỡ nhỏ. Dùng được trên <code><button></code> lẫn <code><a></code> (căn giữa sẵn).</p><figure class="cat-demo"><figcaption>Mặc định · chính · ghost · nhỏ · tắt</figcaption><div class="cat-live"><div class="cat-row"><button type="button" class="ui-btn">Lưu nháp</button><button type="button" class="ui-btn ui-btn--primary">Xuất bản</button><button type="button" class="ui-btn ui-btn--ghost">Huỷ</button><button type="button" class="ui-btn ui-btn--sm">Nhỏ</button><button type="button" class="ui-btn ui-btn--primary" disabled>Đang lưu…</button><a class="ui-btn" href="#buttons">Link dạng nút</a></div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="cat-row">
|
|
32
|
+
<section id="buttons"><h2>Nút</h2><p>Một lớp <code>ui-btn</code>, ba biến thể, tông đỏ, một cỡ nhỏ. Cao 32px dưới chuột (bằng ô nhập và ô chọn), 44px dưới ngón tay và ở khổ điện thoại, cỡ nhỏ cũng vậy. Dùng được trên <code><button></code> lẫn <code><a></code> (căn giữa sẵn).</p><figure class="cat-demo"><figcaption>Mặc định · chính · ghost · nhỏ · tắt</figcaption><div class="cat-live"><div class="cat-row"><button type="button" class="ui-btn">Lưu nháp</button><button type="button" class="ui-btn ui-btn--primary">Xuất bản</button><button type="button" class="ui-btn ui-btn--ghost">Huỷ</button><button type="button" class="ui-btn ui-btn--sm">Nhỏ</button><button type="button" class="ui-btn ui-btn--primary" disabled>Đang lưu…</button><a class="ui-btn" href="#buttons">Link dạng nút</a></div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="cat-row">
|
|
33
33
|
<button type="button" class="ui-btn">Lưu nháp</button>
|
|
34
34
|
<button type="button" class="ui-btn ui-btn--primary">Xuất bản</button>
|
|
35
35
|
<button type="button" class="ui-btn ui-btn--ghost">Huỷ</button>
|
|
36
36
|
<button type="button" class="ui-btn ui-btn--sm">Nhỏ</button>
|
|
37
37
|
<button type="button" class="ui-btn ui-btn--primary" disabled>Đang lưu…</button>
|
|
38
38
|
<a class="ui-btn" href="#buttons">Link dạng nút</a>
|
|
39
|
+
</div></code></pre></details></figure><figure class="cat-demo"><figcaption>Tông đỏ cho thao tác xoá (<code>ui-btn--critical</code>, Polaris <code>tone=critical</code>)</figcaption><div class="cat-live"><div class="cat-row"><button type="button" class="ui-btn ui-btn--critical">Thu hồi khoá</button><button type="button" class="ui-btn ui-btn--primary ui-btn--critical">Xoá vĩnh viễn</button></div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="cat-row">
|
|
40
|
+
<button type="button" class="ui-btn ui-btn--critical">Thu hồi khoá</button>
|
|
41
|
+
<button type="button" class="ui-btn ui-btn--primary ui-btn--critical">Xoá vĩnh viễn</button>
|
|
39
42
|
</div></code></pre></details></figure></section>
|
|
40
43
|
<section id="fields"><h2>Ô nhập</h2><p>Mọi ô chữ dùng <code>gemboss-field</code>: cùng viền, cùng focus, 44px trên màn chạm.</p><figure class="cat-demo"><figcaption>Ô chữ · ô có biểu tượng · chọn · vùng chữ</figcaption><div class="cat-live"><div class="cat-stack"><label class="ui-label" for="cat-f1">Tên chiến dịch</label><input id="cat-f1" class="gemboss-field" placeholder="Tên chiến dịch"><label class="gemboss-field gemboss-field--group"><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="8.8" cy="8.8" r="5.3"></circle><path d="M12.8 12.8 17 17"></path></g></svg><input class="gemboss-field__bare" placeholder="Tìm store theo domain…"></label><select class="ui-select"><option>Mọi ngành</option><option>Mỹ phẩm</option></select><textarea class="gemboss-field" rows="4" placeholder="Ghi chú"></textarea><textarea class="ui-textarea" placeholder="ui-textarea: cùng họ, cao sẵn 96px"></textarea><label class="ui-check"><input type="checkbox" checked> Chỉ thứ đã duyệt</label><label class="ui-check"><input type="checkbox"> Khoá preset</label></div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="cat-stack">
|
|
41
44
|
<label class="ui-label" for="cat-f1">Tên chiến dịch</label>
|
|
@@ -63,7 +66,20 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
|
|
|
63
66
|
<input type="checkbox" checked> Chỉ thứ đã duyệt</label>
|
|
64
67
|
<label class="ui-check">
|
|
65
68
|
<input type="checkbox"> Khoá preset</label>
|
|
66
|
-
</div></code></pre></details></figure></
|
|
69
|
+
</div></code></pre></details></figure><figure class="cat-demo"><figcaption>Gợi ý và lỗi dưới ô (<code>ui-help</code>, <code>ui-error</code>, <code>aria-invalid</code> tô đỏ ô)</figcaption><div class="cat-live"><div class="cat-stack"><label class="ui-label" for="cat-f2">Domain</label><input id="cat-f2" class="gemboss-field gemboss-field--tall" value="https://glowrecipe.com" aria-invalid="true" aria-describedby="cat-f2-h cat-f2-e"><p class="ui-help" id="cat-f2-h">Không kèm https://, ví dụ glowrecipe.com.</p><p class="ui-error" id="cat-f2-e">Bỏ phần https:// rồi lưu lại.</p></div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="cat-stack">
|
|
70
|
+
<label class="ui-label" for="cat-f2">Domain</label>
|
|
71
|
+
<input id="cat-f2" class="gemboss-field gemboss-field--tall" value="https://glowrecipe.com" aria-invalid="true" aria-describedby="cat-f2-h cat-f2-e">
|
|
72
|
+
<p class="ui-help" id="cat-f2-h">Không kèm https://, ví dụ glowrecipe.com.</p>
|
|
73
|
+
<p class="ui-error" id="cat-f2-e">Bỏ phần https:// rồi lưu lại.</p>
|
|
74
|
+
</div></code></pre></details></figure><figure class="cat-demo"><figcaption>Radio (<code>ui-choices</code> + <code>ui-check</code>) · công tắc (<code>ui-switch</code>, áp dụng ngay, không có nút Lưu)</figcaption><div class="cat-live"><fieldset class="ui-choices"><legend class="ui-label">Gửi bản tin</legend><label class="ui-check"><input type="radio" name="cat-r" checked> Thứ Hai hằng tuần</label><label class="ui-check"><input type="radio" name="cat-r"> Mỗi ngày</label></fieldset><label class="ui-check ui-switch"><input type="checkbox" role="switch" checked> Báo khi có đối thủ mới</label></div><details class="cat-code"><summary>Markup</summary><pre><code><fieldset class="ui-choices">
|
|
75
|
+
<legend class="ui-label">Gửi bản tin</legend>
|
|
76
|
+
<label class="ui-check">
|
|
77
|
+
<input type="radio" name="cat-r" checked> Thứ Hai hằng tuần</label>
|
|
78
|
+
<label class="ui-check">
|
|
79
|
+
<input type="radio" name="cat-r"> Mỗi ngày</label>
|
|
80
|
+
</fieldset>
|
|
81
|
+
<label class="ui-check ui-switch">
|
|
82
|
+
<input type="checkbox" role="switch" checked> Báo khi có đối thủ mới</label></code></pre></details></figure></section>
|
|
67
83
|
<section id="choice"><h2>Tab, nhóm nút, thẻ</h2><figure class="cat-demo"><figcaption>Tab (<code>aria-selected</code> quyết định tab đang chọn)</figcaption><div class="cat-live"><div class="ui-tabs" role="tablist"><button type="button" role="tab" aria-selected="true">Tổng quan</button><button type="button" role="tab" aria-selected="false">Chi tiết</button><button type="button" role="tab" aria-selected="false" disabled>Sắp có</button></div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="ui-tabs" role="tablist">
|
|
68
84
|
<button type="button" role="tab" aria-selected="true">Tổng quan</button>
|
|
69
85
|
<button type="button" role="tab" aria-selected="false">Chi tiết</button>
|
|
@@ -115,6 +131,12 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
|
|
|
115
131
|
<span class="ui-tag ui-tag--accent">Đã duyệt</span>
|
|
116
132
|
<span class="ui-tag ui-tag--chip">SECTION</span>
|
|
117
133
|
<span class="ui-badge">12</span>
|
|
134
|
+
</div></code></pre></details></figure><figure class="cat-demo"><figcaption>Badge theo tông (<code>ui-badge--success|--warning|--critical|--info</code>, <code>--dot</code> có chấm trạng thái)</figcaption><div class="cat-live"><div class="cat-row"><span class="ui-badge">Nháp</span><span class="ui-badge ui-badge--success ui-badge--dot">Đang chạy</span><span class="ui-badge ui-badge--warning">Chờ duyệt</span><span class="ui-badge ui-badge--critical">Lỗi tải</span><span class="ui-badge ui-badge--info">Mới</span></div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="cat-row">
|
|
135
|
+
<span class="ui-badge">Nháp</span>
|
|
136
|
+
<span class="ui-badge ui-badge--success ui-badge--dot">Đang chạy</span>
|
|
137
|
+
<span class="ui-badge ui-badge--warning">Chờ duyệt</span>
|
|
138
|
+
<span class="ui-badge ui-badge--critical">Lỗi tải</span>
|
|
139
|
+
<span class="ui-badge ui-badge--info">Mới</span>
|
|
118
140
|
</div></code></pre></details></figure><figure class="cat-demo"><figcaption>Tab bằng link (<code><nav class=ui-tabs></code>, <code>aria-current=page</code> là tab đang chọn)</figcaption><div class="cat-live"><nav class="ui-tabs" aria-label="Chế độ xem"><a href="#" aria-current="page">Tăng trưởng</a><a href="#">Mới lên</a><a href="#">Quảng cáo</a></nav></div><details class="cat-code"><summary>Markup</summary><pre><code><nav class="ui-tabs" aria-label="Chế độ xem">
|
|
119
141
|
<a href="#" aria-current="page">Tăng trưởng</a>
|
|
120
142
|
<a href="#">Mới lên</a>
|
|
@@ -179,7 +201,48 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
|
|
|
179
201
|
<dt>Điểm tiềm năng</dt>
|
|
180
202
|
<dd>71</dd>
|
|
181
203
|
</div>
|
|
182
|
-
</dl></code></pre></details></figure><figure class="cat-demo"><figcaption>Thông báo (<code>ui-notice</code>, tông <code>--warning|--danger|--success</code>)</figcaption><div class="cat-live"><div class="ui-notice ui-notice--warning">Token Slack đã hết hạn: bản tin thứ Hai sẽ không gửi được.</div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="ui-notice ui-notice--warning">Token Slack đã hết hạn: bản tin thứ Hai sẽ không gửi được.</div></code></pre></details></figure><figure class="cat-demo"><figcaption>
|
|
204
|
+
</dl></code></pre></details></figure><figure class="cat-demo"><figcaption>Thông báo (<code>ui-notice</code>, tông <code>--warning|--danger|--success</code>)</figcaption><div class="cat-live"><div class="ui-notice ui-notice--warning">Token Slack đã hết hạn: bản tin thứ Hai sẽ không gửi được.</div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="ui-notice ui-notice--warning">Token Slack đã hết hạn: bản tin thứ Hai sẽ không gửi được.</div></code></pre></details></figure><figure class="cat-demo"><figcaption>Banner (<code>ui-banner</code>, tông <code>--warning|--critical|--success|--info</code>): việc người đọc phải làm</figcaption><div class="cat-live"><div class="ui-banner ui-banner--warning"><div class="ui-banner__head"><svg class="ui-banner__icon" viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2.5 1.5 17h17L10 2.5Zm-.75 5h1.5v5h-1.5v-5Zm.75 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"/></svg><h3 class="ui-banner__title">Token Slack đã hết hạn</h3><button type="button" class="ui-banner__close" aria-label="Ẩn"><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 5l10 10M15 5 5 15"></path></g></svg></button></div><div class="ui-banner__body"><p>Bản tin thứ Hai sẽ không gửi được cho tới khi kết nối lại.</p><div class="ui-banner__actions"><a class="ui-btn" href="#surfaces">Kết nối lại</a></div></div></div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="ui-banner ui-banner--warning">
|
|
205
|
+
<div class="ui-banner__head">
|
|
206
|
+
<svg class="ui-banner__icon" viewBox="0 0 20 20" aria-hidden="true">
|
|
207
|
+
<path d="M10 2.5 1.5 17h17L10 2.5Zm-.75 5h1.5v5h-1.5v-5Zm.75 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"/>
|
|
208
|
+
</svg>
|
|
209
|
+
<h3 class="ui-banner__title">Token Slack đã hết hạn</h3>
|
|
210
|
+
<button type="button" class="ui-banner__close" aria-label="Ẩn">
|
|
211
|
+
<svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false">
|
|
212
|
+
<g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
213
|
+
<path d="M5 5l10 10M15 5 5 15">
|
|
214
|
+
</path>
|
|
215
|
+
</g>
|
|
216
|
+
</svg>
|
|
217
|
+
</button>
|
|
218
|
+
</div>
|
|
219
|
+
<div class="ui-banner__body">
|
|
220
|
+
<p>Bản tin thứ Hai sẽ không gửi được cho tới khi kết nối lại.</p>
|
|
221
|
+
<div class="ui-banner__actions">
|
|
222
|
+
<a class="ui-btn" href="#surfaces">Kết nối lại</a>
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
</div></code></pre></details></figure><figure class="cat-demo"><figcaption>Đang chờ (<code>ui-spinner</code>, <code>--lg</code>) · tiến độ (<code>ui-progress</code>) · chú giải (<code>ui-tooltip</code>, rê hoặc Tab vào nút)</figcaption><div class="cat-live"><div class="cat-row"><span class="ui-spinner" role="status"><span class="ui-sr-only">Đang tải…</span></span><span class="ui-spinner ui-spinner--lg" role="status"><span class="ui-sr-only">Đang tải…</span></span><progress class="ui-progress" value="37" max="100" aria-label="Nhập dữ liệu" style="flex:1 1 200px">37%</progress><progress class="ui-progress ui-progress--success" value="100" max="100" aria-label="Xong" style="flex:1 1 120px">100%</progress><span class="ui-tooltip" style="margin-top:48px"><button type="button" class="ui-btn ui-btn--icon" aria-label="Lưu trữ" aria-describedby="cat-tt"><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 5l10 10M15 5 5 15"></path></g></svg></button><span class="ui-tooltip__bubble" role="tooltip" id="cat-tt">Lưu trữ</span></span></div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="cat-row">
|
|
226
|
+
<span class="ui-spinner" role="status">
|
|
227
|
+
<span class="ui-sr-only">Đang tải…</span>
|
|
228
|
+
</span>
|
|
229
|
+
<span class="ui-spinner ui-spinner--lg" role="status">
|
|
230
|
+
<span class="ui-sr-only">Đang tải…</span>
|
|
231
|
+
</span>
|
|
232
|
+
<progress class="ui-progress" value="37" max="100" aria-label="Nhập dữ liệu" style="flex:1 1 200px">37%</progress>
|
|
233
|
+
<progress class="ui-progress ui-progress--success" value="100" max="100" aria-label="Xong" style="flex:1 1 120px">100%</progress>
|
|
234
|
+
<span class="ui-tooltip" style="margin-top:48px">
|
|
235
|
+
<button type="button" class="ui-btn ui-btn--icon" aria-label="Lưu trữ" aria-describedby="cat-tt">
|
|
236
|
+
<svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false">
|
|
237
|
+
<g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
238
|
+
<path d="M5 5l10 10M15 5 5 15">
|
|
239
|
+
</path>
|
|
240
|
+
</g>
|
|
241
|
+
</svg>
|
|
242
|
+
</button>
|
|
243
|
+
<span class="ui-tooltip__bubble" role="tooltip" id="cat-tt">Lưu trữ</span>
|
|
244
|
+
</span>
|
|
245
|
+
</div></code></pre></details></figure><figure class="cat-demo"><figcaption>Phân trang (<code>ui-pager</code>)</figcaption><div class="cat-live"><nav class="ui-pager" aria-label="Trang"><a href="#" rel="prev"><span aria-hidden="true">‹</span> Trước</a><span aria-current="page">2 / 9</span><a href="#" rel="next">Sau <span aria-hidden="true">›</span></a></nav></div><details class="cat-code"><summary>Markup</summary><pre><code><nav class="ui-pager" aria-label="Trang">
|
|
183
246
|
<a href="#" rel="prev">
|
|
184
247
|
<span aria-hidden="true">‹</span> Trước</a>
|
|
185
248
|
<span aria-current="page">2 / 9</span>
|
|
@@ -497,10 +560,11 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
|
|
|
497
560
|
</div>
|
|
498
561
|
<div style="padding:12px;background:var(--gemboss-surface)">Nội dung</div>
|
|
499
562
|
</div></code></pre></details></figure></section>
|
|
500
|
-
<section id="modal"><h2>Hộp thoại, toast, menu (JS thuần)</h2><p>Lớp phủ <code>ui-overlay</code> + hộp <code>ui-modal</code>, thân <code>ui-modal__body</code>, chân <code>ui-modal__foot</code>. Bề mặt không dùng React nạp <code>@gemboss/ui/kit-plain.js</code> (script thường, chèn thẳng vào trang được) và gọi <code>gembossUI.openModal</code> / <code>toast</code> / <code>initMenus</code>: Escape, chạm nền, giữ Tab trong hộp, hộp chồng nhau, hỏi trước khi đóng. Bấm thử các nút dưới đây.</p><figure class="cat-demo"><figcaption>Bấm thử (<code>gembossUI</code>) <span>chạy kit-plain.js thật của gói</span></figcaption><div class="cat-live"><div class="cat-row"><button type="button" class="ui-btn ui-btn--primary" data-cat-js="modal">Mở hộp thoại</button><button type="button" class="ui-btn" data-cat-js="toast">Toast</button><button type="button" class="ui-btn" data-cat-js="toast-error">Toast lỗi</button></div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="cat-row">
|
|
563
|
+
<section id="modal"><h2>Hộp thoại, toast, menu (JS thuần)</h2><p>Lớp phủ <code>ui-overlay</code> + hộp <code>ui-modal</code>, thân <code>ui-modal__body</code>, chân <code>ui-modal__foot</code>. Bề mặt không dùng React nạp <code>@gemboss/ui/kit-plain.js</code> (script thường, chèn thẳng vào trang được) và gọi <code>gembossUI.openModal</code> / <code>toast</code> / <code>initMenus</code>: Escape, chạm nền, giữ Tab trong hộp, hộp chồng nhau, hỏi trước khi đóng. Bấm thử các nút dưới đây.</p><figure class="cat-demo"><figcaption>Bấm thử (<code>gembossUI</code>) <span>chạy kit-plain.js thật của gói</span></figcaption><div class="cat-live"><div class="cat-row"><button type="button" class="ui-btn ui-btn--primary" data-cat-js="modal">Mở hộp thoại</button><button type="button" class="ui-btn" data-cat-js="toast">Toast</button><button type="button" class="ui-btn" data-cat-js="toast-error">Toast lỗi</button><button type="button" class="ui-btn ui-btn--critical" data-cat-js="confirm">Xác nhận xoá</button></div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="cat-row">
|
|
501
564
|
<button type="button" class="ui-btn ui-btn--primary" data-cat-js="modal">Mở hộp thoại</button>
|
|
502
565
|
<button type="button" class="ui-btn" data-cat-js="toast">Toast</button>
|
|
503
566
|
<button type="button" class="ui-btn" data-cat-js="toast-error">Toast lỗi</button>
|
|
567
|
+
<button type="button" class="ui-btn ui-btn--critical" data-cat-js="confirm">Xác nhận xoá</button>
|
|
504
568
|
</div></code></pre></details></figure><figure class="cat-demo"><figcaption>Hộp thoại (<code>ui-modal__head</code> có nút đóng 44px)</figcaption><div class="cat-live"><div class="ui-modal" role="dialog" aria-modal="true" aria-labelledby="cat-m"><div class="ui-modal__head"><div class="ui-modal__title" id="cat-m">Xoá phiên này?</div><button type="button" class="ui-modal__close" aria-label="Đóng"><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 5l10 10M15 5 5 15"></path></g></svg></button></div><div class="ui-modal__body">Lịch sử vẫn còn trong sổ; phiên chỉ ẩn khỏi danh sách.</div><div class="ui-modal__foot"><button type="button" class="ui-btn ui-btn--ghost">Huỷ</button><button type="button" class="ui-btn ui-btn--primary">Xoá</button></div></div></div><details class="cat-code"><summary>Markup</summary><pre><code><div class="ui-modal" role="dialog" aria-modal="true" aria-labelledby="cat-m">
|
|
505
569
|
<div class="ui-modal__head">
|
|
506
570
|
<div class="ui-modal__title" id="cat-m">Xoá phiên này?</div>
|
|
@@ -519,10 +583,10 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
|
|
|
519
583
|
<button type="button" class="ui-btn ui-btn--primary">Xoá</button>
|
|
520
584
|
</div>
|
|
521
585
|
</div></code></pre></details></figure></section>
|
|
522
|
-
<section id="shell"><h2>Khung app</h2><p>Topbar 56px, rail 240px, ≤760px thành ngăn kéo. Logo <code>BrandLockup</code>, tài khoản <code>AccountMenu</code> (bấm chữ viết tắt), mục Trợ lý ở chân rail có class <code>gnav-assistant</code>.</p><figure class="cat-demo cat-screen"><figcaption>AppShell + BrandLockup + AccountMenu + Icon</figcaption><iframe title="AppShell + BrandLockup + AccountMenu + Icon" style="height:460px" 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"></head><body><div class="gemboss-platform-shell"><header class="gemboss-platform-topbar"><div class="gemboss-topbar-start"><button type="button" class="gemboss-mobile-menu-btn" aria-label="Mở menu" aria-expanded="false" aria-controls=":R0:"><svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><path d="M3 5.5h14M3 10h14M3 14.5h14" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"></path></svg></button><a class="gb-brand" href="#" aria-label="GemFactory home"><svg class="gb-brand-gem" viewBox="0 0 32 40" width="20.8" height="26" aria-hidden="true" focusable="false"><g transform="translate(0,0.8) scale(0.31)"><polygon points="26,14 74,14 66,50 34,50" fill="#5661F5" fill-opacity="0.92"></polygon><path d="M26,14 74,14 96,50 50,110 4,50Z" fill="none" stroke="currentColor" stroke-width="8.75" stroke-linejoin="round"></path><path d="M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110" fill="none" stroke="currentColor" stroke-width="5.45" stroke-linejoin="round"></path></g></svg><span class="gb-brand-name">GemFactory</span></a></div><div class="gemboss-topbar-center"></div><div class="gemboss-topbar-end"><details class="gb-account"><summary class="gemboss-account-chip" aria-label="Account · Minh Anh" title="Minh Anh">MA</summary><div role="menu" class="gemboss-popover-surface gemboss-account-menu"><div class="gb-account-head"><div class="gb-account-name">Minh Anh</div><div class="gb-account-email">ma@gemboss.ai</div><div class="gb-account-role">Designer</div></div><a role="menuitem" class="gemboss-account-menu-item" href="#">Cài đặt</a><form method="post" action="#" class="gb-account-form"><button role="menuitem" type="submit" class="gemboss-account-menu-item danger">Đăng xuất</button></form></div></details></div></header><nav class="icon-nav" aria-label="Main navigation" id=":R0:"><div class="gnav-scroll"><div class="gnav-heading">Kho</div><div class="gnav-group active"><a class="gnav-item active" aria-current="page" href="#"><span class="gnav-ico"><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3.5" width="4" height="13" rx="1.2"></rect><rect x="8" y="3.5" width="4" height="9" rx="1.2"></rect><rect x="13" y="3.5" width="4" height="6" rx="1.2"></rect></g></svg></span><span class="gnav-label">Board</span></a></div><div class="gnav-group"><a class="gnav-item" href="#"><span class="gnav-ico"><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="3" width="13" height="3.5" rx="1"></rect><rect x="3.5" y="8.25" width="13" height="3.5" rx="1"></rect><rect x="3.5" y="13.5" width="13" height="3.5" rx="1"></rect></g></svg></span><span class="gnav-label">Ghép trang</span></a></div><div class="gnav-group"><a class="gnav-item" href="#"><span class="gnav-ico"><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M10 3.2 17.3 16H2.7z"></path><path d="M10 8.2v3.6M10 13.9v.1"></path></g></svg></span><span class="gnav-label">Framework thiếu</span><span class="gnav-count" aria-label="3 mục đang mở">3</span></a></div></div><div class="gnav-bottom"><div class="gnav-sep"></div><a class="gnav-item gnav-assistant" href="#"><span class="gnav-ico"><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 4.5h14v9H8.5L5 16.5v-3H3z"></path></g></svg></span><span class="gnav-label">Trợ lý</span></a></div></nav><button type="button" class="gemboss-mobile-nav-backdrop" aria-label="Đóng menu" tabindex="-1"></button><main class="gemboss-platform-main"><div style="padding:24px"><h1 style="margin:0">Nội dung màn</h1></div></main></div></body></html>"></iframe><details class="cat-code"><summary>Markup</summary><pre><code><div class="gemboss-platform-shell">
|
|
586
|
+
<section id="shell"><h2>Khung app</h2><p>Topbar 56px, rail 240px, ≤760px thành ngăn kéo. Logo <code>BrandLockup</code>, tài khoản <code>AccountMenu</code> (bấm chữ viết tắt), mục Trợ lý ở chân rail có class <code>gnav-assistant</code>.</p><figure class="cat-demo cat-screen"><figcaption>AppShell + BrandLockup + AccountMenu + Icon</figcaption><iframe title="AppShell + BrandLockup + AccountMenu + Icon" style="height:460px" 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"></head><body><div class="gemboss-platform-shell"><header class="gemboss-platform-topbar"><div class="gemboss-topbar-start"><button type="button" class="gemboss-mobile-menu-btn" aria-label="Mở menu" aria-expanded="false" data-label-open="Mở menu" data-label-close="Đóng menu" aria-controls=":R0:"><svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><path d="M3 5.5h14M3 10h14M3 14.5h14" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"></path></svg></button><a class="gb-brand" href="#" aria-label="GemFactory home"><svg class="gb-brand-gem" viewBox="0 0 32 40" width="20.8" height="26" aria-hidden="true" focusable="false"><g transform="translate(0,0.8) scale(0.31)"><polygon points="26,14 74,14 66,50 34,50" fill="#5661F5" fill-opacity="0.92"></polygon><path d="M26,14 74,14 96,50 50,110 4,50Z" fill="none" stroke="currentColor" stroke-width="8.75" stroke-linejoin="round"></path><path d="M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110" fill="none" stroke="currentColor" stroke-width="5.45" stroke-linejoin="round"></path></g></svg><span class="gb-brand-name">GemFactory</span></a></div><div class="gemboss-topbar-center"></div><div class="gemboss-topbar-end"><details class="gb-account"><summary class="gemboss-account-chip" aria-label="Account · Minh Anh" title="Minh Anh">MA</summary><div role="menu" class="gemboss-popover-surface gemboss-account-menu"><div class="gb-account-head"><div class="gb-account-name">Minh Anh</div><div class="gb-account-email">ma@gemboss.ai</div><div class="gb-account-role">Designer</div></div><a role="menuitem" class="gemboss-account-menu-item" href="#">Cài đặt</a><form method="post" action="#" class="gb-account-form"><button role="menuitem" type="submit" class="gemboss-account-menu-item danger">Đăng xuất</button></form></div></details></div></header><nav class="icon-nav" aria-label="Main navigation" id=":R0:"><div class="gnav-scroll"><div class="gnav-heading">Kho</div><div class="gnav-group active"><a class="gnav-item active" aria-current="page" href="#"><span class="gnav-ico"><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3.5" width="4" height="13" rx="1.2"></rect><rect x="8" y="3.5" width="4" height="9" rx="1.2"></rect><rect x="13" y="3.5" width="4" height="6" rx="1.2"></rect></g></svg></span><span class="gnav-label">Board</span></a></div><div class="gnav-group"><a class="gnav-item" href="#"><span class="gnav-ico"><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="3" width="13" height="3.5" rx="1"></rect><rect x="3.5" y="8.25" width="13" height="3.5" rx="1"></rect><rect x="3.5" y="13.5" width="13" height="3.5" rx="1"></rect></g></svg></span><span class="gnav-label">Ghép trang</span></a></div><div class="gnav-group"><a class="gnav-item" href="#"><span class="gnav-ico"><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M10 3.2 17.3 16H2.7z"></path><path d="M10 8.2v3.6M10 13.9v.1"></path></g></svg></span><span class="gnav-label">Framework thiếu</span><span class="gnav-count" aria-label="3 mục đang mở">3</span></a></div></div><div class="gnav-bottom"><div class="gnav-sep"></div><a class="gnav-item gnav-assistant" href="#"><span class="gnav-ico"><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 4.5h14v9H8.5L5 16.5v-3H3z"></path></g></svg></span><span class="gnav-label">Trợ lý</span></a></div></nav><button type="button" class="gemboss-mobile-nav-backdrop" aria-label="Đóng menu" tabindex="-1"></button><main class="gemboss-platform-main"><div style="padding:24px"><h1 style="margin:0">Nội dung màn</h1></div></main></div></body></html>"></iframe><details class="cat-code"><summary>Markup</summary><pre><code><div class="gemboss-platform-shell">
|
|
523
587
|
<header class="gemboss-platform-topbar">
|
|
524
588
|
<div class="gemboss-topbar-start">
|
|
525
|
-
<button type="button" class="gemboss-mobile-menu-btn" aria-label="Mở menu" aria-expanded="false" aria-controls=":R0:">
|
|
589
|
+
<button type="button" class="gemboss-mobile-menu-btn" aria-label="Mở menu" aria-expanded="false" data-label-open="Mở menu" data-label-close="Đóng menu" aria-controls=":R0:">
|
|
526
590
|
<svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true">
|
|
527
591
|
<path d="M3 5.5h14M3 10h14M3 14.5h14" stroke="currentColor" stroke-width="1.7" stroke-linecap="round">
|
|
528
592
|
</path>
|
|
@@ -639,7 +703,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
|
|
|
639
703
|
</div>
|
|
640
704
|
</main>
|
|
641
705
|
</div></code></pre></details></figure></section>
|
|
642
|
-
<section id="auth"><h2>Đăng nhập</h2><figure class="cat-demo cat-screen"><figcaption>AuthLayout + PasswordField</figcaption><iframe title="AuthLayout + PasswordField" style="height:620px" 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"></head><body><main class="gb-auth"><div class="gb-auth-split"><div class="gb-auth-stage"><div class="gb-auth-card"><header class="gb-auth-header"><span class="gb-auth-mark" aria-hidden="true"><svg viewBox="0 0 32 32" width="56" height="56" aria-hidden="true" focusable="false"><rect width="32" height="32" rx="7" style="fill:var(--gb-mark-bg)"></rect><g transform="translate(16,16) scale(0.24) translate(-50,-62)"><polygon points="26,14 74,14 66,50 34,50" fill="#8a93ff"></polygon><path d="M26,14 74,14 96,50 50,110 4,50Z" fill="none" stroke="#f4f4f2" stroke-width="5" stroke-linejoin="round"></path><path d="M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110" fill="none" stroke="#f4f4f2" stroke-opacity="0.72" stroke-width="3" stroke-linejoin="round"></path></g></svg></span><h1>GemFactory</h1><p>Kho section của GemBoss</p></header><form class="gb-auth-form" method="post" action="#"><div class="gb-auth-field"><label for="pw">Mật khẩu</label><div class="gb-auth-pw"><input class="gb-auth-input" id="pw" type="password"/><button type="button" aria-controls="pw" aria-label="Hiện" title="Hiện" class="gb-auth-pw-toggle"><svg width="18" height="18" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M1.5 10S4.6 4.5 10 4.5 18.5 10 18.5 10 15.4 15.5 10 15.5 1.5 10 1.5 10Z"></path><circle cx="10" cy="10" r="2.6"></circle></svg></button></div></div><button type="submit" class="gb-auth-submit">Đăng nhập</button></form></div></div><aside class="gb-auth-panel"><div class="gb-auth-panel-in"><p class="gb-auth-eyebrow">GemBoss</p><h2 class="gb-auth-panel-h">Một ngôn ngữ thiết kế cho mọi công cụ</h2><p class="gb-auth-panel-p">Đăng nhập bằng mật khẩu đội đã gửi riêng.</p></div></aside></div></main></body></html>"></iframe><details class="cat-code"><summary>Markup</summary><pre><code><main class="gb-auth">
|
|
706
|
+
<section id="auth"><h2>Đăng nhập</h2><figure class="cat-demo cat-screen"><figcaption>AuthLayout + PasswordField</figcaption><iframe title="AuthLayout + PasswordField" style="height:620px" 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"></head><body><main class="gb-auth"><div class="gb-auth-split"><div class="gb-auth-stage"><div class="gb-auth-card"><header class="gb-auth-header"><span class="gb-auth-mark" aria-hidden="true"><svg viewBox="0 0 32 32" width="56" height="56" aria-hidden="true" focusable="false"><rect width="32" height="32" rx="7" style="fill:var(--gb-mark-bg)"></rect><g transform="translate(16,16) scale(0.24) translate(-50,-62)"><polygon points="26,14 74,14 66,50 34,50" fill="#8a93ff"></polygon><path d="M26,14 74,14 96,50 50,110 4,50Z" fill="none" stroke="#f4f4f2" stroke-width="5" stroke-linejoin="round"></path><path d="M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110" fill="none" stroke="#f4f4f2" stroke-opacity="0.72" stroke-width="3" stroke-linejoin="round"></path></g></svg></span><h1>GemFactory</h1><p>Kho section của GemBoss</p></header><form class="gb-auth-form" method="post" action="#"><div class="gb-auth-field"><label for="pw">Mật khẩu</label><div class="gb-auth-pw"><input class="gb-auth-input" id="pw" type="password"/><button type="button" aria-controls="pw" aria-label="Hiện" title="Hiện" data-label-show="Hiện" data-label-hide="Ẩn" class="gb-auth-pw-toggle"><svg width="18" height="18" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M1.5 10S4.6 4.5 10 4.5 18.5 10 18.5 10 15.4 15.5 10 15.5 1.5 10 1.5 10Z"></path><circle cx="10" cy="10" r="2.6"></circle></svg></button></div></div><button type="submit" class="gb-auth-submit">Đăng nhập</button></form></div></div><aside class="gb-auth-panel"><div class="gb-auth-panel-in"><p class="gb-auth-eyebrow">GemBoss</p><h2 class="gb-auth-panel-h">Một ngôn ngữ thiết kế cho mọi công cụ</h2><p class="gb-auth-panel-p">Đăng nhập bằng mật khẩu đội đã gửi riêng.</p></div></aside></div></main></body></html>"></iframe><details class="cat-code"><summary>Markup</summary><pre><code><main class="gb-auth">
|
|
643
707
|
<div class="gb-auth-split">
|
|
644
708
|
<div class="gb-auth-stage">
|
|
645
709
|
<div class="gb-auth-card">
|
|
@@ -666,7 +730,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
|
|
|
666
730
|
<label for="pw">Mật khẩu</label>
|
|
667
731
|
<div class="gb-auth-pw">
|
|
668
732
|
<input class="gb-auth-input" id="pw" type="password"/>
|
|
669
|
-
<button type="button" aria-controls="pw" aria-label="Hiện" title="Hiện" class="gb-auth-pw-toggle">
|
|
733
|
+
<button type="button" aria-controls="pw" aria-label="Hiện" title="Hiện" data-label-show="Hiện" data-label-hide="Ẩn" class="gb-auth-pw-toggle">
|
|
670
734
|
<svg width="18" height="18" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
|
|
671
735
|
<path d="M1.5 10S4.6 4.5 10 4.5 18.5 10 18.5 10 15.4 15.5 10 15.5 1.5 10 1.5 10Z">
|
|
672
736
|
</path>
|
|
@@ -873,6 +937,7 @@ document.addEventListener("click", function (e) {
|
|
|
873
937
|
var k = b.dataset.catJs;
|
|
874
938
|
if (k === "toast") gembossUI.toast("Đã lưu");
|
|
875
939
|
else if (k === "toast-error") gembossUI.toast("Không lưu được: mất mạng", { error: true });
|
|
940
|
+
else if (k === "confirm") gembossUI.confirm({ title: "Xoá phiên này?", body: "Lịch sử vẫn còn trong sổ.", confirmLabel: "Xoá", cancelLabel: "Huỷ", closeLabel: "Đóng", tone: "critical" }).then(function (ok) { gembossUI.toast(ok ? "Đã xoá" : "Đã huỷ"); });
|
|
876
941
|
else {
|
|
877
942
|
var m = gembossUI.openModal({ title: "Xoá phiên này?", closeLabel: "Đóng", body: '<div class="ui-modal__body">Lịch sử vẫn còn trong sổ; phiên chỉ ẩn khỏi danh sách.</div>',
|
|
878
943
|
foot: '<button type="button" class="ui-btn ui-btn--ghost" data-v="0">Huỷ</button><button type="button" class="ui-btn ui-btn--primary" data-v="1" autofocus>Xoá</button>',
|