@gemboss/ui 0.4.1 → 0.5.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 +83 -8
- package/catalog/index.html +73 -8
- package/gemboss-ui.css +254 -36
- package/package.json +6 -3
- package/src/app-shell.css +11 -0
- package/src/assistant.css +36 -0
- package/src/chat-composer.css +1 -1
- package/src/chat.css +9 -4
- package/src/gemboss-field.css +2 -2
- package/src/gemboss-tokens.css +1 -1
- package/src/icon.svg +1 -0
- package/src/icons.tsx +2 -0
- package/src/index.ts +1 -0
- package/src/kit-plain.css +163 -4
- package/src/kit-plain.js +102 -1
- package/src/launcher.tsx +33 -0
- package/src/ui.css +29 -22
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,62 @@ 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
|
+
If your surface still sets any of these itself (a `body { font-size }`, a `min-height: 44px` on `.ui-btn--sm`, a
|
|
225
|
+
`.danger` button, a `confirm()`), delete it on the upgrade: the package draws it now, and a surface rule wins the
|
|
226
|
+
cascade over the package's zero-specificity base. `packages/ui/src/kit-look.test.ts` measures the table above in
|
|
227
|
+
Chromium on the built CSS.
|
|
228
|
+
|
|
175
229
|
## Resizable panels
|
|
176
230
|
|
|
177
231
|
`ui-resizer` is the seam a person drags between two panels; `ui-resizing` on `<body>` is the drag in
|
|
@@ -202,6 +256,25 @@ The surface owns where the seam sits and what it does. Five rules, each paid for
|
|
|
202
256
|
React surfaces: `useResizableChatPanel` in the admin is the reference. Others write the same markup and
|
|
203
257
|
the five rules by hand; the catalog's "Thanh kéo giữa hai cột" shows the markup.
|
|
204
258
|
|
|
259
|
+
## The assistant launcher (0.4.2)
|
|
260
|
+
|
|
261
|
+
The top-right corner of the topbar is the ACCOUNT (`AccountMenu`). The button that opens a surface's AI assistant floats
|
|
262
|
+
bottom-right instead (Chris, 02/10/2026): partner-radar had it top-right, and on a phone it became a ✦ circle exactly where
|
|
263
|
+
content-radar shows the account chip.
|
|
264
|
+
|
|
265
|
+
```tsx
|
|
266
|
+
import { AssistantLauncher } from "@gemboss/ui";
|
|
267
|
+
|
|
268
|
+
<AssistantLauncher label="Partner Assistant" shortcut="⌘J"
|
|
269
|
+
hidden={dock.presentation !== "hidden"} onClick={() => dock.reopen()} />
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
- No provider and no state: pass `hidden` while your assistant is open (it would sit under the dock).
|
|
273
|
+
- 44px floor everywhere; label + shortcut on wide screens, the `sparkle` icon alone at ≤760px (the label stays the
|
|
274
|
+
accessible name). Safe-area insets keep it off the iPhone home indicator. z-index 280: under the dock and the topbar,
|
|
275
|
+
over page content.
|
|
276
|
+
- The shortcut is a hint only: the surface owns the key binding.
|
|
277
|
+
|
|
205
278
|
## The topbar kit: lockup, account, icons
|
|
206
279
|
|
|
207
280
|
What goes INTO the frame, so a surface does not draw its own (28/09/2026: GemFactory's rail icons came
|
|
@@ -227,7 +300,7 @@ import { AppShell, BrandLockup, AccountMenu, AccountMenuItem, Icon, RailItem } f
|
|
|
227
300
|
- `AccountMenu`: the admin's 32px initials chip and popover (same CSS). A `<details>`, so it opens
|
|
228
301
|
without JavaScript on a page that never hydrates; with React it also closes on an outside click and
|
|
229
302
|
on Escape. `AccountMenuItem` is a link (`href`), a POST form (`formAction`), or a button.
|
|
230
|
-
- `Icon`: the GemBoss set,
|
|
303
|
+
- `Icon`: the GemBoss set, 39 icons on a 20px grid with 1.5px strokes, drawn to sit next to Polaris.
|
|
231
304
|
`ICON_NAMES` lists them. Internal tools cannot use `@shopify/polaris-icons`: its licence only covers
|
|
232
305
|
applications that integrate with Shopify. Draw a missing one HERE, not in the surface: every rail
|
|
233
306
|
icon must keep `fill="none"` on its inner `<g>`, because `.gnav-ico svg { fill: currentColor }`
|
|
@@ -240,7 +313,7 @@ import { AppShell, BrandLockup, AccountMenu, AccountMenuItem, Icon, RailItem } f
|
|
|
240
313
|
|
|
241
314
|
## Report pages (0.4.0)
|
|
242
315
|
|
|
243
|
-
Plain CSS in `kit-plain.css` for a numbers page written by hand (first user: gemnews `/admin`, 03/10/2026). The
|
|
316
|
+
Plain CSS in `kit-plain.css` for a numbers page written by hand (first user: gemnews `/admin`, 03/10/2026; that page moved to GemCommunity the same day, so gemnews no longer takes the package). The
|
|
244
317
|
surface computes every number and ratio; the kit only draws. Markup for each is in the catalog's "Báo cáo" section.
|
|
245
318
|
|
|
246
319
|
- `ui-metrics--grid` + `ui-metric--lg` + `ui-metric__foot`: KPI tiles in an even grid (never 3 + 1 orphan), label on
|
|
@@ -288,7 +361,7 @@ the slots and props (`brand`, `center`, `actions`, rail items, icons, headings).
|
|
|
288
361
|
|
|
289
362
|
The base font is one of those tokens. `gemboss-ui.css` sets `html`, `body` and `button` in
|
|
290
363
|
`--gemboss-font-sans`, the admin's own body stack (Polaris `--p-font-family-sans`: Inter, then the
|
|
291
|
-
system UI font). The rule sits at zero specificity (`:where()`), so a surface re-themes with
|
|
364
|
+
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
|
|
292
365
|
`:root { --gemboss-font-sans: … }` and needs no `body { font-family }` patch. A surface that loads
|
|
293
366
|
its own web font does it itself; the package loads none.
|
|
294
367
|
|
|
@@ -300,10 +373,12 @@ something the base cannot express, add a token or a prop here, and every surface
|
|
|
300
373
|
|
|
301
374
|
| Path | What |
|
|
302
375
|
|---|---|
|
|
303
|
-
| `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` + `
|
|
376
|
+
| `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`) |
|
|
304
377
|
| `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). |
|
|
305
378
|
| `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. |
|
|
306
|
-
| `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"
|
|
379
|
+
| `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. |
|
|
380
|
+
| `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. |
|
|
381
|
+
| `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). |
|
|
307
382
|
| `packages/ui/src/**/*.tsx` | the components, as TypeScript source. Next: add `@gemboss/ui` to `transpilePackages`. Vite compiles it as is. |
|
|
308
383
|
|
|
309
384
|
`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.5.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>5a8d401f4c0a</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>
|
|
@@ -737,7 +801,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
|
|
|
737
801
|
<button type="submit" aria-label="Gửi">↑</button>
|
|
738
802
|
</form>
|
|
739
803
|
</div></code></pre></details></figure></section>
|
|
740
|
-
<section id="assistant"><h2>Trợ lý: cột phiên</h2><p><code>SessionRail</code> (React). Khung toàn màn hình / cửa sổ nổi / cột phải cao hết màn (<code>allowSide</code>) / thanh là <code>AssistantHost</code>, cần React vì có trạng thái.</p><figure class="cat-demo"><figcaption>SessionRail</figcaption><div class="cat-live"><div style="height:360px;display:flex"><aside class="gemboss-assistant-rail"><div class="gemboss-assistant-rail-top"><button type="button" class="gemboss-assistant-newchat" title="Phiên mới"><svg viewBox="0 0 20 20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H5.5A1.5 1.5 0 0 0 4 5.5v9A1.5 1.5 0 0 0 5.5 16h9a1.5 1.5 0 0 0 1.5-1.5V9"></path><path d="M14.5 3.5l2 2L10 12H8v-2z"></path></g></svg><span>Phiên mới</span></button><button type="button" class="gemboss-assistant-collapse" aria-label="Collapse sidebar" title="Collapse"><svg viewBox="0 0 20 20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5l-5 5 5 5"></path></g></svg></button></div><div class="gemboss-assistant-search gemboss-field gemboss-field--group"><svg viewBox="0 0 20 20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="9" r="5"></circle><path d="M13 13l3.5 3.5"></path></g></svg><input class="gemboss-field__bare" placeholder="Tìm phiên…" aria-label="Search history" value=""/><kbd class="gemboss-assistant-kbd">/</kbd></div><div class="gemboss-assistant-threads"><div class="gemboss-assistant-group"><div class="gemboss-assistant-group-label">Đã ghim</div><div class="gemboss-assistant-thread"><button type="button" class="gemboss-assistant-thread-main" title="So sánh advertorial với listicle"><span class="gemboss-assistant-thread-titlerow"><svg viewBox="0 0 20 20" class="gemboss-assistant-pin-dot" aria-hidden="true" focusable="false"><path d="M8 3.5h4l-.5 5 2.5 2.5H6l2.5-2.5z" fill="currentColor"></path><path d="M10 11v5.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"></path></svg><span class="gemboss-assistant-thread-title">So sánh advertorial với listicle</span></span><span class="gemboss-assistant-thread-meta">
|
|
804
|
+
<section id="assistant"><h2>Trợ lý: cột phiên</h2><p><code>SessionRail</code> (React). Khung toàn màn hình / cửa sổ nổi / cột phải cao hết màn (<code>allowSide</code>) / thanh là <code>AssistantHost</code>, cần React vì có trạng thái.</p><figure class="cat-demo"><figcaption>SessionRail</figcaption><div class="cat-live"><div style="height:360px;display:flex"><aside class="gemboss-assistant-rail"><div class="gemboss-assistant-rail-top"><button type="button" class="gemboss-assistant-newchat" title="Phiên mới"><svg viewBox="0 0 20 20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H5.5A1.5 1.5 0 0 0 4 5.5v9A1.5 1.5 0 0 0 5.5 16h9a1.5 1.5 0 0 0 1.5-1.5V9"></path><path d="M14.5 3.5l2 2L10 12H8v-2z"></path></g></svg><span>Phiên mới</span></button><button type="button" class="gemboss-assistant-collapse" aria-label="Collapse sidebar" title="Collapse"><svg viewBox="0 0 20 20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5l-5 5 5 5"></path></g></svg></button></div><div class="gemboss-assistant-search gemboss-field gemboss-field--group"><svg viewBox="0 0 20 20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="9" r="5"></circle><path d="M13 13l3.5 3.5"></path></g></svg><input class="gemboss-field__bare" placeholder="Tìm phiên…" aria-label="Search history" value=""/><kbd class="gemboss-assistant-kbd">/</kbd></div><div class="gemboss-assistant-threads"><div class="gemboss-assistant-group"><div class="gemboss-assistant-group-label">Đã ghim</div><div class="gemboss-assistant-thread"><button type="button" class="gemboss-assistant-thread-main" title="So sánh advertorial với listicle"><span class="gemboss-assistant-thread-titlerow"><svg viewBox="0 0 20 20" class="gemboss-assistant-pin-dot" aria-hidden="true" focusable="false"><path d="M8 3.5h4l-.5 5 2.5 2.5H6l2.5-2.5z" fill="currentColor"></path><path d="M10 11v5.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"></path></svg><span class="gemboss-assistant-thread-title">So sánh advertorial với listicle</span></span><span class="gemboss-assistant-thread-meta">24/8/2026</span></button><div class="gemboss-assistant-thread-actions"><button type="button" class="gemboss-assistant-thread-act" aria-label="Options"><svg viewBox="0 0 20 20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><circle cx="5" cy="10" r=".8"></circle><circle cx="10" cy="10" r=".8"></circle><circle cx="15" cy="10" r=".8"></circle></g></svg></button></div></div></div><div class="gemboss-assistant-group"><div class="gemboss-assistant-group-label">Hôm nay</div><div class="gemboss-assistant-thread active"><button type="button" class="gemboss-assistant-thread-main" title="Store nào đang dựng loạt landing?"><span class="gemboss-assistant-thread-titlerow"><span class="gemboss-assistant-thread-title">Store nào đang dựng loạt landing?</span></span><span class="gemboss-assistant-thread-meta">3 giờ trước</span></button><div class="gemboss-assistant-thread-actions"><button type="button" class="gemboss-assistant-thread-act" aria-label="Options"><svg viewBox="0 0 20 20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><circle cx="5" cy="10" r=".8"></circle><circle cx="10" cy="10" r=".8"></circle><circle cx="15" cy="10" r=".8"></circle></g></svg></button></div></div></div><div class="gemboss-assistant-group"><div class="gemboss-assistant-group-label">Hôm qua</div><div class="gemboss-assistant-thread"><button type="button" class="gemboss-assistant-thread-main" title="Landing điểm cao nhất của corpus"><span class="gemboss-assistant-thread-titlerow"><span class="gemboss-assistant-thread-title">Landing điểm cao nhất của corpus</span></span><span class="gemboss-assistant-thread-meta">1 ngày trước</span></button><div class="gemboss-assistant-thread-actions"><button type="button" class="gemboss-assistant-thread-act" aria-label="Options"><svg viewBox="0 0 20 20" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><circle cx="5" cy="10" r=".8"></circle><circle cx="10" cy="10" r=".8"></circle><circle cx="15" cy="10" r=".8"></circle></g></svg></button></div></div></div></div></aside></div></div><details class="cat-code"><summary>Markup</summary><pre><code><div style="height:360px;display:flex">
|
|
741
805
|
<aside class="gemboss-assistant-rail">
|
|
742
806
|
<div class="gemboss-assistant-rail-top">
|
|
743
807
|
<button type="button" class="gemboss-assistant-newchat" title="Phiên mới">
|
|
@@ -786,7 +850,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
|
|
|
786
850
|
</svg>
|
|
787
851
|
<span class="gemboss-assistant-thread-title">So sánh advertorial với listicle</span>
|
|
788
852
|
</span>
|
|
789
|
-
<span class="gemboss-assistant-thread-meta">
|
|
853
|
+
<span class="gemboss-assistant-thread-meta">24/8/2026</span>
|
|
790
854
|
</button>
|
|
791
855
|
<div class="gemboss-assistant-thread-actions">
|
|
792
856
|
<button type="button" class="gemboss-assistant-thread-act" aria-label="Options">
|
|
@@ -857,7 +921,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
|
|
|
857
921
|
</div>
|
|
858
922
|
</aside>
|
|
859
923
|
</div></code></pre></details></figure></section>
|
|
860
|
-
<section id="icons"><h2>Icon</h2><p>Bộ icon GemBoss: 40 icon, lưới 20px, nét 1.5. <code>fill="none"</code> nằm trên <code><g></code>, không trên <code><svg></code>.</p><div class="cat-icons"><div class="gnav-ico cat-icon" title="home"><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.5 9 10 3.5 16.5 9"></path><path d="M5 7.8v8.7h10V7.8"></path><path d="M8.5 16.5v-4h3v4"></path></g></svg><code>home</code></div><div class="gnav-ico cat-icon" title="dashboard"><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" width="6" height="6" rx="1.3"></rect><rect x="11" y="3" width="6" height="6" rx="1.3"></rect><rect x="3" y="11" width="6" height="6" rx="1.3"></rect><rect x="11" y="11" width="6" height="6" rx="1.3"></rect></g></svg><code>dashboard</code></div><div class="gnav-ico cat-icon" title="board"><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><code>board</code></div><div class="gnav-ico cat-icon" title="layout"><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><code>layout</code></div><div class="gnav-ico cat-icon" title="layers"><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 17 6.8 10 10.6 3 6.8z"></path><path d="M3 10.1l7 3.8 7-3.8"></path><path d="M3 13.4l7 3.8 7-3.8"></path></g></svg><code>layers</code></div><div class="gnav-ico cat-icon" title="document"><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 2.8h6.8l3.2 3.2v11.2H5z"></path><path d="M11.8 2.8V6H15M7.5 10h5M7.5 13h5"></path></g></svg><code>document</code></div><div class="gnav-ico cat-icon" title="article"><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="14" height="13" rx="1.5"></rect><path d="M6 7h8M6 10h8M6 13h5"></path></g></svg><code>article</code></div><div class="gnav-ico cat-icon" title="page"><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="2.5" y="3.5" width="15" height="13" rx="2"></rect><path d="M2.5 7.5h15M6 11h8M6 13.5h5"></path></g></svg><code>page</code></div><div class="gnav-ico cat-icon" title="image"><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="14" height="13" rx="1.8"></rect><circle cx="7.3" cy="7.8" r="1.3"></circle><path d="M3.5 15l4.2-4.2 3 3 2.2-2.2 3.6 3.6"></path></g></svg><code>image</code></div><div class="gnav-ico cat-icon" title="folder"><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="M2.8 5.3c0-.8.6-1.3 1.3-1.3h3.4l1.8 2h6.6c.8 0 1.3.6 1.3 1.3v7.7c0 .8-.6 1.3-1.3 1.3H4.1c-.8 0-1.3-.6-1.3-1.3z"></path></g></svg><code>folder</code></div><div class="gnav-ico cat-icon" title="list"><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="M8 5h9M8 10h9M8 15h9"></path><circle cx="4" cy="5" r=".9"></circle><circle cx="4" cy="10" r=".9"></circle><circle cx="4" cy="15" r=".9"></circle></g></svg><code>list</code></div><div class="gnav-ico cat-icon" title="activity"><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="M2.5 10h3l2-5 3 10 2-5h5"></path></g></svg><code>activity</code></div><div class="gnav-ico cat-icon" title="chart"><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 16.5h14"></path><rect x="4.5" y="9" width="2.8" height="5.5" rx=".7"></rect><rect x="8.6" y="5" width="2.8" height="9.5" rx=".7"></rect><rect x="12.7" y="11" width="2.8" height="3.5" rx=".7"></rect></g></svg><code>chart</code></div><div class="gnav-ico cat-icon" title="radar"><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="10" cy="10" r="7"></circle><circle cx="10" cy="10" r="3.5"></circle><path d="M10 10l5-5"></path></g></svg><code>radar</code></div><div class="gnav-ico cat-icon" title="map"><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" width="14" height="14" rx="2"></rect><path d="M3 7.7h14M3 12.3h14M7.7 3v14M12.3 3v14"></path></g></svg><code>map</code></div><div class="gnav-ico cat-icon" title="globe"><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="10" cy="10" r="7"></circle><path d="M3 10h14M10 3c2 2 2.8 4.3 2.8 7s-.8 5-2.8 7c-2-2-2.8-4.3-2.8-7s.8-5 2.8-7z"></path></g></svg><code>globe</code></div><div class="gnav-ico cat-icon" title="megaphone"><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 8v4h3l6 4V4L6 8H3z"></path><path d="M15 7.5a3.5 3.5 0 0 1 0 5"></path></g></svg><code>megaphone</code></div><div class="gnav-ico cat-icon" title="star"><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 2.8l2.2 4.5 5 .7-3.6 3.5.9 5-4.5-2.4-4.5 2.4.9-5L2.8 8l5-.7z"></path></g></svg><code>star</code></div><div class="gnav-ico cat-icon" title="eye"><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="M1.8 10S4.7 4.8 10 4.8 18.2 10 18.2 10 15.3 15.2 10 15.2 1.8 10 1.8 10z"></path><circle cx="10" cy="10" r="2.5"></circle></g></svg><code>eye</code></div><div class="gnav-ico cat-icon" title="inbox"><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 11l2-7h10l2 7v5H3z"></path><path d="M3 11h4l1 2h4l1-2h4"></path></g></svg><code>inbox</code></div><div class="gnav-ico cat-icon" title="bell"><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 13.5V9a5 5 0 0 1 10 0v4.5l1.3 1.5H3.7z"></path><path d="M8.3 17.2a1.9 1.9 0 0 0 3.4 0"></path></g></svg><code>bell</code></div><div class="gnav-ico cat-icon" title="chat"><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><code>chat</code></div><div class="gnav-ico cat-icon" title="money"><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="10" cy="10" r="7"></circle><path d="M12 7.6c-.5-.7-1.2-1-2-1-1.1 0-2 .7-2 1.6 0 2.1 4 1.2 4 3.4 0 .9-.9 1.6-2 1.6-.8 0-1.6-.3-2.1-1M10 5v1.6M10 13.2V15"></path></g></svg><code>money</code></div><div class="gnav-ico cat-icon" title="store"><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.2 7.5 4.5 3.5h11l1.3 4"></path><path d="M3.2 7.5c0 1.3 1 2.2 2.3 2.2s2.2-1 2.2-2.2c0 1.3 1 2.2 2.3 2.2s2.3-1 2.3-2.2c0 1.3.9 2.2 2.2 2.2s2.3-.9 2.3-2.2"></path><path d="M4.5 9.5v7h11v-7M8.5 16.5v-3.5h3v3.5"></path></g></svg><code>store</code></div><div class="gnav-ico cat-icon" title="user"><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="10" cy="7" r="3.2"></circle><path d="M3.8 16.5c.8-2.8 3.3-4.5 6.2-4.5s5.4 1.7 6.2 4.5"></path></g></svg><code>user</code></div><div class="gnav-ico cat-icon" title="users"><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="7.5" cy="7.3" r="2.8"></circle><path d="M2.5 16.3c.6-2.5 2.5-4 5-4s4.4 1.5 5 4"></path><path d="M12.3 4.8a2.8 2.8 0 0 1 0 5.2M14.3 12.5c1.6.4 2.7 1.7 3.2 3.8"></path></g></svg><code>users</code></div><div class="gnav-ico cat-icon" title="calendar"><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="4.5" width="14" height="12.5" rx="1.8"></rect><path d="M3 8.5h14M7 3v3M13 3v3"></path></g></svg><code>calendar</code></div><div class="gnav-ico cat-icon" title="clock"><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="10" cy="10" r="7"></circle><path d="M10 6v4l2.8 1.8"></path></g></svg><code>clock</code></div><div class="gnav-ico cat-icon" title="search"><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><code>search</code></div><div class="gnav-ico cat-icon" title="link"><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="M8.6 11.4a3 3 0 0 0 4.2 0l2.6-2.6a3 3 0 0 0-4.2-4.2l-1 1"></path><path d="M11.4 8.6a3 3 0 0 0-4.2 0l-2.6 2.6a3 3 0 0 0 4.2 4.2l1-1"></path></g></svg><code>link</code></div><div class="gnav-ico cat-icon" title="sliders"><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 5h14M3 10h14M3 15h14"></path><circle cx="7" cy="5" r="1.6"></circle><circle cx="13" cy="10" r="1.6"></circle><circle cx="9" cy="15" r="1.6"></circle></g></svg><code>sliders</code></div><div class="gnav-ico cat-icon" title="settings"><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="M15.52 9.08 17.15 9.15 17.15 10.85 15.52 10.92 14.56 13.26 15.66 14.45 14.45 15.66 13.26 14.56 10.92 15.52 10.85 17.15 9.15 17.15 9.08 15.52 6.74 14.56 5.55 15.66 4.34 14.45 5.44 13.26 4.48 10.92 2.85 10.85 2.85 9.15 4.48 9.08 5.44 6.74 4.34 5.55 5.55 4.34 6.74 5.44 9.08 4.48 9.15 2.85 10.85 2.85 10.92 4.48 13.26 5.44 14.45 4.34 15.66 5.55 14.56 6.74Z"></path><circle cx="10" cy="10" r="2.4"></circle></g></svg><code>settings</code></div><div class="gnav-ico cat-icon" title="alert"><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><code>alert</code></div><div class="gnav-ico cat-icon" title="info"><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="10" cy="10" r="7"></circle><path d="M10 9v4.5M10 6.4v.1"></path></g></svg><code>info</code></div><div class="gnav-ico cat-icon" title="check"><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="M4 10.5 8 14.5 16 5.5"></path></g></svg><code>check</code></div><div class="gnav-ico cat-icon" title="plus"><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 4v12M4 10h12"></path></g></svg><code>plus</code></div><div class="gnav-ico cat-icon" title="close"><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><code>close</code></div><div class="gnav-ico cat-icon" title="more"><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="4.5" cy="10" r="1"></circle><circle cx="10" cy="10" r="1"></circle><circle cx="15.5" cy="10" r="1"></circle></g></svg><code>more</code></div><div class="gnav-ico cat-icon" title="utensils"><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="M6 3v5a2 2 0 0 0 4 0V3M8 3v14"></path><path d="M15 3c-1.6 1.4-2.5 3.6-2.5 6.5H15V17"></path></g></svg><code>utensils</code></div><div class="gnav-ico cat-icon" title="signOut"><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="M8 3.5H4v13h4M12.5 6.5 16 10l-3.5 3.5M16 10H8"></path></g></svg><code>signOut</code></div></div><figure class="cat-demo"><figcaption>Một icon (markup)</figcaption><div class="cat-live"><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></div><details class="cat-code"><summary>Markup</summary><pre><code><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false">
|
|
924
|
+
<section id="icons"><h2>Icon</h2><p>Bộ icon GemBoss: 41 icon, lưới 20px, nét 1.5. <code>fill="none"</code> nằm trên <code><g></code>, không trên <code><svg></code>.</p><div class="cat-icons"><div class="gnav-ico cat-icon" title="home"><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.5 9 10 3.5 16.5 9"></path><path d="M5 7.8v8.7h10V7.8"></path><path d="M8.5 16.5v-4h3v4"></path></g></svg><code>home</code></div><div class="gnav-ico cat-icon" title="dashboard"><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" width="6" height="6" rx="1.3"></rect><rect x="11" y="3" width="6" height="6" rx="1.3"></rect><rect x="3" y="11" width="6" height="6" rx="1.3"></rect><rect x="11" y="11" width="6" height="6" rx="1.3"></rect></g></svg><code>dashboard</code></div><div class="gnav-ico cat-icon" title="board"><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><code>board</code></div><div class="gnav-ico cat-icon" title="layout"><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><code>layout</code></div><div class="gnav-ico cat-icon" title="layers"><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 17 6.8 10 10.6 3 6.8z"></path><path d="M3 10.1l7 3.8 7-3.8"></path><path d="M3 13.4l7 3.8 7-3.8"></path></g></svg><code>layers</code></div><div class="gnav-ico cat-icon" title="document"><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 2.8h6.8l3.2 3.2v11.2H5z"></path><path d="M11.8 2.8V6H15M7.5 10h5M7.5 13h5"></path></g></svg><code>document</code></div><div class="gnav-ico cat-icon" title="article"><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="14" height="13" rx="1.5"></rect><path d="M6 7h8M6 10h8M6 13h5"></path></g></svg><code>article</code></div><div class="gnav-ico cat-icon" title="page"><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="2.5" y="3.5" width="15" height="13" rx="2"></rect><path d="M2.5 7.5h15M6 11h8M6 13.5h5"></path></g></svg><code>page</code></div><div class="gnav-ico cat-icon" title="image"><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="14" height="13" rx="1.8"></rect><circle cx="7.3" cy="7.8" r="1.3"></circle><path d="M3.5 15l4.2-4.2 3 3 2.2-2.2 3.6 3.6"></path></g></svg><code>image</code></div><div class="gnav-ico cat-icon" title="folder"><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="M2.8 5.3c0-.8.6-1.3 1.3-1.3h3.4l1.8 2h6.6c.8 0 1.3.6 1.3 1.3v7.7c0 .8-.6 1.3-1.3 1.3H4.1c-.8 0-1.3-.6-1.3-1.3z"></path></g></svg><code>folder</code></div><div class="gnav-ico cat-icon" title="list"><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="M8 5h9M8 10h9M8 15h9"></path><circle cx="4" cy="5" r=".9"></circle><circle cx="4" cy="10" r=".9"></circle><circle cx="4" cy="15" r=".9"></circle></g></svg><code>list</code></div><div class="gnav-ico cat-icon" title="activity"><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="M2.5 10h3l2-5 3 10 2-5h5"></path></g></svg><code>activity</code></div><div class="gnav-ico cat-icon" title="chart"><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 16.5h14"></path><rect x="4.5" y="9" width="2.8" height="5.5" rx=".7"></rect><rect x="8.6" y="5" width="2.8" height="9.5" rx=".7"></rect><rect x="12.7" y="11" width="2.8" height="3.5" rx=".7"></rect></g></svg><code>chart</code></div><div class="gnav-ico cat-icon" title="radar"><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="10" cy="10" r="7"></circle><circle cx="10" cy="10" r="3.5"></circle><path d="M10 10l5-5"></path></g></svg><code>radar</code></div><div class="gnav-ico cat-icon" title="map"><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" width="14" height="14" rx="2"></rect><path d="M3 7.7h14M3 12.3h14M7.7 3v14M12.3 3v14"></path></g></svg><code>map</code></div><div class="gnav-ico cat-icon" title="globe"><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="10" cy="10" r="7"></circle><path d="M3 10h14M10 3c2 2 2.8 4.3 2.8 7s-.8 5-2.8 7c-2-2-2.8-4.3-2.8-7s.8-5 2.8-7z"></path></g></svg><code>globe</code></div><div class="gnav-ico cat-icon" title="megaphone"><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 8v4h3l6 4V4L6 8H3z"></path><path d="M15 7.5a3.5 3.5 0 0 1 0 5"></path></g></svg><code>megaphone</code></div><div class="gnav-ico cat-icon" title="star"><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 2.8l2.2 4.5 5 .7-3.6 3.5.9 5-4.5-2.4-4.5 2.4.9-5L2.8 8l5-.7z"></path></g></svg><code>star</code></div><div class="gnav-ico cat-icon" title="eye"><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="M1.8 10S4.7 4.8 10 4.8 18.2 10 18.2 10 15.3 15.2 10 15.2 1.8 10 1.8 10z"></path><circle cx="10" cy="10" r="2.5"></circle></g></svg><code>eye</code></div><div class="gnav-ico cat-icon" title="inbox"><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 11l2-7h10l2 7v5H3z"></path><path d="M3 11h4l1 2h4l1-2h4"></path></g></svg><code>inbox</code></div><div class="gnav-ico cat-icon" title="bell"><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 13.5V9a5 5 0 0 1 10 0v4.5l1.3 1.5H3.7z"></path><path d="M8.3 17.2a1.9 1.9 0 0 0 3.4 0"></path></g></svg><code>bell</code></div><div class="gnav-ico cat-icon" title="chat"><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><code>chat</code></div><div class="gnav-ico cat-icon" title="money"><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="10" cy="10" r="7"></circle><path d="M12 7.6c-.5-.7-1.2-1-2-1-1.1 0-2 .7-2 1.6 0 2.1 4 1.2 4 3.4 0 .9-.9 1.6-2 1.6-.8 0-1.6-.3-2.1-1M10 5v1.6M10 13.2V15"></path></g></svg><code>money</code></div><div class="gnav-ico cat-icon" title="store"><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.2 7.5 4.5 3.5h11l1.3 4"></path><path d="M3.2 7.5c0 1.3 1 2.2 2.3 2.2s2.2-1 2.2-2.2c0 1.3 1 2.2 2.3 2.2s2.3-1 2.3-2.2c0 1.3.9 2.2 2.2 2.2s2.3-.9 2.3-2.2"></path><path d="M4.5 9.5v7h11v-7M8.5 16.5v-3.5h3v3.5"></path></g></svg><code>store</code></div><div class="gnav-ico cat-icon" title="user"><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="10" cy="7" r="3.2"></circle><path d="M3.8 16.5c.8-2.8 3.3-4.5 6.2-4.5s5.4 1.7 6.2 4.5"></path></g></svg><code>user</code></div><div class="gnav-ico cat-icon" title="users"><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="7.5" cy="7.3" r="2.8"></circle><path d="M2.5 16.3c.6-2.5 2.5-4 5-4s4.4 1.5 5 4"></path><path d="M12.3 4.8a2.8 2.8 0 0 1 0 5.2M14.3 12.5c1.6.4 2.7 1.7 3.2 3.8"></path></g></svg><code>users</code></div><div class="gnav-ico cat-icon" title="calendar"><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="4.5" width="14" height="12.5" rx="1.8"></rect><path d="M3 8.5h14M7 3v3M13 3v3"></path></g></svg><code>calendar</code></div><div class="gnav-ico cat-icon" title="clock"><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="10" cy="10" r="7"></circle><path d="M10 6v4l2.8 1.8"></path></g></svg><code>clock</code></div><div class="gnav-ico cat-icon" title="search"><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><code>search</code></div><div class="gnav-ico cat-icon" title="link"><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="M8.6 11.4a3 3 0 0 0 4.2 0l2.6-2.6a3 3 0 0 0-4.2-4.2l-1 1"></path><path d="M11.4 8.6a3 3 0 0 0-4.2 0l-2.6 2.6a3 3 0 0 0 4.2 4.2l1-1"></path></g></svg><code>link</code></div><div class="gnav-ico cat-icon" title="sliders"><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 5h14M3 10h14M3 15h14"></path><circle cx="7" cy="5" r="1.6"></circle><circle cx="13" cy="10" r="1.6"></circle><circle cx="9" cy="15" r="1.6"></circle></g></svg><code>sliders</code></div><div class="gnav-ico cat-icon" title="settings"><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="M15.52 9.08 17.15 9.15 17.15 10.85 15.52 10.92 14.56 13.26 15.66 14.45 14.45 15.66 13.26 14.56 10.92 15.52 10.85 17.15 9.15 17.15 9.08 15.52 6.74 14.56 5.55 15.66 4.34 14.45 5.44 13.26 4.48 10.92 2.85 10.85 2.85 9.15 4.48 9.08 5.44 6.74 4.34 5.55 5.55 4.34 6.74 5.44 9.08 4.48 9.15 2.85 10.85 2.85 10.92 4.48 13.26 5.44 14.45 4.34 15.66 5.55 14.56 6.74Z"></path><circle cx="10" cy="10" r="2.4"></circle></g></svg><code>settings</code></div><div class="gnav-ico cat-icon" title="alert"><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><code>alert</code></div><div class="gnav-ico cat-icon" title="info"><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="10" cy="10" r="7"></circle><path d="M10 9v4.5M10 6.4v.1"></path></g></svg><code>info</code></div><div class="gnav-ico cat-icon" title="check"><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="M4 10.5 8 14.5 16 5.5"></path></g></svg><code>check</code></div><div class="gnav-ico cat-icon" title="plus"><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 4v12M4 10h12"></path></g></svg><code>plus</code></div><div class="gnav-ico cat-icon" title="close"><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><code>close</code></div><div class="gnav-ico cat-icon" title="more"><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="4.5" cy="10" r="1"></circle><circle cx="10" cy="10" r="1"></circle><circle cx="15.5" cy="10" r="1"></circle></g></svg><code>more</code></div><div class="gnav-ico cat-icon" title="utensils"><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="M6 3v5a2 2 0 0 0 4 0V3M8 3v14"></path><path d="M15 3c-1.6 1.4-2.5 3.6-2.5 6.5H15V17"></path></g></svg><code>utensils</code></div><div class="gnav-ico cat-icon" title="signOut"><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="M8 3.5H4v13h4M12.5 6.5 16 10l-3.5 3.5M16 10H8"></path></g></svg><code>signOut</code></div><div class="gnav-ico cat-icon" title="sparkle"><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="M9 3.5c.4 2.9 1.6 4.1 4.5 4.5-2.9.4-4.1 1.6-4.5 4.5-.4-2.9-1.6-4.1-4.5-4.5 2.9-.4 4.1-1.6 4.5-4.5z"></path><path d="M14.5 12.5c.2 1.3.7 1.8 2 2-1.3.2-1.8.7-2 2-.2-1.3-.7-1.8-2-2 1.3-.2 1.8-.7 2-2z"></path></g></svg><code>sparkle</code></div></div><figure class="cat-demo"><figcaption>Một icon (markup)</figcaption><div class="cat-live"><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></div><details class="cat-code"><summary>Markup</summary><pre><code><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" focusable="false">
|
|
861
925
|
<g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
862
926
|
<rect x="3" y="3.5" width="4" height="13" rx="1.2">
|
|
863
927
|
</rect>
|
|
@@ -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>',
|