@guildofgleks/ui 21.5.2 → 21.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -178,6 +178,10 @@ Full model is in `README.md`'s Theming section and `theming.md`; short version:
178
178
  still resolve and are removed in 21.7.0 — don't write new code with them. The exception is
179
179
  `--gog-input-*`, which is not an abbreviation: it is the shared text-field block that
180
180
  `gog-inputfield` and `gog-textarea` both render, and it keeps that name.
181
+ - **The package does not need the app's `box-sizing` reset** (since 21.6.0): `utilities.css`
182
+ sets `border-box` on every element carrying a `gog-*` class, including the ones the library
183
+ puts on a consumer's own element. Do not add a reset "so the components line up" — they
184
+ already do, and a `* { box-sizing: content-box }` in an app is the only thing that undoes it.
181
185
  - Theme switch is a `data-theme` attribute, usually on `<html>`, toggled through the
182
186
  `ThemeService` (`inject(ThemeService).setTheme('dark')` / `.toggleTheme()` / `.theme` signal).
183
187
  Ships `light` and `dark`. Three more importable presets: `slate`, `one-dark`, `one-light`
@@ -1169,7 +1173,8 @@ they never asked to be.
1169
1173
  | `totalPosition` | `'left'\|'right'\|'opposite'` | `'opposite'` |
1170
1174
  | `loading` | `boolean` | `false` |
1171
1175
  | `showColumnBorders` | `boolean` | `false` |
1172
- | `stickyHeader` | `boolean` | `false` |
1176
+ | `stickyHeader` | `boolean` | `false` — pair with `maxHeight` |
1177
+ | `maxHeight` | `string \| null` | `null` — any CSS length |
1173
1178
  | `size` | `GogSize` | `'lg'` (row density — not `'md'`) |
1174
1179
  | `lazy` | `boolean` | `false` — see below |
1175
1180
  | `totalRecords` | `number \| null` | `null` — `lazy` only |
@@ -1184,6 +1189,29 @@ null }` when the third click clears it), `gogPageChange: number` (1-based; **doe
1184
1189
  first render, nor for the page reset a new sort causes — that reset belongs to the sort),
1185
1190
  `gogRowClick: GogTableRowClickEvent<T>` (`{ row, index, originalEvent }`).
1186
1191
 
1192
+ **`fullWidth` also picks the layout algorithm.** Left at its default the table is `100%` wide with
1193
+ `table-layout: fixed`; since 21.6.0 `[fullWidth]="false"` makes it `fit-content` with
1194
+ `table-layout: auto`, so the columns are measured against their content instead of splitting the
1195
+ total evenly. Before 21.6.0 that split clipped the widest header, and a `width` on the column was
1196
+ the workaround — under auto layout a stated `width` is a suggestion weighed against content
1197
+ rather than a hard split, so those can usually go.
1198
+
1199
+ **`stickyHeader` needs `maxHeight`** (both since 21.6.0 for the pairing). A sticky element
1200
+ resolves against its nearest scroll container, and the table wraps itself in a `gog-scroll`;
1201
+ once that scroller moves on either axis it is a scroll container on *both*, because CSS coerces
1202
+ `overflow-y: visible` to `auto` beside a scrolling `overflow-x` (and `clip` to `hidden`). So the
1203
+ header can only ever stick to something inside the table — and without `maxHeight` that viewport
1204
+ is exactly as tall as its content and never scrolls, so there is nothing to stick to.
1205
+
1206
+ ```html
1207
+ <gog-table [value]="rows" maxHeight="260px" [stickyHeader]="true">…</gog-table>
1208
+ ```
1209
+
1210
+ `maxHeight` takes any CSS length and is what makes the table own its vertical scrolling. Left
1211
+ `null`, the table grows to its content and an ancestor scrolls it — the header then follows that
1212
+ ancestor's scroll like everything else, which is the pre-21.6.0 behaviour and is fine as long as
1213
+ you are not asking for a sticky header.
1214
+
1187
1215
  Columns are declared as **projected `gog-column` children**, not an input array:
1188
1216
 
1189
1217
  ```html
