maverick-wave 5.30.0 → 5.32.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/README.md +2 -2
- package/maverick-wave.min.css +2 -2
- package/package.json +8 -2
- package/src/scss/abstracts/_variables.scss +2 -0
- package/src/scss/components/_modals.scss +23 -9
- package/src/scss/components/_testimonial.scss +2 -0
- package/src/scss/layout/_home.scss +46 -0
- package/src/scss/layout/_main.scss +20 -0
- package/src/scss/layout/_parallax.scss +2 -2
- package/src/scss/main-lean.scss +8 -3
- package/.claude/settings.local.json +0 -43
- package/.claude/skills/mw-maverick-wave/SKILL.md +0 -532
- package/.claude/skills/mw-maverick-wave/examples/angular-form.md +0 -279
- package/.claude/skills/mw-maverick-wave/examples/angular-list-page.md +0 -309
- package/.claude/skills/mw-maverick-wave/examples/angular-services.md +0 -538
- package/.claude/skills/mw-maverick-wave/examples/static-landing-page.md +0 -530
- package/.claude/skills/mw-maverick-wave/references/components.md +0 -2170
- package/.claude/skills/mw-maverick-wave/references/forms.md +0 -358
- package/.claude/skills/mw-maverick-wave/references/javascript.md +0 -164
- package/.claude/skills/mw-maverick-wave/references/layout.md +0 -764
- package/.claude/skills/mw-maverick-wave/references/theming.md +0 -530
- package/.github/workflows/ci.yml +0 -41
- package/.idea/codeStyles/Project.xml +0 -59
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/maverick-wave.iml +0 -12
- package/.idea/modules.xml +0 -8
- package/.idea/prettier.xml +0 -6
- package/.idea/vcs.xml +0 -6
- package/.prettierignore +0 -8
- package/.prettierrc.json +0 -7
- package/CHANGELOG.md +0 -956
- package/CLAUDE.md +0 -60
- package/gulpfile.js +0 -167
- package/index.html +0 -1730
- package/release.sh +0 -31
- package/scripts/verify.js +0 -252
- package/src/assets/favicon/apple-touch-icon.png +0 -0
- package/src/assets/favicon/favicon-96x96.png +0 -0
- package/src/assets/favicon/favicon.svg +0 -1
- package/src/assets/favicon/site.webmanifest +0 -37
- package/src/assets/favicon/web-app-manifest-192x192.png +0 -0
- package/src/assets/favicon/web-app-manifest-512x512.png +0 -0
- package/src/assets/favicon.ico +0 -0
- package/src/assets/header-logo.svg +0 -24
- package/src/assets/images/gallery-city.svg +0 -49
- package/src/assets/images/gallery-desert.svg +0 -25
- package/src/assets/images/gallery-forest.svg +0 -46
- package/src/assets/images/gallery-lake.svg +0 -26
- package/src/assets/images/gallery-mountain.svg +0 -19
- package/src/assets/images/gallery-ocean.svg +0 -26
- package/src/assets/images/gallery-oldtown.svg +0 -41
- package/src/assets/images/gallery-snow.svg +0 -39
- package/src/assets/images/photo-balloon.svg +0 -35
- package/src/assets/images/photo-forest-path.svg +0 -31
- package/src/assets/images/photo-lighthouse.svg +0 -42
- package/src/assets/images/photo-palm.svg +0 -27
- package/src/assets/images/photo-peak.svg +0 -27
- package/src/assets/images/photo-tower.svg +0 -34
- package/src/assets/images/photo-waterfall.svg +0 -32
- package/src/assets/images/slider-field.svg +0 -124
- package/src/assets/images/slider-forest.svg +0 -33
- package/src/assets/images/slider-lake.svg +0 -35
- package/src/assets/images/slider-mountains.svg +0 -29
- package/src/assets/images/slider-trees.svg +0 -41
- package/src/assets/images/story-aurora.svg +0 -36
- package/src/assets/images/story-beach.svg +0 -34
- package/src/assets/images/story-stars.svg +0 -35
- package/src/assets/images/tile-analytics.svg +0 -22
- package/src/assets/images/tile-cloud.svg +0 -19
- package/src/assets/images/tile-ecommerce.svg +0 -14
- package/src/assets/images/tile-enterprise.svg +0 -22
- package/src/assets/images/tile-marketing.svg +0 -16
- package/src/assets/media/demo-chime.wav +0 -0
- package/src/assets/media/story-sunrise.jpg +0 -0
- package/src/assets/media/story-sunrise.mp4 +0 -0
- package/src/partials/accordions-container.html +0 -179
- package/src/partials/alerts-container.html +0 -151
- package/src/partials/announcement-container.html +0 -67
- package/src/partials/avatars-container.html +0 -229
- package/src/partials/badges-container.html +0 -114
- package/src/partials/blog-posts-container.html +0 -158
- package/src/partials/breadcrumbs-container.html +0 -126
- package/src/partials/button-bar-container.html +0 -175
- package/src/partials/buttons-container.html +0 -272
- package/src/partials/calendar-container.html +0 -203
- package/src/partials/cards-container.html +0 -727
- package/src/partials/code-container.html +0 -194
- package/src/partials/colors-container.html +0 -263
- package/src/partials/coming-soon-container.html +0 -10
- package/src/partials/contact-container.html +0 -85
- package/src/partials/content-slider-container.html +0 -36
- package/src/partials/divider-container.html +0 -70
- package/src/partials/documentation-container.html +0 -204
- package/src/partials/dropdown-container.html +0 -119
- package/src/partials/empty-state-container.html +0 -79
- package/src/partials/feed-container.html +0 -506
- package/src/partials/footer-container.html +0 -113
- package/src/partials/form-container.html +0 -262
- package/src/partials/form-elements-container.html +0 -616
- package/src/partials/form-field-container.html +0 -166
- package/src/partials/gallery-container.html +0 -62
- package/src/partials/get-started-container.html +0 -423
- package/src/partials/grid-container.html +0 -191
- package/src/partials/header-container.html +0 -69
- package/src/partials/header-utilities-container.html +0 -331
- package/src/partials/highlights-container.html +0 -71
- package/src/partials/history-container.html +0 -67
- package/src/partials/home-container.html +0 -31
- package/src/partials/html-lists-container.html +0 -63
- package/src/partials/info-container.html +0 -104
- package/src/partials/input-group-container.html +0 -299
- package/src/partials/item-lists-container.html +0 -368
- package/src/partials/kanban-container.html +0 -459
- package/src/partials/kbd-container.html +0 -63
- package/src/partials/leader-row-container.html +0 -139
- package/src/partials/login-container.html +0 -65
- package/src/partials/lunch-menu-container.html +0 -341
- package/src/partials/media-container.html +0 -27
- package/src/partials/meta-info-container.html +0 -21
- package/src/partials/modals-container.html +0 -199
- package/src/partials/mosaic-container.html +0 -173
- package/src/partials/page-header-container.html +0 -78
- package/src/partials/pagination-container.html +0 -64
- package/src/partials/palette-container.html +0 -480
- package/src/partials/panels-container.html +0 -126
- package/src/partials/parallax-container.html +0 -147
- package/src/partials/portrait-gallery-container.html +0 -175
- package/src/partials/preview-container.html +0 -136
- package/src/partials/pricing-container.html +0 -523
- package/src/partials/progress-container.html +0 -230
- package/src/partials/prose-container.html +0 -43
- package/src/partials/ratings-container.html +0 -104
- package/src/partials/section-head-container.html +0 -77
- package/src/partials/segmented-container.html +0 -66
- package/src/partials/skeleton-container.html +0 -87
- package/src/partials/spinners-container.html +0 -96
- package/src/partials/stepper-container.html +0 -111
- package/src/partials/stories-container.html +0 -182
- package/src/partials/tables-container.html +0 -309
- package/src/partials/tabs-container.html +0 -290
- package/src/partials/tags-container.html +0 -242
- package/src/partials/techstack-bucket-container.html +0 -187
- package/src/partials/testimonials-container.html +0 -88
- package/src/partials/tiles-container.html +0 -247
- package/src/partials/timelines-container.html +0 -196
- package/src/partials/typography-container.html +0 -74
- package/src/partials/utilities-container.html +0 -553
package/index.html
DELETED
|
@@ -1,1730 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta
|
|
6
|
-
name="viewport"
|
|
7
|
-
content="width=device-width, minimum-scale=1, initial-scale=1, viewport-fit=cover"
|
|
8
|
-
/>
|
|
9
|
-
<meta
|
|
10
|
-
name="format-detection"
|
|
11
|
-
content="telephone=no,email=no,address=no,date=no"
|
|
12
|
-
/>
|
|
13
|
-
<title>MaverickWave</title>
|
|
14
|
-
<!-- Third-party CSS goes into a layer of its own, declared ahead of the
|
|
15
|
-
framework's. Unlayered CSS beats every layer, so a plain <link> here
|
|
16
|
-
would let Font Awesome's `.fas { display }` win over `.mw-tags-icon`.
|
|
17
|
-
Any project that loads a vendor stylesheet next to MaverickWave wants
|
|
18
|
-
these two lines. -->
|
|
19
|
-
<style>
|
|
20
|
-
@layer vendor, mw;
|
|
21
|
-
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css')
|
|
22
|
-
layer(vendor);
|
|
23
|
-
</style>
|
|
24
|
-
<!-- ?v= so a release actually reaches a browser that has the last one
|
|
25
|
-
cached: the filename never changes, and without it a stale stylesheet
|
|
26
|
-
survives a normal reload -->
|
|
27
|
-
<link rel="stylesheet" href="maverick-wave.min.css?v={{VERSION}}" />
|
|
28
|
-
|
|
29
|
-
<!-- Applies a stored theme choice before the first paint. Without it a
|
|
30
|
-
reader whose choice differs from the OS sees the other theme for a
|
|
31
|
-
frame, because main.js only runs at the end of the body. Inline and
|
|
32
|
-
synchronous on purpose - an external file would paint first. -->
|
|
33
|
-
<script>
|
|
34
|
-
(function () {
|
|
35
|
-
var stored = localStorage.getItem('mw-theme');
|
|
36
|
-
if (stored === 'light' || stored === 'dark') {
|
|
37
|
-
document.documentElement.classList.add('mw-theme-' + stored);
|
|
38
|
-
}
|
|
39
|
-
})();
|
|
40
|
-
</script>
|
|
41
|
-
<!-- Favicons -->
|
|
42
|
-
<link rel="icon" type="image/svg+xml" href="favicon/favicon.svg" />
|
|
43
|
-
<link
|
|
44
|
-
rel="icon"
|
|
45
|
-
type="image/png"
|
|
46
|
-
sizes="96x96"
|
|
47
|
-
href="favicon/favicon-96x96.png"
|
|
48
|
-
/>
|
|
49
|
-
<link rel="shortcut icon" href="favicon.ico" />
|
|
50
|
-
<link
|
|
51
|
-
rel="apple-touch-icon"
|
|
52
|
-
sizes="180x180"
|
|
53
|
-
href="favicon/apple-touch-icon.png"
|
|
54
|
-
/>
|
|
55
|
-
<link rel="manifest" href="favicon/site.webmanifest" />
|
|
56
|
-
|
|
57
|
-
<!-- Showcase starts in dark mode unless localStorage says otherwise -->
|
|
58
|
-
<meta name="theme-color" content="#171f30" />
|
|
59
|
-
<style>
|
|
60
|
-
/* Additional styles only for the showcase page */
|
|
61
|
-
.position-relative {
|
|
62
|
-
position: relative;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/* A version number is digits, so it gets the mono stack - the rest of
|
|
66
|
-
the pill is mw-hero-badge */
|
|
67
|
-
.version-corner {
|
|
68
|
-
font-family: var(--mw-font-family-mono);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.color-card {
|
|
72
|
-
padding: 18px;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
.color-card p {
|
|
76
|
-
margin-bottom: 5px !important;
|
|
77
|
-
font-size: 0.9rem;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.color-swatch {
|
|
81
|
-
width: 100%;
|
|
82
|
-
height: 70px;
|
|
83
|
-
border-radius: 6px;
|
|
84
|
-
margin-bottom: 9px;
|
|
85
|
-
border: 1px solid var(--mw-border);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/* The parallax pattern demo: a gradient has no edge across the travel,
|
|
89
|
-
the second layer brings one */
|
|
90
|
-
.parallax-demo-ground {
|
|
91
|
-
background-image: linear-gradient(
|
|
92
|
-
158deg,
|
|
93
|
-
#3c4f78 0%,
|
|
94
|
-
#2a3550 45%,
|
|
95
|
-
#1b2334 100%
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
.parallax-demo-lines {
|
|
100
|
-
--mw-parallax-pattern-image:
|
|
101
|
-
repeating-linear-gradient(
|
|
102
|
-
to bottom,
|
|
103
|
-
rgb(255 255 255 / 24%) 0 1px,
|
|
104
|
-
transparent 1px 34px
|
|
105
|
-
),
|
|
106
|
-
repeating-linear-gradient(
|
|
107
|
-
to right,
|
|
108
|
-
rgb(255 255 255 / 14%) 0 1px,
|
|
109
|
-
transparent 1px 34px
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/* The travel has to sit on the animated section, the height on the block
|
|
114
|
-
inside it */
|
|
115
|
-
.parallax-band-demo {
|
|
116
|
-
--mw-parallax-slow-travel: 72vh;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
.parallax-band-demo .mw-parallax {
|
|
120
|
-
min-height: 88vh;
|
|
121
|
-
--mw-parallax-depth: 18vh;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/* Reuses the hero picture through the token, not a second download */
|
|
125
|
-
.parallax-band-demo .mw-parallax-media {
|
|
126
|
-
background-image: var(--mw-hero-background);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/* A calendar fills its container; across the full page that stretches the
|
|
130
|
-
cells to 150px, so the demos get a realistic column instead */
|
|
131
|
-
.calendar-demo {
|
|
132
|
-
max-width: 520px;
|
|
133
|
-
margin-inline: auto;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/* Here, not inline - inline it would outrank the compact value too */
|
|
137
|
-
#kanban-demo {
|
|
138
|
-
--mw-kanban-column-min-height: 390px;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
#kanban-demo.mw-kanban-compact {
|
|
142
|
-
--mw-kanban-column-min-height: 210px;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/* A compact calendar has no dots, so its legend has nothing to explain */
|
|
146
|
-
.calendar-demo .mw-calendar-compact .mw-calendar-legend {
|
|
147
|
-
display: none;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/* Medium screens */
|
|
151
|
-
@media (max-width: 992px) {
|
|
152
|
-
/* Two calendars side by side squeeze their cells below md, so they
|
|
153
|
-
stack one breakpoint earlier than mw-grid-2 would on its own */
|
|
154
|
-
.calendar-demos {
|
|
155
|
-
grid-template-columns: minmax(0, 1fr);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/* Small screens */
|
|
160
|
-
@media (max-width: 576px) {
|
|
161
|
-
.color-swatch {
|
|
162
|
-
margin: 0 auto 7px auto;
|
|
163
|
-
width: 92%;
|
|
164
|
-
height: 50px;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/* Palette switcher, showcase only. The framework derives every tone from
|
|
169
|
-
the root colors, so the panel writes nothing but those. */
|
|
170
|
-
.palette-toggle {
|
|
171
|
-
display: none;
|
|
172
|
-
align-items: center;
|
|
173
|
-
justify-content: center;
|
|
174
|
-
width: 50px;
|
|
175
|
-
height: 40px;
|
|
176
|
-
flex-shrink: 0;
|
|
177
|
-
border: none;
|
|
178
|
-
border-radius: calc(10px * var(--mw-radius-scale, 1));
|
|
179
|
-
background: var(--mw-primary-color);
|
|
180
|
-
color: var(--mw-primary-accent-text-color);
|
|
181
|
-
font-size: 1.1rem;
|
|
182
|
-
cursor: pointer;
|
|
183
|
-
transition: var(--mw-transition);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/* Below sm the panel would cover the very thing it is changing */
|
|
187
|
-
@media (min-width: 576px) {
|
|
188
|
-
.palette-toggle {
|
|
189
|
-
display: flex;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
.palette-toggle:hover {
|
|
194
|
-
background: var(--mw-primary-color-hover);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
.palette-toggle:active {
|
|
198
|
-
transform: scale(0.94);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
.palette-panel {
|
|
202
|
-
position: fixed;
|
|
203
|
-
top: calc(var(--mw-header-height) + 8px);
|
|
204
|
-
/* Flush with the container edge, so it lines up with the button in the
|
|
205
|
-
header rather than sitting further out */
|
|
206
|
-
right: max(18px, calc((100% - var(--mw-container-width)) / 2));
|
|
207
|
-
z-index: 400;
|
|
208
|
-
/* Wide enough for three palettes in a row; the min() is for the narrow
|
|
209
|
-
end, where the panel would otherwise reach past the viewport */
|
|
210
|
-
width: min(440px, calc(100% - 24px));
|
|
211
|
-
/* The variant list makes the panel taller than a laptop in landscape -
|
|
212
|
-
it takes what is left under the header and scrolls the rest */
|
|
213
|
-
max-height: calc(100dvh - var(--mw-header-height) - 24px);
|
|
214
|
-
overflow-y: auto;
|
|
215
|
-
overscroll-behavior: contain;
|
|
216
|
-
padding: 18px;
|
|
217
|
-
border-radius: 12px;
|
|
218
|
-
border: 1px solid var(--mw-border);
|
|
219
|
-
background: var(--mw-card-background);
|
|
220
|
-
box-shadow: var(--mw-elevation-5);
|
|
221
|
-
transform: translateY(0);
|
|
222
|
-
opacity: 1;
|
|
223
|
-
/* display is in the list so allow-discrete keeps the panel mounted
|
|
224
|
-
through the fade out - `hidden` is the state the script writes */
|
|
225
|
-
transition-property: opacity, transform, display;
|
|
226
|
-
transition-duration: var(--mw-duration-base);
|
|
227
|
-
transition-timing-function: var(--mw-ease-out);
|
|
228
|
-
transition-behavior: allow-discrete;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
@starting-style {
|
|
232
|
-
.palette-panel {
|
|
233
|
-
opacity: 0;
|
|
234
|
-
transform: translateY(-12px);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
.palette-panel[hidden] {
|
|
239
|
-
opacity: 0;
|
|
240
|
-
transform: translateY(-12px);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
.palette-heading {
|
|
244
|
-
font-size: 1.1rem;
|
|
245
|
-
margin-bottom: 4px;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
.palette-hint {
|
|
249
|
-
font-size: 0.8rem;
|
|
250
|
-
line-height: 1.35;
|
|
251
|
-
color: var(--mw-text-muted-color);
|
|
252
|
-
margin-bottom: 14px;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
.palette-grid {
|
|
256
|
-
display: grid;
|
|
257
|
-
grid-template-columns: repeat(3, 1fr);
|
|
258
|
-
gap: 6px;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
.palette-item {
|
|
262
|
-
display: flex;
|
|
263
|
-
align-items: center;
|
|
264
|
-
gap: 8px;
|
|
265
|
-
padding: 6px 8px;
|
|
266
|
-
border-radius: 8px;
|
|
267
|
-
border: 1px solid var(--mw-border);
|
|
268
|
-
background: transparent;
|
|
269
|
-
color: var(--mw-text-color);
|
|
270
|
-
font-size: 0.8rem;
|
|
271
|
-
text-align: left;
|
|
272
|
-
cursor: pointer;
|
|
273
|
-
transition: var(--mw-transition);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
.palette-item::before {
|
|
277
|
-
content: '';
|
|
278
|
-
width: 16px;
|
|
279
|
-
height: 16px;
|
|
280
|
-
flex-shrink: 0;
|
|
281
|
-
border-radius: 50%;
|
|
282
|
-
background: linear-gradient(
|
|
283
|
-
135deg,
|
|
284
|
-
var(--swatch-primary) 50%,
|
|
285
|
-
var(--swatch-secondary) 50%
|
|
286
|
-
);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
.palette-item:hover,
|
|
290
|
-
.palette-item.mw-active {
|
|
291
|
-
border-color: var(--mw-primary-text-color);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
.palette-item.mw-active {
|
|
295
|
-
background: var(--mw-primary-background);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
.palette-custom {
|
|
299
|
-
display: flex;
|
|
300
|
-
gap: 10px;
|
|
301
|
-
margin-top: 14px;
|
|
302
|
-
padding-top: 12px;
|
|
303
|
-
border-top: 1px solid var(--mw-border);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
.palette-field {
|
|
307
|
-
flex: 1;
|
|
308
|
-
display: flex;
|
|
309
|
-
flex-direction: column;
|
|
310
|
-
gap: 4px;
|
|
311
|
-
font-size: 0.75rem;
|
|
312
|
-
color: var(--mw-text-muted-color);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
.palette-field input {
|
|
316
|
-
width: 100%;
|
|
317
|
-
height: 30px;
|
|
318
|
-
padding: 2px;
|
|
319
|
-
border: 1px solid var(--mw-border);
|
|
320
|
-
border-radius: 6px;
|
|
321
|
-
background: var(--mw-card-background);
|
|
322
|
-
cursor: pointer;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/* Single accent means the secondary picker writes a token nothing reads any
|
|
326
|
-
more - left live it is a knob that does nothing */
|
|
327
|
-
:root.mw-accent-single .palette-field:has(#palette-secondary) {
|
|
328
|
-
opacity: 0.4;
|
|
329
|
-
pointer-events: none;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
.palette-heading-split {
|
|
333
|
-
margin-top: 18px;
|
|
334
|
-
padding-top: 14px;
|
|
335
|
-
border-top: 1px solid var(--mw-border);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/* Splits the list by where a switch shows up, because half of them act on
|
|
339
|
-
parts of the page the preview does not contain */
|
|
340
|
-
.variant-group {
|
|
341
|
-
margin: 20px 0 2px;
|
|
342
|
-
font-size: 0.78rem;
|
|
343
|
-
font-weight: 600;
|
|
344
|
-
color: var(--mw-text-color);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
.variant-group:first-child {
|
|
348
|
-
margin-top: 4px;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
.variant-group-hint {
|
|
352
|
-
margin: 0 0 4px;
|
|
353
|
-
font-size: 0.68rem;
|
|
354
|
-
line-height: 1.35;
|
|
355
|
-
color: var(--mw-text-muted-color);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
.variant-row {
|
|
359
|
-
display: flex;
|
|
360
|
-
align-items: center;
|
|
361
|
-
justify-content: space-between;
|
|
362
|
-
gap: 12px;
|
|
363
|
-
padding-block: 9px;
|
|
364
|
-
font-size: 0.8rem;
|
|
365
|
-
color: var(--mw-text-color);
|
|
366
|
-
cursor: pointer;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
.variant-label {
|
|
370
|
-
display: flex;
|
|
371
|
-
flex-direction: column;
|
|
372
|
-
gap: 2px;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
.variant-label small {
|
|
376
|
-
font-size: 0.68rem;
|
|
377
|
-
line-height: 1.35;
|
|
378
|
-
color: var(--mw-text-muted-color);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
.variant-row + .variant-row {
|
|
382
|
-
border-top: 1px solid var(--mw-border);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
/* Width and the two size tokens are taken back from .mw-select for the
|
|
386
|
-
same reason the switch below is hand-drawn: the field must not resize
|
|
387
|
-
itself while it is the knob for density and radius */
|
|
388
|
-
.variant-row .mw-select {
|
|
389
|
-
--mw-radius-scale: 1;
|
|
390
|
-
--mw-control-height-sm: 1.875rem;
|
|
391
|
-
flex-shrink: 0;
|
|
392
|
-
width: auto;
|
|
393
|
-
max-width: 135px;
|
|
394
|
-
cursor: pointer;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
/* Drawn by hand rather than reusing mw-toggle: a framework switch would
|
|
398
|
-
reshape itself along with the variants it is there to control */
|
|
399
|
-
.variant-row input[type='checkbox'] {
|
|
400
|
-
appearance: none;
|
|
401
|
-
flex-shrink: 0;
|
|
402
|
-
position: relative;
|
|
403
|
-
width: 34px;
|
|
404
|
-
height: 18px;
|
|
405
|
-
margin: 0;
|
|
406
|
-
border: 1px solid var(--mw-border);
|
|
407
|
-
border-radius: 9px;
|
|
408
|
-
background: var(--mw-gray-background);
|
|
409
|
-
cursor: pointer;
|
|
410
|
-
transition: var(--mw-transition);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
.variant-row input[type='checkbox']::after {
|
|
414
|
-
content: '';
|
|
415
|
-
position: absolute;
|
|
416
|
-
top: 2px;
|
|
417
|
-
left: 2px;
|
|
418
|
-
width: 12px;
|
|
419
|
-
height: 12px;
|
|
420
|
-
border-radius: 50%;
|
|
421
|
-
background: var(--mw-text-muted-color);
|
|
422
|
-
transition: var(--mw-transition);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
.variant-row input[type='checkbox']:checked {
|
|
426
|
-
background: var(--mw-primary-color);
|
|
427
|
-
border-color: var(--mw-primary-color);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
.variant-row input[type='checkbox']:checked::after {
|
|
431
|
-
left: 18px;
|
|
432
|
-
background: var(--mw-primary-accent-text-color);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
/* The sticky bar would otherwise sit on the section title it jumps to */
|
|
436
|
-
#preview {
|
|
437
|
-
scroll-margin-top: calc(var(--mw-header-height) + 1rem);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
.preview-head {
|
|
441
|
-
display: flex;
|
|
442
|
-
align-items: flex-start;
|
|
443
|
-
justify-content: space-between;
|
|
444
|
-
gap: 1rem;
|
|
445
|
-
margin-bottom: 1.5rem;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
.preview-title {
|
|
449
|
-
margin: 0 0 0.35rem;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
.preview-lede {
|
|
453
|
-
margin: 0;
|
|
454
|
-
max-inline-size: 60ch;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
/* The panel is fixed over the right of the page, flush with the container
|
|
458
|
-
edge. Below xl there is no room to dodge it and it simply covers part of
|
|
459
|
-
the preview; from there the preview keeps to the strip beside it,
|
|
460
|
-
because a switch that moves something hidden behind the panel
|
|
461
|
-
demonstrates nothing. */
|
|
462
|
-
@media (width >= 1200px) {
|
|
463
|
-
body:has(.palette-panel:not([hidden])) #preview > .mw-container {
|
|
464
|
-
padding-inline-end: 460px;
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/* Both wrap rather than squeezing a field to nothing on a phone */
|
|
469
|
-
.preview-row,
|
|
470
|
-
.preview-actions {
|
|
471
|
-
display: flex;
|
|
472
|
-
flex-wrap: wrap;
|
|
473
|
-
align-items: center;
|
|
474
|
-
gap: 0.75rem;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
.preview-row .mw-input {
|
|
478
|
-
flex: 1 1 12rem;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
/* The one thing here that keeps moving without being touched, so Motion
|
|
482
|
-
tempo has something to show that a hover state cannot */
|
|
483
|
-
.preview-status {
|
|
484
|
-
display: flex;
|
|
485
|
-
align-items: center;
|
|
486
|
-
gap: 14px;
|
|
487
|
-
margin: 0 0 1.25rem;
|
|
488
|
-
font-size: 0.82rem;
|
|
489
|
-
color: var(--mw-text-muted-color);
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
.preview-status strong {
|
|
493
|
-
display: block;
|
|
494
|
-
color: var(--mw-text-color);
|
|
495
|
-
font-weight: 500;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
.preview-status small {
|
|
499
|
-
font-size: 0.75rem;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
.preview-row .mw-select {
|
|
503
|
-
flex: 0 1 14rem;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
/* The spacing sits on the row and not on the label: the button is taller
|
|
507
|
-
than the caption beside it, so a margin under the label leaves the
|
|
508
|
-
button itself resting on the box */
|
|
509
|
-
.variant-setup-head {
|
|
510
|
-
display: flex;
|
|
511
|
-
align-items: baseline;
|
|
512
|
-
justify-content: space-between;
|
|
513
|
-
gap: 10px;
|
|
514
|
-
margin: 14px 0 10px;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
.variant-setup-label {
|
|
518
|
-
display: block;
|
|
519
|
-
margin: 0;
|
|
520
|
-
font-size: 0.7rem;
|
|
521
|
-
color: var(--mw-text-muted-color);
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
/* The one control here that leads somewhere - everything else in the
|
|
525
|
-
panel only changes what is on screen. Carries the brand colour so it
|
|
526
|
-
reads as the way out rather than as one more switch. */
|
|
527
|
-
.variant-share {
|
|
528
|
-
display: inline-flex;
|
|
529
|
-
align-items: center;
|
|
530
|
-
gap: 6px;
|
|
531
|
-
flex-shrink: 0;
|
|
532
|
-
padding: 5px 12px;
|
|
533
|
-
border-radius: 999px;
|
|
534
|
-
border: 1px solid var(--mw-primary-color);
|
|
535
|
-
background: var(--mw-primary-color);
|
|
536
|
-
color: var(--mw-primary-accent-text-color);
|
|
537
|
-
font: inherit;
|
|
538
|
-
font-size: 0.72rem;
|
|
539
|
-
font-weight: 500;
|
|
540
|
-
cursor: pointer;
|
|
541
|
-
transition: var(--mw-transition-fast);
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
.variant-share:hover {
|
|
545
|
-
background: var(--mw-primary-color-hover, var(--mw-primary-color));
|
|
546
|
-
transform: translateY(-1px);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
.variant-share:active {
|
|
550
|
-
transform: translateY(0);
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
.variant-share:focus-visible {
|
|
554
|
-
outline: var(--mw-focus-ring-width) solid var(--mw-focus-ring-color);
|
|
555
|
-
outline-offset: var(--mw-focus-ring-offset);
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
.variant-setup {
|
|
559
|
-
display: block;
|
|
560
|
-
width: 100%;
|
|
561
|
-
resize: vertical;
|
|
562
|
-
padding: 10px;
|
|
563
|
-
border-radius: 8px;
|
|
564
|
-
border: 1px solid var(--mw-border);
|
|
565
|
-
background: var(--mw-gray-background);
|
|
566
|
-
color: var(--mw-text-muted-color);
|
|
567
|
-
font-family: var(--mw-font-family-mono);
|
|
568
|
-
font-size: 0.68rem;
|
|
569
|
-
line-height: 1.5;
|
|
570
|
-
white-space: pre-wrap;
|
|
571
|
-
word-break: break-word;
|
|
572
|
-
}
|
|
573
|
-
</style>
|
|
574
|
-
|
|
575
|
-
<script src="maverick-wave.min.js?v={{VERSION}}"></script>
|
|
576
|
-
</head>
|
|
577
|
-
|
|
578
|
-
<body>
|
|
579
|
-
<a class="mw-skip-link" href="#main">Skip to content</a>
|
|
580
|
-
|
|
581
|
-
<!-- Header -->
|
|
582
|
-
<header class="mw-header mw-localhost-indicator-activated mw-header-reveal">
|
|
583
|
-
<div class="mw-container">
|
|
584
|
-
@@include('./src/partials/header-container.html')
|
|
585
|
-
</div>
|
|
586
|
-
</header>
|
|
587
|
-
|
|
588
|
-
<main class="mw-main" id="main">
|
|
589
|
-
<!-- Home section -->
|
|
590
|
-
<section id="home" class="mw-section mw-parallax-sticky mw-parallax-rise">
|
|
591
|
-
<div class="mw-container mw-parallax">
|
|
592
|
-
@@include('./src/partials/home-container.html')
|
|
593
|
-
</div>
|
|
594
|
-
</section>
|
|
595
|
-
|
|
596
|
-
<!-- Highlights section -->
|
|
597
|
-
<section id="highlights" class="mw-section mw-section-alternate">
|
|
598
|
-
<div class="mw-container">
|
|
599
|
-
@@include('./src/partials/highlights-container.html')
|
|
600
|
-
</div>
|
|
601
|
-
</section>
|
|
602
|
-
|
|
603
|
-
<!-- Get started section -->
|
|
604
|
-
<section id="get-started" class="mw-section">
|
|
605
|
-
<div class="mw-container">
|
|
606
|
-
<div class="mw-section-head">
|
|
607
|
-
<h2 class="mw-section-head-title">Get started</h2>
|
|
608
|
-
</div>
|
|
609
|
-
@@include('./src/partials/get-started-container.html')
|
|
610
|
-
</div>
|
|
611
|
-
</section>
|
|
612
|
-
|
|
613
|
-
<!-- Documentation section -->
|
|
614
|
-
<section id="documentation" class="mw-section mw-section-alternate">
|
|
615
|
-
<div class="mw-container">
|
|
616
|
-
<div class="mw-section-head">
|
|
617
|
-
<h2 class="mw-section-head-title">Documentation</h2>
|
|
618
|
-
</div>
|
|
619
|
-
@@include('./src/partials/documentation-container.html')
|
|
620
|
-
</div>
|
|
621
|
-
</section>
|
|
622
|
-
|
|
623
|
-
<!-- Foundations section -->
|
|
624
|
-
<section id="foundations" class="mw-section">
|
|
625
|
-
<div class="mw-container">
|
|
626
|
-
<div class="mw-section-head">
|
|
627
|
-
<h2 class="mw-section-head-title">Foundations</h2>
|
|
628
|
-
<p class="mw-section-head-intro">
|
|
629
|
-
The raw material - type, color, spacing and the small utilities
|
|
630
|
-
everything else is built from.
|
|
631
|
-
</p>
|
|
632
|
-
</div>
|
|
633
|
-
<nav class="mw-section-nav">
|
|
634
|
-
<a href="#typography" class="mw-section-btn">Typography</a>
|
|
635
|
-
<a href="#colors" class="mw-section-btn">Main Colors</a>
|
|
636
|
-
<a href="#utilities" class="mw-section-btn">Utilities</a>
|
|
637
|
-
<a href="#header-utilities" class="mw-section-btn"
|
|
638
|
-
>Header Utilities</a
|
|
639
|
-
>
|
|
640
|
-
<a href="#coming-soon" class="mw-section-btn">Coming Soon Banner</a>
|
|
641
|
-
<a href="#divider" class="mw-section-btn">Divider</a>
|
|
642
|
-
</nav>
|
|
643
|
-
|
|
644
|
-
<!-- Typography container -->
|
|
645
|
-
<div id="typography">
|
|
646
|
-
@@include('./src/partials/typography-container.html')
|
|
647
|
-
</div>
|
|
648
|
-
|
|
649
|
-
<!-- Colors container -->
|
|
650
|
-
<div id="colors">
|
|
651
|
-
@@include('./src/partials/colors-container.html')
|
|
652
|
-
</div>
|
|
653
|
-
|
|
654
|
-
<!-- Utilities container -->
|
|
655
|
-
<div id="utilities">
|
|
656
|
-
@@include('./src/partials/utilities-container.html')
|
|
657
|
-
</div>
|
|
658
|
-
|
|
659
|
-
<!-- Header Utilities container -->
|
|
660
|
-
<div id="header-utilities">
|
|
661
|
-
@@include('./src/partials/header-utilities-container.html')
|
|
662
|
-
</div>
|
|
663
|
-
|
|
664
|
-
<!-- Coming Soon container -->
|
|
665
|
-
<div id="coming-soon">
|
|
666
|
-
@@include('./src/partials/coming-soon-container.html')
|
|
667
|
-
</div>
|
|
668
|
-
|
|
669
|
-
<!-- Divider container -->
|
|
670
|
-
<div id="divider">
|
|
671
|
-
@@include('./src/partials/divider-container.html')
|
|
672
|
-
</div>
|
|
673
|
-
</div>
|
|
674
|
-
</section>
|
|
675
|
-
|
|
676
|
-
<!-- Layout section -->
|
|
677
|
-
<section id="layout" class="mw-section mw-section-alternate">
|
|
678
|
-
<div class="mw-container">
|
|
679
|
-
<div class="mw-section-head">
|
|
680
|
-
<h2 class="mw-section-head-title">Layout</h2>
|
|
681
|
-
<p class="mw-section-head-intro">
|
|
682
|
-
The bones of a page - grids, cards, panels and the containers that
|
|
683
|
-
hold content together.
|
|
684
|
-
</p>
|
|
685
|
-
</div>
|
|
686
|
-
<nav class="mw-section-nav">
|
|
687
|
-
<a href="#section-head" class="mw-section-btn">Section Head</a>
|
|
688
|
-
<a href="#grid" class="mw-section-btn">Grid System</a>
|
|
689
|
-
<a href="#cards" class="mw-section-btn">Cards</a>
|
|
690
|
-
<a href="#panels" class="mw-section-btn">Panels</a>
|
|
691
|
-
<a href="#tabs" class="mw-section-btn">Tabs</a>
|
|
692
|
-
<a href="#accordions" class="mw-section-btn">Accordions</a>
|
|
693
|
-
<a href="#tiles" class="mw-section-btn">Tiles</a>
|
|
694
|
-
<a href="#breadcrumbs" class="mw-section-btn">Breadcrumbs</a>
|
|
695
|
-
<a href="#modals" class="mw-section-btn">Modals</a>
|
|
696
|
-
<a href="#html-lists" class="mw-section-btn">HTML Lists</a>
|
|
697
|
-
<a href="#item-lists" class="mw-section-btn">Item Lists</a>
|
|
698
|
-
<a href="#leader-row" class="mw-section-btn">Leader Row</a>
|
|
699
|
-
<a href="#stepper" class="mw-section-btn">Stepper</a>
|
|
700
|
-
<a href="#parallax" class="mw-section-btn">Parallax</a>
|
|
701
|
-
</nav>
|
|
702
|
-
|
|
703
|
-
<!-- Section head container -->
|
|
704
|
-
<div id="section-head">
|
|
705
|
-
@@include('./src/partials/section-head-container.html')
|
|
706
|
-
</div>
|
|
707
|
-
|
|
708
|
-
<!-- Grid container -->
|
|
709
|
-
<div id="grid">@@include('./src/partials/grid-container.html')</div>
|
|
710
|
-
|
|
711
|
-
<!-- Cards container -->
|
|
712
|
-
<div id="cards">@@include('./src/partials/cards-container.html')</div>
|
|
713
|
-
|
|
714
|
-
<!-- Panels container -->
|
|
715
|
-
<div id="panels">
|
|
716
|
-
@@include('./src/partials/panels-container.html')
|
|
717
|
-
</div>
|
|
718
|
-
|
|
719
|
-
<!-- Tabs container -->
|
|
720
|
-
<div id="tabs">@@include('./src/partials/tabs-container.html')</div>
|
|
721
|
-
|
|
722
|
-
<!-- Accordions contaier -->
|
|
723
|
-
<div id="accordions">
|
|
724
|
-
@@include('./src/partials/accordions-container.html')
|
|
725
|
-
</div>
|
|
726
|
-
|
|
727
|
-
<!-- Tiles container -->
|
|
728
|
-
<div id="tiles">@@include('./src/partials/tiles-container.html')</div>
|
|
729
|
-
|
|
730
|
-
<!-- Breadcrumbs container -->
|
|
731
|
-
<div id="breadcrumbs">
|
|
732
|
-
@@include('./src/partials/breadcrumbs-container.html')
|
|
733
|
-
</div>
|
|
734
|
-
|
|
735
|
-
<!-- Modals container -->
|
|
736
|
-
<div id="modals">
|
|
737
|
-
@@include('./src/partials/modals-container.html')
|
|
738
|
-
</div>
|
|
739
|
-
|
|
740
|
-
<!-- HTML Lists container -->
|
|
741
|
-
<div id="html-lists">
|
|
742
|
-
@@include('./src/partials/html-lists-container.html')
|
|
743
|
-
</div>
|
|
744
|
-
|
|
745
|
-
<!-- Item Lists container -->
|
|
746
|
-
<div id="item-lists">
|
|
747
|
-
@@include('./src/partials/item-lists-container.html')
|
|
748
|
-
</div>
|
|
749
|
-
|
|
750
|
-
<!-- Leader Row container -->
|
|
751
|
-
<div id="leader-row">
|
|
752
|
-
@@include('./src/partials/leader-row-container.html')
|
|
753
|
-
</div>
|
|
754
|
-
|
|
755
|
-
<!-- Stepper container -->
|
|
756
|
-
<div id="stepper">
|
|
757
|
-
@@include('./src/partials/stepper-container.html')
|
|
758
|
-
</div>
|
|
759
|
-
|
|
760
|
-
<!-- Parallax container -->
|
|
761
|
-
<div id="parallax">
|
|
762
|
-
@@include('./src/partials/parallax-container.html')
|
|
763
|
-
</div>
|
|
764
|
-
</div>
|
|
765
|
-
</section>
|
|
766
|
-
|
|
767
|
-
<!-- Parallax band -->
|
|
768
|
-
<section class="mw-parallax-slow parallax-band-demo">
|
|
769
|
-
<div class="mw-parallax mw-parallax-dimmed">
|
|
770
|
-
<div class="mw-parallax-media"></div>
|
|
771
|
-
<div class="mw-parallax-content mw-text-center">
|
|
772
|
-
<div class="mw-container">
|
|
773
|
-
<h2>The page rides over the picture</h2>
|
|
774
|
-
<p class="mw-mb-0">
|
|
775
|
-
This band travels at a fifth of your scrolling. The components
|
|
776
|
-
close in from below.
|
|
777
|
-
</p>
|
|
778
|
-
</div>
|
|
779
|
-
</div>
|
|
780
|
-
</div>
|
|
781
|
-
</section>
|
|
782
|
-
|
|
783
|
-
<!-- Components section -->
|
|
784
|
-
<section id="components" class="mw-section">
|
|
785
|
-
<div class="mw-container">
|
|
786
|
-
<div class="mw-section-head">
|
|
787
|
-
<h2 class="mw-section-head-title">Components</h2>
|
|
788
|
-
<p class="mw-section-head-intro">
|
|
789
|
-
The everyday parts - buttons, tags, alerts and their many friends,
|
|
790
|
-
ready to drop in.
|
|
791
|
-
</p>
|
|
792
|
-
</div>
|
|
793
|
-
<nav class="mw-section-nav">
|
|
794
|
-
<a href="#buttons" class="mw-section-btn">Buttons</a>
|
|
795
|
-
<a href="#button-bar" class="mw-section-btn">Button Bar</a>
|
|
796
|
-
<a href="#progress" class="mw-section-btn">Progress Bars</a>
|
|
797
|
-
<a href="#spinners" class="mw-section-btn">Loading Spinners</a>
|
|
798
|
-
<a href="#avatars" class="mw-section-btn">Avatars</a>
|
|
799
|
-
<a href="#tags" class="mw-section-btn">Tags</a>
|
|
800
|
-
<a href="#badges" class="mw-section-btn">Badges</a>
|
|
801
|
-
<a href="#dropdown" class="mw-section-btn">Dropdown</a>
|
|
802
|
-
<a href="#kbd" class="mw-section-btn">Keyboard Keys</a>
|
|
803
|
-
<a href="#ratings" class="mw-section-btn">Ratings</a>
|
|
804
|
-
<a href="#info" class="mw-section-btn">Info</a>
|
|
805
|
-
<a href="#alerts" class="mw-section-btn">Alerts</a>
|
|
806
|
-
<a href="#announcement" class="mw-section-btn">Announcement</a>
|
|
807
|
-
<a href="#code" class="mw-section-btn">Code</a>
|
|
808
|
-
<a href="#skeleton" class="mw-section-btn">Skeleton</a>
|
|
809
|
-
<a href="#empty-state" class="mw-section-btn">Empty State</a>
|
|
810
|
-
<a href="#pricing" class="mw-section-btn">Pricing</a>
|
|
811
|
-
</nav>
|
|
812
|
-
|
|
813
|
-
<!-- Buttons container -->
|
|
814
|
-
<div id="buttons">
|
|
815
|
-
@@include('./src/partials/buttons-container.html')
|
|
816
|
-
</div>
|
|
817
|
-
|
|
818
|
-
<!-- Button Bar container -->
|
|
819
|
-
<div id="button-bar">
|
|
820
|
-
@@include('./src/partials/button-bar-container.html')
|
|
821
|
-
</div>
|
|
822
|
-
|
|
823
|
-
<!-- Progress container -->
|
|
824
|
-
<div id="progress">
|
|
825
|
-
@@include('./src/partials/progress-container.html')
|
|
826
|
-
</div>
|
|
827
|
-
|
|
828
|
-
<!-- Spinners container -->
|
|
829
|
-
<div id="spinners">
|
|
830
|
-
@@include('./src/partials/spinners-container.html')
|
|
831
|
-
</div>
|
|
832
|
-
|
|
833
|
-
<!-- Avatars container -->
|
|
834
|
-
<div id="avatars">
|
|
835
|
-
@@include('./src/partials/avatars-container.html')
|
|
836
|
-
</div>
|
|
837
|
-
|
|
838
|
-
<!-- Tags container -->
|
|
839
|
-
<div id="tags">@@include('./src/partials/tags-container.html')</div>
|
|
840
|
-
|
|
841
|
-
<!-- Badges container -->
|
|
842
|
-
<div id="badges">
|
|
843
|
-
@@include('./src/partials/badges-container.html')
|
|
844
|
-
</div>
|
|
845
|
-
|
|
846
|
-
<!-- Dropdown container -->
|
|
847
|
-
<div id="dropdown">
|
|
848
|
-
@@include('./src/partials/dropdown-container.html')
|
|
849
|
-
</div>
|
|
850
|
-
|
|
851
|
-
<!-- Keyboard keys container -->
|
|
852
|
-
<div id="kbd">@@include('./src/partials/kbd-container.html')</div>
|
|
853
|
-
|
|
854
|
-
<!-- Ratings container -->
|
|
855
|
-
<div id="ratings">
|
|
856
|
-
@@include('./src/partials/ratings-container.html')
|
|
857
|
-
</div>
|
|
858
|
-
|
|
859
|
-
<!-- Info container -->
|
|
860
|
-
<div id="info">@@include('./src/partials/info-container.html')</div>
|
|
861
|
-
|
|
862
|
-
<!-- Alerts container -->
|
|
863
|
-
<div id="alerts">
|
|
864
|
-
@@include('./src/partials/alerts-container.html')
|
|
865
|
-
</div>
|
|
866
|
-
|
|
867
|
-
<!-- Announcement container -->
|
|
868
|
-
<div id="announcement">
|
|
869
|
-
@@include('./src/partials/announcement-container.html')
|
|
870
|
-
</div>
|
|
871
|
-
|
|
872
|
-
<!-- Code container -->
|
|
873
|
-
<div id="code">@@include('./src/partials/code-container.html')</div>
|
|
874
|
-
|
|
875
|
-
<!-- Skeleton container -->
|
|
876
|
-
<div id="skeleton">
|
|
877
|
-
@@include('./src/partials/skeleton-container.html')
|
|
878
|
-
</div>
|
|
879
|
-
|
|
880
|
-
<!-- Empty State container -->
|
|
881
|
-
<div id="empty-state">
|
|
882
|
-
@@include('./src/partials/empty-state-container.html')
|
|
883
|
-
</div>
|
|
884
|
-
|
|
885
|
-
<!-- Pricing container -->
|
|
886
|
-
<div id="pricing">
|
|
887
|
-
@@include('./src/partials/pricing-container.html')
|
|
888
|
-
</div>
|
|
889
|
-
</div>
|
|
890
|
-
</section>
|
|
891
|
-
|
|
892
|
-
<!-- Forms section -->
|
|
893
|
-
<section id="forms" class="mw-section mw-section-alternate">
|
|
894
|
-
<div class="mw-container">
|
|
895
|
-
<div class="mw-section-head">
|
|
896
|
-
<h2 class="mw-section-head-title">Forms</h2>
|
|
897
|
-
<p class="mw-section-head-intro">
|
|
898
|
-
Inputs, selects, toggles and validation - fields and buttons share
|
|
899
|
-
one height scale by construction.
|
|
900
|
-
</p>
|
|
901
|
-
</div>
|
|
902
|
-
<nav class="mw-section-nav">
|
|
903
|
-
<a href="#form-elements" class="mw-section-btn">Form Elements</a>
|
|
904
|
-
<a href="#input-group" class="mw-section-btn">Input Group</a>
|
|
905
|
-
<a href="#segmented" class="mw-section-btn">Segmented Control</a>
|
|
906
|
-
<a href="#form-field" class="mw-section-btn">Field Pattern</a>
|
|
907
|
-
<a href="#form" class="mw-section-btn">Form</a>
|
|
908
|
-
<a href="#login" class="mw-section-btn">Login</a>
|
|
909
|
-
</nav>
|
|
910
|
-
|
|
911
|
-
<!-- Form elements container -->
|
|
912
|
-
<div id="form-elements">
|
|
913
|
-
@@include('./src/partials/form-elements-container.html')
|
|
914
|
-
</div>
|
|
915
|
-
|
|
916
|
-
<!-- Input Group container -->
|
|
917
|
-
<div id="input-group">
|
|
918
|
-
@@include('./src/partials/input-group-container.html')
|
|
919
|
-
</div>
|
|
920
|
-
|
|
921
|
-
<!-- Segmented control container -->
|
|
922
|
-
<div id="segmented">
|
|
923
|
-
@@include('./src/partials/segmented-container.html')
|
|
924
|
-
</div>
|
|
925
|
-
|
|
926
|
-
<!-- Form Field pattern container -->
|
|
927
|
-
<div id="form-field">
|
|
928
|
-
@@include('./src/partials/form-field-container.html')
|
|
929
|
-
</div>
|
|
930
|
-
|
|
931
|
-
<!-- Form container -->
|
|
932
|
-
<div id="form">@@include('./src/partials/form-container.html')</div>
|
|
933
|
-
|
|
934
|
-
<!-- Login container -->
|
|
935
|
-
<div id="login">@@include('./src/partials/login-container.html')</div>
|
|
936
|
-
</div>
|
|
937
|
-
</section>
|
|
938
|
-
|
|
939
|
-
<!-- Data & display section -->
|
|
940
|
-
<section id="data-display" class="mw-section">
|
|
941
|
-
<div class="mw-container">
|
|
942
|
-
<div class="mw-section-head">
|
|
943
|
-
<h2 class="mw-section-head-title">Data & Display</h2>
|
|
944
|
-
<p class="mw-section-head-intro">
|
|
945
|
-
Tables, boards, timelines and long-form content - everything that
|
|
946
|
-
shows real data.
|
|
947
|
-
</p>
|
|
948
|
-
</div>
|
|
949
|
-
<nav class="mw-section-nav">
|
|
950
|
-
<a href="#page-header" class="mw-section-btn">Page Header</a>
|
|
951
|
-
<a href="#meta-info" class="mw-section-btn">Meta Info</a>
|
|
952
|
-
<a href="#tables" class="mw-section-btn">Tables</a>
|
|
953
|
-
<a href="#kanban" class="mw-section-btn">Kanban</a>
|
|
954
|
-
<a href="#calendar" class="mw-section-btn">Calendar</a>
|
|
955
|
-
<a href="#lunch-menu" class="mw-section-btn">Lunch Menu</a>
|
|
956
|
-
<a href="#contact" class="mw-section-btn">Contact</a>
|
|
957
|
-
<a href="#pagination" class="mw-section-btn">Pagination</a>
|
|
958
|
-
<a href="#timelines" class="mw-section-btn">Timelines</a>
|
|
959
|
-
<a href="#gallery" class="mw-section-btn">Image Gallery</a>
|
|
960
|
-
<a href="#portrait-gallery" class="mw-section-btn"
|
|
961
|
-
>Portrait Gallery</a
|
|
962
|
-
>
|
|
963
|
-
<a href="#mosaic" class="mw-section-btn">Mosaic</a>
|
|
964
|
-
<a href="#feed" class="mw-section-btn">Photo Feed</a>
|
|
965
|
-
<a href="#stories" class="mw-section-btn">Story Archive</a>
|
|
966
|
-
<a href="#techstack-bucket" class="mw-section-btn"
|
|
967
|
-
>Technology Stack Bucket</a
|
|
968
|
-
>
|
|
969
|
-
<a href="#content-slider" class="mw-section-btn">Content Slider</a>
|
|
970
|
-
<a href="#testimonials" class="mw-section-btn">Testimonials</a>
|
|
971
|
-
<a href="#prose" class="mw-section-btn">Prose</a>
|
|
972
|
-
<a href="#media" class="mw-section-btn">Media</a>
|
|
973
|
-
<a href="#blog-posts" class="mw-section-btn">Blog Posts</a>
|
|
974
|
-
</nav>
|
|
975
|
-
|
|
976
|
-
<!-- Page Header container -->
|
|
977
|
-
<div id="page-header">
|
|
978
|
-
@@include('./src/partials/page-header-container.html')
|
|
979
|
-
</div>
|
|
980
|
-
|
|
981
|
-
<!-- Meta Info container -->
|
|
982
|
-
<div id="meta-info">
|
|
983
|
-
@@include('./src/partials/meta-info-container.html')
|
|
984
|
-
</div>
|
|
985
|
-
|
|
986
|
-
<!-- Tables container -->
|
|
987
|
-
<div id="tables">
|
|
988
|
-
@@include('./src/partials/tables-container.html')
|
|
989
|
-
</div>
|
|
990
|
-
|
|
991
|
-
<!-- Kanban container -->
|
|
992
|
-
<div id="kanban">
|
|
993
|
-
@@include('./src/partials/kanban-container.html')
|
|
994
|
-
</div>
|
|
995
|
-
|
|
996
|
-
<!-- Calendar container -->
|
|
997
|
-
<div id="calendar">
|
|
998
|
-
@@include('./src/partials/calendar-container.html')
|
|
999
|
-
</div>
|
|
1000
|
-
|
|
1001
|
-
<!-- Lunch Menu container -->
|
|
1002
|
-
<div id="lunch-menu">
|
|
1003
|
-
@@include('./src/partials/lunch-menu-container.html')
|
|
1004
|
-
</div>
|
|
1005
|
-
|
|
1006
|
-
<!-- Contact container -->
|
|
1007
|
-
<div id="contact">
|
|
1008
|
-
@@include('./src/partials/contact-container.html')
|
|
1009
|
-
</div>
|
|
1010
|
-
|
|
1011
|
-
<!-- Pagination container -->
|
|
1012
|
-
<div id="pagination">
|
|
1013
|
-
@@include('./src/partials/pagination-container.html')
|
|
1014
|
-
</div>
|
|
1015
|
-
|
|
1016
|
-
<!-- Timeline container -->
|
|
1017
|
-
<div id="timelines">
|
|
1018
|
-
@@include('./src/partials/timelines-container.html')
|
|
1019
|
-
</div>
|
|
1020
|
-
|
|
1021
|
-
<!-- Gallery container-->
|
|
1022
|
-
<div id="gallery">
|
|
1023
|
-
@@include('./src/partials/gallery-container.html')
|
|
1024
|
-
</div>
|
|
1025
|
-
|
|
1026
|
-
<!-- Portrait gallery container-->
|
|
1027
|
-
<div id="portrait-gallery">
|
|
1028
|
-
@@include('./src/partials/portrait-gallery-container.html')
|
|
1029
|
-
</div>
|
|
1030
|
-
|
|
1031
|
-
<!-- Mosaic container-->
|
|
1032
|
-
<div id="mosaic">
|
|
1033
|
-
@@include('./src/partials/mosaic-container.html')
|
|
1034
|
-
</div>
|
|
1035
|
-
|
|
1036
|
-
<!-- Feed container-->
|
|
1037
|
-
<div id="feed">@@include('./src/partials/feed-container.html')</div>
|
|
1038
|
-
|
|
1039
|
-
<!-- Stories container-->
|
|
1040
|
-
<div id="stories">
|
|
1041
|
-
@@include('./src/partials/stories-container.html')
|
|
1042
|
-
</div>
|
|
1043
|
-
|
|
1044
|
-
<!-- Tech stack container-->
|
|
1045
|
-
<div id="techstack-bucket">
|
|
1046
|
-
@@include('./src/partials/techstack-bucket-container.html')
|
|
1047
|
-
</div>
|
|
1048
|
-
|
|
1049
|
-
<!-- Content slider container-->
|
|
1050
|
-
<div id="content-slider">
|
|
1051
|
-
@@include('./src/partials/content-slider-container.html')
|
|
1052
|
-
</div>
|
|
1053
|
-
|
|
1054
|
-
<!-- Testimonials container-->
|
|
1055
|
-
<div id="testimonials">
|
|
1056
|
-
@@include('./src/partials/testimonials-container.html')
|
|
1057
|
-
</div>
|
|
1058
|
-
|
|
1059
|
-
<!-- Prose container-->
|
|
1060
|
-
<div id="prose">@@include('./src/partials/prose-container.html')</div>
|
|
1061
|
-
|
|
1062
|
-
<!-- Media container-->
|
|
1063
|
-
<div id="media">@@include('./src/partials/media-container.html')</div>
|
|
1064
|
-
|
|
1065
|
-
<!-- Blogposts container-->
|
|
1066
|
-
<div id="blog-posts">
|
|
1067
|
-
@@include('./src/partials/blog-posts-container.html')
|
|
1068
|
-
</div>
|
|
1069
|
-
</div>
|
|
1070
|
-
</section>
|
|
1071
|
-
<!-- History section -->
|
|
1072
|
-
<section id="history" class="mw-section mw-section-alternate">
|
|
1073
|
-
<div class="mw-container">
|
|
1074
|
-
<div class="mw-section-head">
|
|
1075
|
-
<h2 class="mw-section-head-title">History</h2>
|
|
1076
|
-
<p class="mw-section-head-intro">
|
|
1077
|
-
The major releases so far. Everything in between - the minors and
|
|
1078
|
-
the patch releases - sits in the changelog.
|
|
1079
|
-
</p>
|
|
1080
|
-
</div>
|
|
1081
|
-
@@include('./src/partials/history-container.html')
|
|
1082
|
-
</div>
|
|
1083
|
-
</section>
|
|
1084
|
-
<!-- Preview section, showcase only - see the partial -->
|
|
1085
|
-
<section id="preview" class="mw-section">
|
|
1086
|
-
<div class="mw-container">
|
|
1087
|
-
<div class="mw-section-head">
|
|
1088
|
-
<h2 class="mw-section-head-title">Preview</h2>
|
|
1089
|
-
<p class="mw-section-head-intro">
|
|
1090
|
-
One page-shaped example, so the variant switches in the palette
|
|
1091
|
-
panel have something to act on that is not a component gallery.
|
|
1092
|
-
Open the panel and the page lands here.
|
|
1093
|
-
</p>
|
|
1094
|
-
</div>
|
|
1095
|
-
@@include('./src/partials/preview-container.html')
|
|
1096
|
-
</div>
|
|
1097
|
-
</section>
|
|
1098
|
-
</main>
|
|
1099
|
-
|
|
1100
|
-
<!-- Footer -->
|
|
1101
|
-
<footer class="mw-footer">
|
|
1102
|
-
<div class="mw-container">
|
|
1103
|
-
@@include('./src/partials/footer-container.html')
|
|
1104
|
-
</div>
|
|
1105
|
-
</footer>
|
|
1106
|
-
|
|
1107
|
-
<!-- Palette switcher -->
|
|
1108
|
-
@@include('./src/partials/palette-container.html')
|
|
1109
|
-
<script>
|
|
1110
|
-
// just for the showcase (login button triggers login error)
|
|
1111
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
1112
|
-
const loginCard = document.querySelector('.mw-login');
|
|
1113
|
-
const form = document.getElementById('login-form');
|
|
1114
|
-
if (form) {
|
|
1115
|
-
const btn = form.querySelector('.mw-btn-primary');
|
|
1116
|
-
if (btn) {
|
|
1117
|
-
btn.addEventListener('click', (e) => {
|
|
1118
|
-
e.preventDefault();
|
|
1119
|
-
loginCard.classList.remove('mw-login-error');
|
|
1120
|
-
void loginCard.offsetWidth;
|
|
1121
|
-
loginCard.classList.add('mw-login-error');
|
|
1122
|
-
setTimeout(() => {
|
|
1123
|
-
loginCard.classList.remove('mw-login-error');
|
|
1124
|
-
}, 4000);
|
|
1125
|
-
});
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
});
|
|
1129
|
-
|
|
1130
|
-
// just for the showcase: one segmented switch above the offer grid drives
|
|
1131
|
-
// every card in it. The framework ships the look, not the arithmetic - a
|
|
1132
|
-
// real application has its own prices and its own state, so this stays
|
|
1133
|
-
// here rather than in maverick-wave.js.
|
|
1134
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
1135
|
-
const cycleSwitch = document.getElementById('cycle-switch');
|
|
1136
|
-
const offers = document.getElementById('cycle-offers');
|
|
1137
|
-
if (!cycleSwitch || !offers) return;
|
|
1138
|
-
|
|
1139
|
-
// Trailing zero cents are noise on a price - "24 Euro", not "24,00
|
|
1140
|
-
// Euro". The tabular figures keep the row from jumping anyway.
|
|
1141
|
-
const money = (n) => {
|
|
1142
|
-
const fixed = n.toFixed(2);
|
|
1143
|
-
return fixed.endsWith('.00')
|
|
1144
|
-
? fixed.slice(0, -3)
|
|
1145
|
-
: fixed.replace('.', ',');
|
|
1146
|
-
};
|
|
1147
|
-
|
|
1148
|
-
const apply = (button) => {
|
|
1149
|
-
const months = Number(button.dataset.cycle);
|
|
1150
|
-
const off = Number(button.dataset.cycleOff || 0);
|
|
1151
|
-
|
|
1152
|
-
cycleSwitch.querySelectorAll('.mw-segmented-item').forEach((item) => {
|
|
1153
|
-
const on = item === button;
|
|
1154
|
-
item.classList.toggle('mw-active', on);
|
|
1155
|
-
item.setAttribute('aria-pressed', String(on));
|
|
1156
|
-
});
|
|
1157
|
-
|
|
1158
|
-
offers.querySelectorAll('.mw-offer').forEach((card) => {
|
|
1159
|
-
const rate = Number(card.dataset.rate);
|
|
1160
|
-
const perMonth = rate * (1 - off / 100);
|
|
1161
|
-
const [whole, cents] = money(perMonth).split(',');
|
|
1162
|
-
|
|
1163
|
-
card.querySelector('[data-price-amount]').innerHTML = cents
|
|
1164
|
-
? whole + '<span class="mw-price-fraction">,' + cents + '</span>'
|
|
1165
|
-
: whole;
|
|
1166
|
-
|
|
1167
|
-
const original = card.querySelector('.mw-price-original');
|
|
1168
|
-
original.hidden = off === 0;
|
|
1169
|
-
original.querySelector('[data-price-rate]').textContent =
|
|
1170
|
-
money(rate);
|
|
1171
|
-
|
|
1172
|
-
const tag = card.querySelector('[data-price-off]');
|
|
1173
|
-
tag.hidden = off === 0;
|
|
1174
|
-
tag.textContent = '-' + off + '%';
|
|
1175
|
-
|
|
1176
|
-
card.querySelector('[data-price-billing]').textContent =
|
|
1177
|
-
off === 0
|
|
1178
|
-
? button.dataset.cycleLabel + '.'
|
|
1179
|
-
: money(perMonth * months) +
|
|
1180
|
-
' Euro ' +
|
|
1181
|
-
button.dataset.cycleLabel +
|
|
1182
|
-
'.';
|
|
1183
|
-
});
|
|
1184
|
-
};
|
|
1185
|
-
|
|
1186
|
-
cycleSwitch.querySelectorAll('.mw-segmented-item').forEach((item) => {
|
|
1187
|
-
item.addEventListener('click', () => apply(item));
|
|
1188
|
-
});
|
|
1189
|
-
apply(cycleSwitch.querySelector('.mw-active'));
|
|
1190
|
-
});
|
|
1191
|
-
|
|
1192
|
-
// just for the showcase: the switches above the photo layouts put one of
|
|
1193
|
-
// their modifiers on the demo they name and take the others off
|
|
1194
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
1195
|
-
document.querySelectorAll('[data-modifier-demo]').forEach((group) => {
|
|
1196
|
-
const target = document.getElementById(group.dataset.modifierDemo);
|
|
1197
|
-
const items = group.querySelectorAll('.mw-segmented-item');
|
|
1198
|
-
items.forEach((item) => {
|
|
1199
|
-
item.setAttribute(
|
|
1200
|
-
'aria-pressed',
|
|
1201
|
-
String(item.classList.contains('mw-active'))
|
|
1202
|
-
);
|
|
1203
|
-
item.addEventListener('click', () => {
|
|
1204
|
-
items.forEach((other) => {
|
|
1205
|
-
other.classList.toggle('mw-active', other === item);
|
|
1206
|
-
other.setAttribute('aria-pressed', String(other === item));
|
|
1207
|
-
if (other.dataset.modifier) {
|
|
1208
|
-
target.classList.remove(other.dataset.modifier);
|
|
1209
|
-
}
|
|
1210
|
-
});
|
|
1211
|
-
if (item.dataset.modifier) {
|
|
1212
|
-
target.classList.add(item.dataset.modifier);
|
|
1213
|
-
}
|
|
1214
|
-
});
|
|
1215
|
-
});
|
|
1216
|
-
});
|
|
1217
|
-
});
|
|
1218
|
-
|
|
1219
|
-
// just for the showcase: the palette switcher. Every tone in the framework
|
|
1220
|
-
// is derived from the root colors with color-mix(), so writing those on the
|
|
1221
|
-
// root element repaints the page - bar, ink, borders and tints included.
|
|
1222
|
-
// Nothing is persisted - a palette is for looking at, a reload is the way back.
|
|
1223
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
1224
|
-
const toggleBtn = document.getElementById('palette-toggle');
|
|
1225
|
-
const panel = document.getElementById('palette-panel');
|
|
1226
|
-
const primaryInput = document.getElementById('palette-primary');
|
|
1227
|
-
const secondaryInput = document.getElementById('palette-secondary');
|
|
1228
|
-
const items = [...document.querySelectorAll('.palette-item')];
|
|
1229
|
-
if (!toggleBtn || !panel) return;
|
|
1230
|
-
|
|
1231
|
-
const root = document.documentElement;
|
|
1232
|
-
|
|
1233
|
-
// The values the markup ships with, so the setup box below can tell a
|
|
1234
|
-
// chosen colour from the built-in one and print only the difference
|
|
1235
|
-
const BUILT_IN = {
|
|
1236
|
-
primary: primaryInput.value,
|
|
1237
|
-
secondary: secondaryInput.value,
|
|
1238
|
-
};
|
|
1239
|
-
|
|
1240
|
-
const DARK_INK = '#131925';
|
|
1241
|
-
const LIGHT_INK = '#f2f6fc';
|
|
1242
|
-
|
|
1243
|
-
const luminance = (hex) => {
|
|
1244
|
-
const [r, g, b] = [1, 3, 5].map((i) => {
|
|
1245
|
-
const channel = parseInt(hex.slice(i, i + 2), 16) / 255;
|
|
1246
|
-
return channel <= 0.04045
|
|
1247
|
-
? channel / 12.92
|
|
1248
|
-
: ((channel + 0.055) / 1.055) ** 2.4;
|
|
1249
|
-
});
|
|
1250
|
-
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
1251
|
-
};
|
|
1252
|
-
|
|
1253
|
-
const contrast = (a, b) => {
|
|
1254
|
-
const [high, low] = [luminance(a), luminance(b)].sort(
|
|
1255
|
-
(x, y) => y - x
|
|
1256
|
-
);
|
|
1257
|
-
return (high + 0.05) / (low + 0.05);
|
|
1258
|
-
};
|
|
1259
|
-
|
|
1260
|
-
// Measured, not thresholded - a lightness cutoff gets a saturated mid
|
|
1261
|
-
// tone wrong
|
|
1262
|
-
const ink = (fill) =>
|
|
1263
|
-
contrast(fill, DARK_INK) > contrast(fill, LIGHT_INK)
|
|
1264
|
-
? DARK_INK
|
|
1265
|
-
: LIGHT_INK;
|
|
1266
|
-
|
|
1267
|
-
// Cuts the transition the new colours started: the whole page
|
|
1268
|
-
// interpolating at once is the expensive part, and the hex labels in the
|
|
1269
|
-
// Colors section read computed values, so they need the landed ones
|
|
1270
|
-
const settle = () => {
|
|
1271
|
-
root.classList.add('mw-theme-switching');
|
|
1272
|
-
void root.offsetHeight;
|
|
1273
|
-
root.classList.remove('mw-theme-switching');
|
|
1274
|
-
window.mwRefreshColorSwatches?.();
|
|
1275
|
-
window.mwRefreshSetup?.();
|
|
1276
|
-
};
|
|
1277
|
-
|
|
1278
|
-
const paint = (name, color) => {
|
|
1279
|
-
root.style.setProperty(`--mw-${name}-color`, color);
|
|
1280
|
-
root.style.setProperty(`--mw-${name}-accent-text-color`, ink(color));
|
|
1281
|
-
};
|
|
1282
|
-
|
|
1283
|
-
items.forEach((item) => {
|
|
1284
|
-
const { primary, secondary, dark, light } = item.dataset;
|
|
1285
|
-
item.style.setProperty('--swatch-primary', primary);
|
|
1286
|
-
item.style.setProperty('--swatch-secondary', secondary);
|
|
1287
|
-
|
|
1288
|
-
item.addEventListener('click', () => {
|
|
1289
|
-
items.forEach((other) =>
|
|
1290
|
-
other.classList.toggle('mw-active', other === item)
|
|
1291
|
-
);
|
|
1292
|
-
paint('primary', primary);
|
|
1293
|
-
paint('secondary', secondary);
|
|
1294
|
-
root.style.setProperty('--mw-dark-page-background', dark);
|
|
1295
|
-
root.style.setProperty('--mw-light-page-background', light);
|
|
1296
|
-
primaryInput.value = primary;
|
|
1297
|
-
secondaryInput.value = secondary;
|
|
1298
|
-
settle();
|
|
1299
|
-
});
|
|
1300
|
-
});
|
|
1301
|
-
|
|
1302
|
-
// A hand-picked color belongs to no preset - the page backgrounds stay put
|
|
1303
|
-
[
|
|
1304
|
-
['primary', primaryInput],
|
|
1305
|
-
['secondary', secondaryInput],
|
|
1306
|
-
].forEach(([name, input]) => {
|
|
1307
|
-
input.addEventListener('input', () => {
|
|
1308
|
-
items.forEach((item) => item.classList.remove('mw-active'));
|
|
1309
|
-
paint(name, input.value);
|
|
1310
|
-
});
|
|
1311
|
-
// Dragging the picker fires `input` per pixel - the rest waits for the end
|
|
1312
|
-
input.addEventListener('change', settle);
|
|
1313
|
-
});
|
|
1314
|
-
|
|
1315
|
-
const preview = document.getElementById('preview');
|
|
1316
|
-
|
|
1317
|
-
const toggle = (open) => {
|
|
1318
|
-
panel.hidden = !open;
|
|
1319
|
-
toggleBtn.setAttribute('aria-expanded', String(open));
|
|
1320
|
-
|
|
1321
|
-
// Or the switches act on whatever section the reader is parked at,
|
|
1322
|
-
// which is one component at a time and says little about a look.
|
|
1323
|
-
//
|
|
1324
|
-
// `instant` against the smooth default in the reset: the preview sits
|
|
1325
|
-
// at the end of a page some 80 000px long, and over that distance a
|
|
1326
|
-
// smooth scroll either crawls through every section on the way or, as
|
|
1327
|
-
// here, never starts at all.
|
|
1328
|
-
if (open)
|
|
1329
|
-
preview?.scrollIntoView({ block: 'start', behavior: 'instant' });
|
|
1330
|
-
};
|
|
1331
|
-
|
|
1332
|
-
toggleBtn.addEventListener('click', (event) => {
|
|
1333
|
-
event.stopPropagation();
|
|
1334
|
-
toggle(panel.hidden);
|
|
1335
|
-
});
|
|
1336
|
-
document.addEventListener('click', (event) => {
|
|
1337
|
-
if (!panel.hidden && !panel.contains(event.target)) toggle(false);
|
|
1338
|
-
});
|
|
1339
|
-
document.addEventListener('keydown', (event) => {
|
|
1340
|
-
if (event.key === 'Escape') toggle(false);
|
|
1341
|
-
});
|
|
1342
|
-
|
|
1343
|
-
// The seam to the variants panel below, which prints and reads the whole
|
|
1344
|
-
// setup - the palette is half of it. Only inline values count as chosen:
|
|
1345
|
-
// anything still coming from the stylesheet is the built-in one.
|
|
1346
|
-
const PAGE_GROUNDS = {
|
|
1347
|
-
dark: '--mw-dark-page-background',
|
|
1348
|
-
light: '--mw-light-page-background',
|
|
1349
|
-
};
|
|
1350
|
-
|
|
1351
|
-
window.mwPalette = {
|
|
1352
|
-
read: () => ({
|
|
1353
|
-
primary: root.style.getPropertyValue('--mw-primary-color') || null,
|
|
1354
|
-
secondary:
|
|
1355
|
-
root.style.getPropertyValue('--mw-secondary-color') || null,
|
|
1356
|
-
// The label colour ink() measured for each fill. It has to travel
|
|
1357
|
-
// with the setup: a project that only copies the two brand colours
|
|
1358
|
-
// keeps the stock accent text, and on a light brand tone that is an
|
|
1359
|
-
// unreadable button. write() recomputes it, so pasting it back is
|
|
1360
|
-
// harmless.
|
|
1361
|
-
primaryInk:
|
|
1362
|
-
root.style.getPropertyValue('--mw-primary-accent-text-color') ||
|
|
1363
|
-
null,
|
|
1364
|
-
secondaryInk:
|
|
1365
|
-
root.style.getPropertyValue('--mw-secondary-accent-text-color') ||
|
|
1366
|
-
null,
|
|
1367
|
-
dark: root.style.getPropertyValue(PAGE_GROUNDS.dark) || null,
|
|
1368
|
-
light: root.style.getPropertyValue(PAGE_GROUNDS.light) || null,
|
|
1369
|
-
}),
|
|
1370
|
-
|
|
1371
|
-
write: ({ primary, secondary, dark, light }) => {
|
|
1372
|
-
const current = window.mwPalette.read();
|
|
1373
|
-
const same =
|
|
1374
|
-
current.primary === primary &&
|
|
1375
|
-
current.secondary === secondary &&
|
|
1376
|
-
current.dark === dark &&
|
|
1377
|
-
current.light === light;
|
|
1378
|
-
// Typing into the setup box fires per keystroke, and settle() forces
|
|
1379
|
-
// a reflow - so a run that changes nothing has to cost nothing
|
|
1380
|
-
if (same) return;
|
|
1381
|
-
|
|
1382
|
-
[
|
|
1383
|
-
['primary', primary, primaryInput],
|
|
1384
|
-
['secondary', secondary, secondaryInput],
|
|
1385
|
-
].forEach(([name, value, input]) => {
|
|
1386
|
-
if (value) {
|
|
1387
|
-
paint(name, value);
|
|
1388
|
-
input.value = value;
|
|
1389
|
-
} else {
|
|
1390
|
-
root.style.removeProperty(`--mw-${name}-color`);
|
|
1391
|
-
root.style.removeProperty(`--mw-${name}-accent-text-color`);
|
|
1392
|
-
input.value = BUILT_IN[name];
|
|
1393
|
-
}
|
|
1394
|
-
});
|
|
1395
|
-
|
|
1396
|
-
Object.entries(PAGE_GROUNDS).forEach(([key, prop]) => {
|
|
1397
|
-
const value = key === 'dark' ? dark : light;
|
|
1398
|
-
if (value) root.style.setProperty(prop, value);
|
|
1399
|
-
else root.style.removeProperty(prop);
|
|
1400
|
-
});
|
|
1401
|
-
|
|
1402
|
-
const shownPrimary = primary || BUILT_IN.primary;
|
|
1403
|
-
const shownSecondary = secondary || BUILT_IN.secondary;
|
|
1404
|
-
items.forEach((item) =>
|
|
1405
|
-
item.classList.toggle(
|
|
1406
|
-
'mw-active',
|
|
1407
|
-
item.dataset.primary === shownPrimary &&
|
|
1408
|
-
item.dataset.secondary === shownSecondary
|
|
1409
|
-
)
|
|
1410
|
-
);
|
|
1411
|
-
|
|
1412
|
-
settle();
|
|
1413
|
-
},
|
|
1414
|
-
};
|
|
1415
|
-
});
|
|
1416
|
-
|
|
1417
|
-
// just for the showcase: the variant switches. Each one is a class on <html>
|
|
1418
|
-
// or a single custom property, never a walk over the DOM - markup that
|
|
1419
|
-
// arrives later (a modal, a toast, a kanban card) is covered by the same
|
|
1420
|
-
// class that was already set. The readout at the bottom of the panel is the
|
|
1421
|
-
// whole setup a project would carry to get the look it is currently seeing.
|
|
1422
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
1423
|
-
const list = document.getElementById('variant-list');
|
|
1424
|
-
const setup = document.getElementById('variant-setup');
|
|
1425
|
-
if (!list || !setup) return;
|
|
1426
|
-
|
|
1427
|
-
const root = document.documentElement;
|
|
1428
|
-
const controls = [...list.querySelectorAll('input, select')];
|
|
1429
|
-
|
|
1430
|
-
// Built on every render, put into the address bar by nobody: a setup
|
|
1431
|
-
// written to the URL as you go comes back on the next reload, and then
|
|
1432
|
-
// the showcase opens in someone else's look for good. Copy link is the
|
|
1433
|
-
// one way out of here, and what it hands over is this.
|
|
1434
|
-
//
|
|
1435
|
-
// URLSearchParams and not a hand-rolled separator: a value like the
|
|
1436
|
-
// heading font or the page width is full of commas, quotes and brackets,
|
|
1437
|
-
// and escaping those by hand is where this kind of thing breaks.
|
|
1438
|
-
let shareUrl = location.origin + location.pathname;
|
|
1439
|
-
|
|
1440
|
-
const buildShareUrl = (classes, dropped, pairs) => {
|
|
1441
|
-
const params = new URLSearchParams();
|
|
1442
|
-
if (classes.length) params.set('c', classes.join(' '));
|
|
1443
|
-
if (dropped.length) params.set('d', dropped.join(' '));
|
|
1444
|
-
pairs.forEach(([prop, value]) => params.set(prop, value));
|
|
1445
|
-
|
|
1446
|
-
const query = params.toString();
|
|
1447
|
-
return (
|
|
1448
|
-
location.origin + location.pathname + (query ? '#' + query : '')
|
|
1449
|
-
);
|
|
1450
|
-
};
|
|
1451
|
-
|
|
1452
|
-
// Back into the shape load() reads, so the link and a pasted setup go
|
|
1453
|
-
// through one parser rather than two that can drift apart. The target in
|
|
1454
|
-
// front of `: no` is only there to make the line read like the printed
|
|
1455
|
-
// one - load() matches on the class name alone.
|
|
1456
|
-
const readHash = () => {
|
|
1457
|
-
const params = new URLSearchParams(location.hash.slice(1));
|
|
1458
|
-
const lines = [];
|
|
1459
|
-
|
|
1460
|
-
const classes = params.get('c');
|
|
1461
|
-
if (classes) lines.push('html class="' + classes + '"');
|
|
1462
|
-
|
|
1463
|
-
(params.get('d') || '')
|
|
1464
|
-
.split(/\s+/)
|
|
1465
|
-
.filter(Boolean)
|
|
1466
|
-
.forEach((name) => lines.push('markup: no ' + name));
|
|
1467
|
-
|
|
1468
|
-
const pairs = [...params.entries()].filter(([key]) =>
|
|
1469
|
-
key.startsWith('--')
|
|
1470
|
-
);
|
|
1471
|
-
if (pairs.length) {
|
|
1472
|
-
lines.push(
|
|
1473
|
-
':root {',
|
|
1474
|
-
...pairs.map(([key, value]) => ` ${key}: ${value};`),
|
|
1475
|
-
'}'
|
|
1476
|
-
);
|
|
1477
|
-
}
|
|
1478
|
-
|
|
1479
|
-
return lines.length ? lines.join('\n') : null;
|
|
1480
|
-
};
|
|
1481
|
-
|
|
1482
|
-
const isOn = (input) =>
|
|
1483
|
-
input.hasAttribute('data-variant-invert')
|
|
1484
|
-
? !input.checked
|
|
1485
|
-
: input.checked;
|
|
1486
|
-
|
|
1487
|
-
const render = () => {
|
|
1488
|
-
// Never while it is being typed in - the box is an input as well as a
|
|
1489
|
-
// readout, and rewriting it under the cursor would eat the paste
|
|
1490
|
-
if (document.activeElement === setup) return;
|
|
1491
|
-
|
|
1492
|
-
const classes = [];
|
|
1493
|
-
// Unformatted, because both the box and the link are written from
|
|
1494
|
-
// these and formatting only one of the two ways is a bug waiting
|
|
1495
|
-
const notes = [];
|
|
1496
|
-
const pairs = [];
|
|
1497
|
-
|
|
1498
|
-
// The palette is part of the setup, and it is printed first because a
|
|
1499
|
-
// project sets its brand colours before it retunes anything else
|
|
1500
|
-
const palette = window.mwPalette?.read() ?? {};
|
|
1501
|
-
[
|
|
1502
|
-
['--mw-primary-color', palette.primary],
|
|
1503
|
-
['--mw-primary-accent-text-color', palette.primaryInk],
|
|
1504
|
-
['--mw-secondary-color', palette.secondary],
|
|
1505
|
-
['--mw-secondary-accent-text-color', palette.secondaryInk],
|
|
1506
|
-
['--mw-dark-page-background', palette.dark],
|
|
1507
|
-
['--mw-light-page-background', palette.light],
|
|
1508
|
-
].forEach(([prop, value]) => {
|
|
1509
|
-
if (value) pairs.push([prop, value]);
|
|
1510
|
-
});
|
|
1511
|
-
|
|
1512
|
-
controls.forEach((control) => {
|
|
1513
|
-
if (control.type !== 'checkbox') {
|
|
1514
|
-
// A select whose options are class names picks one of a set the
|
|
1515
|
-
// markup cannot hold at the same time - a shape is one or none
|
|
1516
|
-
if (!control.value) return;
|
|
1517
|
-
if (control.hasAttribute('data-variant-classes')) {
|
|
1518
|
-
classes.push(control.value);
|
|
1519
|
-
} else {
|
|
1520
|
-
pairs.push([control.dataset.variantProp, control.value]);
|
|
1521
|
-
}
|
|
1522
|
-
return;
|
|
1523
|
-
}
|
|
1524
|
-
|
|
1525
|
-
// A targeted class is one the markup already ships, so its absence is
|
|
1526
|
-
// the deviation worth naming - the rest are classes to add
|
|
1527
|
-
const target = control.dataset.variantTarget;
|
|
1528
|
-
if (target) {
|
|
1529
|
-
if (!isOn(control)) {
|
|
1530
|
-
notes.push([target, control.dataset.variantClass]);
|
|
1531
|
-
}
|
|
1532
|
-
} else if (isOn(control)) {
|
|
1533
|
-
classes.push(control.dataset.variantClass);
|
|
1534
|
-
}
|
|
1535
|
-
});
|
|
1536
|
-
|
|
1537
|
-
const lines = [];
|
|
1538
|
-
if (classes.length) {
|
|
1539
|
-
lines.push('html class="' + classes.join(' ') + '"');
|
|
1540
|
-
}
|
|
1541
|
-
lines.push(...notes.map(([target, name]) => `${target}: no ${name}`));
|
|
1542
|
-
if (pairs.length) {
|
|
1543
|
-
lines.push(
|
|
1544
|
-
':root {',
|
|
1545
|
-
...pairs.map(([prop, value]) => ` ${prop}: ${value};`),
|
|
1546
|
-
'}'
|
|
1547
|
-
);
|
|
1548
|
-
}
|
|
1549
|
-
|
|
1550
|
-
setup.value = lines.length
|
|
1551
|
-
? lines.join('\n')
|
|
1552
|
-
: 'Default setup - nothing to change.';
|
|
1553
|
-
|
|
1554
|
-
shareUrl = buildShareUrl(
|
|
1555
|
-
classes,
|
|
1556
|
-
notes.map(([, name]) => name),
|
|
1557
|
-
pairs
|
|
1558
|
-
);
|
|
1559
|
-
};
|
|
1560
|
-
|
|
1561
|
-
const optionClasses = (control) =>
|
|
1562
|
-
[...control.options].map((option) => option.value).filter(Boolean);
|
|
1563
|
-
|
|
1564
|
-
const apply = (control) => {
|
|
1565
|
-
if (control.type === 'checkbox') {
|
|
1566
|
-
const target = control.dataset.variantTarget;
|
|
1567
|
-
const el = target ? document.querySelector(target) : root;
|
|
1568
|
-
el?.classList.toggle(control.dataset.variantClass, isOn(control));
|
|
1569
|
-
} else if (control.hasAttribute('data-variant-classes')) {
|
|
1570
|
-
root.classList.remove(...optionClasses(control));
|
|
1571
|
-
if (control.value) root.classList.add(control.value);
|
|
1572
|
-
} else if (control.value) {
|
|
1573
|
-
root.style.setProperty(control.dataset.variantProp, control.value);
|
|
1574
|
-
} else {
|
|
1575
|
-
root.style.removeProperty(control.dataset.variantProp);
|
|
1576
|
-
}
|
|
1577
|
-
};
|
|
1578
|
-
|
|
1579
|
-
// The box read backwards: someone else's setup pasted in drives the
|
|
1580
|
-
// switches, which drive the page. Anything the text does not mention
|
|
1581
|
-
// falls back to the default, so an empty box is a reset.
|
|
1582
|
-
const load = (text) => {
|
|
1583
|
-
const named = new Set(
|
|
1584
|
-
(text.match(/class\s*=\s*"([^"]*)"/)?.[1] || '')
|
|
1585
|
-
.trim()
|
|
1586
|
-
.split(/\s+/)
|
|
1587
|
-
.filter(Boolean)
|
|
1588
|
-
);
|
|
1589
|
-
// `.mw-header: no mw-header-reveal` - a class the markup ships and the
|
|
1590
|
-
// setup takes away, which is the deviation worth reading
|
|
1591
|
-
const dropped = new Set(
|
|
1592
|
-
[...text.matchAll(/:\s*no\s+([\w-]+)/g)].map((m) => m[1])
|
|
1593
|
-
);
|
|
1594
|
-
const props = new Map(
|
|
1595
|
-
[...text.matchAll(/(--[\w-]+)\s*:\s*([^;\n}]+)/g)].map((m) => [
|
|
1596
|
-
m[1],
|
|
1597
|
-
m[2].trim(),
|
|
1598
|
-
])
|
|
1599
|
-
);
|
|
1600
|
-
|
|
1601
|
-
window.mwPalette?.write({
|
|
1602
|
-
primary: props.get('--mw-primary-color') ?? null,
|
|
1603
|
-
secondary: props.get('--mw-secondary-color') ?? null,
|
|
1604
|
-
dark: props.get('--mw-dark-page-background') ?? null,
|
|
1605
|
-
light: props.get('--mw-light-page-background') ?? null,
|
|
1606
|
-
});
|
|
1607
|
-
|
|
1608
|
-
controls.forEach((control) => {
|
|
1609
|
-
if (control.type === 'checkbox') {
|
|
1610
|
-
const name = control.dataset.variantClass;
|
|
1611
|
-
const on = control.dataset.variantTarget
|
|
1612
|
-
? !dropped.has(name)
|
|
1613
|
-
: named.has(name);
|
|
1614
|
-
control.checked = control.hasAttribute('data-variant-invert')
|
|
1615
|
-
? !on
|
|
1616
|
-
: on;
|
|
1617
|
-
} else if (control.hasAttribute('data-variant-classes')) {
|
|
1618
|
-
control.value =
|
|
1619
|
-
optionClasses(control).find((name) => named.has(name)) ?? '';
|
|
1620
|
-
} else {
|
|
1621
|
-
control.value = props.get(control.dataset.variantProp) ?? '';
|
|
1622
|
-
}
|
|
1623
|
-
apply(control);
|
|
1624
|
-
});
|
|
1625
|
-
};
|
|
1626
|
-
|
|
1627
|
-
// Picking a palette repaints the page, and the box has to say so
|
|
1628
|
-
window.mwRefreshSetup = render;
|
|
1629
|
-
|
|
1630
|
-
setup.addEventListener('input', () => inPlace(() => load(setup.value)));
|
|
1631
|
-
// Normalises what was pasted back into the shape render() writes
|
|
1632
|
-
setup.addEventListener('blur', render);
|
|
1633
|
-
|
|
1634
|
-
// Type and spacing switches change the height of all 80 000px of page
|
|
1635
|
-
// above the preview as well, so the section slides out from under
|
|
1636
|
-
// whoever is watching it - Text size alone moves it by 16 000px. Hold
|
|
1637
|
-
// its top edge where it was and the change happens in place.
|
|
1638
|
-
//
|
|
1639
|
-
// Only while the preview is on screen: correcting the scroll for someone
|
|
1640
|
-
// parked up in the component sections would move *them* by those 16 000
|
|
1641
|
-
// instead. `instant` because the smooth default would animate the
|
|
1642
|
-
// correction as a scroll of its own.
|
|
1643
|
-
const previewSection = document.getElementById('preview');
|
|
1644
|
-
|
|
1645
|
-
const inPlace = (change) => {
|
|
1646
|
-
const box = previewSection?.getBoundingClientRect();
|
|
1647
|
-
const watching =
|
|
1648
|
-
box && box.bottom > 0 && box.top < window.innerHeight;
|
|
1649
|
-
if (!watching) return change();
|
|
1650
|
-
|
|
1651
|
-
const before = box.top;
|
|
1652
|
-
change();
|
|
1653
|
-
const shift = previewSection.getBoundingClientRect().top - before;
|
|
1654
|
-
if (shift) window.scrollBy({ top: shift, behavior: 'instant' });
|
|
1655
|
-
};
|
|
1656
|
-
|
|
1657
|
-
controls.forEach((control) =>
|
|
1658
|
-
control.addEventListener('change', () =>
|
|
1659
|
-
inPlace(() => {
|
|
1660
|
-
apply(control);
|
|
1661
|
-
render();
|
|
1662
|
-
})
|
|
1663
|
-
)
|
|
1664
|
-
);
|
|
1665
|
-
|
|
1666
|
-
const shared = readHash();
|
|
1667
|
-
if (shared) {
|
|
1668
|
-
// Drives the switches, which drive the page - then render() normalises
|
|
1669
|
-
// the box and writes the link back in the order it prints
|
|
1670
|
-
load(shared);
|
|
1671
|
-
render();
|
|
1672
|
-
} else {
|
|
1673
|
-
// Without a link the showcase opens in its own look, every time. That
|
|
1674
|
-
// has to be spelled out: Firefox restores form state across a reload,
|
|
1675
|
-
// so the switches would otherwise come back set the way the last visit
|
|
1676
|
-
// left them, and the page with them.
|
|
1677
|
-
//
|
|
1678
|
-
// The markup is the one source for that starting state - the written
|
|
1679
|
-
// defaults for a plain switch, and for a targeted one whether the
|
|
1680
|
-
// class it stands for is actually on the element it names. A header
|
|
1681
|
-
// shipped without mw-header-reveal keeps it off.
|
|
1682
|
-
controls.forEach((control) => {
|
|
1683
|
-
const target = control.dataset.variantTarget;
|
|
1684
|
-
const el = target && document.querySelector(target);
|
|
1685
|
-
|
|
1686
|
-
if (el) {
|
|
1687
|
-
const present = el.classList.contains(
|
|
1688
|
-
control.dataset.variantClass
|
|
1689
|
-
);
|
|
1690
|
-
control.checked = control.hasAttribute('data-variant-invert')
|
|
1691
|
-
? !present
|
|
1692
|
-
: present;
|
|
1693
|
-
} else if (control.type === 'checkbox') {
|
|
1694
|
-
control.checked = control.defaultChecked;
|
|
1695
|
-
} else {
|
|
1696
|
-
const preset = [...control.options].find(
|
|
1697
|
-
(o) => o.defaultSelected
|
|
1698
|
-
);
|
|
1699
|
-
control.value = preset ? preset.value : '';
|
|
1700
|
-
}
|
|
1701
|
-
});
|
|
1702
|
-
|
|
1703
|
-
controls.forEach(apply);
|
|
1704
|
-
render();
|
|
1705
|
-
}
|
|
1706
|
-
|
|
1707
|
-
document
|
|
1708
|
-
.getElementById('variant-share')
|
|
1709
|
-
?.addEventListener('click', async (event) => {
|
|
1710
|
-
const button = event.currentTarget;
|
|
1711
|
-
const label = document.getElementById('variant-share-label');
|
|
1712
|
-
try {
|
|
1713
|
-
await navigator.clipboard.writeText(shareUrl);
|
|
1714
|
-
label.textContent = 'Copied';
|
|
1715
|
-
} catch {
|
|
1716
|
-
// Denied permission or an insecure origin. The address bar is no
|
|
1717
|
-
// help here - it never carries the setup - so hand the link over
|
|
1718
|
-
// in the box instead, where it can be selected by hand.
|
|
1719
|
-
setup.value = shareUrl;
|
|
1720
|
-
setup.select();
|
|
1721
|
-
label.textContent = 'Copy from the box';
|
|
1722
|
-
}
|
|
1723
|
-
setTimeout(() => {
|
|
1724
|
-
label.textContent = 'Copy link';
|
|
1725
|
-
}, 1600);
|
|
1726
|
-
});
|
|
1727
|
-
});
|
|
1728
|
-
</script>
|
|
1729
|
-
</body>
|
|
1730
|
-
</html>
|