@guildofgleks/ui 21.4.3 → 21.5.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 +277 -156
- package/CHANGELOG.md +265 -14
- package/README.md +56 -22
- package/TOKENS.md +44 -44
- package/fesm2022/guildofgleks-ui.mjs +2017 -386
- package/fesm2022/guildofgleks-ui.mjs.map +1 -1
- package/package.json +10 -10
- package/schematics/collection.json +9 -0
- package/schematics/ng-add/index.cjs +62 -0
- package/schematics/ng-add/schema.cjs +2 -0
- package/schematics/ng-add/schema.json +15 -0
- package/styles/button.css +112 -79
- package/styles/index.css +2 -0
- package/styles/menu.css +95 -0
- package/styles/theme.css +314 -239
- package/styles/utilities.css +212 -170
- package/types/guildofgleks-ui.d.ts +237 -141
- package/src/styles/button.css +0 -193
- package/src/styles/fonts.css +0 -16
- package/src/styles/index.css +0 -19
- package/src/styles/presets/one-dark.css +0 -48
- package/src/styles/presets/one-light.css +0 -47
- package/src/styles/presets/slate.css +0 -55
- package/src/styles/theme.css +0 -1693
- package/src/styles/typography.css +0 -15
- package/src/styles/utilities.css +0 -170
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guildofgleks/ui",
|
|
3
|
-
"version": "21.
|
|
3
|
+
"version": "21.5.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=20.19.0"
|
|
6
6
|
},
|
|
7
|
-
"description": "A lightweight Angular 21
|
|
7
|
+
"description": "A lightweight component library for Angular 21 and 22 — standalone, signal-based, OnPush, RTL-ready, with no CDK or Material dependency.",
|
|
8
8
|
"keywords": [
|
|
9
9
|
"angular",
|
|
10
10
|
"angular21",
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
"design-system",
|
|
15
15
|
"signals",
|
|
16
16
|
"standalone",
|
|
17
|
-
"accessible"
|
|
17
|
+
"accessible",
|
|
18
|
+
"a11y",
|
|
19
|
+
"rtl"
|
|
18
20
|
],
|
|
19
21
|
"homepage": "https://ui.guildofgleks.com/",
|
|
20
22
|
"license": "Apache-2.0",
|
|
@@ -28,22 +30,20 @@
|
|
|
28
30
|
"url": "https://github.com/GuildOfGleks/gleks_web_ui/issues"
|
|
29
31
|
},
|
|
30
32
|
"peerDependencies": {
|
|
31
|
-
"@angular/common": "^21.2.0",
|
|
32
|
-
"@angular/core": "^21.2.0",
|
|
33
|
-
"@angular/forms": "^21.2.0",
|
|
34
|
-
"@angular/platform-browser": "^21.2.0"
|
|
33
|
+
"@angular/common": "^21.2.0 || ^22.0.0",
|
|
34
|
+
"@angular/core": "^21.2.0 || ^22.0.0",
|
|
35
|
+
"@angular/forms": "^21.2.0 || ^22.0.0",
|
|
36
|
+
"@angular/platform-browser": "^21.2.0 || ^22.0.0"
|
|
35
37
|
},
|
|
36
38
|
"dependencies": {
|
|
37
39
|
"tslib": "^2.3.0"
|
|
38
40
|
},
|
|
39
41
|
"sideEffects": false,
|
|
42
|
+
"schematics": "./schematics/collection.json",
|
|
40
43
|
"exports": {
|
|
41
44
|
"./styles/*": {
|
|
42
45
|
"default": "./styles/*"
|
|
43
46
|
},
|
|
44
|
-
"./src/styles/*": {
|
|
45
|
-
"default": "./src/styles/*"
|
|
46
|
-
},
|
|
47
47
|
"./package.json": {
|
|
48
48
|
"default": "./package.json"
|
|
49
49
|
},
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ngAdd = ngAdd;
|
|
4
|
+
const workspace_1 = require("@schematics/angular/utility/workspace");
|
|
5
|
+
const STYLE_PATH = 'node_modules/@guildofgleks/ui/styles/index.css';
|
|
6
|
+
function ngAdd(options) {
|
|
7
|
+
return (_tree, context) => {
|
|
8
|
+
return (0, workspace_1.updateWorkspace)((workspace) => {
|
|
9
|
+
const projectNames = options.project
|
|
10
|
+
? [options.project]
|
|
11
|
+
: [...workspace.projects.keys()].filter((name) => workspace.projects.get(name)?.extensions['projectType'] === 'application');
|
|
12
|
+
if (projectNames.length === 0) {
|
|
13
|
+
context.logger.warn(`@guildofgleks/ui: no application project found to add "${STYLE_PATH}" to. ` +
|
|
14
|
+
"Add it to your project's styles array yourself.");
|
|
15
|
+
}
|
|
16
|
+
let added = false;
|
|
17
|
+
for (const name of projectNames) {
|
|
18
|
+
const project = workspace.projects.get(name);
|
|
19
|
+
const build = project?.targets.get('build');
|
|
20
|
+
if (!build) {
|
|
21
|
+
if (options.project) {
|
|
22
|
+
context.logger.warn(`@guildofgleks/ui: project "${name}" has no "build" target — skipping the styles setup.`);
|
|
23
|
+
}
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
build.options ?? (build.options = {});
|
|
27
|
+
added = prependStyle(build.options) || added;
|
|
28
|
+
// `@angular/build:unit-test`, the v21 default, has no `styles` of its own — it builds
|
|
29
|
+
// through `buildTarget`, so the line above already covers component tests. The karma
|
|
30
|
+
// builders do carry their own array, and there the build target's styles are not read.
|
|
31
|
+
// Only touch the test target when it already declares one: adding the key to a builder
|
|
32
|
+
// whose schema forbids it would make `ng test` fail schema validation.
|
|
33
|
+
const test = project?.targets.get('test');
|
|
34
|
+
if (test?.options && Array.isArray(test.options['styles'])) {
|
|
35
|
+
added = prependStyle(test.options) || added;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Only say so when something actually changed — a re-run that finds the stylesheet already
|
|
39
|
+
// there, or a workspace where no project could be updated, should not claim otherwise.
|
|
40
|
+
if (added) {
|
|
41
|
+
context.logger.info("@guildofgleks/ui: added the baseline stylesheet to your project's styles. Next: import " +
|
|
42
|
+
'the standalone components you use, and if you use dialogs or toasts, add ' +
|
|
43
|
+
'<gog-dialog /> and <gog-toast-container /> once in your root component. See ' +
|
|
44
|
+
'https://ui.guildofgleks.com for details.');
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Puts the baseline stylesheet first in a target's `styles`, so anything the consumer already had
|
|
51
|
+
* still comes after it and wins. Returns whether it changed anything — a second `ng add` must be
|
|
52
|
+
* a no-op.
|
|
53
|
+
*/
|
|
54
|
+
function prependStyle(options) {
|
|
55
|
+
const existing = options['styles'];
|
|
56
|
+
const styles = Array.isArray(existing) ? existing : [];
|
|
57
|
+
if (styles.includes(STYLE_PATH)) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
options['styles'] = [STYLE_PATH, ...styles];
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema",
|
|
3
|
+
"$id": "GuildOfGleksUiNgAdd",
|
|
4
|
+
"title": "GuildOfGleks UI ng-add schema",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"project": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "The name of the project to add the library's stylesheet to.",
|
|
10
|
+
"$default": {
|
|
11
|
+
"$source": "projectName"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
package/styles/button.css
CHANGED
|
@@ -7,68 +7,101 @@
|
|
|
7
7
|
* `gogBadge` and `gog-collapsible` keep their CSS here.
|
|
8
8
|
*
|
|
9
9
|
* Token layering (see theme.css):
|
|
10
|
-
* --gog-
|
|
10
|
+
* --gog-button-<prop> per-instance override. Never declared here or in the
|
|
11
11
|
* theme, so it always wins when a consumer sets it.
|
|
12
|
-
* --gog-
|
|
13
|
-
* --gog-
|
|
14
|
-
* --gog-
|
|
12
|
+
* --gog-button-variant-<prop> internal, set by the variant classes below.
|
|
13
|
+
* --gog-button-size-<prop> internal, set by the size classes below.
|
|
14
|
+
* --gog-button-<variant>-<prop> the actual values, all in theme.css.
|
|
15
15
|
* Nothing in this file is a literal: every colour, font, metric and duration resolves
|
|
16
16
|
* to a theme token, so a theme can restyle the button without touching this stylesheet.
|
|
17
17
|
*/
|
|
18
18
|
.gog-btn {
|
|
19
19
|
/* Scopes the spinner rendered inside a loading button to the variant's spinner colour. */
|
|
20
20
|
--gog-spinner-color: var(
|
|
21
|
-
--gog-
|
|
22
|
-
var(
|
|
21
|
+
--gog-button-spinner-color,
|
|
22
|
+
var(
|
|
23
|
+
--gog-btn-spinner-color,
|
|
24
|
+
var(--gog-button-variant-spinner-color, var(--gog-button-primary-spinner-color))
|
|
25
|
+
)
|
|
23
26
|
);
|
|
24
27
|
|
|
25
|
-
gap: var(--gog-
|
|
26
|
-
border: var(--gog-
|
|
27
|
-
var(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
28
|
+
gap: var(--gog-button-gap);
|
|
29
|
+
border: var(--gog-button-border-width) var(--gog-button-border-style)
|
|
30
|
+
var(
|
|
31
|
+
--gog-button-border,
|
|
32
|
+
var(--gog-btn-border, var(--gog-button-variant-border, var(--gog-button-primary-border)))
|
|
33
|
+
);
|
|
34
|
+
border-radius: var(--gog-button-radius);
|
|
35
|
+
padding: var(
|
|
36
|
+
--gog-button-padding,
|
|
37
|
+
var(--gog-btn-padding, var(--gog-button-size-padding, var(--gog-button-md-padding)))
|
|
38
|
+
);
|
|
39
|
+
font-family: var(--gog-button-font-family);
|
|
40
|
+
font-weight: var(--gog-button-font-weight);
|
|
41
|
+
font-size: var(
|
|
42
|
+
--gog-button-font-size,
|
|
43
|
+
var(--gog-btn-font-size, var(--gog-button-size-font-size, var(--gog-button-md-font-size)))
|
|
44
|
+
);
|
|
45
|
+
letter-spacing: var(--gog-button-letter-spacing);
|
|
46
|
+
text-transform: var(--gog-button-text-transform);
|
|
47
|
+
line-height: var(--gog-button-line-height);
|
|
48
|
+
background-color: var(
|
|
49
|
+
--gog-button-bg,
|
|
50
|
+
var(--gog-btn-bg, var(--gog-button-variant-bg, var(--gog-button-primary-bg)))
|
|
51
|
+
);
|
|
52
|
+
color: var(
|
|
53
|
+
--gog-button-color,
|
|
54
|
+
var(--gog-btn-color, var(--gog-button-variant-color, var(--gog-button-primary-color)))
|
|
55
|
+
);
|
|
56
|
+
box-shadow: var(
|
|
57
|
+
--gog-button-shadow,
|
|
58
|
+
var(--gog-btn-shadow, var(--gog-button-variant-shadow, var(--gog-button-primary-shadow)))
|
|
59
|
+
);
|
|
39
60
|
cursor: pointer;
|
|
40
61
|
/* An `<a>` carries the UA underline; a `<button>` never did, which is why the component never
|
|
41
62
|
needed this. Reset here so `[gogButton]` on a link is visually identical to the component. */
|
|
42
63
|
text-decoration: none;
|
|
43
64
|
transition:
|
|
44
|
-
background-color var(--gog-
|
|
45
|
-
box-shadow var(--gog-
|
|
46
|
-
color var(--gog-
|
|
65
|
+
background-color var(--gog-button-transition-duration) var(--gog-easing),
|
|
66
|
+
box-shadow var(--gog-button-transition-duration) var(--gog-easing),
|
|
67
|
+
color var(--gog-button-transition-duration) var(--gog-easing);
|
|
47
68
|
}
|
|
48
69
|
|
|
49
70
|
.gog-btn:focus-visible {
|
|
50
|
-
outline: var(--gog-
|
|
51
|
-
var(
|
|
52
|
-
|
|
71
|
+
outline: var(--gog-button-focus-ring-width) solid
|
|
72
|
+
var(
|
|
73
|
+
--gog-button-hover-bg,
|
|
74
|
+
var(
|
|
75
|
+
--gog-btn-hover-bg,
|
|
76
|
+
var(--gog-button-variant-hover-bg, var(--gog-button-primary-hover-bg))
|
|
77
|
+
)
|
|
78
|
+
);
|
|
79
|
+
outline-offset: var(--gog-button-focus-ring-offset);
|
|
53
80
|
}
|
|
54
81
|
|
|
55
82
|
.gog-btn:hover:not(:disabled) {
|
|
56
83
|
background-color: var(
|
|
57
|
-
--gog-
|
|
58
|
-
var(--gog-btn-variant-hover-bg, var(--gog-
|
|
84
|
+
--gog-button-hover-bg,
|
|
85
|
+
var(--gog-btn-hover-bg, var(--gog-button-variant-hover-bg, var(--gog-button-primary-hover-bg)))
|
|
59
86
|
);
|
|
60
87
|
color: var(
|
|
61
|
-
--gog-
|
|
62
|
-
var(
|
|
88
|
+
--gog-button-hover-color,
|
|
89
|
+
var(
|
|
90
|
+
--gog-btn-hover-color,
|
|
91
|
+
var(--gog-button-variant-hover-color, var(--gog-button-primary-hover-color))
|
|
92
|
+
)
|
|
63
93
|
);
|
|
64
94
|
box-shadow: var(
|
|
65
|
-
--gog-
|
|
66
|
-
var(
|
|
95
|
+
--gog-button-hover-shadow,
|
|
96
|
+
var(
|
|
97
|
+
--gog-btn-hover-shadow,
|
|
98
|
+
var(--gog-button-variant-hover-shadow, var(--gog-button-primary-hover-shadow))
|
|
99
|
+
)
|
|
67
100
|
);
|
|
68
101
|
}
|
|
69
102
|
|
|
70
103
|
.gog-btn:active:not(:disabled) {
|
|
71
|
-
transform: scale(var(--gog-
|
|
104
|
+
transform: scale(var(--gog-button-active-scale));
|
|
72
105
|
}
|
|
73
106
|
|
|
74
107
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -82,7 +115,7 @@
|
|
|
82
115
|
}
|
|
83
116
|
|
|
84
117
|
.gog-btn:disabled {
|
|
85
|
-
opacity: var(--gog-
|
|
118
|
+
opacity: var(--gog-button-disabled-opacity);
|
|
86
119
|
cursor: not-allowed;
|
|
87
120
|
}
|
|
88
121
|
|
|
@@ -90,75 +123,75 @@
|
|
|
90
123
|
|
|
91
124
|
/* primary: solid gold */
|
|
92
125
|
.gog-btn--primary {
|
|
93
|
-
--gog-
|
|
94
|
-
--gog-
|
|
95
|
-
--gog-
|
|
96
|
-
--gog-
|
|
97
|
-
--gog-
|
|
98
|
-
--gog-
|
|
99
|
-
--gog-
|
|
100
|
-
--gog-
|
|
126
|
+
--gog-button-variant-bg: var(--gog-button-primary-bg);
|
|
127
|
+
--gog-button-variant-color: var(--gog-button-primary-color);
|
|
128
|
+
--gog-button-variant-border: var(--gog-button-primary-border);
|
|
129
|
+
--gog-button-variant-shadow: var(--gog-button-primary-shadow);
|
|
130
|
+
--gog-button-variant-hover-bg: var(--gog-button-primary-hover-bg);
|
|
131
|
+
--gog-button-variant-hover-color: var(--gog-button-primary-hover-color);
|
|
132
|
+
--gog-button-variant-hover-shadow: var(--gog-button-primary-hover-shadow);
|
|
133
|
+
--gog-button-variant-spinner-color: var(--gog-button-primary-spinner-color);
|
|
101
134
|
}
|
|
102
135
|
|
|
103
136
|
.gog-btn--secondary {
|
|
104
|
-
--gog-
|
|
105
|
-
--gog-
|
|
106
|
-
--gog-
|
|
107
|
-
--gog-
|
|
108
|
-
--gog-
|
|
109
|
-
--gog-
|
|
110
|
-
--gog-
|
|
111
|
-
--gog-
|
|
137
|
+
--gog-button-variant-bg: var(--gog-button-secondary-bg);
|
|
138
|
+
--gog-button-variant-color: var(--gog-button-secondary-color);
|
|
139
|
+
--gog-button-variant-border: var(--gog-button-secondary-border);
|
|
140
|
+
--gog-button-variant-shadow: var(--gog-button-secondary-shadow);
|
|
141
|
+
--gog-button-variant-hover-bg: var(--gog-button-secondary-hover-bg);
|
|
142
|
+
--gog-button-variant-hover-color: var(--gog-button-secondary-hover-color);
|
|
143
|
+
--gog-button-variant-hover-shadow: var(--gog-button-secondary-hover-shadow);
|
|
144
|
+
--gog-button-variant-spinner-color: var(--gog-button-secondary-spinner-color);
|
|
112
145
|
}
|
|
113
146
|
|
|
114
147
|
/* outline: transparent with golden border */
|
|
115
148
|
.gog-btn--outline {
|
|
116
|
-
--gog-
|
|
117
|
-
--gog-
|
|
118
|
-
--gog-
|
|
119
|
-
--gog-
|
|
120
|
-
--gog-
|
|
121
|
-
--gog-
|
|
122
|
-
--gog-
|
|
123
|
-
--gog-
|
|
149
|
+
--gog-button-variant-bg: var(--gog-button-outline-bg);
|
|
150
|
+
--gog-button-variant-color: var(--gog-button-outline-color);
|
|
151
|
+
--gog-button-variant-border: var(--gog-button-outline-border);
|
|
152
|
+
--gog-button-variant-shadow: var(--gog-button-outline-shadow);
|
|
153
|
+
--gog-button-variant-hover-bg: var(--gog-button-outline-hover-bg);
|
|
154
|
+
--gog-button-variant-hover-color: var(--gog-button-outline-hover-color);
|
|
155
|
+
--gog-button-variant-hover-shadow: var(--gog-button-outline-hover-shadow);
|
|
156
|
+
--gog-button-variant-spinner-color: var(--gog-button-outline-spinner-color);
|
|
124
157
|
}
|
|
125
158
|
|
|
126
159
|
/* ghost: no border, subtle hover */
|
|
127
160
|
.gog-btn--ghost {
|
|
128
|
-
--gog-
|
|
129
|
-
--gog-
|
|
130
|
-
--gog-
|
|
131
|
-
--gog-
|
|
132
|
-
--gog-
|
|
133
|
-
--gog-
|
|
134
|
-
--gog-
|
|
135
|
-
--gog-
|
|
161
|
+
--gog-button-variant-bg: var(--gog-button-ghost-bg);
|
|
162
|
+
--gog-button-variant-color: var(--gog-button-ghost-color);
|
|
163
|
+
--gog-button-variant-border: var(--gog-button-ghost-border);
|
|
164
|
+
--gog-button-variant-shadow: var(--gog-button-ghost-shadow);
|
|
165
|
+
--gog-button-variant-hover-bg: var(--gog-button-ghost-hover-bg);
|
|
166
|
+
--gog-button-variant-hover-color: var(--gog-button-ghost-hover-color);
|
|
167
|
+
--gog-button-variant-hover-shadow: var(--gog-button-ghost-hover-shadow);
|
|
168
|
+
--gog-button-variant-spinner-color: var(--gog-button-ghost-spinner-color);
|
|
136
169
|
}
|
|
137
170
|
|
|
138
171
|
/* === Sizes === */
|
|
139
172
|
.gog-btn--xsm {
|
|
140
|
-
--gog-
|
|
141
|
-
--gog-
|
|
173
|
+
--gog-button-size-padding: var(--gog-button-xsm-padding);
|
|
174
|
+
--gog-button-size-font-size: var(--gog-button-xsm-font-size);
|
|
142
175
|
}
|
|
143
176
|
|
|
144
177
|
.gog-btn--sm {
|
|
145
|
-
--gog-
|
|
146
|
-
--gog-
|
|
178
|
+
--gog-button-size-padding: var(--gog-button-sm-padding);
|
|
179
|
+
--gog-button-size-font-size: var(--gog-button-sm-font-size);
|
|
147
180
|
}
|
|
148
181
|
|
|
149
182
|
.gog-btn--md {
|
|
150
|
-
--gog-
|
|
151
|
-
--gog-
|
|
183
|
+
--gog-button-size-padding: var(--gog-button-md-padding);
|
|
184
|
+
--gog-button-size-font-size: var(--gog-button-md-font-size);
|
|
152
185
|
}
|
|
153
186
|
|
|
154
187
|
.gog-btn--lg {
|
|
155
|
-
--gog-
|
|
156
|
-
--gog-
|
|
188
|
+
--gog-button-size-padding: var(--gog-button-lg-padding);
|
|
189
|
+
--gog-button-size-font-size: var(--gog-button-lg-font-size);
|
|
157
190
|
}
|
|
158
191
|
|
|
159
192
|
.gog-btn--slg {
|
|
160
|
-
--gog-
|
|
161
|
-
--gog-
|
|
193
|
+
--gog-button-size-padding: var(--gog-button-slg-padding);
|
|
194
|
+
--gog-button-size-font-size: var(--gog-button-slg-font-size);
|
|
162
195
|
}
|
|
163
196
|
|
|
164
197
|
.gog-btn--loading {
|
|
@@ -167,7 +200,7 @@
|
|
|
167
200
|
/* Loading buttons stay natively focusable (aria-disabled + aria-busy instead of
|
|
168
201
|
`disabled`) so keyboard users don't lose focus mid-action. `:disabled` styling
|
|
169
202
|
below therefore no longer covers this state, so the dim is applied explicitly. */
|
|
170
|
-
opacity: var(--gog-
|
|
203
|
+
opacity: var(--gog-button-loading-opacity);
|
|
171
204
|
}
|
|
172
205
|
|
|
173
206
|
.gog-btn__content--hidden {
|
|
@@ -180,8 +213,8 @@
|
|
|
180
213
|
top: 50%;
|
|
181
214
|
left: 50%;
|
|
182
215
|
transform: translate(-50%, -50%);
|
|
183
|
-
max-width: var(--gog-
|
|
184
|
-
max-height: var(--gog-
|
|
216
|
+
max-width: var(--gog-button-spinner-max-size);
|
|
217
|
+
max-height: var(--gog-button-spinner-max-size);
|
|
185
218
|
}
|
|
186
219
|
|
|
187
220
|
/*
|
package/styles/index.css
CHANGED
package/styles/menu.css
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The menu's visual block, in a **global** stylesheet rather than the component's own.
|
|
3
|
+
*
|
|
4
|
+
* `gogMenuItem` goes on a consumer's own `<button>`, declared in the consumer's template — so
|
|
5
|
+
* the element carries *their* encapsulation attribute, and a rule written in
|
|
6
|
+
* `menu.component.scss` never reaches it. That is the same reason `.gog-btn` lives in
|
|
7
|
+
* `button.css` and `gogBadge` in `utilities.css`; the first version of this component had the
|
|
8
|
+
* item rules scoped to the component, and every menu opened with plain browser buttons in it.
|
|
9
|
+
*
|
|
10
|
+
* The panel is here too, rather than split across two files: it is portaled into `<body>` for
|
|
11
|
+
* `appendToBody`, and keeping the whole block in one place is what stops the two halves drifting.
|
|
12
|
+
*
|
|
13
|
+
* Nothing in this file is a literal: every colour, metric and duration resolves to a
|
|
14
|
+
* `--gog-menu-*` token in theme.css, so a theme can restyle the menu without touching it.
|
|
15
|
+
*/
|
|
16
|
+
/*
|
|
17
|
+
* `fixed`, placed from the trigger's measured rect (see `measure()`). The panel always lives in
|
|
18
|
+
* `<body>`, so nothing above it can clip it and there is no second positioning model to keep in
|
|
19
|
+
* step.
|
|
20
|
+
*/
|
|
21
|
+
.gog-menu {
|
|
22
|
+
position: fixed;
|
|
23
|
+
z-index: var(--gog-menu-z);
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
gap: var(--gog-menu-gap);
|
|
27
|
+
min-width: var(--gog-menu-min-width);
|
|
28
|
+
max-width: var(--gog-menu-max-width);
|
|
29
|
+
max-height: var(--gog-menu-max-height);
|
|
30
|
+
/* The panel masks its own corners; the scrolling happens in `.gog-menu__scroll` inside it. */
|
|
31
|
+
overflow: hidden;
|
|
32
|
+
padding: var(--gog-menu-padding);
|
|
33
|
+
border: var(--gog-menu-border-width) var(--gog-menu-border-style) var(--gog-menu-border-color);
|
|
34
|
+
border-radius: var(--gog-menu-radius);
|
|
35
|
+
background-color: var(--gog-menu-bg);
|
|
36
|
+
box-shadow: var(--gog-menu-shadow);
|
|
37
|
+
font-family: var(--gog-menu-font-family);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/*
|
|
41
|
+
* `min-height: 0` overrides the flex-item default of `auto`, which would otherwise refuse to
|
|
42
|
+
* shrink below the item list's full height and defeat the panel's max-height — the same note
|
|
43
|
+
* `.gog-select__scroll` carries, for the same reason.
|
|
44
|
+
*/
|
|
45
|
+
.gog-menu__scroll {
|
|
46
|
+
flex: 1;
|
|
47
|
+
min-height: 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.gog-menu__item {
|
|
51
|
+
display: flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
gap: var(--gog-menu-item-gap);
|
|
54
|
+
width: 100%;
|
|
55
|
+
padding: var(--gog-menu-item-padding);
|
|
56
|
+
border: 0;
|
|
57
|
+
border-radius: var(--gog-menu-item-radius);
|
|
58
|
+
background: transparent;
|
|
59
|
+
color: var(--gog-menu-item-color);
|
|
60
|
+
font-family: var(--gog-menu-font-family);
|
|
61
|
+
font-size: var(--gog-menu-item-font-size);
|
|
62
|
+
line-height: var(--gog-menu-item-line-height);
|
|
63
|
+
text-align: start;
|
|
64
|
+
cursor: pointer;
|
|
65
|
+
transition: background-color var(--gog-menu-transition-duration) var(--gog-easing);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.gog-menu__item:hover:not(:disabled),
|
|
69
|
+
.gog-menu__item:focus-visible {
|
|
70
|
+
background-color: var(--gog-menu-item-hover-bg);
|
|
71
|
+
color: var(--gog-menu-item-hover-color);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.gog-menu__item:focus-visible {
|
|
75
|
+
outline: var(--gog-menu-focus-ring-width) solid var(--gog-menu-focus-ring);
|
|
76
|
+
outline-offset: calc(var(--gog-menu-focus-ring-width) * -1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.gog-menu__item:disabled {
|
|
80
|
+
color: var(--gog-menu-item-disabled-color);
|
|
81
|
+
opacity: var(--gog-menu-item-disabled-opacity);
|
|
82
|
+
cursor: not-allowed;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* An icon inside an item is decorative next to the label, and must not push it around. */
|
|
86
|
+
.gog-menu__item gog-icon {
|
|
87
|
+
flex-shrink: 0;
|
|
88
|
+
font-size: var(--gog-menu-item-icon-size);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@media (prefers-reduced-motion: reduce) {
|
|
92
|
+
.gog-menu__item {
|
|
93
|
+
transition: none;
|
|
94
|
+
}
|
|
95
|
+
}
|