package/CHANGELOG.md CHANGED
@@ -4,6 +4,129 @@ 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.6.0] - 23.08.2026
8
+
9
+ ### Fixed
10
+
11
+ - **A loading `gog-accordion` announces itself.** It sets `aria-busy="true"` while `loading` is
12
+ on. Its skeleton bars are `aria-hidden` and the real headers are not rendered, so without it the
13
+ component was not "loading" to a screen reader — it was **empty**, which reads as "there is
14
+ nothing here" rather than "this is coming".
15
+
16
+ The placeholder rows also gained the shape they were missing: **a chevron placeholder**, so the
17
+ silhouette is the one that arrives instead of the chevron appearing out of nowhere, and
18
+ **varying title widths** instead of every bar at a flat 55%, which read as a repeating progress
19
+ artifact rather than as titles of differing length. Widths cycle by row index rather than
20
+ randomising, so a server-rendered pass and its hydration agree.
21
+
22
+ The geometry was already correct and is unchanged — measured at the same `size`, the skeleton
23
+ header is 46px against the real 47px.
24
+
25
+ **`gog-table` and `gog-autocomplete` still do not set `aria-busy`.** The rule is now written
26
+ down in the repo's API guide along with which loading treatment belongs to which kind of
27
+ component; those two are its known violations and are tracked.
28
+
29
+ - **The library no longer needs your `box-sizing` reset.** Everything it renders now sizes itself
30
+ `border-box`, set once in `styles/utilities.css` on any element carrying a `gog-*` class.
31
+
32
+ Without a reset the components quietly stopped honouring their own size tokens:
33
+ `--gog-select-min-width` is `120px`, and a `gog-select` measured **148px**; its inner control
34
+ went from 120px to 176px, and `gog-toggle__track` and `gog-checkbox__box` inflated the same way.
35
+ Measured across four showcase pages, 12–16 elements per page came out a different size. Nothing
36
+ looked broken, which is why it went unreported — a consumer without a reset simply got a
37
+ differently-proportioned library.
38
+
39
+ **If your app has `* { box-sizing: border-box }`, nothing changes**; the library was already
40
+ rendering under it. The rule is a single class in specificity, so your own styles still win.
41
+
42
+ - **Disabled and focus styling can no longer be lost to an ordinary app stylesheet.** `[gogButton]`
43
+ and `gogMenuItem` are applied to *your* element, which is the element you style — and a plain
44
+ `.my-button { cursor: pointer }` in an Angular component stylesheet is the same specificity as
45
+ the library's `.gog-btn:disabled` once `[_ngcontent-…]` is stamped on it, so it won on source
46
+ order. Measured: a disabled button reading `cursor: pointer` at full opacity — enabled-looking
47
+ and enabled-feeling while disabled. For a menu item it is worse, because the arrow keys step
48
+ over a disabled item: the pointer and the keyboard disagreed about what was there.
49
+
50
+ Five rules across `styles/button.css` and `styles/menu.css` — the `:disabled` and
51
+ `:focus-visible` pairs — now carry one more point of specificity. `:hover` and `:active` needed
52
+ nothing; their `:not(:disabled)` already had it.
53
+
54
+ **Restyling these is still yours**, it just has to be deliberate now: any selector of your own
55
+ with two classes wins, as before. The base `.gog-btn` look is untouched and as overridable as
56
+ it ever was — what is defended is state and focus visibility, where losing silently is a
57
+ correctness and accessibility bug rather than a difference of taste.
58
+
59
+ - **A disabled `gogCollapsibleTrigger` shows a disabled cursor.** It carried whatever cursor the
60
+ consumer had put on the element — usually `pointer`, since the trigger is their own button.
61
+ The library's `cursor: not-allowed` was there, and losing: an ordinary
62
+ `.my-trigger { cursor: pointer }` in a consumer's component stylesheet is the same specificity
63
+ once Angular stamps `[_ngcontent-…]` onto it, and it comes later in the cascade. The rule is
64
+ now scoped through `gog-collapsible`, which settles it without `!important`.
65
+
66
+ If you added a `cursor` to your own trigger, you can drop it — the directive has set
67
+ `cursor: pointer` since it started applying `.gog-collapsible__trigger`.
68
+
69
+ - **`gog-autocomplete`: the text can be erased again.** With a selection held, backspacing could
70
+ not clear the field — nine backspaces on "Amsterdam" left "Amsterdam". Deleting the last
71
+ character takes the text under `minLength`, which closes the panel; the effect that keeps the
72
+ field showing its selection used `!isOpen()` to mean "the user is not mid-edit", so closing the
73
+ panel made it write the selected label straight back into the input.
74
+
75
+ The panel closes for reasons that are not "the user finished" — text under `minLength`, Escape,
76
+ Tab — so editing is now tracked directly instead of inferred from it. The effect keeps its real
77
+ job, which is syncing a value the component did not set: a form writing one in, or the options
78
+ arriving after the value did.
79
+
80
+ **`forceSelection` is unaffected.** It still snaps the field back to the selection on blur and
81
+ on Escape, which is where that was always meant to happen; what stopped is the snap-back firing
82
+ mid-keystroke.
83
+
84
+ ### Added
85
+
86
+ - **`gog-table`: `maxHeight`** — any CSS length (`'420px'`, `'60vh'`), capping the table's own
87
+ scroll viewport so the table owns its vertical scrolling. **This is what makes `stickyHeader`
88
+ work**, and the two are meant to be used together:
89
+
90
+ ```html
91
+ <gog-table [value]="rows" maxHeight="260px" [stickyHeader]="true">…</gog-table>
92
+ ```
93
+
94
+ `stickyHeader` has never held while the table scrolled sideways. A sticky element resolves
95
+ against its nearest scroll container; the table wraps itself in a `gog-scroll`, and the moment
96
+ that scroller moves on one axis it is a scroll container on **both**, because CSS coerces
97
+ `overflow-y: visible` to `auto` next to a scrolling `overflow-x` — and `clip` to `hidden`, which
98
+ is also a scroll container. Measured in a browser: a header 147px out of view, with the
99
+ component's own `overflow-y: visible` showing as a computed `auto`.
100
+
101
+ So the header cannot be made to stick to anything outside the table, and the fix is to give the
102
+ inside something to stick to. With `maxHeight` set the viewport is the vertical scrollport and
103
+ the header pins to it — verified with both axes scrolling at once.
104
+
105
+ An input rather than a `--gog-table-*` token, even though the value only lands in CSS, because
106
+ it also decides whether the internal scroller handles the vertical axis. It has to for a capped
107
+ table; it must **not** for an uncapped one, or every table becomes a scroll container and takes
108
+ the consumer's own scrolling region out of its descendants' sticky chain — measured at 147px
109
+ when tried that way. That is behaviour, not appearance.
110
+
111
+ **Nothing changes for a table without it.** `maxHeight` defaults to `null`, the viewport stays
112
+ at content height and its vertical axis stays inert.
113
+
114
+ ### Fixed
115
+
116
+ - **`[fullWidth]="false"` no longer clips the widest column's header.** The table is
117
+ `table-layout: fixed` and switches to `width: fit-content` in this mode, so the browser split
118
+ that width evenly across the columns instead of measuring them against their content — and
119
+ `overflow: hidden` on the cell cut whatever did not fit. Measured on a five-column table:
120
+ "Component" was given 100px of 448px while needing 119px.
121
+
122
+ It now lays out with `table-layout: auto` whenever `fullWidth` is false. Fixed layout only buys
123
+ anything when the width comes from outside the table; at `fit-content` it comes from the content
124
+ anyway, so there was nothing to trade away. The same table now gives "Component" 133px of 454px.
125
+
126
+ **`fullWidth` left at its default is untouched** and still uses fixed layout. If you set `width`
127
+ on a `gog-column` purely to work around the clipping, you can drop it — under auto layout a
128
+ stated width becomes a suggestion the browser weighs against content, rather than a hard split.
129
+
7
130
  ## [21.5.2] - 22.08.2026
8
131
 
9
132
  Documentation only, and specifically the copy of this file that ships inside the package: 21.5.0
package/README.md CHANGED
@@ -59,6 +59,10 @@ use — without it they render unstyled.
59
59
  ]
60
60
  ```
61
61
 
62
+ It brings its own `box-sizing: border-box`, scoped to the elements the library renders, so the
63
+ components size correctly whether or not your app has a global reset — since 21.6.0. Your own
64
+ reset is untouched either way, and a single class of specificity means your own styles still win.
65
+
62
66
  **2. Import components where you use them** — each is standalone:
63
67
 
64
68
  ```ts