@guildofgleks/ui 21.6.1 → 21.7.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/AGENTS.md +135 -55
- package/CHANGELOG.md +159 -0
- package/README.md +71 -15
- package/TOKENS.md +7 -7
- package/fesm2022/guildofgleks-ui.mjs +174 -1312
- package/fesm2022/guildofgleks-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/styles/button.css +11 -32
- package/styles/presets/bevel.css +82 -0
- package/styles/presets/ledger.css +66 -0
- package/styles/presets/material.css +111 -0
- package/styles/presets/one-dark.css +22 -5
- package/styles/presets/one-light.css +17 -4
- package/styles/presets/parchment.css +63 -0
- package/styles/presets/parchment.fonts.css +29 -0
- package/styles/presets/primeng.css +121 -0
- package/styles/presets/slate.css +26 -8
- package/styles/presets/terminal.css +67 -0
- package/styles/presets/terminal.fonts.css +26 -0
- package/styles/theme.css +510 -538
- package/types/guildofgleks-ui.d.ts +35 -26
package/AGENTS.md
CHANGED
|
@@ -5,12 +5,13 @@ an app that **consumes** the published `@guildofgleks/ui` npm package. It is not
|
|
|
5
5
|
authoring the library — if you are working inside the `gleks_web_ui` monorepo itself, read
|
|
6
6
|
`.github/instructions/*.md` instead.
|
|
7
7
|
|
|
8
|
-
Everything below reflects the library's actual source as of **`21.
|
|
9
|
-
of deprecated API — see **Removed in 21.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
types and
|
|
8
|
+
Everything below reflects the library's actual source as of **`21.7.0`**. 21.7.0 removed the three
|
|
9
|
+
abbreviated token prefixes and 21.5.0 removed a batch of deprecated API — see **Removed in 21.7.0**
|
|
10
|
+
and **Removed in 21.5.0** near the end of this file, which exist so code written against an older
|
|
11
|
+
version can be migrated — and `CHANGELOG.md` has the rest. `README.md` covers the same ground at a
|
|
12
|
+
higher level — install, setup, theming, global configuration — and is accurate; this file goes
|
|
13
|
+
further, into per-component input tables, and is the one to trust for exact names, types and
|
|
14
|
+
defaults.
|
|
14
15
|
|
|
15
16
|
> **Maintainers:** this file ships inside the npm package and is the API reference an agent reads
|
|
16
17
|
> while writing code against it, so a stale table here becomes wrong code in someone else's app —
|
|
@@ -166,30 +167,66 @@ exist.
|
|
|
166
167
|
|
|
167
168
|
## Theming
|
|
168
169
|
|
|
169
|
-
Full model is in `README.md`'s Theming section
|
|
170
|
+
Full model is in `README.md`'s Theming section; short version:
|
|
170
171
|
|
|
171
172
|
- Every visual value (color, spacing, radius, shadow, duration) is a `--gog-*` CSS custom
|
|
172
173
|
property, layered **foundation** (`--gog-accent-color`, `--gog-space-md`, …, restyles
|
|
173
174
|
everything) → **component** (`--gog-button-primary-bg`, …, one block per component, named after
|
|
174
175
|
the component's own element) → **instance** (`--gog-button-bg`, …, deliberately undeclared
|
|
175
176
|
escape hatch for one element).
|
|
177
|
+
- **Foundation includes a small character layer** (since 21.7.0, `docs/themes.md` iteration 1):
|
|
178
|
+
`--gog-radius` (corner rounding), `--gog-control-border-*`/`--gog-panel-border-*`/`--gog-border-*`
|
|
179
|
+
(border weight — form fields, raised surfaces, everything smaller and inline, respectively),
|
|
180
|
+
`--gog-text-transform`/`--gog-letter-spacing` (emphasis casing/tracking). Component tokens in
|
|
181
|
+
the categories these cover derive from them by default; setting one in a `[data-theme]` block
|
|
182
|
+
restyles every component that reads it, with nothing to re-list per component.
|
|
183
|
+
- **`--gog-density` is the character layer for spacing** (since 21.7.0, `docs/themes.md`
|
|
184
|
+
iteration 6). It multiplies the fourteen-step scale `--gog-space-2` … `--gog-space-48`, named
|
|
185
|
+
for their pixel value at density 1, and every padding and gap in the library derives from a
|
|
186
|
+
step. `--gog-density: 0.9` in a `[data-theme]` block makes the whole library tighter; nothing
|
|
187
|
+
else needs to be named. `--gog-space-xs|sm|md|lg|2xl` are aliases for steps 4/8/16/24/48 and
|
|
188
|
+
still work. Icon offsets follow density; the glyph box, focus-ring offset and float-label
|
|
189
|
+
reserve deliberately do not — they are legibility, not spacing.
|
|
176
190
|
- **Component prefixes are spelled out** since 21.5.0: `--gog-button-*`, `--gog-multiselect-*`,
|
|
177
191
|
`--gog-confirmation-dialog-*`. The abbreviated `--gog-btn-*`, `--gog-ms-*` and `--gog-confirm-*`
|
|
178
|
-
|
|
179
|
-
`--gog-input-*`, which is not an abbreviation: it is
|
|
180
|
-
`gog-inputfield` and `gog-textarea` both render, and it keeps
|
|
192
|
+
were removed in 21.7.0 — if you're reading a codebase or an example that still uses one, rename
|
|
193
|
+
it; it no longer resolves. The exception is `--gog-input-*`, which is not an abbreviation: it is
|
|
194
|
+
the shared text-field block that `gog-inputfield` and `gog-textarea` both render, and it keeps
|
|
195
|
+
that name.
|
|
181
196
|
- **The package does not need the app's `box-sizing` reset** (since 21.6.0): `utilities.css`
|
|
182
197
|
sets `border-box` on every element carrying a `gog-*` class, including the ones the library
|
|
183
198
|
puts on a consumer's own element. Do not add a reset "so the components line up" — they
|
|
184
199
|
already do, and a `* { box-sizing: content-box }` in an app is the only thing that undoes it.
|
|
185
200
|
- Theme switch is a `data-theme` attribute, usually on `<html>`, toggled through the
|
|
186
201
|
`ThemeService` (`inject(ThemeService).setTheme('dark')` / `.toggleTheme()` / `.theme` signal).
|
|
187
|
-
Ships `light` and `dark
|
|
188
|
-
|
|
202
|
+
Ships `light` and `dark`, plus nine importable presets at
|
|
203
|
+
`@guildofgleks/ui/styles/presets/<name>.css`. **All nine set palette and character** (since
|
|
204
|
+
21.7.0 — before it, three were palette-only, which made them recoloured defaults):
|
|
205
|
+
|
|
206
|
+
| Preset | Radius | Density | Identity |
|
|
207
|
+
| ---------------------- | ------ | ------- | ------------------------------------------------ |
|
|
208
|
+
| `slate` | 12px | 1.05 | soft modern — hairline borders, roomy |
|
|
209
|
+
| `one-dark`/`one-light` | 4px | 0.9 | editor chrome; identical character, two tones |
|
|
210
|
+
| `material` | 4px | 1.1 | Material Design 3, pill buttons |
|
|
211
|
+
| `primeng` | 6px | 0.95 | PrimeNG Aura |
|
|
212
|
+
| `ledger` | 0 | 0.9 | administrative — hard offset shadow, no motion |
|
|
213
|
+
| `terminal` | 0 | 0.85 | green phosphor, monospaced throughout, no motion |
|
|
214
|
+
| `bevel` | 0 | 0.9 | early-web desktop — `outset`/`inset` borders |
|
|
215
|
+
| `parchment` | 0 | 1.1 | ink on paper — old-style serif, oxblood |
|
|
216
|
+
|
|
217
|
+
`material`, `primeng` and `bevel` also set a few genuinely per-component things the character
|
|
218
|
+
layer has no vocabulary for (a pill button, a table's header font, a button bevel that has to
|
|
219
|
+
disagree with a field's); see their own file headers.
|
|
220
|
+
|
|
221
|
+
- **A preset never makes a network request.** Each sets a font _stack_ resolving to a real system
|
|
222
|
+
face. Where a webfont is worth offering, it is a separate opt-in file — `terminal.fonts.css`
|
|
223
|
+
(IBM Plex Mono), `parchment.fonts.css` (EB Garamond) — imported **after** the preset, since it
|
|
224
|
+
re-points the same tokens and later wins. Do not add an `@import url(…)` to a preset itself; put
|
|
225
|
+
it in a companion file, or the import becomes a download nobody asked for.
|
|
189
226
|
- Restyle one instance without touching a theme: `<gog-button style="--gog-button-bg: #ff4edb">`.
|
|
190
|
-
- Build a custom theme by declaring a palette against a new `data-theme`
|
|
191
|
-
`
|
|
192
|
-
don't restate them.
|
|
227
|
+
- Build a custom theme by declaring a palette **and a character** against a new `data-theme`
|
|
228
|
+
value (see `README.md`'s Theming section for the full worked example) — component tokens
|
|
229
|
+
re-derive automatically, you don't restate them.
|
|
193
230
|
|
|
194
231
|
## Right-to-left
|
|
195
232
|
|
|
@@ -253,40 +290,39 @@ in English sets these once rather than on every control:
|
|
|
253
290
|
```ts
|
|
254
291
|
provideGogConfig({
|
|
255
292
|
labels: {
|
|
256
|
-
clear: '
|
|
257
|
-
clearSelection: '
|
|
258
|
-
clearDate: '
|
|
259
|
-
selectAll: '
|
|
260
|
-
clearAll: '
|
|
261
|
-
increment: '
|
|
262
|
-
decrement: '
|
|
263
|
-
showPassword: '
|
|
264
|
-
hidePassword: '
|
|
265
|
-
closeDialog: '
|
|
266
|
-
closeToast: '
|
|
267
|
-
pagination: '
|
|
268
|
-
previousPage: '
|
|
269
|
-
nextPage: '
|
|
270
|
-
openCalendar: '
|
|
271
|
-
togglePanel: '
|
|
272
|
-
rowsPerPage: '
|
|
273
|
-
total: '
|
|
274
|
-
tablePagination: '
|
|
275
|
-
selectRow: '
|
|
276
|
-
selectAllRows: '
|
|
277
|
-
today: '
|
|
278
|
-
thisMonth: '
|
|
279
|
-
previousMonth: '
|
|
280
|
-
nextMonth: '
|
|
281
|
-
previousYear: '
|
|
282
|
-
nextYear: '
|
|
283
|
-
hours: '
|
|
284
|
-
minutes: '
|
|
285
|
-
seconds: '
|
|
293
|
+
clear: 'Löschen', // inputfield / textarea clear button
|
|
294
|
+
clearSelection: 'Auswahl löschen', // select / multiselect / autocomplete
|
|
295
|
+
clearDate: 'Datum löschen', // datepicker
|
|
296
|
+
selectAll: 'Alle auswählen', // multiselect panel
|
|
297
|
+
clearAll: 'Alle löschen', // multiselect panel
|
|
298
|
+
increment: 'Erhöhen', // number spin buttons
|
|
299
|
+
decrement: 'Verringern',
|
|
300
|
+
showPassword: 'Passwort anzeigen',
|
|
301
|
+
hidePassword: 'Passwort verbergen',
|
|
302
|
+
closeDialog: 'Schließen',
|
|
303
|
+
closeToast: 'Schließen',
|
|
304
|
+
pagination: 'Seitennavigation',
|
|
305
|
+
previousPage: 'Vorherige Seite',
|
|
306
|
+
nextPage: 'Nächste Seite',
|
|
307
|
+
openCalendar: 'Kalender öffnen',
|
|
308
|
+
togglePanel: 'Bereich umschalten', // gog-panel's toggle, only when it has no heading
|
|
309
|
+
rowsPerPage: 'Zeilen pro Seite', // gog-paginator's size select
|
|
310
|
+
total: 'Gesamt', // gog-table's row-count label
|
|
311
|
+
tablePagination: 'Tabellennavigation',
|
|
312
|
+
selectRow: 'Zeile auswählen',
|
|
313
|
+
selectAllRows: 'Alle Zeilen auswählen',
|
|
314
|
+
today: 'Heute',
|
|
315
|
+
thisMonth: 'Aktueller Monat',
|
|
316
|
+
previousMonth: 'Vorheriger Monat',
|
|
317
|
+
nextMonth: 'Nächster Monat',
|
|
318
|
+
previousYear: 'Vorheriges Jahr',
|
|
319
|
+
nextYear: 'Nächstes Jahr',
|
|
320
|
+
hours: 'Stunden',
|
|
321
|
+
minutes: 'Minuten',
|
|
322
|
+
seconds: 'Sekunden',
|
|
286
323
|
// The one non-string field: it interpolates the page number, and word order and
|
|
287
324
|
// agreement around a number vary by language, so it takes a formatter.
|
|
288
|
-
page: (page, isCurrent) =>
|
|
289
|
-
isCurrent ? `Страница ${page}, текущая` : `Перейти на страницу ${page}`,
|
|
325
|
+
page: (page, isCurrent) => (isCurrent ? `Seite ${page}, aktuell` : `Zu Seite ${page} wechseln`),
|
|
290
326
|
},
|
|
291
327
|
});
|
|
292
328
|
```
|
|
@@ -322,7 +358,7 @@ provideGogConfig({
|
|
|
322
358
|
followSystem: true, // open in the OS prefers-color-scheme, and keep following it
|
|
323
359
|
// until the app calls setTheme/toggleTheme
|
|
324
360
|
lightTheme: 'light', // the two names followSystem maps to and toggleTheme alternates
|
|
325
|
-
darkTheme: '
|
|
361
|
+
darkTheme: 'one-dark', // between
|
|
326
362
|
defaultTheme: 'light', // used when nothing else decides
|
|
327
363
|
},
|
|
328
364
|
});
|
|
@@ -370,10 +406,31 @@ async confirmDelete(): Promise<void> {
|
|
|
370
406
|
}
|
|
371
407
|
```
|
|
372
408
|
|
|
373
|
-
`DialogConfig
|
|
374
|
-
`open()` returns `{ close(result?), afterClosed: Promise<TResult | undefined> }`. Also:
|
|
409
|
+
`DialogConfig<TData>`: `{ title?, component, data?: TData, modal? (default true), closable?, draggable?, closeIconName?, closeIconTemplate?, width?, maxWidth?, role? ('dialog' default | 'alertdialog'), zIndex? }`.
|
|
410
|
+
`open<TResult, TData>()` returns `{ close(result?), afterClosed: Promise<TResult | undefined> }`. Also:
|
|
375
411
|
`closeAll(result?)`, `updatePosition(id, offsetX, offsetY)` (for `draggable` dialogs).
|
|
376
412
|
|
|
413
|
+
**`open<TResult, TData>()` type-checks `data` against `TData` when you supply both type
|
|
414
|
+
arguments** — supplying only `TResult` (the common case above) leaves `TData` as `unknown`,
|
|
415
|
+
exactly as before:
|
|
416
|
+
|
|
417
|
+
```ts
|
|
418
|
+
interface EditUserData {
|
|
419
|
+
userId: string;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const handle = this.dialogService.open<{ saved: boolean }, EditUserData>({
|
|
423
|
+
component: EditDialogComponent,
|
|
424
|
+
data: { userId: user.id }, // checked against EditUserData here
|
|
425
|
+
});
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
This checks only the call site. `EditDialogComponent` still reads its data via `inject(DIALOG_DATA)`
|
|
429
|
+
— an `InjectionToken<unknown>` shared by every dialog, so it still needs its own cast
|
|
430
|
+
(`inject<EditUserData>(DIALOG_DATA)`, shown below). Angular's DI has no way to carry a
|
|
431
|
+
per-call-site type through one shared token, so the receiving half of the round trip is still on
|
|
432
|
+
trust — this closes only the half that can be closed.
|
|
433
|
+
|
|
377
434
|
The library ships a ready-made `ConfirmationDialogComponent` for yes/no prompts — pass it as
|
|
378
435
|
`component` with `data: { title, description, confirmText, cancelText }`; it resolves the
|
|
379
436
|
dialog's result to `true`/`false`.
|
|
@@ -424,6 +481,13 @@ Outputs: `gogClick: MouseEvent`.
|
|
|
424
481
|
**`debounce` is a spam guard, not a delay before the first click.** The first click in a window
|
|
425
482
|
fires immediately (leading edge); further clicks within `debounce` ms are silently dropped.
|
|
426
483
|
|
|
484
|
+
**Use `(gogClick)`, never `(click)`, on `gog-button`.** The click handler that drives `debounce`
|
|
485
|
+
and emits `gogClick` is bound on the `<button>` inside the component's own template, not on the
|
|
486
|
+
host — a native click still bubbles up through `<gog-button>`, so a `(click)` listener written
|
|
487
|
+
there fires on every press, silently bypassing the debounce entirely. This is specific to the
|
|
488
|
+
component: `[gogButton]` on your own `<a>`/`<button>` has no debounce to bypass, so `(click)` on
|
|
489
|
+
it works exactly as written.
|
|
490
|
+
|
|
427
491
|
```html
|
|
428
492
|
<gog-button variant="primary" [loading]="saving()" (gogClick)="save()">Save</gog-button>
|
|
429
493
|
<gog-button variant="ghost" ariaLabel="Close" (gogClick)="close()"
|
|
@@ -1626,17 +1690,33 @@ Everything the package currently deprecates, as data:
|
|
|
1626
1690
|
```ts
|
|
1627
1691
|
import { GOG_DEPRECATIONS, type GogDeprecation } from '@guildofgleks/ui';
|
|
1628
1692
|
|
|
1629
|
-
GOG_DEPRECATIONS
|
|
1630
|
-
// { kind: 'token', name: '--gog-btn-bg', replacement: '--gog-button-bg',
|
|
1631
|
-
// since: '21.5.0', sinceDate: '2026-08-19', removedIn: '21.7.0' }
|
|
1693
|
+
GOG_DEPRECATIONS; // []
|
|
1632
1694
|
```
|
|
1633
1695
|
|
|
1634
1696
|
`kind` is `'symbol'` for an export or input and `'token'` for a `--gog-*` custom property. The
|
|
1635
1697
|
list is generated from the library's source — tags for symbols, stylesheets for tokens — so it
|
|
1636
1698
|
matches what actually still resolves in the version you installed.
|
|
1637
1699
|
|
|
1638
|
-
**
|
|
1639
|
-
|
|
1700
|
+
**As of 21.7.0 the list is empty on both halves.** Nothing in the TypeScript API is deprecated, and
|
|
1701
|
+
the three abbreviated token prefixes that used to fill the token half are gone rather than
|
|
1702
|
+
deprecated — see the removal table below. An empty list here means exactly that: nothing to
|
|
1703
|
+
migrate away from right now.
|
|
1704
|
+
|
|
1705
|
+
## Removed in 21.7.0
|
|
1706
|
+
|
|
1707
|
+
**Nothing in this table exists any more.** Three CSS custom-property prefixes, abbreviations of a
|
|
1708
|
+
component's own name, are gone — each was honoured only as a fallback the spelled-out token wrapped
|
|
1709
|
+
(`--gog-button-x: var(--gog-btn-x, value)`), never declared on its own.
|
|
1710
|
+
|
|
1711
|
+
| Removed | Replacement |
|
|
1712
|
+
| ----------------- | ----------------------------- |
|
|
1713
|
+
| `--gog-btn-*` | `--gog-button-*` |
|
|
1714
|
+
| `--gog-ms-*` | `--gog-multiselect-*` |
|
|
1715
|
+
| `--gog-confirm-*` | `--gog-confirmation-dialog-*` |
|
|
1716
|
+
|
|
1717
|
+
A consumer's CSS that still sets one of the left-hand names doesn't fail their build — an
|
|
1718
|
+
unresolved `var()` just stops matching anything, silently. If a themed surface stopped picking up
|
|
1719
|
+
an override after upgrading to 21.7.0, this table is the first thing to check.
|
|
1640
1720
|
|
|
1641
1721
|
## Removed in 21.5.0
|
|
1642
1722
|
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,165 @@ All notable changes to `@guildofgleks/ui` are documented here. Format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.0.0/); this project has not yet
|
|
5
5
|
reached 1.0, so breaking changes may land in minor versions.
|
|
6
6
|
|
|
7
|
+
## [21.7.0] - 29.08.2026
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Every shipped theme now meets WCAG AA, and the check runs in CI.** Nine gated failures across
|
|
12
|
+
five palettes were fixed: muted text in `slate`, `one-dark` and `one-light`; the filled button's
|
|
13
|
+
label, at rest and on hover, in `light`, `primeng`, `one-light` and `slate`. `check:contrast` is
|
|
14
|
+
now a CI step — it was deliberately kept out while any finding was open, because a permanently
|
|
15
|
+
red step over a known condition teaches everyone to ignore CI.
|
|
16
|
+
|
|
17
|
+
**`one-dark` and `one-light` changed colour, and that is a trade you may notice.** They
|
|
18
|
+
reproduce a named editor palette; `#5c6370` is One Dark's own comment colour and reads at 2.32:1
|
|
19
|
+
on its own background — fine for code, well under AA for UI text. Muted text is now `#9099a8`
|
|
20
|
+
(dark) and `#6e6f77` (light). If you depended on the exact original hues, set
|
|
21
|
+
`--gog-muted-text-color` back in your own theme block.
|
|
22
|
+
|
|
23
|
+
- **Tokens read from TypeScript now resolve `calc()` instead of silently falling back.**
|
|
24
|
+
`--gog-scroll-thumb-min-size`, `--gog-tooltip-gap`, `--gog-tooltip-z` and `--gog-dropdown-z` were
|
|
25
|
+
read with `parseFloat`, which returns `NaN` for `calc(...)` — and every caller turned that into
|
|
26
|
+
its default without a word. **This is a consumer-facing fix:** writing
|
|
27
|
+
`--gog-scroll-thumb-min-size: calc(2rem + 4px)` in your own theme now works, where before it
|
|
28
|
+
quietly became 32px. `rem`, `em` and `%` work too.
|
|
29
|
+
|
|
30
|
+
- **Two WCAG AA contrast fixes, both on a filled button's own label.** The library's own `light`
|
|
31
|
+
theme: `--gog-accent-color` `#9e6f00` → `#926600` (white on the old value was 4.44:1, under
|
|
32
|
+
AA's 4.5), and its hover fill `#c88e00` → `#7a5500` — the hover is now _darker_ than the rest
|
|
33
|
+
state rather than brighter, because gold light enough to read as "a brighter gleam" cannot
|
|
34
|
+
carry white text at all (the old hover was 2.87:1, worse than the rest state everyone had
|
|
35
|
+
noticed). `primeng`: moved one step down Aura's own blue ramp, `#3b82f6` → `#2563eb`
|
|
36
|
+
(500 → 600), rather than inventing a colour outside the palette it reproduces; 3.68:1 → 5.17:1.
|
|
37
|
+
|
|
38
|
+
**If you were overriding either token, nothing breaks** — but a theme built on top of `light`'s
|
|
39
|
+
gold may want to re-check its own derived shades. `check:contrast` now also tests the hover
|
|
40
|
+
fill, which was never checked before; `one-dark`, `one-light` and `slate` keep their known
|
|
41
|
+
findings on purpose (see `docs/backlog.md`).
|
|
42
|
+
|
|
43
|
+
- **Three new presets complete the catalogue: `terminal`, `bevel` and `parchment`.** Retro and
|
|
44
|
+
Historical, the two families `docs/themes.md` had left unbuilt. `terminal` is green phosphor on
|
|
45
|
+
an unlit screen, monospaced throughout, square, no motion. `bevel` is the early-web desktop —
|
|
46
|
+
grey panels, raised buttons, sunken fields, navy — and is the first theme to use
|
|
47
|
+
`--gog-border-style: outset`/`inset`, which is what the character layer carries a border _style_
|
|
48
|
+
for. `parchment` is ink on laid paper: old-style serif, oxblood accent, roomy margins. Each is
|
|
49
|
+
`@import '@guildofgleks/ui/styles/presets/<name>.css'`, then `data-theme="<name>"`. All three
|
|
50
|
+
pass `check:contrast` on every gated pair.
|
|
51
|
+
|
|
52
|
+
- **Optional webfont files, and the rule they exist to keep: a preset never makes a network
|
|
53
|
+
request.** Each preset sets a font stack that resolves to a real system face. Where a webfont
|
|
54
|
+
is worth offering, it is a separate file the consumer imports _after_ the preset —
|
|
55
|
+
`presets/terminal.fonts.css` (IBM Plex Mono) and `presets/parchment.fonts.css` (EB Garamond).
|
|
56
|
+
Import the preset alone and nothing is downloaded.
|
|
57
|
+
|
|
58
|
+
- **`slate`, `one-dark` and `one-light` now set a character, not just a palette** — so every
|
|
59
|
+
shipped preset does. They were palette-only, which made them recoloured defaults: they wore another product's
|
|
60
|
+
colours on this library's shape. Each now sets the character layer and a density —
|
|
61
|
+
`slate` becomes the catalogue's _soft modern_ entry (12px corners, hairline borders, roomier at
|
|
62
|
+
`1.05`), and `one-dark`/`one-light` become editor chrome (4px corners, compact at `0.9`,
|
|
63
|
+
sentence-case labels), deliberately identical to each other so a toggle between them changes
|
|
64
|
+
tone and nothing else. **Palettes are unchanged**; `check:contrast` reports the same eight
|
|
65
|
+
findings as before. See `docs/themes.md` iteration 4.
|
|
66
|
+
|
|
67
|
+
- **`--gog-density`: one number that sets the spacing of the whole library.** A theme makes
|
|
68
|
+
every component tighter or roomier with `--gog-density: 0.9` — no component tokens named, no
|
|
69
|
+
list to keep up to date as components are added. It multiplies a new fourteen-step spacing
|
|
70
|
+
scale (`--gog-space-2` … `--gog-space-48`, named for their pixel value at density 1), and
|
|
71
|
+
every padding and gap in `theme.css` now derives from that scale. The three shipped presets
|
|
72
|
+
that carry a character layer use it: `ledger` at `0.9` (administrative software packed a
|
|
73
|
+
screen), `primeng` at `0.95`, `material` at `1.1` (M3's posture is generous by design).
|
|
74
|
+
|
|
75
|
+
The five existing `--gog-space-xs|sm|md|lg|2xl` names are kept as aliases with their exact
|
|
76
|
+
previous values, so no existing theme or consumer stylesheet changes. **Nothing moves at
|
|
77
|
+
density 1** except thirteen paddings that were never on a grid to begin with — five of them
|
|
78
|
+
fractional `rem` values computing to 3.6px, 4.4px, 4.8px, 7.2px and 9.6px — which now round
|
|
79
|
+
to the nearest 2px step. The largest single change is 4px, on `--gog-panel-slg-padding-x`.
|
|
80
|
+
See `docs/themes.md` iteration 6.
|
|
81
|
+
|
|
82
|
+
- **A new shipped preset: `ledger`** — the square-cornered, hard-shadowed, system-font
|
|
83
|
+
administrative-software identity. Beige and grey, a muted navy accent, uniform 1px borders,
|
|
84
|
+
zero corner radius, a hard offset shadow with no blur, and every transition duration set to
|
|
85
|
+
`0s`. `@import '@guildofgleks/ui/styles/presets/ledger.css'`, then `data-theme="ledger"`.
|
|
86
|
+
Palette-plus-character-layer only, like `material`/`primeng` below but with no per-component
|
|
87
|
+
overrides needed at all — see `docs/themes.md` iteration 4. Named `ledger`, not the plan's own
|
|
88
|
+
"Classic" (that names the catalogue _family_, not this preset) — `ui-showcase` already uses
|
|
89
|
+
"Classic" as the display label for `data-theme="light"`.
|
|
90
|
+
|
|
91
|
+
- **Two new shipped presets: `material` and `primeng`** — full visual identities (Material
|
|
92
|
+
Design 3 baseline and PrimeNG's Aura), not just palettes, ported from `gleks-ui-lab`'s
|
|
93
|
+
compare page. `@import '@guildofgleks/ui/styles/presets/material.css'` /
|
|
94
|
+
`.../presets/primeng.css'`, then `data-theme="material"` / `"primeng"`. Unlike `slate`/
|
|
95
|
+
`one-dark`/`one-light`, both set the character layer (corner rounding, border weight, casing,
|
|
96
|
+
tracking) plus a handful of settings the character layer has no vocabulary for yet (a pill
|
|
97
|
+
button, a table's header font). See each file's own header comment for what's per-component
|
|
98
|
+
and why.
|
|
99
|
+
|
|
100
|
+
- **Four new foundation tokens give a theme somewhere to set corner rounding, border weight and
|
|
101
|
+
emphasis casing/tracking once, instead of per component:** `--gog-text-transform` (default
|
|
102
|
+
`uppercase`), `--gog-letter-spacing` (default `1px`), `--gog-border-width` and `--gog-border-style`
|
|
103
|
+
(default `1px solid` — a third tier alongside the existing `--gog-control-border-*` for form
|
|
104
|
+
fields and `--gog-panel-border-*` for raised surfaces, covering everything smaller and inline:
|
|
105
|
+
chips, tags, badges, toggles, table rows, tabs, calendar cells). 40 component tokens across
|
|
106
|
+
`theme.css` now derive from these plus the pre-existing `--gog-radius` — no default changed;
|
|
107
|
+
every conversion was checked to render the identical pixel value before and after. Not
|
|
108
|
+
converted, on purpose: pill/circle radii and deliberately-flat corners (a rounding axis
|
|
109
|
+
shouldn't reshape a shape choice), and per-component values with no shared pattern to extract.
|
|
110
|
+
`docs/themes.md` has the full audit. Setting any of the four in a `[data-theme]` block now
|
|
111
|
+
restyles every component that reads it, with no per-component overrides to list.
|
|
112
|
+
|
|
113
|
+
- **`DialogService.open()` and `DialogConfig` gain an optional `TData` generic**, checked against
|
|
114
|
+
`data` at the call site: `dialogService.open<TResult, TData>({ data: /* checked against TData */ })`.
|
|
115
|
+
Supplying only `TResult` — the existing, common form — leaves `TData` as `unknown`, exactly as
|
|
116
|
+
before; nothing about an existing call changes. This closes only the sending half of the round
|
|
117
|
+
trip: the component you open still reads its data via `inject(DIALOG_DATA)`, one
|
|
118
|
+
`InjectionToken<unknown>` shared by every dialog, so it still needs its own cast
|
|
119
|
+
(`inject<TData>(DIALOG_DATA)`) — Angular's DI has no way to carry a per-call-site type through a
|
|
120
|
+
single shared token. See `AGENTS.md`'s `DialogService` section for the full example.
|
|
121
|
+
|
|
122
|
+
### Removed
|
|
123
|
+
|
|
124
|
+
- **The three abbreviated token prefixes deprecated in 21.5.0 (21.3.0 for `--gog-ms-*`) are gone.**
|
|
125
|
+
Each had been declared nowhere, honoured only as a fallback the spelled-out token wrapped:
|
|
126
|
+
`--gog-button-x: var(--gog-btn-x, value)`. The fallback layer is deleted; the spelled-out name is
|
|
127
|
+
now the plain declaration, with the same final value as before. Rename any of the following you
|
|
128
|
+
still set, in your own stylesheet — a `var()` reference to a name nothing declares does not fail
|
|
129
|
+
a build, it just silently stops matching anything:
|
|
130
|
+
|
|
131
|
+
| Old | New |
|
|
132
|
+
| ----------------- | ----------------------------- |
|
|
133
|
+
| `--gog-btn-*` | `--gog-button-*` |
|
|
134
|
+
| `--gog-ms-*` | `--gog-multiselect-*` |
|
|
135
|
+
| `--gog-confirm-*` | `--gog-confirmation-dialog-*` |
|
|
136
|
+
|
|
137
|
+
`GogTokenName` (the exported type listing every `--gog-*` custom property) drops the 20 old
|
|
138
|
+
spellings it used to include — a compile error on a variable annotated with one of them is the
|
|
139
|
+
one part of this change your build will actually catch.
|
|
140
|
+
|
|
141
|
+
### Fixed
|
|
142
|
+
|
|
143
|
+
- **Four tokens that resolved to nothing, found while surveying this release's removal below.**
|
|
144
|
+
Each was a `var(--gog-…)` with no fallback, naming a custom property nothing declares — which
|
|
145
|
+
makes the token holding it guaranteed-invalid, so the declaration reading it silently computes to
|
|
146
|
+
nothing. No build error, nothing to see except the missing style:
|
|
147
|
+
|
|
148
|
+
- **`gog-multiselect`'s focus glow never rendered.** Its default read the deprecated
|
|
149
|
+
`--gog-ms-focus-ring`, declared nowhere — now reads its own `--gog-multiselect-focus-ring`,
|
|
150
|
+
matching `gog-input` and `gog-select`.
|
|
151
|
+
- **The filter box inside `gog-select` and `gog-multiselect` had no border and the wrong text
|
|
152
|
+
colour.** Both read a `--gog-{select,multiselect}-control-*` pair that was never declared
|
|
153
|
+
anywhere in the library — now read `--gog-{select,multiselect}-field-*`, the tokens that were
|
|
154
|
+
actually meant. The border loss was total (`border` is a shorthand, so one invalid part drops
|
|
155
|
+
the whole declaration); the colour loss was invisible, because `color` just inherited instead.
|
|
156
|
+
- **`gog-multiselect`'s JS-computed panel height silently used hardcoded defaults instead of the
|
|
157
|
+
themed metrics.** Its `GogDropdownBase` token overrides named the deprecated `--gog-ms-*`
|
|
158
|
+
prefix, which `theme.css` has never declared as a real property — so
|
|
159
|
+
`getComputedStyle().getPropertyValue()` always read `''`. Now reads `--gog-multiselect-*`,
|
|
160
|
+
matching the pattern `gog-select` already used correctly.
|
|
161
|
+
|
|
162
|
+
A consumer who set `--gog-multiselect-focus-glow`, `--gog-select-filter-input-color/-border` or
|
|
163
|
+
their `gog-multiselect` counterparts directly, to work around any of the first two being missing,
|
|
164
|
+
keeps working exactly as before — an explicit override still wins over the (now real) default.
|
|
165
|
+
|
|
7
166
|
## [21.6.1] - 26.08.2026
|
|
8
167
|
|
|
9
168
|
### Added
|
package/README.md
CHANGED
|
@@ -81,6 +81,13 @@ export class ExampleComponent {}
|
|
|
81
81
|
Outputs are prefixed `gog` (`gogClick`, `gogToggle`) so they never collide with native DOM
|
|
82
82
|
events. Inputs keep their natural names.
|
|
83
83
|
|
|
84
|
+
> **Don't write `(click)` on `gog-button`.** Its click handler is bound on the `<button>` inside
|
|
85
|
+
> its own template, not on the host — a native click still bubbles up through the host element, so
|
|
86
|
+
> a `(click)` listener there fires on every press, silently bypassing `debounce`'s throttling.
|
|
87
|
+
> `(gogClick)` is the one that only emits once the debounce window has passed; use it instead. This
|
|
88
|
+
> is specific to the `gog-button` component — `[gogButton]` on your own `<a>`/`<button>` has no
|
|
89
|
+
> debounce to bypass, so your own `(click)` on it works exactly as written.
|
|
90
|
+
|
|
84
91
|
**3. If you use dialogs or toasts, place their hosts once.** `DialogService.open()` and
|
|
85
92
|
`ToastService.show()` update state but render nothing without them:
|
|
86
93
|
|
|
@@ -116,8 +123,12 @@ want for a toast.
|
|
|
116
123
|
|
|
117
124
|
Every value the components paint with lives in `styles/theme.css`, in three layers:
|
|
118
125
|
|
|
119
|
-
**Foundation** — palette, type scale, spacing, motion
|
|
120
|
-
|
|
126
|
+
**Foundation** — palette, type scale, spacing, motion, and a small _character_ layer: corner
|
|
127
|
+
rounding (`--gog-radius`), border weight (`--gog-control-border-*` for form fields,
|
|
128
|
+
`--gog-panel-border-*` for raised surfaces, `--gog-border-*` for everything smaller and inline),
|
|
129
|
+
and emphasis casing/tracking (`--gog-text-transform`, `--gog-letter-spacing`). Override these to
|
|
130
|
+
restyle everything at once; component tokens derive from them, so a palette or character change
|
|
131
|
+
carries through on its own, with nothing to re-list per component.
|
|
121
132
|
|
|
122
133
|
**Component** — `--gog-<component>-*`, one block per component, named after the component you
|
|
123
134
|
write in markup (`gog-button` → `--gog-button-*`), to restyle a single component app-wide:
|
|
@@ -139,11 +150,11 @@ variant and size classes:
|
|
|
139
150
|
}
|
|
140
151
|
```
|
|
141
152
|
|
|
142
|
-
> **Renamed in 21.5.0.** Three prefixes were abbreviated and are now spelled
|
|
143
|
-
> `--gog-btn-*` → `--gog-button-*`, `--gog-confirm-*` → `--gog-confirmation-dialog-*`, and
|
|
144
|
-
> `--gog-ms-*` → `--gog-multiselect-*` (that one since 21.3.0). **The old spellings
|
|
145
|
-
>
|
|
146
|
-
>
|
|
153
|
+
> **Renamed in 21.5.0, removed in 21.7.0.** Three prefixes were abbreviated and are now spelled
|
|
154
|
+
> out: `--gog-btn-*` → `--gog-button-*`, `--gog-confirm-*` → `--gog-confirmation-dialog-*`, and
|
|
155
|
+
> `--gog-ms-*` → `--gog-multiselect-*` (that one since 21.3.0). **The old spellings no longer
|
|
156
|
+
> resolve.** If you set one of them, rename it — a `var()` reference to a name nothing declares
|
|
157
|
+
> doesn't fail your build, it just silently stops matching anything.
|
|
147
158
|
>
|
|
148
159
|
> One prefix that looks abbreviated and is not: **`--gog-input-*`**. It names the shared
|
|
149
160
|
> text-field block that both `gog-inputfield` and `gog-textarea` render (`.gog-input__field`), not
|
|
@@ -167,7 +178,7 @@ The active theme is a `data-theme` attribute on `:root`, managed by `ThemeServic
|
|
|
167
178
|
```ts
|
|
168
179
|
private readonly theme = inject(ThemeService);
|
|
169
180
|
this.theme.toggleTheme(); // light ⇄ dark
|
|
170
|
-
this.theme.setTheme('
|
|
181
|
+
this.theme.setTheme('one-dark'); // any preset you imported, or any name you declared in CSS
|
|
171
182
|
```
|
|
172
183
|
|
|
173
184
|
Out of the box it adopts whatever `data-theme` is already on the document, or `light`.
|
|
@@ -175,19 +186,64 @@ Persisting the choice and following the OS setting are opt-in:
|
|
|
175
186
|
|
|
176
187
|
```ts
|
|
177
188
|
provideGogConfig({
|
|
178
|
-
theme: { storageKey: 'app-theme', followSystem: true, darkTheme: '
|
|
189
|
+
theme: { storageKey: 'app-theme', followSystem: true, darkTheme: 'one-dark' },
|
|
179
190
|
});
|
|
180
191
|
```
|
|
181
192
|
|
|
182
|
-
A theme only declares what it changes — the derived layer re-resolves against whatever
|
|
183
|
-
|
|
184
|
-
|
|
193
|
+
A theme only declares what it changes — the derived layer re-resolves against whatever is in
|
|
194
|
+
scope, so a theme restyles every component without listing any of them. **Eleven declarations
|
|
195
|
+
are a whole visual identity**, not a recolour:
|
|
185
196
|
|
|
186
197
|
```css
|
|
187
|
-
|
|
188
|
-
|
|
198
|
+
[data-theme='compact'] {
|
|
199
|
+
/* Palette: every colour in the library re-derives from these. */
|
|
200
|
+
--gog-background-color: #f4f6f8;
|
|
201
|
+
--gog-surface-color: #ffffff;
|
|
202
|
+
--gog-text-color: #1e293b;
|
|
203
|
+
--gog-accent-color: #4f46e5;
|
|
204
|
+
|
|
205
|
+
/* Character: every corner, border, label and gap in the library re-derives from these. */
|
|
206
|
+
--gog-radius: 2px;
|
|
207
|
+
--gog-density: 0.85; /* one number = every padding and gap at once */
|
|
208
|
+
--gog-control-border-width: 1px;
|
|
209
|
+
--gog-text-transform: none;
|
|
210
|
+
--gog-letter-spacing: normal;
|
|
211
|
+
}
|
|
189
212
|
```
|
|
190
213
|
|
|
214
|
+
The palette half has always worked this way. The **character layer** (`--gog-radius`,
|
|
215
|
+
`--gog-density`, the border and casing tokens — all since 21.7.0) is the other half: it is what
|
|
216
|
+
lets a theme change the library's _shape_ — square or generous corners, thin borders,
|
|
217
|
+
sentence-case labels, tight or roomy spacing — still without naming a single component.
|
|
218
|
+
|
|
219
|
+
Nine presets ship alongside the built-in `light` and `dark`, each at `styles/presets/<name>.css`
|
|
220
|
+
and activated by `data-theme="<name>"`. All nine set palette **and** character:
|
|
221
|
+
|
|
222
|
+
| Preset | The identity |
|
|
223
|
+
| ----------------------- | ----------------------------------------------------------------------- |
|
|
224
|
+
| `slate` | soft modern — 12px corners, hairline borders, roomier than the default |
|
|
225
|
+
| `one-dark`, `one-light` | editor chrome — 4px corners, compact, sentence case; one UI, two tones |
|
|
226
|
+
| `material`, `primeng` | Material Design 3 and PrimeNG Aura, including their shape and density |
|
|
227
|
+
| `ledger` | administrative software — square corners, hard offset shadow, no motion |
|
|
228
|
+
| `terminal` | green phosphor — monospaced throughout, square, no motion |
|
|
229
|
+
| `bevel` | the early-web desktop — raised buttons, sunken fields, grey and navy |
|
|
230
|
+
| `parchment` | ink on laid paper — old-style serif, oxblood accent, roomy |
|
|
231
|
+
|
|
232
|
+
**No preset downloads a font.** Each sets a stack that resolves to a real system face — the
|
|
233
|
+
platform's own monospace for `terminal`, Tahoma/Verdana for `bevel`, Iowan Old Style/Palatino for
|
|
234
|
+
`parchment` — so importing a preset never adds a network request. Where a webfont makes a visible
|
|
235
|
+
difference, it lives in a separate opt-in file you import _after_ the preset:
|
|
236
|
+
|
|
237
|
+
```css
|
|
238
|
+
@import '@guildofgleks/ui/styles/presets/parchment.css';
|
|
239
|
+
@import '@guildofgleks/ui/styles/presets/parchment.fonts.css'; /* optional: EB Garamond */
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
`terminal.fonts.css` (IBM Plex Mono) is the other one. `material` and `primeng` additionally set
|
|
243
|
+
a few things the character layer has no vocabulary for (a pill button, a table's header font), and
|
|
244
|
+
`bevel` sets one (a button's bevel must disagree with a field's). `AGENTS.md` has the per-preset
|
|
245
|
+
detail and the full token list.
|
|
246
|
+
|
|
191
247
|
Fonts are left alone on purpose (system stacks, no webfont download). Add
|
|
192
248
|
`@guildofgleks/ui/styles/fonts.css` for the showcase's typography.
|
|
193
249
|
|
|
@@ -202,7 +258,7 @@ provideGogConfig({
|
|
|
202
258
|
dropdown: { appendToBody: true },
|
|
203
259
|
datepicker: { locale: 'de-DE', format: 'dd.MM.yyyy' },
|
|
204
260
|
ripple: { enabled: true }, // press feedback on every interactive surface at once
|
|
205
|
-
labels: { clear: '
|
|
261
|
+
labels: { clear: 'Löschen', selectAll: 'Alle auswählen' }, // translate the library once
|
|
206
262
|
});
|
|
207
263
|
```
|
|
208
264
|
|