@guildofgleks/ui 21.5.2 → 21.6.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 +221 -29
- package/CHANGELOG.md +232 -1
- package/README.md +31 -5
- package/TOKENS.md +3 -0
- package/fesm2022/guildofgleks-ui.mjs +963 -76
- package/fesm2022/guildofgleks-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/styles/button.css +19 -2
- package/styles/index.css +5 -0
- package/styles/menu.css +13 -3
- package/styles/ripple.css +94 -0
- package/styles/surfaces.css +151 -0
- package/styles/theme.css +132 -0
- package/styles/utilities.css +37 -1
- package/types/guildofgleks-ui.d.ts +377 -16
package/package.json
CHANGED
package/styles/button.css
CHANGED
|
@@ -67,7 +67,24 @@
|
|
|
67
67
|
color var(--gog-button-transition-duration) var(--gog-easing);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
/*
|
|
71
|
+
* The doubled class on this rule and the disabled one below is deliberate, and the only two
|
|
72
|
+
* rules in this file that need it.
|
|
73
|
+
*
|
|
74
|
+
* `[gogButton]` goes on the *consumer's* own element, which is the element they style — and
|
|
75
|
+
* Angular's emulated encapsulation stamps `[_ngcontent-…]` onto every rule in a component
|
|
76
|
+
* stylesheet, so an ordinary `.my-btn { cursor: pointer }` is (0,2,0). That exactly ties
|
|
77
|
+
* `.gog-btn:disabled` and wins on source order, because this file loads before the app's own
|
|
78
|
+
* styles. Measured in the showcase: a disabled button went from `not-allowed`/`0.4` to
|
|
79
|
+
* `pointer`/`1` under a single-class consumer rule — it looked and felt enabled while disabled.
|
|
80
|
+
*
|
|
81
|
+
* `:hover` and `:active` below need no help: their `:not(:disabled)` already makes them (0,3,0).
|
|
82
|
+
* The base `.gog-btn` is left beatable on purpose — restyling the look is the consumer's call.
|
|
83
|
+
* These two are not look, they are state and focus visibility, and losing them silently is a
|
|
84
|
+
* correctness and accessibility regression rather than a taste one. A consumer who genuinely
|
|
85
|
+
* wants to restyle them can still do it by being specific about it.
|
|
86
|
+
*/
|
|
87
|
+
.gog-btn.gog-btn:focus-visible {
|
|
71
88
|
outline: var(--gog-button-focus-ring-width) solid
|
|
72
89
|
var(
|
|
73
90
|
--gog-button-hover-bg,
|
|
@@ -114,7 +131,7 @@
|
|
|
114
131
|
}
|
|
115
132
|
}
|
|
116
133
|
|
|
117
|
-
.gog-btn:disabled {
|
|
134
|
+
.gog-btn.gog-btn:disabled {
|
|
118
135
|
opacity: var(--gog-button-disabled-opacity);
|
|
119
136
|
cursor: not-allowed;
|
|
120
137
|
}
|
package/styles/index.css
CHANGED
|
@@ -19,3 +19,8 @@
|
|
|
19
19
|
@import './button.css';
|
|
20
20
|
/* Same reason: `gogMenuItem` marks a consumer's own <button>. */
|
|
21
21
|
@import './menu.css';
|
|
22
|
+
/* Same reason again: `gogCardHeader`, `gogCardMedia`, `gogCardFooter`, `gogCardLink`,
|
|
23
|
+
`gogPanelHeader` and `gogPanelFooter` all mark a consumer's own element. */
|
|
24
|
+
@import './surfaces.css';
|
|
25
|
+
/* Same reason once more: `gogRipple` paints into a consumer's own element. */
|
|
26
|
+
@import './ripple.css';
|
package/styles/menu.css
CHANGED
|
@@ -74,18 +74,28 @@
|
|
|
74
74
|
transition: background-color var(--gog-menu-transition-duration) var(--gog-easing);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/*
|
|
78
|
+
* Doubled class on the `:focus-visible` and `:disabled` rules, for the reason spelled out in
|
|
79
|
+
* `button.css`: a menu item is the consumer's own `<button>`, so an ordinary single-class rule
|
|
80
|
+
* in their component stylesheet ties these at (0,2,0) and wins on source order. The `:hover`
|
|
81
|
+
* selector is already (0,3,0) through its `:not(:disabled)` and is left alone.
|
|
82
|
+
*
|
|
83
|
+
* It matters more here than for a button. The arrow keys step over a disabled item, so an item
|
|
84
|
+
* that has lost its disabled styling is one the pointer can still see as ordinary while the
|
|
85
|
+
* keyboard refuses to reach it — the two input methods disagreeing about what exists.
|
|
86
|
+
*/
|
|
77
87
|
.gog-menu__item:hover:not(:disabled),
|
|
78
|
-
.gog-menu__item:focus-visible {
|
|
88
|
+
.gog-menu__item.gog-menu__item:focus-visible {
|
|
79
89
|
background-color: var(--gog-menu-item-hover-bg);
|
|
80
90
|
color: var(--gog-menu-item-hover-color);
|
|
81
91
|
}
|
|
82
92
|
|
|
83
|
-
.gog-menu__item:focus-visible {
|
|
93
|
+
.gog-menu__item.gog-menu__item:focus-visible {
|
|
84
94
|
outline: var(--gog-menu-focus-ring-width) solid var(--gog-menu-focus-ring);
|
|
85
95
|
outline-offset: calc(var(--gog-menu-focus-ring-width) * -1);
|
|
86
96
|
}
|
|
87
97
|
|
|
88
|
-
.gog-menu__item:disabled {
|
|
98
|
+
.gog-menu__item.gog-menu__item:disabled {
|
|
89
99
|
color: var(--gog-menu-item-disabled-color);
|
|
90
100
|
opacity: var(--gog-menu-item-disabled-opacity);
|
|
91
101
|
cursor: not-allowed;
|
|
@@ -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
|
+
}
|
package/styles/theme.css
CHANGED
|
@@ -621,6 +621,63 @@
|
|
|
621
621
|
--gog-calendar-slg-font-size: var(--gog-text-lg);
|
|
622
622
|
--gog-calendar-slg-day-size: 46px;
|
|
623
623
|
|
|
624
|
+
/* ── Card ──────────────────────────────────────────────────────────────────
|
|
625
|
+
`--gog-card-bg`, `--gog-card-border-color`, `--gog-card-shadow`, `--gog-card-padding-y`,
|
|
626
|
+
`--gog-card-padding-x` and `--gog-card-gap` are intentionally NOT declared — they are the
|
|
627
|
+
per-instance escape hatch the variant and size classes fall back through. */
|
|
628
|
+
--gog-card-font-family: var(--gog-font-body);
|
|
629
|
+
--gog-card-color: var(--gog-text-color);
|
|
630
|
+
--gog-card-radius: var(--gog-radius);
|
|
631
|
+
--gog-card-border-width: var(--gog-panel-border-width);
|
|
632
|
+
--gog-card-border-style: var(--gog-panel-border-style);
|
|
633
|
+
--gog-card-transition-duration: var(--gog-duration-base);
|
|
634
|
+
|
|
635
|
+
--gog-card-heading-color: var(--gog-text-color);
|
|
636
|
+
--gog-card-heading-font-family: var(--gog-font-heading);
|
|
637
|
+
--gog-card-heading-font-size: var(--gog-text-lg);
|
|
638
|
+
--gog-card-heading-font-weight: 600;
|
|
639
|
+
--gog-card-heading-line-height: 1.3;
|
|
640
|
+
|
|
641
|
+
--gog-card-outlined-bg: var(--gog-surface-color);
|
|
642
|
+
--gog-card-outlined-border-color: var(--gog-border-color);
|
|
643
|
+
--gog-card-outlined-shadow: none;
|
|
644
|
+
--gog-card-elevated-bg: var(--gog-surface-color);
|
|
645
|
+
--gog-card-elevated-border-color: transparent;
|
|
646
|
+
/* The shared surface shadow, so a card sits at the same elevation as a dialog or a
|
|
647
|
+
dropdown panel instead of inventing a second house style for "raised". */
|
|
648
|
+
--gog-card-elevated-shadow: var(--gog-panel-shadow);
|
|
649
|
+
--gog-card-filled-bg: color-mix(in srgb, var(--gog-accent-dim) 8%, var(--gog-surface-color));
|
|
650
|
+
--gog-card-filled-border-color: transparent;
|
|
651
|
+
--gog-card-filled-shadow: none;
|
|
652
|
+
|
|
653
|
+
/* Hover and focus only ever show on a card that holds a `gogCardLink`. */
|
|
654
|
+
--gog-card-hover-border-color: color-mix(in srgb, var(--gog-accent-color) 45%, transparent);
|
|
655
|
+
--gog-card-hover-shadow: var(--gog-panel-shadow);
|
|
656
|
+
--gog-card-focus-ring: var(--gog-accent-color);
|
|
657
|
+
--gog-card-focus-ring-width: var(--gog-focus-ring-width);
|
|
658
|
+
--gog-card-focus-ring-offset: var(--gog-focus-ring-offset);
|
|
659
|
+
--gog-card-disabled-opacity: var(--gog-disabled-opacity);
|
|
660
|
+
|
|
661
|
+
--gog-card-footer-border-color: var(--gog-border-color);
|
|
662
|
+
--gog-card-footer-gap: var(--gog-space-sm);
|
|
663
|
+
--gog-card-footer-padding-top: var(--gog-space-sm);
|
|
664
|
+
|
|
665
|
+
--gog-card-xsm-padding-y: 8px;
|
|
666
|
+
--gog-card-xsm-padding-x: 10px;
|
|
667
|
+
--gog-card-xsm-gap: 6px;
|
|
668
|
+
--gog-card-sm-padding-y: 12px;
|
|
669
|
+
--gog-card-sm-padding-x: 14px;
|
|
670
|
+
--gog-card-sm-gap: var(--gog-space-sm);
|
|
671
|
+
--gog-card-md-padding-y: var(--gog-space-md);
|
|
672
|
+
--gog-card-md-padding-x: 20px;
|
|
673
|
+
--gog-card-md-gap: 12px;
|
|
674
|
+
--gog-card-lg-padding-y: 20px;
|
|
675
|
+
--gog-card-lg-padding-x: var(--gog-space-lg);
|
|
676
|
+
--gog-card-lg-gap: 14px;
|
|
677
|
+
--gog-card-slg-padding-y: 28px;
|
|
678
|
+
--gog-card-slg-padding-x: 32px;
|
|
679
|
+
--gog-card-slg-gap: var(--gog-space-md);
|
|
680
|
+
|
|
624
681
|
/* ── Checkbox ──────────────────────────────────────────────────────────────
|
|
625
682
|
Box/label/icon size and padding come from the `--gog-control-checkbox-*` scale;
|
|
626
683
|
checkbox.component.ts maps the `size` input onto the host. */
|
|
@@ -1229,6 +1286,67 @@
|
|
|
1229
1286
|
--gog-paginator-page-size-min-width: 5rem;
|
|
1230
1287
|
--gog-paginator-ellipsis-min-width: 32px;
|
|
1231
1288
|
|
|
1289
|
+
/* ── Panel ─────────────────────────────────────────────────────────────────
|
|
1290
|
+
The `gog-panel` component, which shares its prefix with the foundation surface tier
|
|
1291
|
+
above (`--gog-panel-radius`, `--gog-panel-shadow`, `--gog-panel-border-width`,
|
|
1292
|
+
`--gog-panel-border-style`) deliberately: a panel is the surface those describe, and a
|
|
1293
|
+
theme that sets a house radius for raised surfaces should get it here too.
|
|
1294
|
+
|
|
1295
|
+
`--gog-panel-bg`, `--gog-panel-border-color`, `--gog-panel-padding-y`,
|
|
1296
|
+
`--gog-panel-padding-x` and `--gog-panel-gap` are intentionally NOT declared — the
|
|
1297
|
+
per-instance escape hatch. There is no `--gog-panel-*-shadow` twin of that hatch for the
|
|
1298
|
+
elevated variant: it reads `--gog-panel-shadow` from a declaration the component makes on
|
|
1299
|
+
its own host, so setting that token on one panel already changes only that panel. */
|
|
1300
|
+
--gog-panel-font-family: var(--gog-font-body);
|
|
1301
|
+
--gog-panel-color: var(--gog-text-color);
|
|
1302
|
+
--gog-panel-transition-duration: var(--gog-duration-base);
|
|
1303
|
+
|
|
1304
|
+
--gog-panel-heading-color: var(--gog-text-color);
|
|
1305
|
+
--gog-panel-heading-font-family: var(--gog-font-heading);
|
|
1306
|
+
--gog-panel-heading-font-size: var(--gog-text-xl);
|
|
1307
|
+
--gog-panel-heading-font-weight: 600;
|
|
1308
|
+
--gog-panel-heading-line-height: 1.25;
|
|
1309
|
+
|
|
1310
|
+
--gog-panel-outlined-bg: var(--gog-surface-color);
|
|
1311
|
+
--gog-panel-outlined-border-color: var(--gog-border-color);
|
|
1312
|
+
--gog-panel-outlined-shadow: none;
|
|
1313
|
+
--gog-panel-elevated-bg: var(--gog-surface-color);
|
|
1314
|
+
--gog-panel-elevated-border-color: transparent;
|
|
1315
|
+
--gog-panel-filled-bg: color-mix(in srgb, var(--gog-accent-dim) 8%, var(--gog-surface-color));
|
|
1316
|
+
--gog-panel-filled-border-color: transparent;
|
|
1317
|
+
--gog-panel-filled-shadow: none;
|
|
1318
|
+
|
|
1319
|
+
--gog-panel-header-gap: var(--gog-space-sm);
|
|
1320
|
+
--gog-panel-toggle-size: 2rem;
|
|
1321
|
+
--gog-panel-toggle-radius: var(--gog-radius);
|
|
1322
|
+
--gog-panel-toggle-color: var(--gog-muted-text-color);
|
|
1323
|
+
--gog-panel-toggle-hover-bg: color-mix(in srgb, var(--gog-hover-color) 70%, transparent);
|
|
1324
|
+
--gog-panel-chevron-size: 1rem;
|
|
1325
|
+
--gog-panel-focus-ring: var(--gog-accent-color);
|
|
1326
|
+
--gog-panel-focus-ring-width: var(--gog-focus-ring-width);
|
|
1327
|
+
--gog-panel-focus-ring-offset: var(--gog-focus-ring-offset);
|
|
1328
|
+
--gog-panel-disabled-opacity: var(--gog-disabled-opacity);
|
|
1329
|
+
|
|
1330
|
+
--gog-panel-footer-border-color: var(--gog-border-color);
|
|
1331
|
+
--gog-panel-footer-gap: var(--gog-space-sm);
|
|
1332
|
+
--gog-panel-footer-padding-top: var(--gog-space-sm);
|
|
1333
|
+
|
|
1334
|
+
--gog-panel-xsm-padding-y: 10px;
|
|
1335
|
+
--gog-panel-xsm-padding-x: 12px;
|
|
1336
|
+
--gog-panel-xsm-gap: var(--gog-space-sm);
|
|
1337
|
+
--gog-panel-sm-padding-y: 14px;
|
|
1338
|
+
--gog-panel-sm-padding-x: var(--gog-space-md);
|
|
1339
|
+
--gog-panel-sm-gap: 10px;
|
|
1340
|
+
--gog-panel-md-padding-y: 18px;
|
|
1341
|
+
--gog-panel-md-padding-x: 20px;
|
|
1342
|
+
--gog-panel-md-gap: 12px;
|
|
1343
|
+
--gog-panel-lg-padding-y: var(--gog-space-lg);
|
|
1344
|
+
--gog-panel-lg-padding-x: 28px;
|
|
1345
|
+
--gog-panel-lg-gap: var(--gog-space-md);
|
|
1346
|
+
--gog-panel-slg-padding-y: 32px;
|
|
1347
|
+
--gog-panel-slg-padding-x: 36px;
|
|
1348
|
+
--gog-panel-slg-gap: 20px;
|
|
1349
|
+
|
|
1232
1350
|
/* ── Progressbar ──────────────────────────────────────────────────────────── */
|
|
1233
1351
|
--gog-progressbar-track-base-bg: color-mix(
|
|
1234
1352
|
in srgb,
|
|
@@ -1273,6 +1391,20 @@
|
|
|
1273
1391
|
--gog-progressbar-info-bg: var(--gog-info-color);
|
|
1274
1392
|
--gog-progressbar-info-buffer-bg: color-mix(in srgb, var(--gog-info-color) 35%, transparent);
|
|
1275
1393
|
|
|
1394
|
+
/* ── Ripple (the `gogRipple` directive; its classes live in ripple.css) ────
|
|
1395
|
+
`currentColor` rather than a fixed colour on purpose: the wash then reads as the host's
|
|
1396
|
+
own foreground, so one value works on a filled button and on a ghost one without a
|
|
1397
|
+
per-variant tier. The property is inherited, so `--gog-ripple-color` set anywhere above
|
|
1398
|
+
the host reaches it — which is the per-instance override, no undeclared tier needed. */
|
|
1399
|
+
--gog-ripple-color: currentColor;
|
|
1400
|
+
--gog-ripple-opacity: 0.16;
|
|
1401
|
+
/* Longer than any other motion in the library, deliberately: a ripple held to the house 0.2s
|
|
1402
|
+
is over before the eye has followed it across the surface. Still expressed in the
|
|
1403
|
+
foundation scale, so setting the durations to 0s still flattens it theme-wide. */
|
|
1404
|
+
--gog-ripple-enter-duration: calc(var(--gog-duration-slow) * 2);
|
|
1405
|
+
--gog-ripple-exit-duration: var(--gog-duration-slow);
|
|
1406
|
+
--gog-ripple-easing: var(--gog-easing);
|
|
1407
|
+
|
|
1276
1408
|
/* ── Scroll ────────────────────────────────────────────────────────────────── */
|
|
1277
1409
|
--gog-scroll-track-bg: transparent;
|
|
1278
1410
|
--gog-scroll-track-radius: var(--gog-radius);
|
package/styles/utilities.css
CHANGED
|
@@ -19,6 +19,31 @@
|
|
|
19
19
|
--gog-direction-sign: 1;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/*
|
|
23
|
+
* Every element the library renders sizes itself border-box, so the package does not depend on
|
|
24
|
+
* the consumer having a `* { box-sizing: border-box }` reset.
|
|
25
|
+
*
|
|
26
|
+
* It used to. `.gog-input__field` is `width: 100%` plus horizontal padding plus a border, so
|
|
27
|
+
* under the CSS default of `content-box` it overflowed its own container by exactly that much —
|
|
28
|
+
* measured 20px at `xsm` rising to 48px at `slg`. It stayed invisible for the life of the
|
|
29
|
+
* package because both apps that render it (`ui-showcase`, and `gleks-ui-lab` since later) carry
|
|
30
|
+
* a global reset of their own, so the library was only ever *looked at* under border-box.
|
|
31
|
+
*
|
|
32
|
+
* Matched on the class prefix rather than by listing elements, because the set that needs it is
|
|
33
|
+
* exactly "things the library painted" — including the ones that live on a consumer's own
|
|
34
|
+
* element (`.gog-btn`, `.gog-menu__item`, `.gog-collapsible__trigger`) and would be missed by a
|
|
35
|
+
* `gog-*` tag list. A consumer's own elements are untouched.
|
|
36
|
+
*
|
|
37
|
+
* Specificity is a single class, deliberately: this is a default the library needs, not a
|
|
38
|
+
* decision it should win. `:where()` would drop it to zero and lose to the UA's own
|
|
39
|
+
* `content-box`… which is not a thing, but it would also lose to a consumer's `*` reset setting
|
|
40
|
+
* `content-box` back, and matching that intent is right.
|
|
41
|
+
*/
|
|
42
|
+
[class^='gog-'],
|
|
43
|
+
[class*=' gog-'] {
|
|
44
|
+
box-sizing: border-box;
|
|
45
|
+
}
|
|
46
|
+
|
|
22
47
|
[dir='rtl'] {
|
|
23
48
|
--gog-inline-start-side: right;
|
|
24
49
|
--gog-inline-end-side: left;
|
|
@@ -171,7 +196,18 @@
|
|
|
171
196
|
cursor: pointer;
|
|
172
197
|
}
|
|
173
198
|
|
|
174
|
-
|
|
199
|
+
/*
|
|
200
|
+
* Scoped through the host on purpose, for one point of specificity the plain
|
|
201
|
+
* `.gog-collapsible__trigger[aria-disabled='true']` (0,2,0) does not have.
|
|
202
|
+
*
|
|
203
|
+
* The trigger is the *consumer's* element, and Angular's emulated encapsulation stamps
|
|
204
|
+
* `[_ngcontent-…]` onto every rule in a component stylesheet — so an ordinary
|
|
205
|
+
* `.my-trigger { cursor: pointer }` in the consumer's own component is also (0,2,0) and wins on
|
|
206
|
+
* source order, since this file loads before their app's styles. Measured: a disabled trigger
|
|
207
|
+
* reading `cursor: pointer` while this rule's `opacity` applied, in the showcase's own demo.
|
|
208
|
+
* A disabled state the consumer has to know to opt out of is not a disabled state.
|
|
209
|
+
*/
|
|
210
|
+
gog-collapsible .gog-collapsible__trigger[aria-disabled='true'] {
|
|
175
211
|
cursor: not-allowed;
|
|
176
212
|
opacity: var(--gog-collapsible-disabled-opacity);
|
|
177
213
|
}
|