@jungherz-de/glasskit 1.33.0 → 1.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +113 -0
- package/README.md +29 -11
- package/SKILL.md +24 -7
- package/glasskit-styles.js +3 -3
- package/glasskit.css +302 -36
- package/glasskit.min.css +2 -2
- package/glasskit.min.css.map +1 -1
- package/package.json +1 -1
- package/theme-override.css +45 -0
package/glasskit.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* ============================================================
|
|
2
2
|
GLASSKIT COMPONENT LIBRARY
|
|
3
|
-
Jungherz GmbH – v1.
|
|
3
|
+
Jungherz GmbH – v1.35.0
|
|
4
4
|
|
|
5
5
|
Features:
|
|
6
6
|
- Scoped Reset (box-sizing fix)
|
|
@@ -133,6 +133,21 @@
|
|
|
133
133
|
--gl-card-glow-mid: rgba(255, 255, 255, 0.22);
|
|
134
134
|
--gl-card-glow-low: rgba(255, 255, 255, 0.14);
|
|
135
135
|
--gl-card-glow-bottom: rgba(255, 255, 255, 0.08);
|
|
136
|
+
/* Dark glass of a modal or a sheet is brighter than the page (since
|
|
137
|
+
1.35.0): its glow starts at the middle one, a segmented control on it
|
|
138
|
+
lies in a well with its chosen option one step darker, a tertiary
|
|
139
|
+
button too is one step darker, and a chosen badge says its label in
|
|
140
|
+
the text colour. Unset in light mode. */
|
|
141
|
+
--gl-dialog-glow-top: var(--gl-card-glow-mid);
|
|
142
|
+
--gl-dialog-well: rgba(0, 0, 0, 0.10);
|
|
143
|
+
--gl-dialog-raised: var(--gl-surface-3);
|
|
144
|
+
--gl-dialog-control: var(--gl-surface-1);
|
|
145
|
+
--gl-badge-selected-color: var(--gl-color-text);
|
|
146
|
+
/* The accent as text on the glass of a card, a modal or a sheet (since
|
|
147
|
+
1.35.0): the primary text lightened by 40 % white. A card is brighter
|
|
148
|
+
than the page, and the primary as a link, a range value or an accent
|
|
149
|
+
row fell to 4.2:1 on it. Light mode keeps the primary text. */
|
|
150
|
+
--gl-color-primary-on-glass: color-mix(in srgb, var(--gl-color-primary-text) 60%, #ffffff);
|
|
136
151
|
|
|
137
152
|
/* Card Text & Icons */
|
|
138
153
|
--gl-card-icon-color: rgba(255, 255, 255, 0.8);
|
|
@@ -359,6 +374,12 @@
|
|
|
359
374
|
--gl-card-glow-mid: rgba(255, 255, 255, 0.78);
|
|
360
375
|
--gl-card-glow-low: rgba(255, 255, 255, 0.65);
|
|
361
376
|
--gl-card-glow-bottom: rgba(255, 255, 255, 0.50);
|
|
377
|
+
--gl-dialog-glow-top: initial;
|
|
378
|
+
--gl-dialog-well: initial;
|
|
379
|
+
--gl-dialog-raised: initial;
|
|
380
|
+
--gl-dialog-control: initial;
|
|
381
|
+
--gl-badge-selected-color: initial;
|
|
382
|
+
--gl-color-primary-on-glass: var(--gl-color-primary-text);
|
|
362
383
|
|
|
363
384
|
--gl-card-icon-color: rgba(26, 42, 54, 0.65);
|
|
364
385
|
--gl-card-text-color: rgba(26, 42, 54, 0.68);
|
|
@@ -723,6 +744,8 @@
|
|
|
723
744
|
box-shadow: var(--gl-shadow-card), var(--gl-inset-strong);
|
|
724
745
|
/* A .glass-list--flush inside reaches the card's edges (since 1.29.1). */
|
|
725
746
|
--gl-list-flush-inset: var(--gl-space-xl);
|
|
747
|
+
/* Accent text on it takes --gl-color-primary-on-glass (since 1.35.0). */
|
|
748
|
+
--gl-ctx-primary-text: var(--gl-color-primary-on-glass);
|
|
726
749
|
}
|
|
727
750
|
|
|
728
751
|
.glass-card--glow {
|
|
@@ -837,10 +860,13 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
837
860
|
.glass-btn--secondary:active { transform: translateY(1px); }
|
|
838
861
|
|
|
839
862
|
/* Tertiary */
|
|
863
|
+
/* On the glass of a modal or a sheet (since 1.35.0) one step darker in dark
|
|
864
|
+
mode, --gl-dialog-control, and without a blur of its own: its muted
|
|
865
|
+
label read 3 to 4:1 there. */
|
|
840
866
|
.glass-btn--tertiary {
|
|
841
|
-
background: var(--gl-surface-2);
|
|
842
|
-
backdrop-filter: blur(var(--gl-blur-light));
|
|
843
|
-
-webkit-backdrop-filter: blur(var(--gl-blur-light));
|
|
867
|
+
background: var(--gl-ctx-btn-tertiary-bg, var(--gl-surface-2));
|
|
868
|
+
backdrop-filter: var(--gl-ctx-control-backdrop, blur(var(--gl-blur-light)));
|
|
869
|
+
-webkit-backdrop-filter: var(--gl-ctx-control-backdrop, blur(var(--gl-blur-light)));
|
|
844
870
|
border: 1px solid var(--gl-border-subtle);
|
|
845
871
|
color: var(--gl-color-text-muted);
|
|
846
872
|
box-shadow: 0 4px 12px rgba(0,0,0,0.10), var(--gl-inset-subtle);
|
|
@@ -868,7 +894,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
868
894
|
.glass-btn[aria-disabled="true"]:is(:hover, :active) { transform: none; }
|
|
869
895
|
.glass-btn--tertiary:disabled:hover,
|
|
870
896
|
.glass-btn--tertiary[aria-disabled="true"]:hover {
|
|
871
|
-
background: var(--gl-surface-2); color: var(--gl-color-text-muted);
|
|
897
|
+
background: var(--gl-ctx-btn-tertiary-bg, var(--gl-surface-2)); color: var(--gl-color-text-muted);
|
|
872
898
|
}
|
|
873
899
|
|
|
874
900
|
/* Sizes */
|
|
@@ -903,7 +929,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
903
929
|
}
|
|
904
930
|
|
|
905
931
|
.glass-status p {
|
|
906
|
-
color: var(--gl-color-text-muted);
|
|
932
|
+
color: var(--gl-status-color, var(--gl-color-text-muted));
|
|
907
933
|
font-size: var(--gl-font-size-sm);
|
|
908
934
|
font-weight: var(--gl-font-weight-normal);
|
|
909
935
|
line-height: 1.45;
|
|
@@ -1391,7 +1417,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
1391
1417
|
.glass-range-value {
|
|
1392
1418
|
font-size: var(--gl-font-size-sm);
|
|
1393
1419
|
font-weight: var(--gl-font-weight-semibold);
|
|
1394
|
-
color: var(--gl-color-primary-text);
|
|
1420
|
+
color: var(--gl-ctx-primary-text, var(--gl-color-primary-text));
|
|
1395
1421
|
font-variant-numeric: tabular-nums;
|
|
1396
1422
|
}
|
|
1397
1423
|
|
|
@@ -1546,9 +1572,11 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
1546
1572
|
|
|
1547
1573
|
.glass-modal {
|
|
1548
1574
|
width: 100%; max-width: var(--gl-modal-max-width, 340px);
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1575
|
+
/* --gl-modal-bg replaces the surface (since 1.35.0); in dark mode the
|
|
1576
|
+
glow starts at --gl-dialog-glow-top, the card's middle one. */
|
|
1577
|
+
background: var(--gl-modal-bg, linear-gradient(to bottom,
|
|
1578
|
+
var(--gl-dialog-glow-top, var(--gl-card-glow-top)) 0%, var(--gl-card-glow-bottom) 100%
|
|
1579
|
+
));
|
|
1552
1580
|
backdrop-filter: blur(var(--gl-blur-heavy));
|
|
1553
1581
|
-webkit-backdrop-filter: blur(var(--gl-blur-heavy));
|
|
1554
1582
|
border: 1.5px solid var(--gl-border-medium);
|
|
@@ -1586,7 +1614,7 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
1586
1614
|
.glass-modal__action:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
1587
1615
|
.glass-modal__action:disabled:hover { background: transparent; }
|
|
1588
1616
|
.glass-modal__action + .glass-modal__action { border-inline-start: 1px solid var(--gl-border-subtle); }
|
|
1589
|
-
.glass-modal__action--primary { color: var(--gl-color-primary-text); font-weight: var(--gl-font-weight-semibold); }
|
|
1617
|
+
.glass-modal__action--primary { color: var(--gl-ctx-primary-text, var(--gl-color-primary-text)); font-weight: var(--gl-font-weight-semibold); }
|
|
1590
1618
|
.glass-modal__action--danger { color: var(--gl-color-error); font-weight: var(--gl-font-weight-semibold); }
|
|
1591
1619
|
|
|
1592
1620
|
|
|
@@ -2078,7 +2106,7 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
2078
2106
|
.glass-segmented.glass-segmented--droplet[data-droplet]::before {
|
|
2079
2107
|
background:
|
|
2080
2108
|
var(--gl-gloss-droplet, none),
|
|
2081
|
-
var(--gl-segmented-active-bg, linear-gradient(to bottom, var(--gl-surface-5) 0%, var(--gl-surface-3) 100%));
|
|
2109
|
+
var(--gl-segmented-active-bg, var(--gl-ctx-segmented-active-bg, linear-gradient(to bottom, var(--gl-surface-5) 0%, var(--gl-surface-3) 100%)));
|
|
2082
2110
|
box-shadow:
|
|
2083
2111
|
var(--gl-segmented-active-shadow, 0 4px 14px rgba(0,0,0,0.18), 0 1px 3px rgba(0,0,0,0.12)),
|
|
2084
2112
|
inset 0 0 0 1px var(--gl-border-subtle),
|
|
@@ -2488,7 +2516,7 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
2488
2516
|
-webkit-tap-highlight-color: transparent;
|
|
2489
2517
|
}
|
|
2490
2518
|
|
|
2491
|
-
.glass-accordion__trigger:hover { color: var(--gl-color-primary-text); }
|
|
2519
|
+
.glass-accordion__trigger:hover { color: var(--gl-ctx-primary-text, var(--gl-color-primary-text)); }
|
|
2492
2520
|
|
|
2493
2521
|
.glass-accordion__trigger-icon { display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
|
|
2494
2522
|
|
|
@@ -2543,8 +2571,11 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
2543
2571
|
display: inline-flex; align-items: center; gap: var(--gl-space-2xs);
|
|
2544
2572
|
padding: var(--gl-space-2xs) var(--gl-space-sm);
|
|
2545
2573
|
background: var(--gl-surface-3);
|
|
2546
|
-
|
|
2547
|
-
|
|
2574
|
+
/* No blur of its own on the glass of a modal or a sheet (since 1.35.0):
|
|
2575
|
+
the dialog blurs already, and Chromium counted its glow twice beneath
|
|
2576
|
+
a nested backdrop filter — a chip there came out 2.9:1 for white. */
|
|
2577
|
+
backdrop-filter: var(--gl-ctx-control-backdrop, blur(var(--gl-blur-soft)));
|
|
2578
|
+
-webkit-backdrop-filter: var(--gl-ctx-control-backdrop, blur(var(--gl-blur-soft)));
|
|
2548
2579
|
border: 1px solid var(--gl-border-subtle);
|
|
2549
2580
|
border-radius: var(--gl-radius-full);
|
|
2550
2581
|
font-size: var(--gl-font-size-xs);
|
|
@@ -2632,9 +2663,12 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
2632
2663
|
box-shadow: var(--gl-shadow-focus), var(--gl-inset-subtle);
|
|
2633
2664
|
}
|
|
2634
2665
|
|
|
2666
|
+
/* In dark mode the label takes the text colour (since 1.35.0): the accent
|
|
2667
|
+
lightened for dark surfaces read 2.2 to 3:1 on a chip over glass. The
|
|
2668
|
+
selection shows in the border and the tint. */
|
|
2635
2669
|
.glass-badge--selected {
|
|
2636
2670
|
border-color: color-mix(in srgb, var(--gl-badge-accent) 55%, transparent);
|
|
2637
|
-
color: var(--gl-badge-accent-text);
|
|
2671
|
+
color: var(--gl-badge-selected-color, var(--gl-badge-accent-text));
|
|
2638
2672
|
box-shadow: var(--gl-inset-subtle),
|
|
2639
2673
|
inset 0 0 0 100px color-mix(in srgb, var(--gl-badge-accent) 22%, transparent);
|
|
2640
2674
|
}
|
|
@@ -3037,10 +3071,14 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3037
3071
|
list-style: none;
|
|
3038
3072
|
}
|
|
3039
3073
|
|
|
3074
|
+
/* The divider starts under the text: after the leading icon, or at the
|
|
3075
|
+
row's padding without one. --gl-list-item-divider-inset (since 1.34.0)
|
|
3076
|
+
sets the start for rows laid out otherwise — a drag handle before the
|
|
3077
|
+
icon, a wider leading element. */
|
|
3040
3078
|
.glass-list__item:not(:last-child)::after {
|
|
3041
3079
|
content: '';
|
|
3042
3080
|
position: absolute;
|
|
3043
|
-
inset-inline-start: calc(var(--gl-space-lg) + 28px + var(--gl-space-sm));
|
|
3081
|
+
inset-inline-start: var(--gl-list-item-divider-inset, calc(var(--gl-space-lg) + 28px + var(--gl-space-sm)));
|
|
3044
3082
|
inset-inline-end: var(--gl-space-lg);
|
|
3045
3083
|
bottom: 0;
|
|
3046
3084
|
height: 1px;
|
|
@@ -3050,10 +3088,16 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3050
3088
|
/* Items without a leading icon — no slot, or a hidden one: divider follows
|
|
3051
3089
|
the standard horizontal padding instead of the icon slot. */
|
|
3052
3090
|
.glass-list__item:not(:has(.glass-list__leading:not([hidden]))):not(:last-child)::after {
|
|
3053
|
-
inset-inline-start: var(--gl-space-lg);
|
|
3091
|
+
inset-inline-start: var(--gl-list-item-divider-inset, var(--gl-space-lg));
|
|
3054
3092
|
}
|
|
3055
3093
|
.glass-list__item:has(.glass-list__leading--lg:not([hidden])):not(:last-child)::after {
|
|
3056
|
-
inset-inline-start: calc(var(--gl-space-lg) + 40px + var(--gl-space-sm));
|
|
3094
|
+
inset-inline-start: var(--gl-list-item-divider-inset, calc(var(--gl-space-lg) + 40px + var(--gl-space-sm)));
|
|
3095
|
+
}
|
|
3096
|
+
/* A drag handle at the start of the row (since 1.34.0): its width is the
|
|
3097
|
+
page's, so the line runs from the row's padding, as in a row without an
|
|
3098
|
+
icon, until --gl-list-item-divider-inset says where the text begins. */
|
|
3099
|
+
.glass-list__item:has(> .glass-sort__handle:first-child:not([hidden])):not(:last-child)::after {
|
|
3100
|
+
inset-inline-start: var(--gl-list-item-divider-inset, var(--gl-space-lg));
|
|
3057
3101
|
}
|
|
3058
3102
|
|
|
3059
3103
|
.glass-list__item--center {
|
|
@@ -3091,11 +3135,36 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3091
3135
|
.glass-list__item--interactive:disabled:is(:hover, :active),
|
|
3092
3136
|
.glass-list__item--interactive[aria-disabled="true"]:is(:hover, :active) { background: transparent; }
|
|
3093
3137
|
|
|
3138
|
+
/* The chosen row of a list beside its detail (since 1.34.0) — the entry an
|
|
3139
|
+
editor next to it shows: a pill of raised glass inside the row, as the
|
|
3140
|
+
chosen tree row and the active row of a sidebar, with the title in the
|
|
3141
|
+
heading colour and the icon in the accent. The state is .is-selected;
|
|
3142
|
+
aria-current="true" (or aria-selected in a listbox) tells assistive
|
|
3143
|
+
technology. Hover and press leave it as it is; the keyboard ring stays
|
|
3144
|
+
around the row. While the row is a drop target of a drag, the pill makes
|
|
3145
|
+
way for the line or the tint. */
|
|
3146
|
+
/* Tokens since 1.35.0 shape it otherwise: --gl-list-item-selected-inset
|
|
3147
|
+
(3px --gl-space-xs), -radius (--gl-radius-sm), -shadow (edge light and a
|
|
3148
|
+
button's shadow), -color (the heading colour) and -weight (semibold).
|
|
3149
|
+
Inset 0, radius 0 and shadow none make a flat tint over the whole row. */
|
|
3150
|
+
.glass-list__item.is-selected { color: var(--gl-list-item-selected-color, var(--gl-color-text-heading)); isolation: isolate; }
|
|
3151
|
+
.glass-list__item.is-selected:not(.is-sort-before, .is-sort-after, .is-sort-inside, .is-sort-refused)::before {
|
|
3152
|
+
content: ''; position: absolute; z-index: -1;
|
|
3153
|
+
inset: var(--gl-list-item-selected-inset, 3px var(--gl-space-xs));
|
|
3154
|
+
border-radius: var(--gl-list-item-selected-radius, var(--gl-radius-sm));
|
|
3155
|
+
background: var(--gl-list-item-selected-bg, var(--gl-surface-4));
|
|
3156
|
+
box-shadow: var(--gl-list-item-selected-shadow, var(--gl-inset-strong), var(--gl-shadow-btn));
|
|
3157
|
+
pointer-events: none;
|
|
3158
|
+
}
|
|
3159
|
+
.glass-list__item--interactive.is-selected:is(:hover, :active, :focus-visible) { background: transparent; }
|
|
3160
|
+
.glass-list__item.is-selected .glass-list__title { font-weight: var(--gl-list-item-selected-weight, var(--gl-font-weight-semibold)); }
|
|
3161
|
+
.glass-list__item.is-selected .glass-list__leading { color: var(--gl-color-primary-text); }
|
|
3162
|
+
|
|
3094
3163
|
.glass-list__item--danger { color: var(--gl-color-error); }
|
|
3095
3164
|
.glass-list__item--danger .glass-list__title,
|
|
3096
3165
|
.glass-list__item--danger .glass-list__leading { color: inherit; }
|
|
3097
3166
|
|
|
3098
|
-
.glass-list__item--accent { color: var(--gl-color-primary-text); }
|
|
3167
|
+
.glass-list__item--accent { color: var(--gl-ctx-primary-text, var(--gl-color-primary-text)); }
|
|
3099
3168
|
.glass-list__item--accent .glass-list__title,
|
|
3100
3169
|
.glass-list__item--accent .glass-list__leading { color: inherit; }
|
|
3101
3170
|
|
|
@@ -3160,9 +3229,11 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3160
3229
|
out of it — an e-mail address in a --wrap subtitle used to — while text
|
|
3161
3230
|
still breaks at spaces. hyphens is left to inheritance: set it on the
|
|
3162
3231
|
list or the page for breaks at syllables. */
|
|
3232
|
+
/* --gl-list-title-size, --gl-list-title-weight and --gl-list-subtitle-size
|
|
3233
|
+
(since 1.35.0) set the type of a row, on the list or one row. */
|
|
3163
3234
|
.glass-list__title {
|
|
3164
|
-
font-size: var(--gl-font-size-base);
|
|
3165
|
-
font-weight: var(--gl-font-weight-medium);
|
|
3235
|
+
font-size: var(--gl-list-title-size, var(--gl-font-size-base));
|
|
3236
|
+
font-weight: var(--gl-list-title-weight, var(--gl-font-weight-medium));
|
|
3166
3237
|
color: var(--gl-color-text);
|
|
3167
3238
|
white-space: var(--gl-list-title-white-space, nowrap);
|
|
3168
3239
|
overflow: hidden;
|
|
@@ -3170,7 +3241,7 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3170
3241
|
overflow-wrap: anywhere;
|
|
3171
3242
|
}
|
|
3172
3243
|
.glass-list__subtitle {
|
|
3173
|
-
font-size: var(--gl-font-size-sm);
|
|
3244
|
+
font-size: var(--gl-list-subtitle-size, var(--gl-font-size-sm));
|
|
3174
3245
|
color: var(--gl-color-text-muted);
|
|
3175
3246
|
white-space: var(--gl-list-subtitle-white-space, nowrap);
|
|
3176
3247
|
overflow: hidden;
|
|
@@ -3187,6 +3258,27 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3187
3258
|
/* display: -webkit-box above beats the hidden attribute's own rule: an empty
|
|
3188
3259
|
--wrap subtitle kept its place, and the title sat 1px off centre. */
|
|
3189
3260
|
.glass-list__subtitle[hidden] { display: none; }
|
|
3261
|
+
/* Room beside the title and below the subtitle (since 1.35.0). __title-row
|
|
3262
|
+
holds the title and __title-trailing — a badge such as "AI", a mark —,
|
|
3263
|
+
which moves under the title where the row is too narrow; the title keeps
|
|
3264
|
+
its ellipsis. __extra below the subtitle takes a link ("Undo") or a line
|
|
3265
|
+
of chips. */
|
|
3266
|
+
.glass-list__title-row {
|
|
3267
|
+
display: flex; flex-wrap: wrap; align-items: center;
|
|
3268
|
+
gap: var(--gl-space-2xs) var(--gl-space-xs);
|
|
3269
|
+
min-width: 0;
|
|
3270
|
+
}
|
|
3271
|
+
.glass-list__title-row > .glass-list__title { flex: 0 1 auto; min-width: 0; }
|
|
3272
|
+
.glass-list__item--center .glass-list__title-row { justify-content: center; }
|
|
3273
|
+
.glass-list__title-trailing { flex: none; display: inline-flex; align-items: center; gap: var(--gl-space-2xs); }
|
|
3274
|
+
.glass-list__extra {
|
|
3275
|
+
display: flex; flex-wrap: wrap; align-items: center; gap: var(--gl-space-xs);
|
|
3276
|
+
margin-top: var(--gl-space-2xs);
|
|
3277
|
+
font-size: var(--gl-font-size-sm);
|
|
3278
|
+
color: var(--gl-color-text-muted);
|
|
3279
|
+
}
|
|
3280
|
+
.glass-list__title-trailing[hidden],
|
|
3281
|
+
.glass-list__extra[hidden] { display: none; }
|
|
3190
3282
|
|
|
3191
3283
|
.glass-list__trailing {
|
|
3192
3284
|
flex-shrink: 0;
|
|
@@ -3212,6 +3304,63 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3212
3304
|
white-space: nowrap;
|
|
3213
3305
|
}
|
|
3214
3306
|
|
|
3307
|
+
/* Tiles side by side (since 1.34.0): the list as a grid of panes of glass
|
|
3308
|
+
— components, apps, choices — each with the surface, edge light and
|
|
3309
|
+
shadow the list has as a whole, which itself has none. The icon stands
|
|
3310
|
+
at the top, the title and subtitle at the foot, the trailing content in
|
|
3311
|
+
the top end corner and a drag handle in the bottom end corner; no
|
|
3312
|
+
dividers. --gl-list-tile-width (140px) is the least width of a column,
|
|
3313
|
+
--gl-list-tile-gap (--gl-space-sm) the gap, --gl-list-tile-min-height
|
|
3314
|
+
(112px) the least height. In plain markup the items of a .glass-list
|
|
3315
|
+
--grid are tiles; GlassKit Elements puts .glass-list__item--tile on the
|
|
3316
|
+
rows of <glk-list grid>, which lie in shadow roots of their own. */
|
|
3317
|
+
.glass-list--grid {
|
|
3318
|
+
display: grid;
|
|
3319
|
+
grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--gl-list-tile-width, 140px)), 1fr));
|
|
3320
|
+
gap: var(--gl-list-tile-gap, var(--gl-space-sm));
|
|
3321
|
+
background: none;
|
|
3322
|
+
backdrop-filter: none;
|
|
3323
|
+
-webkit-backdrop-filter: none;
|
|
3324
|
+
border: none;
|
|
3325
|
+
border-radius: 0;
|
|
3326
|
+
box-shadow: none;
|
|
3327
|
+
overflow: visible;
|
|
3328
|
+
}
|
|
3329
|
+
:where(.glass-list--grid) > .glass-list__item,
|
|
3330
|
+
.glass-list__item--tile {
|
|
3331
|
+
flex-direction: column;
|
|
3332
|
+
align-items: flex-start;
|
|
3333
|
+
gap: var(--gl-space-sm);
|
|
3334
|
+
height: 100%;
|
|
3335
|
+
min-height: var(--gl-list-tile-min-height, 112px);
|
|
3336
|
+
padding: var(--gl-space-md);
|
|
3337
|
+
border-radius: var(--gl-radius-btn);
|
|
3338
|
+
background: var(--gl-surface-1);
|
|
3339
|
+
backdrop-filter: blur(var(--gl-blur-light));
|
|
3340
|
+
-webkit-backdrop-filter: blur(var(--gl-blur-light));
|
|
3341
|
+
border: 1px solid var(--gl-border-subtle);
|
|
3342
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.08), var(--gl-inset-subtle);
|
|
3343
|
+
}
|
|
3344
|
+
.glass-list--grid > .glass-list__item::after,
|
|
3345
|
+
.glass-list__item.glass-list__item--tile::after { content: none; }
|
|
3346
|
+
/* The text sits at the foot. It never shrinks below its lines — its
|
|
3347
|
+
overflow: hidden would let it, and cut the title's descenders —, so a
|
|
3348
|
+
tile with more to say grows. */
|
|
3349
|
+
:where(.glass-list--grid) > .glass-list__item .glass-list__content,
|
|
3350
|
+
.glass-list__item--tile .glass-list__content { flex: 1 0 auto; align-self: stretch; justify-content: flex-end; }
|
|
3351
|
+
:where(.glass-list--grid) > .glass-list__item .glass-list__trailing,
|
|
3352
|
+
.glass-list__item--tile .glass-list__trailing { position: absolute; top: var(--gl-space-sm); inset-inline-end: var(--gl-space-sm); }
|
|
3353
|
+
:where(.glass-list--grid) > .glass-list__item > .glass-sort__handle,
|
|
3354
|
+
.glass-list__item--tile > .glass-sort__handle { position: absolute; bottom: var(--gl-space-sm); inset-inline-end: var(--gl-space-sm); }
|
|
3355
|
+
/* The chosen tile is raised glass as a whole. */
|
|
3356
|
+
.glass-list--grid > .glass-list__item.is-selected:not(.is-sort-before, .is-sort-after, .is-sort-inside, .is-sort-refused)::before,
|
|
3357
|
+
.glass-list__item--tile.is-selected:not(.is-sort-before, .is-sort-after, .is-sort-inside, .is-sort-refused)::before { inset: -1px; border-radius: inherit; }
|
|
3358
|
+
/* The drop line stands in the middle of the gap. */
|
|
3359
|
+
.glass-list--grid > .glass-list__item.is-sort-inline.is-sort-before::before,
|
|
3360
|
+
.glass-list__item--tile.is-sort-inline.is-sort-before::before { inset-inline-start: calc(var(--gl-list-tile-gap, var(--gl-space-sm)) / -2 - 1px); }
|
|
3361
|
+
.glass-list--grid > .glass-list__item.is-sort-inline.is-sort-after::before,
|
|
3362
|
+
.glass-list__item--tile.is-sort-inline.is-sort-after::before { inset-inline-end: calc(var(--gl-list-tile-gap, var(--gl-space-sm)) / -2 - 1px); }
|
|
3363
|
+
|
|
3215
3364
|
|
|
3216
3365
|
/* ============================================================
|
|
3217
3366
|
25b. TREE
|
|
@@ -3278,15 +3427,18 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3278
3427
|
animation: glass-tree-spin .8s linear infinite;
|
|
3279
3428
|
}
|
|
3280
3429
|
@keyframes glass-tree-spin { to { transform: rotate(360deg); } }
|
|
3430
|
+
/* The icon field is --gl-tree-icon-size square (since 1.34.0; 18px), and
|
|
3431
|
+
so is its SVG: a larger mark — a tinted 28px chip with a symbol, as list
|
|
3432
|
+
rows show — gets a field of its size instead of being squeezed into 18px. */
|
|
3281
3433
|
.glass-tree__icon {
|
|
3282
|
-
flex: none; width: 18px; height: 18px;
|
|
3434
|
+
flex: none; width: var(--gl-tree-icon-size, 18px); height: var(--gl-tree-icon-size, 18px);
|
|
3283
3435
|
display: flex; align-items: center; justify-content: center;
|
|
3284
3436
|
color: var(--gl-icon-default);
|
|
3285
3437
|
}
|
|
3286
3438
|
.glass-tree__icon:empty, .glass-tree__icon[hidden] { display: none; }
|
|
3287
3439
|
.glass-tree__icon svg,
|
|
3288
3440
|
.glass-tree__icon ::slotted(svg) {
|
|
3289
|
-
width: 18px; height: 18px; fill: none;
|
|
3441
|
+
width: var(--gl-tree-icon-size, 18px); height: var(--gl-tree-icon-size, 18px); fill: none;
|
|
3290
3442
|
stroke: currentColor; stroke-width: 1.8;
|
|
3291
3443
|
stroke-linecap: round; stroke-linejoin: round;
|
|
3292
3444
|
}
|
|
@@ -3413,11 +3565,24 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3413
3565
|
}
|
|
3414
3566
|
.is-sort-before::before { top: -1px; }
|
|
3415
3567
|
.is-sort-after::before { bottom: -1px; }
|
|
3416
|
-
.
|
|
3568
|
+
/* Items side by side — tiles in a grid, a row of them (since 1.34.0): with
|
|
3569
|
+
.is-sort-inline the line stands upright at the target's start or end
|
|
3570
|
+
edge, where the item lands. */
|
|
3571
|
+
.is-sort-inline.is-sort-before::before,
|
|
3572
|
+
.is-sort-inline.is-sort-after::before { inset-block: var(--gl-space-xs); width: 2px; height: auto; }
|
|
3573
|
+
.is-sort-inline.is-sort-before::before { inset-inline: -1px auto; }
|
|
3574
|
+
.is-sort-inline.is-sort-after::before { inset-inline: auto -1px; }
|
|
3575
|
+
/* On a list or tree row also over its hover and its chosen state (since
|
|
3576
|
+
1.34.0; before, both covered the tint). */
|
|
3577
|
+
.is-sort-inside,
|
|
3578
|
+
.glass-list__item.is-sort-inside,
|
|
3579
|
+
.glass-tree__row.is-sort-inside {
|
|
3417
3580
|
background: color-mix(in srgb, var(--gl-color-primary) 16%, transparent);
|
|
3418
3581
|
box-shadow: inset 0 0 0 1.5px var(--gl-border-focus);
|
|
3419
3582
|
}
|
|
3420
|
-
.is-sort-refused
|
|
3583
|
+
.is-sort-refused,
|
|
3584
|
+
.glass-list__item.is-sort-refused,
|
|
3585
|
+
.glass-tree__row.is-sort-refused {
|
|
3421
3586
|
background: var(--gl-color-error-surface);
|
|
3422
3587
|
box-shadow: inset 0 0 0 1.5px var(--gl-color-error-border);
|
|
3423
3588
|
}
|
|
@@ -3659,7 +3824,7 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3659
3824
|
.glass-prose ul, .glass-prose ol { padding-inline-start: 1.3em; }
|
|
3660
3825
|
.glass-prose strong { color: var(--gl-color-text-heading); }
|
|
3661
3826
|
/* Links in running text are underlined: colour alone does not mark them. */
|
|
3662
|
-
.glass-prose a { color: var(--gl-color-primary-text); text-decoration: underline; text-underline-offset: 2px; }
|
|
3827
|
+
.glass-prose a { color: var(--gl-ctx-primary-text, var(--gl-color-primary-text)); text-decoration: underline; text-underline-offset: 2px; }
|
|
3663
3828
|
.glass-prose code {
|
|
3664
3829
|
font-family: ui-monospace, 'SF Mono', Menlo, monospace; font-size: 0.9em;
|
|
3665
3830
|
background: var(--gl-surface-2); padding: 1px 5px; border-radius: 4px;
|
|
@@ -3697,7 +3862,9 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3697
3862
|
.glass-segmented {
|
|
3698
3863
|
display: inline-flex; gap: 4px; padding: 4px;
|
|
3699
3864
|
max-width: 100%;
|
|
3700
|
-
|
|
3865
|
+
/* --gl-segmented-bg (since 1.35.0); on the glass of a modal or a sheet
|
|
3866
|
+
in dark mode the track is a well, --gl-dialog-well. */
|
|
3867
|
+
background: var(--gl-segmented-bg, var(--gl-ctx-segmented-bg, var(--gl-surface-1)));
|
|
3701
3868
|
border: 1px solid var(--gl-border-subtle);
|
|
3702
3869
|
border-radius: var(--gl-radius-btn);
|
|
3703
3870
|
box-shadow: var(--gl-inset-subtle);
|
|
@@ -3741,7 +3908,7 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3741
3908
|
values; the drop of --droplet takes the same surface (18c). The shadow
|
|
3742
3909
|
sits in shadow lists: switch it off with a zero shadow, not none. */
|
|
3743
3910
|
.glass-segmented__item[aria-pressed="true"] {
|
|
3744
|
-
background: var(--gl-segmented-active-bg, var(--gl-surface-5));
|
|
3911
|
+
background: var(--gl-segmented-active-bg, var(--gl-ctx-segmented-active-bg, var(--gl-surface-5)));
|
|
3745
3912
|
color: var(--gl-segmented-active-color, var(--gl-color-text-heading));
|
|
3746
3913
|
box-shadow: var(--gl-segmented-active-shadow, var(--gl-shadow-btn));
|
|
3747
3914
|
}
|
|
@@ -3772,8 +3939,13 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3772
3939
|
}
|
|
3773
3940
|
.glass-segmented__icon[hidden] { display: none; }
|
|
3774
3941
|
.glass-segmented__icon svg,
|
|
3775
|
-
.glass-segmented__icon ::slotted(svg) {
|
|
3776
|
-
|
|
3942
|
+
.glass-segmented__icon ::slotted(svg) { width: 18px; height: 18px; }
|
|
3943
|
+
/* A line icon strokes in the option's colour. --color (since 1.35.0) keeps
|
|
3944
|
+
a coloured logo's own fills and strokes; before, its shapes inherited the
|
|
3945
|
+
stroke and came out outlined in the text colour. */
|
|
3946
|
+
.glass-segmented__icon:not(.glass-segmented__icon--color) svg,
|
|
3947
|
+
.glass-segmented__icon:not(.glass-segmented__icon--color) ::slotted(svg) {
|
|
3948
|
+
fill: none;
|
|
3777
3949
|
stroke: currentColor; stroke-width: 1.8;
|
|
3778
3950
|
stroke-linecap: round; stroke-linejoin: round;
|
|
3779
3951
|
}
|
|
@@ -3938,7 +4110,7 @@ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
|
|
|
3938
4110
|
layout instead of idling at opacity 0. <glk-sheet> in GlassKit Elements
|
|
3939
4111
|
does exactly this. --inline embeds the panel in the flow, no overlay. */
|
|
3940
4112
|
.glass-sheet-overlay {
|
|
3941
|
-
position: fixed; inset: 0; z-index: 1000;
|
|
4113
|
+
position: fixed; inset: 0; z-index: var(--gl-sheet-z-index, 1000);
|
|
3942
4114
|
display: flex; align-items: flex-end; justify-content: center;
|
|
3943
4115
|
background: var(--gl-surface-overlay);
|
|
3944
4116
|
/* Like the modal's dimmer: --gl-blur-overlay where set (1.25.0). */
|
|
@@ -3976,9 +4148,9 @@ dialog.glass-sheet-overlay::backdrop { background: transparent; }
|
|
|
3976
4148
|
light in dark mode — with --gl-color-text on it the sheet read white
|
|
3977
4149
|
on white-grey. The card glow gradient over heavy blur is what the
|
|
3978
4150
|
text tokens are made for, in both themes. */
|
|
3979
|
-
background: linear-gradient(to bottom,
|
|
3980
|
-
var(--gl-card-glow-top) 0%, var(--gl-card-glow-bottom) 100%
|
|
3981
|
-
);
|
|
4151
|
+
background: var(--gl-sheet-bg, linear-gradient(to bottom,
|
|
4152
|
+
var(--gl-dialog-glow-top, var(--gl-card-glow-top)) 0%, var(--gl-card-glow-bottom) 100%
|
|
4153
|
+
));
|
|
3982
4154
|
backdrop-filter: blur(var(--gl-blur-heavy));
|
|
3983
4155
|
-webkit-backdrop-filter: blur(var(--gl-blur-heavy));
|
|
3984
4156
|
color: var(--gl-color-text);
|
|
@@ -3993,12 +4165,106 @@ dialog.glass-sheet-overlay::backdrop { background: transparent; }
|
|
|
3993
4165
|
.glass-sheet-overlay.is-active .glass-sheet { transform: translateY(0); }
|
|
3994
4166
|
.glass-sheet--inline { border-radius: var(--gl-radius-card); box-shadow: var(--gl-shadow-card); }
|
|
3995
4167
|
|
|
4168
|
+
/* Controls on the glass of a modal or a sheet (since 1.35.0) take the
|
|
4169
|
+
theme's dialog values where the page set none of its own: a segmented
|
|
4170
|
+
control lies in --gl-dialog-well with its chosen option on
|
|
4171
|
+
--gl-dialog-raised, a tertiary button on --gl-dialog-control (all dark
|
|
4172
|
+
mode only), and badges and tertiary buttons take no blur of their own;
|
|
4173
|
+
accent text — a link, an accent row — takes --gl-color-primary-on-glass,
|
|
4174
|
+
as on a card. Inherited, so they reach the controls of GlassKit Elements in
|
|
4175
|
+
their shadow roots. */
|
|
4176
|
+
.glass-modal, .glass-sheet {
|
|
4177
|
+
--gl-ctx-segmented-bg: var(--gl-dialog-well);
|
|
4178
|
+
--gl-ctx-segmented-active-bg: var(--gl-dialog-raised);
|
|
4179
|
+
--gl-ctx-btn-tertiary-bg: var(--gl-dialog-control);
|
|
4180
|
+
--gl-ctx-control-backdrop: none;
|
|
4181
|
+
--gl-ctx-primary-text: var(--gl-color-primary-on-glass);
|
|
4182
|
+
}
|
|
4183
|
+
|
|
4184
|
+
/* At a side (since 1.35.0): --start or --end on the overlay puts the panel
|
|
4185
|
+
at that edge, as high as the window less --gl-sheet-side-inset (16px) at
|
|
4186
|
+
both ends and that far from its edge, --gl-sheet-side-width (440px) wide,
|
|
4187
|
+
with a card's corners. It slides in from that edge, has no grip, and its
|
|
4188
|
+
actions stand side by side at its foot. --modeless leaves the page
|
|
4189
|
+
usable: no scrim and no blur, and only the panel takes the pointer — for
|
|
4190
|
+
a sheet opened with show() instead of showModal(), beside a list whose
|
|
4191
|
+
chosen row stays in view. --gl-sheet-z-index (1000) stacks it. */
|
|
4192
|
+
/* The inset is the panel's margin: the dialog's own padding is undone. */
|
|
4193
|
+
.glass-sheet-overlay--start,
|
|
4194
|
+
.glass-sheet-overlay--end { align-items: stretch; }
|
|
4195
|
+
.glass-sheet-overlay--start { justify-content: flex-start; }
|
|
4196
|
+
.glass-sheet-overlay--end { justify-content: flex-end; }
|
|
4197
|
+
:is(.glass-sheet-overlay--start, .glass-sheet-overlay--end) .glass-sheet {
|
|
4198
|
+
width: min(var(--gl-sheet-side-width, 440px), 100% - 2 * var(--gl-sheet-side-inset, 16px)); max-height: none;
|
|
4199
|
+
margin: var(--gl-sheet-side-inset, 16px);
|
|
4200
|
+
display: flex; flex-direction: column;
|
|
4201
|
+
padding-top: var(--gl-space-lg);
|
|
4202
|
+
border-radius: var(--gl-radius-card);
|
|
4203
|
+
}
|
|
4204
|
+
.glass-sheet-overlay--end .glass-sheet,
|
|
4205
|
+
.glass-sheet-overlay--start:dir(rtl) .glass-sheet { transform: translateX(calc(100% + var(--gl-sheet-side-inset, 16px))); }
|
|
4206
|
+
.glass-sheet-overlay--start .glass-sheet,
|
|
4207
|
+
.glass-sheet-overlay--end:dir(rtl) .glass-sheet { transform: translateX(calc(-100% - var(--gl-sheet-side-inset, 16px))); }
|
|
4208
|
+
:is(.glass-sheet-overlay--start, .glass-sheet-overlay--end).is-active .glass-sheet { transform: none; }
|
|
4209
|
+
:is(.glass-sheet-overlay--start, .glass-sheet-overlay--end) .glass-sheet__grip { display: none; }
|
|
4210
|
+
:is(.glass-sheet-overlay--start, .glass-sheet-overlay--end) .glass-sheet__body { flex: 1 0 auto; }
|
|
4211
|
+
:is(.glass-sheet-overlay--start, .glass-sheet-overlay--end) .glass-sheet__actions { flex-direction: row; flex-wrap: wrap; justify-content: flex-end; }
|
|
4212
|
+
.glass-sheet-overlay--modeless {
|
|
4213
|
+
background: none;
|
|
4214
|
+
backdrop-filter: none;
|
|
4215
|
+
-webkit-backdrop-filter: none;
|
|
4216
|
+
pointer-events: none;
|
|
4217
|
+
}
|
|
4218
|
+
.glass-sheet-overlay--modeless .glass-sheet { pointer-events: auto; }
|
|
4219
|
+
/* The panel takes the focus only as a whole, to hand it on; no ring. */
|
|
4220
|
+
.glass-sheet:focus { outline: none; }
|
|
4221
|
+
|
|
3996
4222
|
.glass-sheet__grip { width: 40px; height: 4px; margin: 4px auto 12px; border-radius: 2px; background: var(--gl-border-strong); }
|
|
3997
4223
|
.glass-sheet__title {
|
|
3998
4224
|
margin: 0 0 8px;
|
|
3999
4225
|
font-size: var(--gl-font-size-modal); font-weight: var(--gl-font-weight-semibold);
|
|
4000
4226
|
color: var(--gl-color-text-heading);
|
|
4001
4227
|
}
|
|
4228
|
+
/* The head (since 1.35.0): the title with a short line above it
|
|
4229
|
+
(__eyebrow), something before it (__leading, a mark or an icon chip),
|
|
4230
|
+
something after it (__trailing, a badge) and a close button (__close) at
|
|
4231
|
+
its end. __head takes the title's place and its spacing; a title alone
|
|
4232
|
+
in it stands as it did without one. */
|
|
4233
|
+
.glass-sheet__head { display: flex; align-items: center; gap: var(--gl-space-sm); margin: 0 0 8px; }
|
|
4234
|
+
.glass-sheet__heading { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
4235
|
+
.glass-sheet__head .glass-sheet__title { margin: 0; }
|
|
4236
|
+
.glass-sheet__eyebrow {
|
|
4237
|
+
font-size: var(--gl-font-size-xs); font-weight: var(--gl-font-weight-semibold);
|
|
4238
|
+
letter-spacing: 0.3px; text-transform: uppercase;
|
|
4239
|
+
color: var(--gl-color-text-muted);
|
|
4240
|
+
}
|
|
4241
|
+
.glass-sheet__leading,
|
|
4242
|
+
.glass-sheet__trailing { flex: none; display: flex; align-items: center; gap: var(--gl-space-xs); }
|
|
4243
|
+
.glass-sheet__eyebrow[hidden],
|
|
4244
|
+
.glass-sheet__leading[hidden],
|
|
4245
|
+
.glass-sheet__trailing[hidden],
|
|
4246
|
+
.glass-sheet__close[hidden] { display: none; }
|
|
4247
|
+
/* A round glass button, 32px, with a 44px target. */
|
|
4248
|
+
.glass-sheet__close {
|
|
4249
|
+
-webkit-appearance: none; appearance: none;
|
|
4250
|
+
flex: none; position: relative;
|
|
4251
|
+
width: 32px; height: 32px; margin-inline-end: -4px; padding: 0;
|
|
4252
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
4253
|
+
border: 1px solid var(--gl-border-subtle); border-radius: 50%;
|
|
4254
|
+
background: var(--gl-surface-2);
|
|
4255
|
+
color: var(--gl-color-text-muted);
|
|
4256
|
+
box-shadow: var(--gl-inset-subtle);
|
|
4257
|
+
font: inherit; cursor: pointer;
|
|
4258
|
+
transition: var(--gl-transition-fast);
|
|
4259
|
+
outline: none; -webkit-tap-highlight-color: transparent;
|
|
4260
|
+
}
|
|
4261
|
+
.glass-sheet__close::after { content: ""; position: absolute; inset: -6px; }
|
|
4262
|
+
.glass-sheet__close:hover { background: var(--gl-surface-3); color: var(--gl-color-text); }
|
|
4263
|
+
.glass-sheet__close:focus-visible { box-shadow: var(--gl-shadow-focus), var(--gl-inset-subtle); }
|
|
4264
|
+
.glass-sheet__close svg {
|
|
4265
|
+
width: 16px; height: 16px; fill: none; stroke: currentColor;
|
|
4266
|
+
stroke-width: 2; stroke-linecap: round;
|
|
4267
|
+
}
|
|
4002
4268
|
.glass-sheet__body { font-size: var(--gl-font-size-base); line-height: 1.55; }
|
|
4003
4269
|
.glass-sheet__actions { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }
|
|
4004
4270
|
@media (prefers-reduced-motion: reduce) {
|