@guildofgleks/ui 21.6.0 → 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 +326 -82
- package/CHANGELOG.md +269 -2
- package/README.md +98 -20
- package/TOKENS.md +10 -7
- package/fesm2022/guildofgleks-ui.mjs +1067 -1383
- package/fesm2022/guildofgleks-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/styles/button.css +11 -32
- package/styles/index.css +5 -0
- 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/ripple.css +94 -0
- package/styles/surfaces.css +151 -0
- package/styles/theme.css +620 -516
- package/types/guildofgleks-ui.d.ts +359 -36
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* `primeng` — PrimeNG's Aura theme (light, blue primary), as a @guildofgleks/ui theme.
|
|
3
|
+
*
|
|
4
|
+
* Import it after `index.css`, then put the attribute on the root — or on any subtree:
|
|
5
|
+
*
|
|
6
|
+
* @import '@guildofgleks/ui/styles/index.css';
|
|
7
|
+
* @import '@guildofgleks/ui/styles/presets/primeng.css';
|
|
8
|
+
*
|
|
9
|
+
* <html data-theme="primeng">
|
|
10
|
+
*
|
|
11
|
+
* Unlike `slate.css`/`one-dark.css`/`one-light.css`, this is not palette-only. PrimeNG's Aura
|
|
12
|
+
* has its own visual character — thin borders, a 6px radius, medium-weight sentence-case
|
|
13
|
+
* labels instead of this library's default shouty caps — and matching that needs the
|
|
14
|
+
* `docs/themes.md` iteration-1 character layer (`--gog-radius`, `--gog-control-border-width`,
|
|
15
|
+
* `--gog-text-transform`, `--gog-letter-spacing`) plus a small number of genuinely per-component
|
|
16
|
+
* settings the character layer has no vocabulary for (a table's header font, a slider's neutral
|
|
17
|
+
* track colour). Ported from `gleks-ui-lab`'s hand-authored `[data-theme='primeng']` block
|
|
18
|
+
* (`docs/themes.md`, iteration 3) — see that file's own comment for what changed in the move,
|
|
19
|
+
* beyond the palette staying byte-for-byte identical.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
:root[data-theme='primeng'],
|
|
23
|
+
[data-theme='primeng'] {
|
|
24
|
+
color-scheme: light;
|
|
25
|
+
|
|
26
|
+
/* Palette */
|
|
27
|
+
--gog-background-color: #f8fafc;
|
|
28
|
+
--gog-surface-color: #ffffff;
|
|
29
|
+
--gog-hover-color: #f1f5f9;
|
|
30
|
+
--gog-border-color: #e2e8f0;
|
|
31
|
+
--gog-text-color: #0f172a;
|
|
32
|
+
--gog-accent-text-color: #ffffff;
|
|
33
|
+
--gog-muted-text-color: #64748b;
|
|
34
|
+
--gog-primary-color: #0f172a;
|
|
35
|
+
/* Shifted one step down Aura's own blue scale in 21.7.0 — 500/600/700 became 600/700/800.
|
|
36
|
+
White on blue-500 is 3.68:1, under WCAG AA's 4.5 for the label of a filled button, and it
|
|
37
|
+
is `#3b82f6` verbatim from the palette this reproduces. Rather than invent a colour, this
|
|
38
|
+
takes the next step of the same ramp: still Aura's blue, one shade deeper, 5.17:1. */
|
|
39
|
+
--gog-accent-color: #2563eb;
|
|
40
|
+
--gog-accent-bright: #1d4ed8;
|
|
41
|
+
--gog-accent-dim: #1e40af;
|
|
42
|
+
--gog-accent-pale: #dbeafe;
|
|
43
|
+
--gog-secondary-color: #64748b;
|
|
44
|
+
--gog-success-color: #22c55e;
|
|
45
|
+
--gog-danger-color: #ef4444;
|
|
46
|
+
--gog-warning-color: #f59e0b;
|
|
47
|
+
--gog-info-color: #0ea5e9;
|
|
48
|
+
--gog-panel-shadow: 0 4px 6px -2px rgba(0, 0, 0, 0.05), 0 12px 16px -4px rgba(0, 0, 0, 0.08);
|
|
49
|
+
--gog-spinner-overlay-bg: rgba(248, 250, 252, 0.75);
|
|
50
|
+
|
|
51
|
+
/* Fonts — PrimeNG doesn't split heading/body, one system sans everywhere */
|
|
52
|
+
--gog-font-heading:
|
|
53
|
+
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
54
|
+
--gog-font-body:
|
|
55
|
+
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
56
|
+
--gog-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
57
|
+
|
|
58
|
+
/* Character layer — thinner borders, tighter focus ring, 6px radius everywhere that
|
|
59
|
+
derives from --gog-radius (buttons, fields, checkboxes, dialogs), sentence-case labels
|
|
60
|
+
instead of shouty caps. This is the whole reason iteration 1 exists: before it, the two
|
|
61
|
+
lines below were ten — one letter-spacing/text-transform pair per component
|
|
62
|
+
(button/input-label/select-label/multiselect-label, plus text-transform-only on
|
|
63
|
+
accordion-header/table-header) — and even at ten lines it missed six more components
|
|
64
|
+
that share the same idea (button-toggle, calendar-weekday, autocomplete-label,
|
|
65
|
+
datepicker-label, slider-label, table-total all still shouted in caps under this theme,
|
|
66
|
+
an inconsistency nobody had a way to see until there was one token to check instead of
|
|
67
|
+
twenty). Setting the character layer once now covers all eighteen correctly. */
|
|
68
|
+
--gog-radius: 6px;
|
|
69
|
+
/* Aura runs slightly tighter than this library's default — a data-dense posture, closer to
|
|
70
|
+
ledger's than to material's, which is the distinction density exists to express. */
|
|
71
|
+
--gog-density: 0.95;
|
|
72
|
+
--gog-control-border-width: 1px;
|
|
73
|
+
--gog-focus-ring-width: 2px;
|
|
74
|
+
--gog-focus-ring-offset: 2px;
|
|
75
|
+
--gog-text-transform: none;
|
|
76
|
+
--gog-letter-spacing: normal;
|
|
77
|
+
|
|
78
|
+
/* Button — medium weight, body font (casing/tracking now come from the character layer) */
|
|
79
|
+
--gog-button-font-family: var(--gog-font-body);
|
|
80
|
+
--gog-button-font-weight: 500;
|
|
81
|
+
|
|
82
|
+
/* Field labels — muted gray, not accent-colored (casing/tracking from the character layer) */
|
|
83
|
+
--gog-input-label-color: var(--gog-muted-text-color);
|
|
84
|
+
--gog-input-label-font-family: var(--gog-font-body);
|
|
85
|
+
--gog-input-field-border: var(--gog-border-color);
|
|
86
|
+
--gog-select-label-color: var(--gog-muted-text-color);
|
|
87
|
+
--gog-select-label-font-family: var(--gog-font-body);
|
|
88
|
+
--gog-select-field-border: var(--gog-border-color);
|
|
89
|
+
--gog-multiselect-label-color: var(--gog-muted-text-color);
|
|
90
|
+
--gog-multiselect-label-font-family: var(--gog-font-body);
|
|
91
|
+
--gog-multiselect-field-border: var(--gog-border-color);
|
|
92
|
+
--gog-multiselect-checkbox-border: var(--gog-border-color);
|
|
93
|
+
|
|
94
|
+
/* Checkbox */
|
|
95
|
+
--gog-checkbox-border-color: var(--gog-border-color);
|
|
96
|
+
--gog-checkbox-label-color: var(--gog-text-color);
|
|
97
|
+
|
|
98
|
+
/* Accordion — surface header instead of transparent (casing from the character layer) */
|
|
99
|
+
--gog-accordion-font-family: var(--gog-font-body);
|
|
100
|
+
--gog-accordion-header-bg: var(--gog-surface-color);
|
|
101
|
+
--gog-accordion-hover-bg: var(--gog-hover-color);
|
|
102
|
+
--gog-accordion-body-bg: var(--gog-surface-color);
|
|
103
|
+
--gog-accordion-border-color: var(--gog-border-color);
|
|
104
|
+
--gog-accordion-radius: 6px;
|
|
105
|
+
--gog-accordion-body-radius: 6px;
|
|
106
|
+
|
|
107
|
+
/* Table — neutral row hover (header casing from the character layer) */
|
|
108
|
+
--gog-table-header-font-family: var(--gog-font-body);
|
|
109
|
+
--gog-table-border-color: var(--gog-border-color);
|
|
110
|
+
--gog-table-hover-bg: var(--gog-hover-color);
|
|
111
|
+
|
|
112
|
+
/* Slider / spinner — neutral track instead of accent-tinted */
|
|
113
|
+
--gog-slider-track-bg: var(--gog-border-color);
|
|
114
|
+
--gog-slider-label-color: var(--gog-muted-text-color);
|
|
115
|
+
--gog-spinner-track-color: var(--gog-border-color);
|
|
116
|
+
|
|
117
|
+
/* Dialog / toast */
|
|
118
|
+
--gog-dialog-backdrop-bg: rgba(0, 0, 0, 0.32);
|
|
119
|
+
--gog-dialog-shadow: 0 4px 6px -2px rgba(0, 0, 0, 0.05), 0 12px 16px -4px rgba(0, 0, 0, 0.08);
|
|
120
|
+
--gog-toast-radius: 6px;
|
|
121
|
+
}
|
package/styles/presets/slate.css
CHANGED
|
@@ -8,12 +8,18 @@
|
|
|
8
8
|
*
|
|
9
9
|
* <html data-theme="slate">
|
|
10
10
|
*
|
|
11
|
-
* Note what this file does *not* contain: no component tokens, no `--gog-
|
|
12
|
-
* `--gog-table-*`. It declares the palette and
|
|
13
|
-
* `theme.css`'s derived layer is re-declared on `[data-theme]`,
|
|
14
|
-
* whichever palette
|
|
15
|
-
* entire library. If you find yourself listing component
|
|
16
|
-
* derived layer is missing instead.
|
|
11
|
+
* Note what this file does *not* contain: no component tokens, no `--gog-button-*`, no
|
|
12
|
+
* `--gog-table-*`. It declares the palette and a handful of foundation tokens, and nothing
|
|
13
|
+
* else. Every component token in `theme.css`'s derived layer is re-declared on `[data-theme]`,
|
|
14
|
+
* so it re-resolves against whichever palette and character are in scope — which is exactly why
|
|
15
|
+
* a theme this short can restyle the entire library. If you find yourself listing component
|
|
16
|
+
* tokens in a theme, something in the derived layer is missing instead.
|
|
17
|
+
*
|
|
18
|
+
* Until 21.7.0 this file was the palette-only worked example, and the README pointed at it to
|
|
19
|
+
* make that argument. The argument is still true and the README still makes it — but it did not
|
|
20
|
+
* need a whole preset held back to prove it, and holding one back meant shipping a theme that
|
|
21
|
+
* was a recoloured default. `slate` is now the *soft modern* entry in the catalogue: generous
|
|
22
|
+
* rounding, thin borders, a little more air than the house default.
|
|
17
23
|
*
|
|
18
24
|
* Both selectors are listed for the same reason `theme.css` lists both: `:root[data-theme]`
|
|
19
25
|
* themes the page, the bare `[data-theme]` themes any subtree, so several themes can render
|
|
@@ -24,6 +30,16 @@
|
|
|
24
30
|
[data-theme='slate'] {
|
|
25
31
|
color-scheme: light;
|
|
26
32
|
|
|
33
|
+
/* Character layer — soft modern. Generous rounding against `ledger`'s zero and the editor
|
|
34
|
+
presets' 4px, hairline borders, sentence case, and a density slightly above the house
|
|
35
|
+
default: this is the roomy end of the catalogue, and the contrast with `ledger` at 0.9 is
|
|
36
|
+
the point of having both. */
|
|
37
|
+
--gog-radius: 12px;
|
|
38
|
+
--gog-density: 1.05;
|
|
39
|
+
--gog-control-border-width: 1px;
|
|
40
|
+
--gog-text-transform: none;
|
|
41
|
+
--gog-letter-spacing: normal;
|
|
42
|
+
|
|
27
43
|
/* Surfaces — cool neutrals rather than the house obsidian */
|
|
28
44
|
--gog-background-color: #f4f6f8;
|
|
29
45
|
--gog-surface-color: #ffffff;
|
|
@@ -33,12 +49,14 @@
|
|
|
33
49
|
/* Type */
|
|
34
50
|
--gog-text-color: #1e293b;
|
|
35
51
|
--gog-accent-text-color: #ffffff;
|
|
36
|
-
|
|
52
|
+
/* #64748b missed AA by 0.11 against the page ground; deepened one step. */
|
|
53
|
+
--gog-muted-text-color: #5c6b80;
|
|
37
54
|
|
|
38
55
|
/* Brand — indigo instead of gold, to make the swap unmistakable */
|
|
39
56
|
--gog-primary-color: #1e293b;
|
|
40
57
|
--gog-accent-color: #4f46e5;
|
|
41
|
-
|
|
58
|
+
/* Hover fill: white on #6366f1 was 4.47:1, short of AA by 0.03. */
|
|
59
|
+
--gog-accent-bright: #5b5ee8;
|
|
42
60
|
--gog-accent-dim: #4338ca;
|
|
43
61
|
--gog-accent-pale: #e0e7ff;
|
|
44
62
|
--gog-secondary-color: #0ea5e9;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* `terminal` — monochrome phosphor. Green on near-black, everything monospaced, square
|
|
3
|
+
* corners, no motion: the character-cell terminal, which is `docs/themes.md`'s Retro family.
|
|
4
|
+
*
|
|
5
|
+
* Import it after `index.css`, then put the attribute on the root — or on any subtree:
|
|
6
|
+
*
|
|
7
|
+
* @import '@guildofgleks/ui/styles/index.css';
|
|
8
|
+
* @import '@guildofgleks/ui/styles/presets/terminal.css';
|
|
9
|
+
*
|
|
10
|
+
* <html data-theme="terminal">
|
|
11
|
+
*
|
|
12
|
+
* Palette plus the character layer, no per-component overrides. The font is the one thing this
|
|
13
|
+
* identity cannot do without, and it does not need a download to get it: `ui-monospace` resolves
|
|
14
|
+
* to the platform's own terminal face (SF Mono, Cascadia, DejaVu Sans Mono), which is more
|
|
15
|
+
* authentic here than any webfont would be. `presets/terminal.fonts.css` is an optional extra
|
|
16
|
+
* for a period face — importing this file alone makes no network request.
|
|
17
|
+
*
|
|
18
|
+
* Amber instead of green is two declarations: swap `--gog-accent-*` and `--gog-text-color` for
|
|
19
|
+
* their amber equivalents. The rest of the theme does not care which phosphor it is.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
:root[data-theme='terminal'],
|
|
23
|
+
[data-theme='terminal'] {
|
|
24
|
+
color-scheme: dark;
|
|
25
|
+
|
|
26
|
+
/* Palette — P1 green phosphor on an unlit screen */
|
|
27
|
+
--gog-background-color: #0a0e0a;
|
|
28
|
+
--gog-surface-color: #121a12;
|
|
29
|
+
--gog-hover-color: #1b2a1b;
|
|
30
|
+
--gog-border-color: #274a2c;
|
|
31
|
+
--gog-text-color: #c8f5c8;
|
|
32
|
+
--gog-accent-text-color: #04120a;
|
|
33
|
+
--gog-muted-text-color: #6fae6f;
|
|
34
|
+
--gog-primary-color: #c8f5c8;
|
|
35
|
+
--gog-accent-color: #3ddc5c;
|
|
36
|
+
--gog-accent-bright: #7cf591;
|
|
37
|
+
--gog-accent-dim: #2fae48;
|
|
38
|
+
--gog-accent-pale: #17311c;
|
|
39
|
+
--gog-secondary-color: #6fae6f;
|
|
40
|
+
|
|
41
|
+
/* Semantics — a monochrome display had no colour to spare, so these stay within the phosphor
|
|
42
|
+
family and separate by brightness. Only danger breaks out, because a destructive action is
|
|
43
|
+
the one thing worth spending the screen's only other colour on. */
|
|
44
|
+
--gog-success-color: #3ddc5c;
|
|
45
|
+
--gog-danger-color: #ff5f56;
|
|
46
|
+
--gog-warning-color: #d4d44a;
|
|
47
|
+
--gog-info-color: #8fd8a0;
|
|
48
|
+
|
|
49
|
+
/* A glow, not a shadow: a phosphor screen bleeds light outwards instead of casting one. */
|
|
50
|
+
--gog-panel-shadow: 0 0 0 1px var(--gog-border-color), 0 0 18px rgba(61, 220, 92, 0.12);
|
|
51
|
+
--gog-spinner-overlay-bg: rgba(10, 14, 10, 0.88);
|
|
52
|
+
|
|
53
|
+
/* Character layer — the whole identity in seven declarations. Monospace everywhere, not just
|
|
54
|
+
in code: a character-cell display had one grid and one face. Square corners and 1px rules
|
|
55
|
+
because the display drew box-drawing characters, and no motion because it had no way to
|
|
56
|
+
animate anything that was not a blinking cursor. */
|
|
57
|
+
--gog-font-heading: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
58
|
+
--gog-font-body: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
59
|
+
--gog-radius: 0;
|
|
60
|
+
--gog-density: 0.85;
|
|
61
|
+
--gog-control-border-width: 1px;
|
|
62
|
+
--gog-text-transform: uppercase;
|
|
63
|
+
--gog-letter-spacing: 1px;
|
|
64
|
+
--gog-duration-fast: 0s;
|
|
65
|
+
--gog-duration-base: 0s;
|
|
66
|
+
--gog-duration-slow: 0s;
|
|
67
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* `terminal.fonts.css` — the optional webfont half of `presets/terminal.css`.
|
|
3
|
+
*
|
|
4
|
+
* **This file makes a network request. That is the whole reason it is a separate file.**
|
|
5
|
+
* See `parchment.fonts.css` for the full argument; the contract is identical.
|
|
6
|
+
*
|
|
7
|
+
* @import '@guildofgleks/ui/styles/index.css';
|
|
8
|
+
* @import '@guildofgleks/ui/styles/presets/terminal.css';
|
|
9
|
+
* @import '@guildofgleks/ui/styles/presets/terminal.fonts.css'; ← opt in
|
|
10
|
+
*
|
|
11
|
+
* Import it *after* the preset — it re-points the same tokens, and later wins.
|
|
12
|
+
*
|
|
13
|
+
* Worth knowing before you do: `terminal.css` on its own resolves to `ui-monospace`, which is
|
|
14
|
+
* the platform's *own* terminal face. That is arguably the more authentic result, and it is
|
|
15
|
+
* certainly the faster one. Take this file when you want the same face on every machine —
|
|
16
|
+
* a screenshot in documentation, a kiosk — rather than when you want it to look better.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&display=swap');
|
|
20
|
+
|
|
21
|
+
:root[data-theme='terminal'],
|
|
22
|
+
[data-theme='terminal'] {
|
|
23
|
+
--gog-font-heading: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
24
|
+
--gog-font-body: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
25
|
+
--gog-font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
26
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* `[gogRipple]`'s classes, in a **global** stylesheet for the same reason as `gogBadge`'s and
|
|
3
|
+
* `.gog-btn`'s: the directive appends its nodes into a *consumer's* own element, which is light
|
|
4
|
+
* DOM belonging to that consumer's view, so a component-scoped stylesheet could never reach it.
|
|
5
|
+
*
|
|
6
|
+
* ── Why the layer exists at all ─────────────────────────────────────────────────
|
|
7
|
+
* The obvious ripple gives the host `overflow: hidden` and paints inside it. That breaks the
|
|
8
|
+
* first ordinary pairing anyone tries: `gogBadge` pins its badge with **negative** insets so it
|
|
9
|
+
* sits outside the host's box on purpose (see utilities.css), and a host that clips its overflow
|
|
10
|
+
* clips the badge too. So the host is never clipped — `.gog-ripple-layer` is, and it is the only
|
|
11
|
+
* thing that is.
|
|
12
|
+
*
|
|
13
|
+
* ── How the layer learns the host's corner radius ───────────────────────────────
|
|
14
|
+
* `border-radius` set to `inherit`. It is not an inherited property, but the explicit
|
|
15
|
+
* keyword takes the parent's computed value — so the layer matches whatever radius the host
|
|
16
|
+
* ended up with, per instance, per theme, with no token to declare and nothing for a host
|
|
17
|
+
* component to remember to set. The plan expected a token here; this is exact and free.
|
|
18
|
+
*
|
|
19
|
+
* ── Why the wash paints over the host's content ─────────────────────────────────
|
|
20
|
+
* The layer is a positioned child with no `z-index`, so it paints above the host's text. The
|
|
21
|
+
* alternative — `z-index: -1` inside an `isolation: isolate` host, which paints it between the
|
|
22
|
+
* background and the text — is prettier where it works, and silently invisible where it does
|
|
23
|
+
* not: on a wrapper host like `<gog-button gogRipple>` the inner `.gog-btn`'s own background
|
|
24
|
+
* would cover it, and "the ripple just does not appear" is a far worse failure than a low-alpha
|
|
25
|
+
* wash crossing a label. Material makes the same call, at a similar opacity.
|
|
26
|
+
*/
|
|
27
|
+
.gog-ripple-host {
|
|
28
|
+
/* The layer is positioned against this element, so it has to be a containing block. Harmless
|
|
29
|
+
on an already-relative host; a host that is itself absolutely positioned should set its own
|
|
30
|
+
position after this class, which ordinary specificity allows. */
|
|
31
|
+
position: relative;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.gog-ripple-layer {
|
|
35
|
+
position: absolute;
|
|
36
|
+
inset: 0;
|
|
37
|
+
border-radius: inherit;
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
pointer-events: none;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.gog-ripple {
|
|
43
|
+
position: absolute;
|
|
44
|
+
border-radius: 50%;
|
|
45
|
+
background-color: var(--gog-ripple-color);
|
|
46
|
+
/* Both animations are `forwards`, so these are only the pre-first-frame values. */
|
|
47
|
+
opacity: 0;
|
|
48
|
+
transform: scale(0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.gog-ripple--entering {
|
|
52
|
+
animation: gog-ripple-enter var(--gog-ripple-enter-duration) var(--gog-ripple-easing) forwards;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.gog-ripple--leaving {
|
|
56
|
+
animation: gog-ripple-exit var(--gog-ripple-exit-duration) var(--gog-ripple-easing) forwards;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@keyframes gog-ripple-enter {
|
|
60
|
+
from {
|
|
61
|
+
opacity: 0;
|
|
62
|
+
transform: scale(0);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
to {
|
|
66
|
+
opacity: var(--gog-ripple-opacity);
|
|
67
|
+
transform: scale(1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* The scale is held at 1 through the fade — without it the node snaps back to the base rule's
|
|
72
|
+
`scale(0)` and the wave collapses inwards instead of dissolving. */
|
|
73
|
+
@keyframes gog-ripple-exit {
|
|
74
|
+
from {
|
|
75
|
+
opacity: var(--gog-ripple-opacity);
|
|
76
|
+
transform: scale(1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
to {
|
|
80
|
+
opacity: 0;
|
|
81
|
+
transform: scale(1);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/*
|
|
86
|
+
* Suppressed, not shortened. The directive already refuses to create a node when the preference
|
|
87
|
+
* is set, so this rule only covers a preference switched on while a ripple is mid-flight — and
|
|
88
|
+
* documents the intent in the one file a reader checks for it.
|
|
89
|
+
*/
|
|
90
|
+
@media (prefers-reduced-motion: reduce) {
|
|
91
|
+
.gog-ripple-layer {
|
|
92
|
+
display: none;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The projected pieces of `gog-card` and `gog-panel`.
|
|
3
|
+
*
|
|
4
|
+
* Global for the same reason `gog-collapsible`'s trigger/content classes and `[gogButton]`'s
|
|
5
|
+
* `.gog-btn` are: every class below lands on an element the *consumer* wrote — their `<h3>`,
|
|
6
|
+
* their `<img>`, their `<a>` — which is light DOM belonging to the consumer's own view. A
|
|
7
|
+
* component's scoped stylesheet can never reach it, so these rules have to live here or the
|
|
8
|
+
* slots would come out unstyled with no way to fix them from inside the library.
|
|
9
|
+
*
|
|
10
|
+
* Everything each component paints on *itself* stays in its own `.scss`.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/* ── gog-card ───────────────────────────────────────────────────────────────── */
|
|
14
|
+
|
|
15
|
+
.gog-card__header {
|
|
16
|
+
margin: 0;
|
|
17
|
+
color: var(--gog-card-heading-color);
|
|
18
|
+
font-family: var(--gog-card-heading-font-family);
|
|
19
|
+
font-size: var(--gog-card-heading-font-size);
|
|
20
|
+
font-weight: var(--gog-card-heading-font-weight);
|
|
21
|
+
line-height: var(--gog-card-heading-line-height);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* Media runs to the card's edges rather than sitting inside its padding — that is the whole
|
|
26
|
+
* difference between `gogCardMedia` and an `<img>` a consumer drops in the body, and it is why
|
|
27
|
+
* the negative margins repeat the card's own padding chain instead of a fixed number.
|
|
28
|
+
*/
|
|
29
|
+
.gog-card__media {
|
|
30
|
+
display: block;
|
|
31
|
+
inline-size: calc(
|
|
32
|
+
100% + 2 *
|
|
33
|
+
var(--gog-card-padding-x, var(--gog-card-size-padding-x, var(--gog-card-md-padding-x)))
|
|
34
|
+
);
|
|
35
|
+
margin-inline: calc(
|
|
36
|
+
-1 * var(--gog-card-padding-x, var(--gog-card-size-padding-x, var(--gog-card-md-padding-x)))
|
|
37
|
+
);
|
|
38
|
+
object-fit: cover;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Only a first child can round into the card's own top corners; anywhere else it is a band. */
|
|
42
|
+
.gog-card__media:first-child {
|
|
43
|
+
margin-block-start: calc(
|
|
44
|
+
-1 * var(--gog-card-padding-y, var(--gog-card-size-padding-y, var(--gog-card-md-padding-y)))
|
|
45
|
+
);
|
|
46
|
+
border-start-end-radius: calc(var(--gog-card-radius) - var(--gog-card-border-width));
|
|
47
|
+
border-start-start-radius: calc(var(--gog-card-radius) - var(--gog-card-border-width));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.gog-card__footer {
|
|
51
|
+
display: flex;
|
|
52
|
+
flex-wrap: wrap;
|
|
53
|
+
align-items: center;
|
|
54
|
+
gap: var(--gog-card-footer-gap);
|
|
55
|
+
padding-block-start: var(--gog-card-footer-padding-top);
|
|
56
|
+
border-block-start: var(--gog-card-border-width) var(--gog-card-border-style)
|
|
57
|
+
var(--gog-card-footer-border-color);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/*
|
|
61
|
+
* `gogCardLink` — the whole card activates this one link.
|
|
62
|
+
*
|
|
63
|
+
* The link keeps every bit of its own behaviour (href, Enter, middle-click, "open in new tab");
|
|
64
|
+
* only its hit area grows, as a pseudo-element stretched over the card. The card is the
|
|
65
|
+
* containing block for it (`position: relative` on `gog-card`), so this element itself must NOT
|
|
66
|
+
* be positioned — that is also why the escape rule below excludes it.
|
|
67
|
+
*/
|
|
68
|
+
.gog-card__link {
|
|
69
|
+
/*
|
|
70
|
+
* The card is the affordance — its cursor, its hover elevation and its focus ring all say
|
|
71
|
+
* "this activates". A link rendered in the browser's blue-and-underlined inside that reads as
|
|
72
|
+
* a second, separate control sitting on the surface, which is exactly what it is not. One
|
|
73
|
+
* class of specificity, so a consumer who wants their own link colour simply writes it.
|
|
74
|
+
*/
|
|
75
|
+
color: inherit;
|
|
76
|
+
text-decoration: none;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.gog-card__link::after {
|
|
80
|
+
position: absolute;
|
|
81
|
+
inset: 0;
|
|
82
|
+
content: '';
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* The usual "this row is a link" hint, moved to the whole card since the whole card is one. */
|
|
86
|
+
.gog-card--interactive:hover .gog-card__link {
|
|
87
|
+
text-decoration: underline;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.gog-card__link.gog-card__link:focus-visible {
|
|
91
|
+
outline: none;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* The ring belongs around the card, because the card is what the link's hit area covers. */
|
|
95
|
+
.gog-card__link.gog-card__link:focus-visible::after {
|
|
96
|
+
border-radius: var(--gog-card-radius);
|
|
97
|
+
outline: var(--gog-card-focus-ring-width) solid var(--gog-card-focus-ring);
|
|
98
|
+
outline-offset: var(--gog-card-focus-ring-offset);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
* Doubled class for one point of specificity over a consumer's plainest rule — see
|
|
103
|
+
* `scripts/check-state-specificity.mjs`. A disabled card whose link still swallowed clicks
|
|
104
|
+
* would be the same defect the disabled-button rules were hardened against.
|
|
105
|
+
*/
|
|
106
|
+
.gog-card--disabled.gog-card--disabled .gog-card__link,
|
|
107
|
+
.gog-card--loading.gog-card--loading .gog-card__link {
|
|
108
|
+
pointer-events: none;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/*
|
|
112
|
+
* Anything *else* interactive inside an interactive card or a collapsible panel header sits
|
|
113
|
+
* above the stretched hit area, instead of being covered by it — a footer button in a clickable
|
|
114
|
+
* card is the common case, and having it silently activate the card's link instead would be the
|
|
115
|
+
* pattern's classic trap.
|
|
116
|
+
*
|
|
117
|
+
* The two elements that own a stretched hit area are excluded: positioning them would make each
|
|
118
|
+
* one its own containing block, and the pseudo-element would then cover the control instead of
|
|
119
|
+
* the surface — the exact thing it exists to spread across.
|
|
120
|
+
*
|
|
121
|
+
* Written entirely in `:where()` so it carries zero specificity: it is a default that must never
|
|
122
|
+
* win against a consumer positioning their own element.
|
|
123
|
+
*/
|
|
124
|
+
:where(.gog-card--interactive, .gog-panel__header)
|
|
125
|
+
:where(a, button, input, select, textarea, summary, [tabindex]):where(
|
|
126
|
+
:not(.gog-card__link, .gog-panel__toggle)
|
|
127
|
+
) {
|
|
128
|
+
position: relative;
|
|
129
|
+
z-index: 1;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* ── gog-panel ──────────────────────────────────────────────────────────────── */
|
|
133
|
+
|
|
134
|
+
.gog-panel__heading {
|
|
135
|
+
margin: 0;
|
|
136
|
+
color: var(--gog-panel-heading-color);
|
|
137
|
+
font-family: var(--gog-panel-heading-font-family);
|
|
138
|
+
font-size: var(--gog-panel-heading-font-size);
|
|
139
|
+
font-weight: var(--gog-panel-heading-font-weight);
|
|
140
|
+
line-height: var(--gog-panel-heading-line-height);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.gog-panel__footer {
|
|
144
|
+
display: flex;
|
|
145
|
+
flex-wrap: wrap;
|
|
146
|
+
align-items: center;
|
|
147
|
+
gap: var(--gog-panel-footer-gap);
|
|
148
|
+
padding-block-start: var(--gog-panel-footer-padding-top);
|
|
149
|
+
border-block-start: var(--gog-panel-border-width) var(--gog-panel-border-style)
|
|
150
|
+
var(--gog-panel-footer-border-color);
|
|
151
|
+
}
|