@jungherz-de/glasskit-elements 1.19.2 → 1.21.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/CHANGELOG.md +45 -0
- package/README.md +56 -31
- package/SKILL.md +124 -27
- package/dist/components/base.js +185 -12
- package/dist/components/glk-accordion-item.js +20 -5
- package/dist/components/glk-button.js +69 -2
- package/dist/components/glk-calendar.js +3 -0
- package/dist/components/glk-checkbox.js +12 -2
- package/dist/components/glk-input.js +25 -4
- package/dist/components/glk-modal.js +99 -21
- package/dist/components/glk-pill.js +14 -1
- package/dist/components/glk-popover.js +21 -3
- package/dist/components/glk-radio.js +26 -2
- package/dist/components/glk-range.js +3 -1
- package/dist/components/glk-search.js +14 -1
- package/dist/components/glk-segmented.js +4 -0
- package/dist/components/glk-select.js +8 -2
- package/dist/components/glk-textarea.js +8 -2
- package/dist/components/glk-toggle.js +18 -11
- package/dist/glasskit-elements.esm.js +528 -68
- package/dist/glasskit-elements.js +528 -68
- package/dist/glasskit-elements.min.js +1 -1
- package/package.json +3 -3
- package/src/base.js +184 -11
- package/src/components/buttons/glk-button.js +69 -2
- package/src/components/containers/glk-accordion-item.js +20 -5
- package/src/components/feedback/glk-modal.js +99 -21
- package/src/components/feedback/glk-popover.js +21 -3
- package/src/components/forms/glk-calendar.js +3 -0
- package/src/components/forms/glk-checkbox.js +12 -2
- package/src/components/forms/glk-input.js +25 -4
- package/src/components/forms/glk-radio.js +26 -2
- package/src/components/forms/glk-range.js +3 -1
- package/src/components/forms/glk-search.js +14 -1
- package/src/components/forms/glk-segmented.js +4 -0
- package/src/components/forms/glk-select.js +8 -2
- package/src/components/forms/glk-textarea.js +8 -2
- package/src/components/forms/glk-toggle.js +18 -11
- package/src/components/navigation/glk-pill.js +14 -1
package/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: glasskit-elements
|
|
3
|
-
description: GlassKit Elements is a vanilla-JS Web Components library (v1.
|
|
3
|
+
description: GlassKit Elements is a vanilla-JS Web Components library (v1.21.0) wrapping GlassKit CSS v1.21.0. It provides 36 custom elements with the `glk-` prefix, Dark/Light mode with automatic theme sync, Shadow DOM encapsulation, and form-associated custom elements. Use this reference whenever generating HTML that uses `<glk-*>` tags to ensure correct attributes, slots, events, and composition.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# GlassKit Elements – AI Component Reference
|
|
@@ -18,7 +18,7 @@ description: GlassKit Elements is a vanilla-JS Web Components library (v1.19.2)
|
|
|
18
18
|
npm install @jungherz-de/glasskit-elements @jungherz-de/glasskit
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
Peer dependency `@jungherz-de/glasskit >=1.
|
|
21
|
+
Peer dependency `@jungherz-de/glasskit >=1.21.0` is required — 1.21.0 brings the density tokens behind `data-density`, 1.20.0 the rules the elements build on since then (the dialog overlay, hidden list slots, empty control labels, control inputs on top); 1.9.0 is the release that made the stylesheet splittable, which is what lets document-level branding reach the elements at all.
|
|
22
22
|
|
|
23
23
|
### Import (ES modules)
|
|
24
24
|
|
|
@@ -37,8 +37,9 @@ import { GlkButton } from '@jungherz-de/glasskit-elements/components/glk-button.
|
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
Every element has its own entry at `components/glk-{name}.js`; they import `./base.js` and leave `@jungherz-de/glasskit/glasskit-styles.js` external (bundler or import map resolves it). Importing one pulls that
|
|
40
|
-
file plus
|
|
41
|
-
the
|
|
40
|
+
file plus `base.js` (~16 KB, shared by all of them) and GlassKit's `glasskit-styles.js`
|
|
41
|
+
(~70 KB, resolved once by your project) rather than the 221 KB full bundle; several imports
|
|
42
|
+
share both. Each module registers its
|
|
42
43
|
custom element as a side effect, so a bare `import '…'` is enough.
|
|
43
44
|
|
|
44
45
|
### CDN
|
|
@@ -88,6 +89,14 @@ function toggleTheme() {
|
|
|
88
89
|
|
|
89
90
|
A single module-level `MutationObserver` watches `data-theme` on `<html>` and syncs every live GlassKit Element instance — you never set `data-theme` on individual elements.
|
|
90
91
|
|
|
92
|
+
### Density
|
|
93
|
+
|
|
94
|
+
```html
|
|
95
|
+
<html data-theme="dark" data-density="compact">
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Denser controls for admin screens, desktop layouts and narrow forms: fields and buttons 40px instead of 52 and 56, smaller toggles, checkboxes and radios, denser list rows and modal actions. Without the attribute nothing changes; `removeAttribute('data-density')` switches back at runtime. The sizes are GlassKit's density tokens (GlassKit 1.21.0 or later), so they reach every shadow root by inheritance, and a project's own values do too (`[data-density='compact'] { --gl-btn-height: 36px; }`); with `data-glk-defaults="off"` the preset comes from `glasskit.css` on the page, like every other token. The same observer mirrors `data-density` onto each element's theme wrapper — set it on `<html>` only, never on individual elements.
|
|
99
|
+
|
|
91
100
|
---
|
|
92
101
|
|
|
93
102
|
## 2. Core Concepts
|
|
@@ -97,16 +106,17 @@ A single module-level `MutationObserver` watches `data-theme` on `<html>` and sy
|
|
|
97
106
|
| Tag prefix | `glk-*` (analogous to the `glass-*` CSS prefix) |
|
|
98
107
|
| Rendering | Shadow DOM (`mode: 'open'`) with `adoptedStyleSheets` |
|
|
99
108
|
| Stylesheet sharing | GlassKit's `componentsSheet` is the same `CSSStyleSheet` object in every element — no CSS duplication. Token declarations live on the document, not in the shadow roots |
|
|
100
|
-
| Theme sync | Global MutationObserver on `<html data-theme>` |
|
|
109
|
+
| Theme sync | Global MutationObserver on `<html data-theme>` and `<html data-density>` |
|
|
101
110
|
| Events | Custom `glk-*` events, all `bubbles: true, composed: true` |
|
|
102
|
-
| Form participation | `GlkFormElement` uses `ElementInternals` (`static formAssociated = true`) |
|
|
111
|
+
| Form participation | `GlkFormElement` uses `ElementInternals` (`static formAssociated = true`): value, reset and — since 1.20.0 — the inner field's validity |
|
|
112
|
+
| Focus | Form elements with one field delegate focus (since 1.20.0): `element.focus()`, a click on the label, a `<label for>` land in the field |
|
|
103
113
|
| API style | Declarative HTML attributes + reflected JS properties |
|
|
104
114
|
|
|
105
115
|
Custom properties (`--gl-*`) defined on `:root` or `<html>` pass through shadow boundaries by inheritance, so custom theming works with a single global stylesheet.
|
|
106
116
|
|
|
107
117
|
### Building your own element (since 1.14.0)
|
|
108
118
|
|
|
109
|
-
`GlkElement` and `GlkFormElement` are exported — from the bundle (`import { GlkElement } from '@jungherz-de/glasskit-elements'`), from the stable subpath `@jungherz-de/glasskit-elements/base.js` (the very module the components import, so `instanceof GlkElement` holds across both), and as `GlassKitElements.GlkElement` from the CDN `<script>` bundle. A subclass inherits the whole setup: open shadow root with GlassKit's stylesheet adopted (`.glass-*` classes work inside), the theme wrapper following `data-theme`, listeners re-armed when the element moves, `emit()` for bubbling, composed events.
|
|
119
|
+
`GlkElement` and `GlkFormElement` are exported — from the bundle (`import { GlkElement } from '@jungherz-de/glasskit-elements'`), from the stable subpath `@jungherz-de/glasskit-elements/base.js` (the very module the components import, so `instanceof GlkElement` holds across both), and as `GlassKitElements.GlkElement` from the CDN `<script>` bundle. A subclass inherits the whole setup: open shadow root with GlassKit's stylesheet adopted (`.glass-*` classes work inside), the theme wrapper following `data-theme` and `data-density`, listeners re-armed when the element moves, `emit()` for bubbling, composed events.
|
|
110
120
|
|
|
111
121
|
```js
|
|
112
122
|
class DemoCounter extends GlkElement {
|
|
@@ -129,7 +139,7 @@ customElements.define('demo-counter', DemoCounter);
|
|
|
129
139
|
|
|
130
140
|
Which import to take depends on how the elements are loaded, and mixing them is the one mistake to avoid: the `<script>` / ESM **bundle** carries its own copy of `GlkElement`, so a subclass built on `base.js` next to it is a different class — `instanceof` fails across the two, and the GlassKit stylesheet lives twice. Bundle loaded → take `GlassKitElements.GlkElement` or `import { GlkElement } from '@jungherz-de/glasskit-elements'`. Per-component files loaded → `base.js`, which the components import themselves. The per-component files leave `@jungherz-de/glasskit/glasskit-styles.js` external, so a bundler resolves it from `node_modules` and an import-map project maps it to the one copy it already loads for its own elements.
|
|
131
141
|
|
|
132
|
-
Rules for a subclass: build only inside `this._wrapper` (it carries `data-theme`); keep listeners in `setupEvents()` / `teardownEvents()`, never in `render()`, or a moved element loses them; use `emit()` instead of `dispatchEvent()` so the event bubbles and crosses the shadow boundary — `emit(name, detail, { cancelable: true })` lets a listener call `preventDefault()`, and `emit()` returns `false` then (since 1.19.0); return `true` from `static get displayInline()` for inline elements; set `static get observesLightDom()` to `true` and implement `projectLightDom()` when copying light-DOM children into the shadow tree. `GlkFormElement` adds `setFormValue()`, `setValidity()`, `resetValue()` / `restoreValue()` and `static formAssociated = true`.
|
|
142
|
+
Rules for a subclass: build only inside `this._wrapper` (it carries `data-theme`, and `data-density` while `<html>` has one); keep listeners in `setupEvents()` / `teardownEvents()`, never in `render()`, or a moved element loses them; use `emit()` instead of `dispatchEvent()` so the event bubbles and crosses the shadow boundary — `emit(name, detail, { cancelable: true })` lets a listener call `preventDefault()`, and `emit()` returns `false` then (since 1.19.0); return `true` from `static get displayInline()` for inline elements; set `static get observesLightDom()` to `true` and implement `projectLightDom()` when copying light-DOM children into the shadow tree. `GlkFormElement` adds `setFormValue()`, `setValidity()`, `resetValue()` / `restoreValue()` and `static formAssociated = true`.
|
|
133
143
|
|
|
134
144
|
### Light-DOM children (since 1.12.0)
|
|
135
145
|
|
|
@@ -152,6 +162,8 @@ listeners and its theme-sync registration are re-armed on every connect, so it k
|
|
|
152
162
|
working. Before 1.12.0 they were torn down on disconnect and never restored: the
|
|
153
163
|
element still looked right but no longer fired events.
|
|
154
164
|
|
|
165
|
+
An element that was out of the document while `data-theme` or `data-density` changed on `<html>` catches up when it is connected again (since 1.21.0); before, its wrapper kept the old value — and since 1.20.0 that value also sets the `color-scheme` of the native parts inside.
|
|
166
|
+
|
|
155
167
|
### Branding (since 1.9.0)
|
|
156
168
|
|
|
157
169
|
Override `--gl-*` tokens anywhere in the document — a brand stylesheet, a `<style>` block,
|
|
@@ -185,6 +197,23 @@ this module puts them on the document once, wrapped in `@layer glasskit-defaults
|
|
|
185
197
|
If your app assigns `document.adoptedStyleSheets = [...]` wholesale at some later point,
|
|
186
198
|
re-append the existing entries rather than replacing them, or the defaults are lost.
|
|
187
199
|
|
|
200
|
+
**Only the tokens, not `color-scheme` (since 1.20.0).** GlassKit's token blocks also set
|
|
201
|
+
`color-scheme`; on the document that switched the whole page to dark — unstyled text white,
|
|
202
|
+
links light blue, native controls dark — on pages that never asked for GlassKit's theme. The
|
|
203
|
+
layer now carries the `--gl-*` tokens only, and every element sets `color-scheme` on its own
|
|
204
|
+
theme wrapper, so native parts inside it (a select's list, a date picker) match the element.
|
|
205
|
+
|
|
206
|
+
**Opting out.** The token names are global, so a component of the page that reads
|
|
207
|
+
`var(--gl-…, fallback)` sees GlassKit's values. A page that declares the tokens itself, or
|
|
208
|
+
wants them in part of the page only, switches the defaults off — the attribute is watched:
|
|
209
|
+
|
|
210
|
+
```html
|
|
211
|
+
<html data-glk-defaults="off">
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
The elements then inherit the tokens from `glasskit.css` or from a block of the page's own,
|
|
215
|
+
for instance on a container around them.
|
|
216
|
+
|
|
188
217
|
### Passing icons (fixed in 1.10.0)
|
|
189
218
|
|
|
190
219
|
Pass an icon as a **direct child** — the `<svg>` itself, not wrapped:
|
|
@@ -277,6 +306,9 @@ Default slot: icon SVG (24×24).
|
|
|
277
306
|
|
|
278
307
|
Events: `glk-click` when clicked.
|
|
279
308
|
|
|
309
|
+
`aria-expanded`, `aria-haspopup` and `aria-pressed` set on the element are handed on to the
|
|
310
|
+
native button inside (since 1.20.0) — `<glk-popover>` sets `aria-expanded` on its trigger.
|
|
311
|
+
|
|
280
312
|
---
|
|
281
313
|
|
|
282
314
|
### 3.3 `<glk-tab-bar>` + `<glk-tab-item>`
|
|
@@ -521,10 +553,25 @@ Full-width glass button (56 px). Three variants, four sizes.
|
|
|
521
553
|
| `variant` | String | — | `primary`, `secondary`, `tertiary` |
|
|
522
554
|
| `size` | String | `md` | `sm`, `md`, `lg`, `auto` |
|
|
523
555
|
| `disabled` | Boolean | `false` | Disabled state |
|
|
524
|
-
| `type` | String | `button` |
|
|
556
|
+
| `type` | String | `button` | `button`, `submit`, `reset` — submit and reset act on the element's form (since 1.20.0) |
|
|
525
557
|
|
|
526
558
|
Events: `glk-click` (suppressed when disabled).
|
|
527
559
|
|
|
560
|
+
**Submitting (since 1.20.0).** The element is form-associated: `type="submit"` submits the
|
|
561
|
+
form it sits in and `type="reset"` resets it. Before 1.20.0 both did nothing — the native
|
|
562
|
+
button lives in the shadow root, outside every form. It acts once the click has finished
|
|
563
|
+
bubbling, so `preventDefault()` on the click stops it, as on a native button; invalid fields
|
|
564
|
+
stop the submit with the browser's message; the submit event's `submitter` is the element;
|
|
565
|
+
`.form` is its form; `element.click()` acts like a click. No implicit submission: Enter in a
|
|
566
|
+
`<glk-input>` does not submit the form.
|
|
567
|
+
|
|
568
|
+
**Upgrading from ≤ 1.19:** code that set `type="submit"` and did the work in a `glk-click`
|
|
569
|
+
handler now gets a real submit as well — handle the form's `submit` event (with
|
|
570
|
+
`preventDefault()` in an SPA) or drop `type="submit"`, or the browser reloads the page.
|
|
571
|
+
|
|
572
|
+
`aria-expanded`, `aria-haspopup` and `aria-pressed` set on the element are handed on to the
|
|
573
|
+
native button inside, which is what screen readers read (since 1.20.0).
|
|
574
|
+
|
|
528
575
|
Default slot: button label (text or SVG + text).
|
|
529
576
|
|
|
530
577
|
---
|
|
@@ -545,9 +592,14 @@ Form-associated checkbox with glass styling.
|
|
|
545
592
|
| `disabled` | Boolean | Disabled state |
|
|
546
593
|
| `name` | String | Form field name |
|
|
547
594
|
| `value` | String | Value submitted when checked (default `"on"`) |
|
|
595
|
+
| `required` | Boolean | The form does not submit until it is ticked (since 1.20.0) |
|
|
548
596
|
|
|
549
597
|
Events: `glk-change` → `{ checked }`; also dispatches native `change`. Property: `.checked`.
|
|
550
598
|
|
|
599
|
+
`element.click()` and a `<label>` around the element or naming it tick it, as they do a
|
|
600
|
+
native checkbox (since 1.20.0). A press on the element's empty width (it is a block, the
|
|
601
|
+
control narrower) still does nothing.
|
|
602
|
+
|
|
551
603
|
---
|
|
552
604
|
|
|
553
605
|
### 3.12 `<glk-input>`
|
|
@@ -565,10 +617,10 @@ Text input with label + hint.
|
|
|
565
617
|
| `label` | String | Label above the input |
|
|
566
618
|
| `type` | String | Native input type (`text`, `email`, `password`, `number`, …) |
|
|
567
619
|
| `placeholder` | String | Placeholder text |
|
|
568
|
-
| `hint` | String | Helper text below the input |
|
|
569
|
-
| `error` | Boolean | Error styling (red border + red hint) |
|
|
620
|
+
| `hint` | String | Helper text below the input, read as the field's description (`aria-describedby`) |
|
|
621
|
+
| `error` | Boolean | Error styling (red border + red hint) and `aria-invalid` on the field — it does not block the form |
|
|
570
622
|
| `disabled` | Boolean | Disabled state |
|
|
571
|
-
| `required` | Boolean | Required field |
|
|
623
|
+
| `required` | Boolean | Required field — the form does not submit while it is empty (since 1.20.0) |
|
|
572
624
|
| `name` | String | Form field name |
|
|
573
625
|
| `value` | String | Current value |
|
|
574
626
|
| `min`, `max`, `step` | String | Passed to the inner field — range and step of the picker for dates, times and numbers (since 1.17.0) |
|
|
@@ -577,7 +629,18 @@ Text input with label + hint.
|
|
|
577
629
|
|
|
578
630
|
Events: `glk-input` → `{ value }`, `glk-change` → `{ value }`. Native `input` / `change` also dispatched. Property: `.value`.
|
|
579
631
|
|
|
580
|
-
The inner field's validity
|
|
632
|
+
**Validity (since 1.20.0).** The element reports its inner field's validity to the form:
|
|
633
|
+
`required`, `pattern`, `min`/`max`, `minlength`, `type="email"` … make `form.checkValidity()`
|
|
634
|
+
false and stop a submit at the first invalid field with the browser's own message;
|
|
635
|
+
`reportValidity()` focuses the field. `element.validity`, `.validationMessage`,
|
|
636
|
+
`.willValidate`, `.checkValidity()` and `.reportValidity()` answer on the element. Before
|
|
637
|
+
1.20.0 none of this reached the form. `error` stays a marker: a server's verdict arrives that
|
|
638
|
+
way, and it must not block the next attempt.
|
|
639
|
+
|
|
640
|
+
**Label and focus (since 1.20.0).** The `label` is tied to the field: it names it for screen
|
|
641
|
+
readers, and a click on it focuses it — as do `element.focus()` and a `<label for>` naming the
|
|
642
|
+
element. An outer `<label for>` focuses, but cannot name, the field inside the shadow root;
|
|
643
|
+
use `label` for the name.
|
|
581
644
|
|
|
582
645
|
---
|
|
583
646
|
|
|
@@ -598,6 +661,7 @@ Radio button. Group multiple with the same `name`.
|
|
|
598
661
|
| `value` | String | Value submitted when checked |
|
|
599
662
|
| `checked` | Boolean | Checked state |
|
|
600
663
|
| `disabled` | Boolean | Disabled state |
|
|
664
|
+
| `required` | Boolean | On any radio of the group: the group is required, any checked radio satisfies it (since 1.20.0) |
|
|
601
665
|
|
|
602
666
|
Events: `glk-change` → `{ checked, value }`.
|
|
603
667
|
|
|
@@ -660,6 +724,7 @@ Search input with leading icon.
|
|
|
660
724
|
| Attribute | Type | Description |
|
|
661
725
|
|---|---|---|
|
|
662
726
|
| `placeholder` | String | Placeholder text |
|
|
727
|
+
| `label` | String | Accessible name of the field — it has no visible label (since 1.20.0) |
|
|
663
728
|
| `value` | String | Current value |
|
|
664
729
|
| `name` | String | Form field name |
|
|
665
730
|
| `disabled` | Boolean | Disabled state |
|
|
@@ -683,10 +748,11 @@ Dropdown select. Pass native `<option>` elements as children.
|
|
|
683
748
|
|
|
684
749
|
| Attribute | Type | Description |
|
|
685
750
|
|---|---|---|
|
|
686
|
-
| `label` | String | Label text |
|
|
751
|
+
| `label` | String | Label text, tied to the field |
|
|
687
752
|
| `name` | String | Form field name |
|
|
688
753
|
| `value` | String | Selected value |
|
|
689
754
|
| `disabled` | Boolean | Disabled state |
|
|
755
|
+
| `required` | Boolean | With an empty first option (`value=""`), the form does not submit until a choice is made (since 1.20.0) |
|
|
690
756
|
|
|
691
757
|
Children: native `<option>` elements, read from the light DOM.
|
|
692
758
|
|
|
@@ -755,8 +821,17 @@ Switch-style toggle (form-associated).
|
|
|
755
821
|
| `disabled` | Boolean | Disabled state |
|
|
756
822
|
| `name` | String | Form field name |
|
|
757
823
|
| `value` | String | Submitted value when checked (default `"on"`) |
|
|
824
|
+
| `required` | Boolean | Must be on before the form submits (since 1.20.0) |
|
|
825
|
+
|
|
826
|
+
Events: `glk-change` → `{ checked }`. Property: `.checked`.
|
|
758
827
|
|
|
759
|
-
|
|
828
|
+
**One control (since 1.20.0).** The switch is the native checkbox inside, with
|
|
829
|
+
`role="switch"`, named by `label`. The element itself no longer carries `role`,
|
|
830
|
+
`aria-checked` or `aria-disabled` — before 1.20.0 screen readers met a switch with a checkbox
|
|
831
|
+
inside. Select and style on `[checked]` / `[disabled]`; in tests,
|
|
832
|
+
`getByRole('switch', { name })` finds the input and `.click()`, `.check()` work on it.
|
|
833
|
+
`element.click()` and a `<label>` around the element or naming it toggle it, like a native
|
|
834
|
+
checkbox. Without `label` the element is exactly its track, 52 × 30 px (it was 64 × 34).
|
|
760
835
|
|
|
761
836
|
---
|
|
762
837
|
|
|
@@ -783,7 +858,7 @@ Modal dialog with overlay, title, body, and footer actions.
|
|
|
783
858
|
| Attribute | Type | Description |
|
|
784
859
|
|---|---|---|
|
|
785
860
|
| `open` | Boolean | Visibility state (reflected as `.is-active` on the overlay) |
|
|
786
|
-
| `title` | String | Header title |
|
|
861
|
+
| `title` | String | Header title; names the dialog |
|
|
787
862
|
|
|
788
863
|
Slots:
|
|
789
864
|
- default — modal body content
|
|
@@ -791,7 +866,17 @@ Slots:
|
|
|
791
866
|
|
|
792
867
|
Methods: `.show()`, `.close()`. Property: `.open`. Events: `glk-close`.
|
|
793
868
|
|
|
794
|
-
Closes automatically on overlay click and <kbd>Escape</kbd
|
|
869
|
+
Closes automatically on overlay click and <kbd>Escape</kbd>, with its fade, and emits
|
|
870
|
+
`glk-close` then; `.close()` and removing `open` do not emit.
|
|
871
|
+
|
|
872
|
+
**A native `<dialog>` (since 1.20.0).** The overlay is opened with `showModal()`: it lies in
|
|
873
|
+
the top layer, the page behind it is inert for pointer, keyboard and screen readers, focus
|
|
874
|
+
moves in and returns to where it came from on close, and the content is out of reach while
|
|
875
|
+
closed. Chrome focuses the first field of the content, Safari the first action — put
|
|
876
|
+
`autofocus` on the element that should get the focus, in the content or on an action.
|
|
877
|
+
|
|
878
|
+
While it is open, **everything outside is inert** — a `<glk-toast>` shown then is neither
|
|
879
|
+
clickable nor announced. Give feedback inside the modal, or close it first.
|
|
795
880
|
|
|
796
881
|
---
|
|
797
882
|
|
|
@@ -822,6 +907,9 @@ Slots:
|
|
|
822
907
|
Methods: `.show()`, `.close()`, `.toggle()`. Property: `.open`.
|
|
823
908
|
Events: `glk-open`, `glk-close`.
|
|
824
909
|
|
|
910
|
+
The trigger gets `aria-expanded`, kept in step with `open` and set again when the trigger is
|
|
911
|
+
swapped (since 1.20.0); `<glk-button>` and `<glk-pill>` hand it on to their native button.
|
|
912
|
+
|
|
825
913
|
**Naming warning:** the toggle method is deliberately called `.toggle()`, **not** `.togglePopover()` — the latter collides with the native `HTMLElement.togglePopover()` API from the HTML Popover specification.
|
|
826
914
|
|
|
827
915
|
---
|
|
@@ -908,6 +996,10 @@ Collapsible sections.
|
|
|
908
996
|
|
|
909
997
|
Default slot: body content. Events: `glk-toggle` → `{ open }`. Property: `.open`.
|
|
910
998
|
|
|
999
|
+
The trigger carries `aria-expanded` and `aria-controls`; a closed section is `inert`, so its
|
|
1000
|
+
links and fields are out of the tab order and the accessibility tree until it opens (since
|
|
1001
|
+
1.20.0 — before, they were only squeezed to zero height and Tab still reached them).
|
|
1002
|
+
|
|
911
1003
|
---
|
|
912
1004
|
|
|
913
1005
|
### 3.24 `<glk-list>` + `<glk-list-item>`
|
|
@@ -1216,8 +1308,9 @@ Events: `glk-change { dataUrl, width, height, size }` after a pick, on remove wi
|
|
|
1216
1308
|
<form id="contract-form">
|
|
1217
1309
|
<glk-title>New Contract</glk-title>
|
|
1218
1310
|
|
|
1311
|
+
<!-- required stops the submit with the browser's message (since 1.20.0) -->
|
|
1219
1312
|
<glk-input label="Contract Name" name="name" required></glk-input>
|
|
1220
|
-
<glk-select label="Category" name="category">
|
|
1313
|
+
<glk-select label="Category" name="category" required>
|
|
1221
1314
|
<option value="">Please select…</option>
|
|
1222
1315
|
<option value="insurance">Insurance</option>
|
|
1223
1316
|
<option value="rental">Rental</option>
|
|
@@ -1350,7 +1443,7 @@ All `glk-*` events bubble and are `composed: true`, so they pierce shadow bounda
|
|
|
1350
1443
|
|
|
1351
1444
|
### Always follow
|
|
1352
1445
|
|
|
1353
|
-
1. **`data-theme` on `<html>`** — never on `<body>` or individual elements; the global MutationObserver only watches `<html>`.
|
|
1446
|
+
1. **`data-theme` and `data-density` on `<html>`** — never on `<body>` or individual elements; the global MutationObserver only watches `<html>`.
|
|
1354
1447
|
2. **Form elements belong inside a `<form>`** — otherwise `ElementInternals.setFormValue()` has no effect and `new FormData()` will be empty.
|
|
1355
1448
|
3. **`<glk-list-item>` must be a direct child of `<glk-list>`** — nested deeper, it won't be observed for the auto-divider last-item detection.
|
|
1356
1449
|
4. **Popover trigger via `slot="trigger"`** — don't reference external elements by ID. The popover's built-in click handler listens on the trigger slot.
|
|
@@ -1369,6 +1462,7 @@ All `glk-*` events bubble and are `composed: true`, so they pierce shadow bounda
|
|
|
1369
1462
|
| `<glk-list>` inside `<glk-popover>` without `bare` | Add `bare` to the inner list so only the popover surface has glass. |
|
|
1370
1463
|
| `document.querySelector('.glass-modal').classList.add('is-active')` | Set `<glk-modal>.open = true` instead — the element manages `.is-active` internally. |
|
|
1371
1464
|
| `data-theme` directly on a `<glk-*>` element | Set it on `<html>`; theme propagates automatically through the MutationObserver. |
|
|
1465
|
+
| Shrinking elements one by one (`::part`, host heights) for a denser UI | `data-density="compact"` on `<html>`, or a density token such as `--gl-btn-height` on `:root` — GlassKit 1.21.0 or later. |
|
|
1372
1466
|
| Form element outside `<form>` | Wrap in a `<form>`; `ElementInternals` needs a form owner. |
|
|
1373
1467
|
| Overriding shadow styles with external CSS | Use CSS custom properties (`--gl-color-primary`, etc.) — they pierce shadow roots. Hard-coded selectors inside shadow roots cannot be targeted externally. |
|
|
1374
1468
|
| Forgetting `slot="trigger"` on the popover trigger element | Without it, the popover's internal click handler can't identify the trigger and never toggles. |
|
|
@@ -1376,6 +1470,9 @@ All `glk-*` events bubble and are `composed: true`, so they pierce shadow bounda
|
|
|
1376
1470
|
| `<glk-tab-bar>` without `.glass-bg--has-tab-bar` on the outer background | Tab bar covers bottom content. Add the modifier to the outer `.glass-bg` container. |
|
|
1377
1471
|
| `<glk-tab-bar floating>` without `<glk-tab-dock>` wrapper | Floating bar relies on the dock for fixed centered positioning. Always wrap it in `<glk-tab-dock>`. |
|
|
1378
1472
|
| `<glk-tab-dock>` without `.glass-bg--has-tab-bar-floating` on the outer background | Use `--has-tab-bar-floating` (not `--has-tab-bar`) for the floating variant — the padding budget differs. |
|
|
1473
|
+
| `<glk-toast>` shown while a `<glk-modal>` is open | Everything outside the open modal is inert — the toast is neither clickable nor announced. Show the message inside the modal, or close it first. |
|
|
1474
|
+
| `glk-toggle[aria-checked="true"]` / `[role="switch"]` on the host | Since 1.20.0 the host carries neither; use `glk-toggle[checked]`. The role sits on the native checkbox inside. |
|
|
1475
|
+
| Validating `<glk-input required>` by hand before submit | Not needed since 1.20.0 — the form's own validation stops the submit. |
|
|
1379
1476
|
|
|
1380
1477
|
---
|
|
1381
1478
|
|
|
@@ -1403,14 +1500,14 @@ All `glk-*` events bubble and are `composed: true`, so they pierce shadow bounda
|
|
|
1403
1500
|
| `<glk-status>` | Content | `message` | — | — |
|
|
1404
1501
|
| `<glk-title>` | Content | — | default | — |
|
|
1405
1502
|
| `<glk-button>` | Buttons | `variant`, `size`, `disabled`, `type` | default | `glk-click` |
|
|
1406
|
-
| `<glk-checkbox>` | Forms | `label`, `checked`, `disabled`, `name`, `value` | — | `glk-change` |
|
|
1503
|
+
| `<glk-checkbox>` | Forms | `label`, `checked`, `disabled`, `name`, `value`, `required` | — | `glk-change` |
|
|
1407
1504
|
| `<glk-input>` | Forms | `label`, `type`, `placeholder`, `hint`, `error`, `disabled`, `required`, `name`, `value`, `min`, `max`, `step`, `minlength`, `maxlength`, `pattern`, `autocomplete`, `inputmode` | — | `glk-input`, `glk-change` |
|
|
1408
|
-
| `<glk-radio>` | Forms | `label`, `name`, `value`, `checked`, `disabled` | — | `glk-change` |
|
|
1505
|
+
| `<glk-radio>` | Forms | `label`, `name`, `value`, `checked`, `disabled`, `required` | — | `glk-change` |
|
|
1409
1506
|
| `<glk-range>` | Forms | `label`, `min`, `max`, `value`, `step`, `name`, `disabled` | — | `glk-input`, `glk-change` |
|
|
1410
|
-
| `<glk-search>` | Forms | `placeholder`, `value`, `name`, `disabled` | — | `glk-input`, `glk-change` |
|
|
1411
|
-
| `<glk-select>` | Forms | `label`, `name`, `value`, `disabled` | default (`<option>`) | `glk-change` |
|
|
1507
|
+
| `<glk-search>` | Forms | `placeholder`, `label`, `value`, `name`, `disabled` | — | `glk-input`, `glk-change` |
|
|
1508
|
+
| `<glk-select>` | Forms | `label`, `name`, `value`, `disabled`, `required` | default (`<option>`) | `glk-change` |
|
|
1412
1509
|
| `<glk-textarea>` | Forms | `label`, `rows`, `placeholder`, `name`, `value`, `disabled`, `required` | — | `glk-input`, `glk-change` |
|
|
1413
|
-
| `<glk-toggle>` | Forms | `label`, `checked`, `disabled`, `name`, `value` | — | `glk-change` |
|
|
1510
|
+
| `<glk-toggle>` | Forms | `label`, `checked`, `disabled`, `name`, `value`, `required` | — | `glk-change` |
|
|
1414
1511
|
| `<glk-modal>` | Feedback | `open`, `title` | default, `actions` | `glk-close` |
|
|
1415
1512
|
| `<glk-popover>` | Feedback | `open`, `placement` | `trigger`, default | `glk-open`, `glk-close` |
|
|
1416
1513
|
| `<glk-progress>` | Feedback | `value`, `label`, `variant`, `size` | — | — |
|
|
@@ -1538,18 +1635,18 @@ See the class-based [GlassKit CSS `SKILL.md`](https://github.com/JUNGHERZ/GlassK
|
|
|
1538
1635
|
|---|---|
|
|
1539
1636
|
| Base class | `src/base.js` → `GlkElement`, `GlkFormElement` |
|
|
1540
1637
|
| Theme sync | Single module-level `MutationObserver` in `base.js` |
|
|
1541
|
-
| Adopted stylesheets | `
|
|
1638
|
+
| Adopted stylesheets | `componentsSheet` (from `@jungherz-de/glasskit/glasskit-styles.js`) + module-level `hostSheet` / `inlineHostSheet` (they also set `color-scheme` per theme) + an element's own `hostStyles` |
|
|
1542
1639
|
| Per-component structure | One `.js` file per element in `src/components/{category}/glk-{name}.js` |
|
|
1543
1640
|
| Barrel | `src/index.js` — exports and registers all 36 elements, and exports `GlkElement` / `GlkFormElement` (since 1.14.0) |
|
|
1544
1641
|
| Build | Rollup → IIFE (`glasskit-elements.js`), minified IIFE, ESM (`glasskit-elements.esm.js`), and per-element ESM in `dist/components/` with `base.js` as a stable entry |
|
|
1545
1642
|
|
|
1546
1643
|
Each element is a subclass of `GlkElement` (or `GlkFormElement` for form controls) and follows a consistent lifecycle:
|
|
1547
1644
|
|
|
1548
|
-
1. `constructor()` — attach open shadow, adopt GlassKit stylesheet + host display sheet
|
|
1645
|
+
1. `constructor()` — attach open shadow (`delegatesFocus` for form elements with one field), adopt GlassKit stylesheet + host display sheet
|
|
1549
1646
|
2. `connectedCallback()` — create theme wrapper, call `render()`, call `setupEvents()`, register for global theme sync
|
|
1550
1647
|
3. `render()` — build shadow DOM tree (override per component)
|
|
1551
1648
|
4. `setupEvents()` — attach DOM listeners (override per component)
|
|
1552
1649
|
5. `attributeChangedCallback()` — call `onAttributeChanged()` (override per component)
|
|
1553
1650
|
6. `disconnectedCallback()` — unregister, call `teardownEvents()`
|
|
1554
1651
|
|
|
1555
|
-
The `GlkFormElement` subclass adds `ElementInternals` for native form participation via `this.setFormValue(value)`, plus `formResetCallback` → `resetValue()` and `formStateRestoreCallback` → `restoreValue()`.
|
|
1652
|
+
The `GlkFormElement` subclass adds `ElementInternals` for native form participation via `this.setFormValue(value)`, plus `formResetCallback` → `resetValue()` and `formStateRestoreCallback` → `restoreValue()`. Since 1.20.0 it mirrors the validity of the native field returned by `get _validityField()` onto the host (`syncValidity()`, run after every `setFormValue()` and attribute change); `<glk-radio>` overrides it with the group's verdict.
|