@guildofgleks/ui 21.6.1 → 21.7.1
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 +229 -0
- package/README.md +81 -15
- package/TOKENS.md +9 -9
- package/fesm2022/guildofgleks-ui.mjs +188 -1322
- 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 +27 -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 +72 -0
- package/styles/presets/terminal.fonts.css +26 -0
- package/styles/theme.css +696 -592
- 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,235 @@ 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.1] - 29.08.2026
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **A toast now still shows how long it has left when animations are off.** The progress bar was
|
|
12
|
+
switched off along with everything else under `prefers-reduced-motion`, so the toast vanished
|
|
13
|
+
with no warning — the animation was carrying the information. It now runs in `steps(20, end)`:
|
|
14
|
+
the bar still reports the time remaining, in twenty discrete jumps rather than a slide. Nothing
|
|
15
|
+
appears to move, and nothing counts down in silence.
|
|
16
|
+
|
|
17
|
+
- **`gog-textarea`'s scrollbar matches `gog-scroll`.** It cannot _be_ `gog-scroll` — that
|
|
18
|
+
component hides a container's native chrome and draws an overlay thumb over it, and a
|
|
19
|
+
`<textarea>` scrolls its own text, so the overlay would sit on the editing surface and either
|
|
20
|
+
swallow clicks or drift from the content. The real scrollbar is styled from the same
|
|
21
|
+
`--gog-scroll-*` tokens instead, via `scrollbar-width`/`scrollbar-color` in Firefox and
|
|
22
|
+
`::-webkit-scrollbar` in Blink and WebKit. Restyle `gog-scroll` in a theme and this follows.
|
|
23
|
+
|
|
24
|
+
- **`gog-accordion`'s loading skeleton is visible again.** Its placeholders are mixed against
|
|
25
|
+
`--gog-surface-color`, which is what a skeleton normally lies on — but the header strip now
|
|
26
|
+
paints `--gog-accordion-header-bg`, putting a `#261e16` placeholder on a `#241d17` strip on the
|
|
27
|
+
dark theme. Contrast 1.02: the title and chevron placeholders were both invisible while still
|
|
28
|
+
occupying their full 18px in the DOM. The skeleton inside that header is now based on
|
|
29
|
+
`--gog-border-color` instead, the one palette tone guaranteed to sit above the strip.
|
|
30
|
+
|
|
31
|
+
- **Three surfaces that had no visual separation now have one.** All three were reported from a
|
|
32
|
+
dark theme, where a shadow has nothing to darken:
|
|
33
|
+
|
|
34
|
+
- **`gog-table`'s header** painted `--gog-table-surface` — the same colour as the body — so a
|
|
35
|
+
sticky header slid over rows of identical background with only the accent colour and the caps
|
|
36
|
+
to distinguish it. New `--gog-table-header-bg`, defaulting to `--gog-hover-color`.
|
|
37
|
+
- **`gog-accordion`'s header and body** were both `transparent`, making several open items one
|
|
38
|
+
continuous band with a hairline between them. `--gog-accordion-header-bg` now defaults to
|
|
39
|
+
`--gog-hover-color`; the body stays transparent on purpose, so an accordion on a coloured
|
|
40
|
+
surface still sits on that colour. (The token's own comment already claimed the body "reads
|
|
41
|
+
slightly darker than the header" — that was only true under `data-theme="dark"`.)
|
|
42
|
+
- **`elevated` cards and panels were indistinguishable from `outlined` on dark themes.** The
|
|
43
|
+
dark `--gog-panel-shadow` carries a `0 0 0 1px` ring for overlays that need an edge against
|
|
44
|
+
the page — and that ring is exactly what `outlined` draws, so the two variants rendered the
|
|
45
|
+
same. `elevated` now uses a shadow without the ring in the three dark themes (`dark`,
|
|
46
|
+
`one-dark`, `terminal`). Nor does it keep the wide black blur: black haze over a near-black
|
|
47
|
+
page reads as smudge, not lift. Elevation is now stated the way a dark UI states it — a
|
|
48
|
+
hairline of light along the top edge, over a tight, close shadow.
|
|
49
|
+
**No background changed** — `gog-panel` defaults to `elevated`, so tinting that surface would
|
|
50
|
+
have repainted every panel in every app. `--gog-elevated-surface-color` exists as a foundation
|
|
51
|
+
token for a theme that wants to express elevation as a lighter surface instead, and equals
|
|
52
|
+
`--gog-surface-color` unless a theme sets it.
|
|
53
|
+
|
|
54
|
+
- **`gog-select`'s chevron now turns over when the panel opens.** It never did — there was no
|
|
55
|
+
rotation in any state, which looked like a reduced-motion problem and was a missing one:
|
|
56
|
+
`gog-multiselect` and `gog-accordion` both already had it. Only the default chevron rotates; a
|
|
57
|
+
custom icon supplied through the chevron slot keeps the orientation you drew, the same rule
|
|
58
|
+
`gog-accordion` follows. The rotation is a `transform`, so with `prefers-reduced-motion` the
|
|
59
|
+
arrow still points the right way and only the tween is dropped.
|
|
60
|
+
|
|
61
|
+
- **Colours no longer vanish in browsers without `color-mix()`.** 36 tokens in `theme.css` used
|
|
62
|
+
`color-mix()` with no fallback, and **a custom property does not fall back the way an ordinary
|
|
63
|
+
one does**: it accepts almost any value at parse time and only fails when substituted, so a
|
|
64
|
+
second declaration always wins and `var()` on it then resolves to nothing at all. Measured in
|
|
65
|
+
Chrome: an element styled that way with an unsupported function computed `rgba(0, 0, 0, 0)` —
|
|
66
|
+
transparent, not the earlier value. That is why hover fills, focus rings, chips, skeletons and
|
|
67
|
+
slider tracks looked wrong in Samsung Internet and older Firefox: the declarations were not
|
|
68
|
+
falling back, they were disappearing.
|
|
69
|
+
|
|
70
|
+
Every one of those tokens now has a flat palette value, with the mixed value moved into an
|
|
71
|
+
`@supports (color: color-mix(…))` block — the only mechanism that gates a custom property on
|
|
72
|
+
feature support. **Nothing changes in a browser that supports `color-mix()`**; below that line
|
|
73
|
+
the library renders in flat colours: less depth, every surface still legible and every focus
|
|
74
|
+
ring still visible. `package.json` now carries a `browserslist` stating that floor
|
|
75
|
+
(Chrome 111, Firefox 113, Safari 16.2, Samsung Internet 22).
|
|
76
|
+
|
|
77
|
+
## [21.7.0] - 29.08.2026
|
|
78
|
+
|
|
79
|
+
### Added
|
|
80
|
+
|
|
81
|
+
- **Every shipped theme now meets WCAG AA, and the check runs in CI.** Nine gated failures across
|
|
82
|
+
five palettes were fixed: muted text in `slate`, `one-dark` and `one-light`; the filled button's
|
|
83
|
+
label, at rest and on hover, in `light`, `primeng`, `one-light` and `slate`. `check:contrast` is
|
|
84
|
+
now a CI step — it was deliberately kept out while any finding was open, because a permanently
|
|
85
|
+
red step over a known condition teaches everyone to ignore CI.
|
|
86
|
+
|
|
87
|
+
**`one-dark` and `one-light` changed colour, and that is a trade you may notice.** They
|
|
88
|
+
reproduce a named editor palette; `#5c6370` is One Dark's own comment colour and reads at 2.32:1
|
|
89
|
+
on its own background — fine for code, well under AA for UI text. Muted text is now `#9099a8`
|
|
90
|
+
(dark) and `#6e6f77` (light). If you depended on the exact original hues, set
|
|
91
|
+
`--gog-muted-text-color` back in your own theme block.
|
|
92
|
+
|
|
93
|
+
- **Tokens read from TypeScript now resolve `calc()` instead of silently falling back.**
|
|
94
|
+
`--gog-scroll-thumb-min-size`, `--gog-tooltip-gap`, `--gog-tooltip-z` and `--gog-dropdown-z` were
|
|
95
|
+
read with `parseFloat`, which returns `NaN` for `calc(...)` — and every caller turned that into
|
|
96
|
+
its default without a word. **This is a consumer-facing fix:** writing
|
|
97
|
+
`--gog-scroll-thumb-min-size: calc(2rem + 4px)` in your own theme now works, where before it
|
|
98
|
+
quietly became 32px. `rem`, `em` and `%` work too.
|
|
99
|
+
|
|
100
|
+
- **Two WCAG AA contrast fixes, both on a filled button's own label.** The library's own `light`
|
|
101
|
+
theme: `--gog-accent-color` `#9e6f00` → `#926600` (white on the old value was 4.44:1, under
|
|
102
|
+
AA's 4.5), and its hover fill `#c88e00` → `#7a5500` — the hover is now _darker_ than the rest
|
|
103
|
+
state rather than brighter, because gold light enough to read as "a brighter gleam" cannot
|
|
104
|
+
carry white text at all (the old hover was 2.87:1, worse than the rest state everyone had
|
|
105
|
+
noticed). `primeng`: moved one step down Aura's own blue ramp, `#3b82f6` → `#2563eb`
|
|
106
|
+
(500 → 600), rather than inventing a colour outside the palette it reproduces; 3.68:1 → 5.17:1.
|
|
107
|
+
|
|
108
|
+
**If you were overriding either token, nothing breaks** — but a theme built on top of `light`'s
|
|
109
|
+
gold may want to re-check its own derived shades. `check:contrast` now also tests the hover
|
|
110
|
+
fill, which was never checked before; `one-dark`, `one-light` and `slate` keep their known
|
|
111
|
+
findings on purpose (see `docs/backlog.md`).
|
|
112
|
+
|
|
113
|
+
- **Three new presets complete the catalogue: `terminal`, `bevel` and `parchment`.** Retro and
|
|
114
|
+
Historical, the two families `docs/themes.md` had left unbuilt. `terminal` is green phosphor on
|
|
115
|
+
an unlit screen, monospaced throughout, square, no motion. `bevel` is the early-web desktop —
|
|
116
|
+
grey panels, raised buttons, sunken fields, navy — and is the first theme to use
|
|
117
|
+
`--gog-border-style: outset`/`inset`, which is what the character layer carries a border _style_
|
|
118
|
+
for. `parchment` is ink on laid paper: old-style serif, oxblood accent, roomy margins. Each is
|
|
119
|
+
`@import '@guildofgleks/ui/styles/presets/<name>.css'`, then `data-theme="<name>"`. All three
|
|
120
|
+
pass `check:contrast` on every gated pair.
|
|
121
|
+
|
|
122
|
+
- **Optional webfont files, and the rule they exist to keep: a preset never makes a network
|
|
123
|
+
request.** Each preset sets a font stack that resolves to a real system face. Where a webfont
|
|
124
|
+
is worth offering, it is a separate file the consumer imports _after_ the preset —
|
|
125
|
+
`presets/terminal.fonts.css` (IBM Plex Mono) and `presets/parchment.fonts.css` (EB Garamond).
|
|
126
|
+
Import the preset alone and nothing is downloaded.
|
|
127
|
+
|
|
128
|
+
- **`slate`, `one-dark` and `one-light` now set a character, not just a palette** — so every
|
|
129
|
+
shipped preset does. They were palette-only, which made them recoloured defaults: they wore another product's
|
|
130
|
+
colours on this library's shape. Each now sets the character layer and a density —
|
|
131
|
+
`slate` becomes the catalogue's _soft modern_ entry (12px corners, hairline borders, roomier at
|
|
132
|
+
`1.05`), and `one-dark`/`one-light` become editor chrome (4px corners, compact at `0.9`,
|
|
133
|
+
sentence-case labels), deliberately identical to each other so a toggle between them changes
|
|
134
|
+
tone and nothing else. **Palettes are unchanged**; `check:contrast` reports the same eight
|
|
135
|
+
findings as before. See `docs/themes.md` iteration 4.
|
|
136
|
+
|
|
137
|
+
- **`--gog-density`: one number that sets the spacing of the whole library.** A theme makes
|
|
138
|
+
every component tighter or roomier with `--gog-density: 0.9` — no component tokens named, no
|
|
139
|
+
list to keep up to date as components are added. It multiplies a new fourteen-step spacing
|
|
140
|
+
scale (`--gog-space-2` … `--gog-space-48`, named for their pixel value at density 1), and
|
|
141
|
+
every padding and gap in `theme.css` now derives from that scale. The three shipped presets
|
|
142
|
+
that carry a character layer use it: `ledger` at `0.9` (administrative software packed a
|
|
143
|
+
screen), `primeng` at `0.95`, `material` at `1.1` (M3's posture is generous by design).
|
|
144
|
+
|
|
145
|
+
The five existing `--gog-space-xs|sm|md|lg|2xl` names are kept as aliases with their exact
|
|
146
|
+
previous values, so no existing theme or consumer stylesheet changes. **Nothing moves at
|
|
147
|
+
density 1** except thirteen paddings that were never on a grid to begin with — five of them
|
|
148
|
+
fractional `rem` values computing to 3.6px, 4.4px, 4.8px, 7.2px and 9.6px — which now round
|
|
149
|
+
to the nearest 2px step. The largest single change is 4px, on `--gog-panel-slg-padding-x`.
|
|
150
|
+
See `docs/themes.md` iteration 6.
|
|
151
|
+
|
|
152
|
+
- **A new shipped preset: `ledger`** — the square-cornered, hard-shadowed, system-font
|
|
153
|
+
administrative-software identity. Beige and grey, a muted navy accent, uniform 1px borders,
|
|
154
|
+
zero corner radius, a hard offset shadow with no blur, and every transition duration set to
|
|
155
|
+
`0s`. `@import '@guildofgleks/ui/styles/presets/ledger.css'`, then `data-theme="ledger"`.
|
|
156
|
+
Palette-plus-character-layer only, like `material`/`primeng` below but with no per-component
|
|
157
|
+
overrides needed at all — see `docs/themes.md` iteration 4. Named `ledger`, not the plan's own
|
|
158
|
+
"Classic" (that names the catalogue _family_, not this preset) — `ui-showcase` already uses
|
|
159
|
+
"Classic" as the display label for `data-theme="light"`.
|
|
160
|
+
|
|
161
|
+
- **Two new shipped presets: `material` and `primeng`** — full visual identities (Material
|
|
162
|
+
Design 3 baseline and PrimeNG's Aura), not just palettes, ported from `gleks-ui-lab`'s
|
|
163
|
+
compare page. `@import '@guildofgleks/ui/styles/presets/material.css'` /
|
|
164
|
+
`.../presets/primeng.css'`, then `data-theme="material"` / `"primeng"`. Unlike `slate`/
|
|
165
|
+
`one-dark`/`one-light`, both set the character layer (corner rounding, border weight, casing,
|
|
166
|
+
tracking) plus a handful of settings the character layer has no vocabulary for yet (a pill
|
|
167
|
+
button, a table's header font). See each file's own header comment for what's per-component
|
|
168
|
+
and why.
|
|
169
|
+
|
|
170
|
+
- **Four new foundation tokens give a theme somewhere to set corner rounding, border weight and
|
|
171
|
+
emphasis casing/tracking once, instead of per component:** `--gog-text-transform` (default
|
|
172
|
+
`uppercase`), `--gog-letter-spacing` (default `1px`), `--gog-border-width` and `--gog-border-style`
|
|
173
|
+
(default `1px solid` — a third tier alongside the existing `--gog-control-border-*` for form
|
|
174
|
+
fields and `--gog-panel-border-*` for raised surfaces, covering everything smaller and inline:
|
|
175
|
+
chips, tags, badges, toggles, table rows, tabs, calendar cells). 40 component tokens across
|
|
176
|
+
`theme.css` now derive from these plus the pre-existing `--gog-radius` — no default changed;
|
|
177
|
+
every conversion was checked to render the identical pixel value before and after. Not
|
|
178
|
+
converted, on purpose: pill/circle radii and deliberately-flat corners (a rounding axis
|
|
179
|
+
shouldn't reshape a shape choice), and per-component values with no shared pattern to extract.
|
|
180
|
+
`docs/themes.md` has the full audit. Setting any of the four in a `[data-theme]` block now
|
|
181
|
+
restyles every component that reads it, with no per-component overrides to list.
|
|
182
|
+
|
|
183
|
+
- **`DialogService.open()` and `DialogConfig` gain an optional `TData` generic**, checked against
|
|
184
|
+
`data` at the call site: `dialogService.open<TResult, TData>({ data: /* checked against TData */ })`.
|
|
185
|
+
Supplying only `TResult` — the existing, common form — leaves `TData` as `unknown`, exactly as
|
|
186
|
+
before; nothing about an existing call changes. This closes only the sending half of the round
|
|
187
|
+
trip: the component you open still reads its data via `inject(DIALOG_DATA)`, one
|
|
188
|
+
`InjectionToken<unknown>` shared by every dialog, so it still needs its own cast
|
|
189
|
+
(`inject<TData>(DIALOG_DATA)`) — Angular's DI has no way to carry a per-call-site type through a
|
|
190
|
+
single shared token. See `AGENTS.md`'s `DialogService` section for the full example.
|
|
191
|
+
|
|
192
|
+
### Removed
|
|
193
|
+
|
|
194
|
+
- **The three abbreviated token prefixes deprecated in 21.5.0 (21.3.0 for `--gog-ms-*`) are gone.**
|
|
195
|
+
Each had been declared nowhere, honoured only as a fallback the spelled-out token wrapped:
|
|
196
|
+
`--gog-button-x: var(--gog-btn-x, value)`. The fallback layer is deleted; the spelled-out name is
|
|
197
|
+
now the plain declaration, with the same final value as before. Rename any of the following you
|
|
198
|
+
still set, in your own stylesheet — a `var()` reference to a name nothing declares does not fail
|
|
199
|
+
a build, it just silently stops matching anything:
|
|
200
|
+
|
|
201
|
+
| Old | New |
|
|
202
|
+
| ----------------- | ----------------------------- |
|
|
203
|
+
| `--gog-btn-*` | `--gog-button-*` |
|
|
204
|
+
| `--gog-ms-*` | `--gog-multiselect-*` |
|
|
205
|
+
| `--gog-confirm-*` | `--gog-confirmation-dialog-*` |
|
|
206
|
+
|
|
207
|
+
`GogTokenName` (the exported type listing every `--gog-*` custom property) drops the 20 old
|
|
208
|
+
spellings it used to include — a compile error on a variable annotated with one of them is the
|
|
209
|
+
one part of this change your build will actually catch.
|
|
210
|
+
|
|
211
|
+
### Fixed
|
|
212
|
+
|
|
213
|
+
- **Four tokens that resolved to nothing, found while surveying this release's removal below.**
|
|
214
|
+
Each was a `var(--gog-…)` with no fallback, naming a custom property nothing declares — which
|
|
215
|
+
makes the token holding it guaranteed-invalid, so the declaration reading it silently computes to
|
|
216
|
+
nothing. No build error, nothing to see except the missing style:
|
|
217
|
+
|
|
218
|
+
- **`gog-multiselect`'s focus glow never rendered.** Its default read the deprecated
|
|
219
|
+
`--gog-ms-focus-ring`, declared nowhere — now reads its own `--gog-multiselect-focus-ring`,
|
|
220
|
+
matching `gog-input` and `gog-select`.
|
|
221
|
+
- **The filter box inside `gog-select` and `gog-multiselect` had no border and the wrong text
|
|
222
|
+
colour.** Both read a `--gog-{select,multiselect}-control-*` pair that was never declared
|
|
223
|
+
anywhere in the library — now read `--gog-{select,multiselect}-field-*`, the tokens that were
|
|
224
|
+
actually meant. The border loss was total (`border` is a shorthand, so one invalid part drops
|
|
225
|
+
the whole declaration); the colour loss was invisible, because `color` just inherited instead.
|
|
226
|
+
- **`gog-multiselect`'s JS-computed panel height silently used hardcoded defaults instead of the
|
|
227
|
+
themed metrics.** Its `GogDropdownBase` token overrides named the deprecated `--gog-ms-*`
|
|
228
|
+
prefix, which `theme.css` has never declared as a real property — so
|
|
229
|
+
`getComputedStyle().getPropertyValue()` always read `''`. Now reads `--gog-multiselect-*`,
|
|
230
|
+
matching the pattern `gog-select` already used correctly.
|
|
231
|
+
|
|
232
|
+
A consumer who set `--gog-multiselect-focus-glow`, `--gog-select-filter-input-color/-border` or
|
|
233
|
+
their `gog-multiselect` counterparts directly, to work around any of the first two being missing,
|
|
234
|
+
keeps working exactly as before — an explicit override still wins over the (now real) default.
|
|
235
|
+
|
|
7
236
|
## [21.6.1] - 26.08.2026
|
|
8
237
|
|
|
9
238
|
### Added
|