@jungherz-de/glasskit 1.26.0 → 1.28.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 +38 -1
- package/README.md +61 -10
- package/SKILL.md +110 -8
- package/glasskit-droplet.js +241 -0
- package/glasskit-styles.js +3 -3
- package/glasskit.css +264 -33
- package/glasskit.min.css +2 -2
- package/glasskit.min.css.map +1 -1
- package/package.json +2 -1
- package/theme-override.css +22 -0
package/glasskit.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* ============================================================
|
|
2
2
|
GLASSKIT COMPONENT LIBRARY
|
|
3
|
-
Jungherz GmbH – v1.
|
|
3
|
+
Jungherz GmbH – v1.28.0
|
|
4
4
|
|
|
5
5
|
Features:
|
|
6
6
|
- Scoped Reset (box-sizing fix)
|
|
@@ -199,6 +199,10 @@
|
|
|
199
199
|
rgba(255,255,255,0.5) 50%, rgba(255,255,255,0.4) 70%, transparent 100%);
|
|
200
200
|
--gl-gloss-progress: linear-gradient(to bottom, rgba(255,255,255,0.3) 0%, transparent 100%);
|
|
201
201
|
--gl-range-thumb-border: 2px solid rgba(255,255,255,0.5);
|
|
202
|
+
/* The light in the drop of the --droplet rows (tab bar, segmented): a
|
|
203
|
+
highlight at the top, the caustic glow it throws at the bottom. */
|
|
204
|
+
--gl-gloss-droplet: radial-gradient(60% 55% at 32% 12%, rgba(255,255,255,0.42) 0%, transparent 70%),
|
|
205
|
+
radial-gradient(75% 60% at 50% 112%, rgba(255,255,255,0.18) 0%, transparent 70%);
|
|
202
206
|
|
|
203
207
|
/* ---- Background Effects ----
|
|
204
208
|
Deliberately *not* derived from --gl-color-primary: the aurora is the scene
|
|
@@ -501,6 +505,7 @@
|
|
|
501
505
|
--gl-gloss-card: none;
|
|
502
506
|
--gl-gloss-modal: none;
|
|
503
507
|
--gl-gloss-progress: none;
|
|
508
|
+
--gl-gloss-droplet: none;
|
|
504
509
|
--gl-range-thumb-border: 2px solid transparent;
|
|
505
510
|
}
|
|
506
511
|
/* Solid, light theme — and the tint preset's ground in it. */
|
|
@@ -1676,10 +1681,18 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
1676
1681
|
-webkit-backdrop-filter: blur(var(--gl-blur));
|
|
1677
1682
|
border-top: 1px solid var(--gl-border-subtle);
|
|
1678
1683
|
display: flex; justify-content: space-around;
|
|
1684
|
+
/* The items sit in the middle of the room the home indicator leaves.
|
|
1685
|
+
Where its inset leaves less than they need (an iPhone with
|
|
1686
|
+
viewport-fit=cover), they overflow the content box and `safe` keeps
|
|
1687
|
+
them at the top, as before 1.28.0. Without one — Android, the desktop —
|
|
1688
|
+
the inset is 0px, not the fallback, and the items sat 9px below the
|
|
1689
|
+
top edge with 26px empty below them. A browser without `safe` keeps
|
|
1690
|
+
flex-start. */
|
|
1679
1691
|
align-items: flex-start;
|
|
1692
|
+
align-items: safe center;
|
|
1680
1693
|
padding-top: var(--gl-space-xs);
|
|
1681
|
-
padding-bottom: env(safe-area-inset-bottom,
|
|
1682
|
-
z-index: 900;
|
|
1694
|
+
padding-bottom: max(var(--gl-space-xs), env(safe-area-inset-bottom, 0px));
|
|
1695
|
+
z-index: var(--gl-tab-bar-z-index, 900);
|
|
1683
1696
|
box-shadow: 0 -4px 20px rgba(0,0,0,0.08), var(--gl-inset-subtle);
|
|
1684
1697
|
}
|
|
1685
1698
|
|
|
@@ -1688,39 +1701,64 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
1688
1701
|
gap: var(--gl-space-2xs);
|
|
1689
1702
|
padding: var(--gl-space-2xs) var(--gl-space-sm);
|
|
1690
1703
|
background: none; border: none; cursor: pointer;
|
|
1704
|
+
border-radius: var(--gl-radius-sm);
|
|
1691
1705
|
transition: var(--gl-transition); outline: none;
|
|
1692
1706
|
-webkit-tap-highlight-color: transparent;
|
|
1693
1707
|
min-width: 60px;
|
|
1694
1708
|
}
|
|
1695
1709
|
|
|
1710
|
+
/* Every state colours the icon box, and the SVG strokes in currentColor
|
|
1711
|
+
(since 1.28.0): an icon font, an <img> mask or an element slotted in
|
|
1712
|
+
takes the colour as well, with the lens of the drop and the drag state.
|
|
1713
|
+
A font icon takes the box's size unless it sets its own. Unset, the
|
|
1714
|
+
inactive colour is --gl-icon-muted and the hovered one --gl-icon-default;
|
|
1715
|
+
--gl-tab-bar-color and --gl-tab-bar-hover-color set them, for icon and
|
|
1716
|
+
label alike. */
|
|
1696
1717
|
.glass-tab-bar__icon {
|
|
1697
1718
|
width: 24px; height: 24px;
|
|
1698
1719
|
display: flex; align-items: center; justify-content: center;
|
|
1699
1720
|
position: relative;
|
|
1721
|
+
color: var(--gl-tab-bar-color, var(--gl-icon-muted));
|
|
1722
|
+
font-size: 24px;
|
|
1723
|
+
transition: var(--gl-transition);
|
|
1700
1724
|
}
|
|
1701
1725
|
|
|
1702
|
-
.glass-tab-bar__icon svg
|
|
1726
|
+
.glass-tab-bar__icon svg,
|
|
1727
|
+
.glass-tab-bar__icon ::slotted(svg) {
|
|
1703
1728
|
width: 24px; height: 24px; fill: none;
|
|
1704
|
-
stroke:
|
|
1729
|
+
stroke: currentColor; stroke-width: 1.8;
|
|
1705
1730
|
stroke-linecap: round; stroke-linejoin: round;
|
|
1706
1731
|
transition: var(--gl-transition);
|
|
1707
1732
|
}
|
|
1708
1733
|
|
|
1709
1734
|
.glass-tab-bar__label {
|
|
1710
|
-
font-size: 10px; font-weight: var(--gl-font-weight-medium);
|
|
1711
|
-
color: var(--gl-icon-muted); transition: var(--gl-transition);
|
|
1735
|
+
font-size: var(--gl-tab-bar-label-size, 10px); font-weight: var(--gl-font-weight-medium);
|
|
1736
|
+
color: var(--gl-tab-bar-color, var(--gl-icon-muted)); transition: var(--gl-transition);
|
|
1712
1737
|
letter-spacing: 0.2px;
|
|
1713
1738
|
}
|
|
1714
1739
|
|
|
1715
1740
|
/* --gl-tab-bar-active-color, where set, colours the active icon and label
|
|
1716
1741
|
alone: the spotlight lightens the active item more than any other surface.
|
|
1717
|
-
Glow, dot and spotlight stay in the primary.
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1742
|
+
Glow, dot and spotlight stay in the primary. The glow lies on the icon
|
|
1743
|
+
itself, not on the badge beside it; :where() keeps the rule as specific
|
|
1744
|
+
as it was when it named the svg. */
|
|
1745
|
+
.glass-tab-bar__item.is-active .glass-tab-bar__icon { color: var(--gl-tab-bar-active-color, var(--gl-color-primary-text)); }
|
|
1746
|
+
.glass-tab-bar__item.is-active .glass-tab-bar__icon > :where(:not(.glass-tab-bar__badge)),
|
|
1747
|
+
.glass-tab-bar__item.is-active .glass-tab-bar__icon ::slotted(*) {
|
|
1748
|
+
filter: var(--gl-tab-bar-active-glow, drop-shadow(0 0 6px color-mix(in srgb, var(--gl-color-primary) 35%, transparent)));
|
|
1721
1749
|
}
|
|
1722
1750
|
.glass-tab-bar__item.is-active .glass-tab-bar__label { color: var(--gl-tab-bar-active-color, var(--gl-color-primary-text)); }
|
|
1723
1751
|
|
|
1752
|
+
/* The active item's own surface; unset, it has none. A capsule like the
|
|
1753
|
+
selected tab of iOS 26 takes --gl-tab-bar-active-bg and -shadow; on the
|
|
1754
|
+
floating bar --gl-tab-bar-spotlight-opacity: 0 turns the spotlight off,
|
|
1755
|
+
and --gl-tab-bar-active-glow: none the glow above, which reads as a blur
|
|
1756
|
+
on a light capsule. */
|
|
1757
|
+
.glass-tab-bar__item.is-active {
|
|
1758
|
+
background: var(--gl-tab-bar-active-bg, none);
|
|
1759
|
+
box-shadow: var(--gl-tab-bar-active-shadow, none);
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1724
1762
|
.glass-tab-bar__item.is-active .glass-tab-bar__icon::after {
|
|
1725
1763
|
content: '';
|
|
1726
1764
|
position: absolute; bottom: -6px; left: 50%; transform: translateX(-50%);
|
|
@@ -1730,8 +1768,8 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
1730
1768
|
box-shadow: 0 0 6px color-mix(in srgb, var(--gl-color-primary) 50%, transparent);
|
|
1731
1769
|
}
|
|
1732
1770
|
|
|
1733
|
-
.glass-tab-bar__item:not(.is-active):hover .glass-tab-bar__icon
|
|
1734
|
-
.glass-tab-bar__item:not(.is-active):hover .glass-tab-bar__label { color: var(--gl-icon-default); }
|
|
1771
|
+
.glass-tab-bar__item:not(.is-active):hover .glass-tab-bar__icon,
|
|
1772
|
+
.glass-tab-bar__item:not(.is-active):hover .glass-tab-bar__label { color: var(--gl-tab-bar-hover-color, var(--gl-icon-default)); }
|
|
1735
1773
|
|
|
1736
1774
|
.glass-tab-bar__badge {
|
|
1737
1775
|
position: absolute; top: -4px; inset-inline-end: -8px;
|
|
@@ -1755,7 +1793,7 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
1755
1793
|
transform: translateX(-50%);
|
|
1756
1794
|
display: flex; align-items: center;
|
|
1757
1795
|
gap: var(--gl-tab-bar-floating-gap);
|
|
1758
|
-
z-index: 900;
|
|
1796
|
+
z-index: var(--gl-tab-bar-z-index, 900);
|
|
1759
1797
|
max-width: calc(100vw - 2 * var(--gl-space-md));
|
|
1760
1798
|
}
|
|
1761
1799
|
|
|
@@ -1800,6 +1838,7 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
1800
1838
|
color-mix(in srgb, var(--gl-tab-bar-spotlight-color) 10%, transparent) 55%,
|
|
1801
1839
|
transparent 100%
|
|
1802
1840
|
);
|
|
1841
|
+
opacity: var(--gl-tab-bar-spotlight-opacity, 1);
|
|
1803
1842
|
pointer-events: none; z-index: 0;
|
|
1804
1843
|
}
|
|
1805
1844
|
|
|
@@ -1826,22 +1865,26 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
1826
1865
|
outline: none; padding: 0;
|
|
1827
1866
|
-webkit-tap-highlight-color: transparent;
|
|
1828
1867
|
flex-shrink: 0;
|
|
1868
|
+
/* The icon colour sits on the button, the SVG strokes in currentColor
|
|
1869
|
+
(since 1.28.0), so a font icon follows hover and the colour variants. */
|
|
1870
|
+
color: var(--gl-icon-default);
|
|
1829
1871
|
}
|
|
1830
1872
|
|
|
1831
1873
|
.glass-tab-bar__accessory svg,
|
|
1832
1874
|
.glass-tab-bar__accessory ::slotted(svg) {
|
|
1833
1875
|
width: 22px; height: 22px; fill: none;
|
|
1834
|
-
stroke:
|
|
1876
|
+
stroke: currentColor; stroke-width: 1.8;
|
|
1835
1877
|
stroke-linecap: round; stroke-linejoin: round;
|
|
1836
1878
|
transition: var(--gl-transition);
|
|
1837
1879
|
}
|
|
1838
1880
|
|
|
1839
|
-
/* :where() keeps the hover
|
|
1840
|
-
disabled accessory out of
|
|
1881
|
+
/* :where() keeps the hover rule at its specificity while leaving a
|
|
1882
|
+
disabled accessory out of it — a reset could not restore the icon
|
|
1841
1883
|
colour, which each tone variant sets on its own. */
|
|
1842
|
-
.glass-tab-bar__accessory:where(:not(:disabled, [aria-disabled="true"])):hover {
|
|
1843
|
-
|
|
1844
|
-
|
|
1884
|
+
.glass-tab-bar__accessory:where(:not(:disabled, [aria-disabled="true"])):hover {
|
|
1885
|
+
transform: translateY(-1px);
|
|
1886
|
+
color: var(--gl-icon-strong);
|
|
1887
|
+
}
|
|
1845
1888
|
.glass-tab-bar__accessory:disabled,
|
|
1846
1889
|
.glass-tab-bar__accessory[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; }
|
|
1847
1890
|
|
|
@@ -1852,7 +1895,10 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
1852
1895
|
var(--gl-inset-subtle);
|
|
1853
1896
|
}
|
|
1854
1897
|
|
|
1855
|
-
/* Accent variants – use existing color tokens
|
|
1898
|
+
/* Accent variants – use existing color tokens. Each keeps its ink on
|
|
1899
|
+
hover; until 1.28.0 only the accent one did, and the success and error
|
|
1900
|
+
capsules turned their icon --gl-icon-strong, dark grey in the light
|
|
1901
|
+
theme. */
|
|
1856
1902
|
.glass-tab-bar__accessory--accent {
|
|
1857
1903
|
background: linear-gradient(135deg,
|
|
1858
1904
|
var(--gl-color-primary) 0%,
|
|
@@ -1863,10 +1909,8 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
1863
1909
|
0 8px 32px color-mix(in srgb, var(--gl-color-primary) 35%, transparent),
|
|
1864
1910
|
var(--gl-inset-medium);
|
|
1865
1911
|
}
|
|
1866
|
-
.glass-tab-bar__accessory--accent
|
|
1867
|
-
.glass-tab-bar__accessory--accent
|
|
1868
|
-
.glass-tab-bar__accessory--accent:hover svg,
|
|
1869
|
-
.glass-tab-bar__accessory--accent:hover ::slotted(svg) { stroke: var(--gl-color-on-primary, #ffffff); }
|
|
1912
|
+
.glass-tab-bar__accessory--accent,
|
|
1913
|
+
.glass-tab-bar__accessory--accent:hover { color: var(--gl-color-on-primary, #ffffff); }
|
|
1870
1914
|
|
|
1871
1915
|
.glass-tab-bar__accessory--success {
|
|
1872
1916
|
background: linear-gradient(135deg,
|
|
@@ -1878,8 +1922,8 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
1878
1922
|
0 8px 32px color-mix(in srgb, var(--gl-color-success) 35%, transparent),
|
|
1879
1923
|
var(--gl-inset-medium);
|
|
1880
1924
|
}
|
|
1881
|
-
.glass-tab-bar__accessory--success
|
|
1882
|
-
.glass-tab-bar__accessory--success
|
|
1925
|
+
.glass-tab-bar__accessory--success,
|
|
1926
|
+
.glass-tab-bar__accessory--success:hover { color: var(--gl-color-on-success, #ffffff); }
|
|
1883
1927
|
|
|
1884
1928
|
.glass-tab-bar__accessory--error {
|
|
1885
1929
|
background: linear-gradient(135deg,
|
|
@@ -1891,8 +1935,159 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
1891
1935
|
0 8px 32px color-mix(in srgb, var(--gl-color-error) 35%, transparent),
|
|
1892
1936
|
var(--gl-inset-medium);
|
|
1893
1937
|
}
|
|
1894
|
-
.glass-tab-bar__accessory--error
|
|
1895
|
-
.glass-tab-bar__accessory--error
|
|
1938
|
+
.glass-tab-bar__accessory--error,
|
|
1939
|
+
.glass-tab-bar__accessory--error:hover { color: var(--gl-color-on-error, #ffffff); }
|
|
1940
|
+
|
|
1941
|
+
|
|
1942
|
+
/* ============================================================
|
|
1943
|
+
18c. DROPLET – TAB BAR AND SEGMENTED
|
|
1944
|
+
============================================================ */
|
|
1945
|
+
/* --droplet on .glass-tab-bar or .glass-segmented sets the chosen item on
|
|
1946
|
+
a drop of glass that floats a little above the row. On a change it runs
|
|
1947
|
+
to the new item like water on a pane: the leading edge goes first, the
|
|
1948
|
+
trailing one follows and overshoots, the drop runs flatter on the way
|
|
1949
|
+
and settles with a small wobble. A finger can drag it along the row; the
|
|
1950
|
+
item below it lights up as under a lens. In a segmented row that
|
|
1951
|
+
scrolls (--scroll) a swipe still scrolls: there only the drop itself is
|
|
1952
|
+
dragged, and the row follows it at its edges.
|
|
1953
|
+
|
|
1954
|
+
The drop is the row's ::before, and a script places it: it sets
|
|
1955
|
+
data-droplet on the row and --gl-droplet-left, -right, -top and -bottom
|
|
1956
|
+
to the chosen item's box, measured in the row's padding box (in a row
|
|
1957
|
+
that scrolls, in its scrolled content). On a change it sets
|
|
1958
|
+
data-droplet-dir="left" or "right" and data-droplet-lift while the drop
|
|
1959
|
+
travels, data-droplet-drag while a finger holds it, and .is-under-droplet
|
|
1960
|
+
on the item below it. Without the script a row keeps its usual look:
|
|
1961
|
+
the tab bar its spotlight, the segmented row its raised option. GlassKit
|
|
1962
|
+
Elements' <glk-tab-bar droplet> and <glk-segmented droplet> do all of
|
|
1963
|
+
this; for plain markup the docs have the script. */
|
|
1964
|
+
.glass-tab-bar--floating.glass-tab-bar--droplet,
|
|
1965
|
+
.glass-segmented.glass-segmented--droplet { position: relative; }
|
|
1966
|
+
.glass-tab-bar.glass-tab-bar--droplet[data-droplet],
|
|
1967
|
+
.glass-segmented.glass-segmented--droplet[data-droplet] { isolation: isolate; touch-action: pan-y; }
|
|
1968
|
+
/* A row that scrolls keeps its swipe; the chosen option takes the drag. */
|
|
1969
|
+
.glass-segmented--scroll.glass-segmented--droplet[data-droplet] { touch-action: auto; }
|
|
1970
|
+
.glass-segmented--scroll.glass-segmented--droplet[data-droplet] .glass-segmented__item[aria-pressed="true"] { touch-action: pan-y; }
|
|
1971
|
+
|
|
1972
|
+
:is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet]::before {
|
|
1973
|
+
content: '';
|
|
1974
|
+
position: absolute; z-index: -1;
|
|
1975
|
+
top: var(--gl-droplet-top, 0px);
|
|
1976
|
+
bottom: var(--gl-droplet-bottom, 0px);
|
|
1977
|
+
left: var(--gl-droplet-left, 0px);
|
|
1978
|
+
right: var(--gl-droplet-right, 0px);
|
|
1979
|
+
border-radius: var(--gl-radius-sm);
|
|
1980
|
+
background:
|
|
1981
|
+
var(--gl-gloss-droplet, none),
|
|
1982
|
+
linear-gradient(to bottom, var(--gl-surface-5) 0%, var(--gl-surface-3) 100%);
|
|
1983
|
+
box-shadow:
|
|
1984
|
+
0 4px 14px rgba(0,0,0,0.18), 0 1px 3px rgba(0,0,0,0.12),
|
|
1985
|
+
inset 0 0 0 1px var(--gl-border-subtle),
|
|
1986
|
+
var(--gl-inset-strong);
|
|
1987
|
+
backdrop-filter: blur(var(--gl-blur-light)) saturate(1.6);
|
|
1988
|
+
-webkit-backdrop-filter: blur(var(--gl-blur-light)) saturate(1.6);
|
|
1989
|
+
pointer-events: none;
|
|
1990
|
+
transition:
|
|
1991
|
+
transform 0.55s cubic-bezier(0.34, 1.8, 0.5, 1),
|
|
1992
|
+
box-shadow 0.3s ease;
|
|
1993
|
+
}
|
|
1994
|
+
/* The tab bar's drop is a capsule, in the active item's surface where a
|
|
1995
|
+
project set one (--gl-tab-bar-active-bg, -shadow). */
|
|
1996
|
+
.glass-tab-bar.glass-tab-bar--droplet[data-droplet]::before {
|
|
1997
|
+
border-radius: var(--gl-radius-full);
|
|
1998
|
+
background:
|
|
1999
|
+
var(--gl-gloss-droplet, none),
|
|
2000
|
+
var(--gl-tab-bar-active-bg, linear-gradient(to bottom, var(--gl-surface-5) 0%, var(--gl-surface-3) 100%));
|
|
2001
|
+
box-shadow:
|
|
2002
|
+
var(--gl-tab-bar-active-shadow, 0 4px 14px rgba(0,0,0,0.18), 0 1px 3px rgba(0,0,0,0.12)),
|
|
2003
|
+
inset 0 0 0 1px var(--gl-border-subtle),
|
|
2004
|
+
var(--gl-inset-strong);
|
|
2005
|
+
}
|
|
2006
|
+
/* The segmented drop likewise, in the chosen option's surface where a
|
|
2007
|
+
project set one (--gl-segmented-active-bg, -shadow; since 1.28.0). */
|
|
2008
|
+
.glass-segmented.glass-segmented--droplet[data-droplet]::before {
|
|
2009
|
+
background:
|
|
2010
|
+
var(--gl-gloss-droplet, none),
|
|
2011
|
+
var(--gl-segmented-active-bg, linear-gradient(to bottom, var(--gl-surface-5) 0%, var(--gl-surface-3) 100%));
|
|
2012
|
+
box-shadow:
|
|
2013
|
+
var(--gl-segmented-active-shadow, 0 4px 14px rgba(0,0,0,0.18), 0 1px 3px rgba(0,0,0,0.12)),
|
|
2014
|
+
inset 0 0 0 1px var(--gl-border-subtle),
|
|
2015
|
+
var(--gl-inset-strong);
|
|
2016
|
+
}
|
|
2017
|
+
/* On the way: the leading edge runs ahead, the trailing one is pulled
|
|
2018
|
+
after it and overshoots, so the drop stretches and draws together. */
|
|
2019
|
+
:is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-dir="right"]::before {
|
|
2020
|
+
transition:
|
|
2021
|
+
right 0.3s cubic-bezier(0.3, 1.2, 0.5, 1),
|
|
2022
|
+
left 0.5s cubic-bezier(0.5, 1.5, 0.45, 0.92) 0.04s,
|
|
2023
|
+
top 0.3s ease, bottom 0.3s ease,
|
|
2024
|
+
transform 0.55s cubic-bezier(0.34, 1.8, 0.5, 1),
|
|
2025
|
+
box-shadow 0.3s ease;
|
|
2026
|
+
}
|
|
2027
|
+
:is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-dir="left"]::before {
|
|
2028
|
+
transition:
|
|
2029
|
+
left 0.3s cubic-bezier(0.3, 1.2, 0.5, 1),
|
|
2030
|
+
right 0.5s cubic-bezier(0.5, 1.5, 0.45, 0.92) 0.04s,
|
|
2031
|
+
top 0.3s ease, bottom 0.3s ease,
|
|
2032
|
+
transform 0.55s cubic-bezier(0.34, 1.8, 0.5, 1),
|
|
2033
|
+
box-shadow 0.3s ease;
|
|
2034
|
+
}
|
|
2035
|
+
/* While it travels the drop runs flatter and lifts off the row; it comes
|
|
2036
|
+
back with the overshoot of its transform, the wobble at the end. Held
|
|
2037
|
+
by a finger it grows instead, a lens over the row, and follows the
|
|
2038
|
+
finger closely. */
|
|
2039
|
+
:is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-lift]::before,
|
|
2040
|
+
:is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-drag]::before {
|
|
2041
|
+
box-shadow:
|
|
2042
|
+
0 10px 24px rgba(0,0,0,0.24), 0 2px 6px rgba(0,0,0,0.14),
|
|
2043
|
+
inset 0 0 0 1px var(--gl-border-medium),
|
|
2044
|
+
var(--gl-inset-strong);
|
|
2045
|
+
}
|
|
2046
|
+
:is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-lift]::before {
|
|
2047
|
+
transform: scale(1, 0.86);
|
|
2048
|
+
}
|
|
2049
|
+
:is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-drag]::before {
|
|
2050
|
+
transform: scale(1.1, 1.22);
|
|
2051
|
+
transition:
|
|
2052
|
+
left 0.1s ease-out, right 0.1s ease-out,
|
|
2053
|
+
transform 0.25s ease-out, box-shadow 0.25s ease;
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2056
|
+
/* The drop is the chosen item's surface, so the item draws none; on the
|
|
2057
|
+
tab bar neither spotlight, dot nor glow. */
|
|
2058
|
+
.glass-tab-bar--droplet[data-droplet] .glass-tab-bar__item.is-active { background: none; box-shadow: none; }
|
|
2059
|
+
.glass-tab-bar--droplet[data-droplet] .glass-tab-bar__item.is-active::before { display: none; }
|
|
2060
|
+
.glass-tab-bar--droplet[data-droplet] .glass-tab-bar__item.is-active .glass-tab-bar__icon::after { display: none; }
|
|
2061
|
+
.glass-tab-bar--droplet[data-droplet] .glass-tab-bar__item.is-active .glass-tab-bar__icon > :where(:not(.glass-tab-bar__badge)),
|
|
2062
|
+
.glass-tab-bar--droplet[data-droplet] .glass-tab-bar__item.is-active .glass-tab-bar__icon ::slotted(*) { filter: var(--gl-tab-bar-active-glow, none); }
|
|
2063
|
+
.glass-segmented--droplet[data-droplet] .glass-segmented__item[aria-pressed="true"] { background: transparent; box-shadow: none; }
|
|
2064
|
+
.glass-segmented--droplet[data-droplet] .glass-segmented__item[aria-pressed="true"]:focus-visible { box-shadow: var(--gl-shadow-focus); }
|
|
2065
|
+
/* A disabled choice dims its drop as it dims itself. */
|
|
2066
|
+
:is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet]:has(:is(.glass-tab-bar__item.is-active, .glass-segmented__item[aria-pressed="true"]):disabled)::before { opacity: 0.45; }
|
|
2067
|
+
|
|
2068
|
+
/* Under the drop a tab icon, a segmented icon or a tone dot grows as under
|
|
2069
|
+
a lens. While a finger drags the drop, the item below it takes the
|
|
2070
|
+
chosen colour and the chosen item lets it go. The tab icon keeps the
|
|
2071
|
+
fade of its colour next to the lens. */
|
|
2072
|
+
.glass-tab-bar--droplet[data-droplet] .glass-tab-bar__icon { transition: var(--gl-transition), transform 0.4s cubic-bezier(0.34, 1.6, 0.5, 1); }
|
|
2073
|
+
.glass-segmented--droplet[data-droplet] .glass-segmented__dot,
|
|
2074
|
+
.glass-segmented--droplet[data-droplet] .glass-segmented__icon { transition: transform 0.4s cubic-bezier(0.34, 1.6, 0.5, 1); }
|
|
2075
|
+
.glass-tab-bar--droplet[data-droplet] .glass-tab-bar__item.is-under-droplet .glass-tab-bar__icon { transform: scale(1.15); }
|
|
2076
|
+
.glass-segmented--droplet[data-droplet] .glass-segmented__item.is-under-droplet .glass-segmented__dot { transform: scale(1.3); }
|
|
2077
|
+
.glass-segmented--droplet[data-droplet] .glass-segmented__item.is-under-droplet .glass-segmented__icon { transform: scale(1.15); }
|
|
2078
|
+
.glass-tab-bar--droplet[data-droplet] .glass-tab-bar__item.is-under-droplet :is(.glass-tab-bar__icon, .glass-tab-bar__label) { color: var(--gl-tab-bar-active-color, var(--gl-color-primary-text)); }
|
|
2079
|
+
.glass-segmented--droplet[data-droplet] .glass-segmented__item.is-under-droplet { color: var(--gl-segmented-active-color, var(--gl-color-text-heading)); }
|
|
2080
|
+
.glass-tab-bar--droplet[data-droplet-drag] .glass-tab-bar__item.is-active:not(.is-under-droplet) :is(.glass-tab-bar__icon, .glass-tab-bar__label) { color: var(--gl-tab-bar-color, var(--gl-icon-muted)); }
|
|
2081
|
+
.glass-segmented--droplet[data-droplet-drag] .glass-segmented__item[aria-pressed="true"]:not(.is-under-droplet) { color: var(--gl-color-text-muted); }
|
|
2082
|
+
|
|
2083
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2084
|
+
:is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet]::before,
|
|
2085
|
+
:is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-dir]::before,
|
|
2086
|
+
:is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-drag]::before { transition: none; }
|
|
2087
|
+
.glass-tab-bar--droplet[data-droplet] .glass-tab-bar__icon { transition: var(--gl-transition), transform 0s; }
|
|
2088
|
+
.glass-segmented--droplet[data-droplet] .glass-segmented__dot,
|
|
2089
|
+
.glass-segmented--droplet[data-droplet] .glass-segmented__icon { transition: none; }
|
|
2090
|
+
}
|
|
1896
2091
|
|
|
1897
2092
|
|
|
1898
2093
|
/* ============================================================
|
|
@@ -2603,13 +2798,18 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
2603
2798
|
outline: none; -webkit-tap-highlight-color: transparent;
|
|
2604
2799
|
}
|
|
2605
2800
|
.glass-segmented__item:hover { color: var(--gl-color-text); }
|
|
2801
|
+
/* The chosen option's surface, shadow and text colour can be set
|
|
2802
|
+
(since 1.28.0), like the tab bar's active item: on a dark brand the
|
|
2803
|
+
light surface left a white label below 4.5:1. Unset, they keep their
|
|
2804
|
+
values; the drop of --droplet takes the same surface (18c). The shadow
|
|
2805
|
+
sits in shadow lists: switch it off with a zero shadow, not none. */
|
|
2606
2806
|
.glass-segmented__item[aria-pressed="true"] {
|
|
2607
|
-
background: var(--gl-surface-5);
|
|
2608
|
-
color: var(--gl-color-text-heading);
|
|
2609
|
-
box-shadow: var(--gl-shadow-btn);
|
|
2807
|
+
background: var(--gl-segmented-active-bg, var(--gl-surface-5));
|
|
2808
|
+
color: var(--gl-segmented-active-color, var(--gl-color-text-heading));
|
|
2809
|
+
box-shadow: var(--gl-segmented-active-shadow, var(--gl-shadow-btn));
|
|
2610
2810
|
}
|
|
2611
2811
|
.glass-segmented__item:focus-visible { box-shadow: var(--gl-shadow-focus); }
|
|
2612
|
-
.glass-segmented__item[aria-pressed="true"]:focus-visible { box-shadow: var(--gl-shadow-focus), var(--gl-shadow-btn); }
|
|
2812
|
+
.glass-segmented__item[aria-pressed="true"]:focus-visible { box-shadow: var(--gl-shadow-focus), var(--gl-segmented-active-shadow, var(--gl-shadow-btn)); }
|
|
2613
2813
|
.glass-segmented__item:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
2614
2814
|
|
|
2615
2815
|
.glass-segmented__dot {
|
|
@@ -2620,6 +2820,27 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
2620
2820
|
.glass-segmented__item--warning { --gl-segmented-tone: var(--gl-color-warning); }
|
|
2621
2821
|
.glass-segmented__item--error { --gl-segmented-tone: var(--gl-color-error); }
|
|
2622
2822
|
|
|
2823
|
+
/* An icon before the label (since 1.28.0): an SVG strokes in the text
|
|
2824
|
+
colour; any other element — a font icon, an <img>, a mask — takes the
|
|
2825
|
+
colour, and a font icon the size, from the box. Under the drop it grows
|
|
2826
|
+
like the dot. Hidden by script while empty: the display below beats the
|
|
2827
|
+
hidden attribute's own rule. --icons makes a row of icons alone, square,
|
|
2828
|
+
each option's name in its aria-label (and title, for the pointer). */
|
|
2829
|
+
.glass-segmented__icon {
|
|
2830
|
+
flex: none;
|
|
2831
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
2832
|
+
width: 18px; height: 18px;
|
|
2833
|
+
font-size: 18px; line-height: 1;
|
|
2834
|
+
}
|
|
2835
|
+
.glass-segmented__icon[hidden] { display: none; }
|
|
2836
|
+
.glass-segmented__icon svg,
|
|
2837
|
+
.glass-segmented__icon ::slotted(svg) {
|
|
2838
|
+
width: 18px; height: 18px; fill: none;
|
|
2839
|
+
stroke: currentColor; stroke-width: 1.8;
|
|
2840
|
+
stroke-linecap: round; stroke-linejoin: round;
|
|
2841
|
+
}
|
|
2842
|
+
.glass-segmented--icons .glass-segmented__item { padding: 8px; }
|
|
2843
|
+
|
|
2623
2844
|
|
|
2624
2845
|
/* ============================================================
|
|
2625
2846
|
30. STEPS
|
|
@@ -2665,9 +2886,19 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
|
2665
2886
|
color: var(--gl-color-on-primary);
|
|
2666
2887
|
}
|
|
2667
2888
|
.glass-steps__line { flex: 1 1 8px; min-width: 8px; height: 1px; background: var(--gl-border-subtle); }
|
|
2889
|
+
/* Narrow, the current label comes first (since 1.28.0). The circles keep
|
|
2890
|
+
their size and the lines take only the room that is left, down to 2px
|
|
2891
|
+
at 4px from their neighbours: the gap belongs to the list, which is the
|
|
2892
|
+
container itself and out of its own query's reach, so the lines take a
|
|
2893
|
+
negative margin. Only then does the label shorten. Until 1.28.0 every
|
|
2894
|
+
part gave way at once — seven steps cut the current label in a 350px
|
|
2895
|
+
column and pushed the circles past its edge. */
|
|
2668
2896
|
@container (max-width: 360px) {
|
|
2669
2897
|
.glass-steps__label { display: none; }
|
|
2670
2898
|
.glass-steps__item--current .glass-steps__label { display: inline; }
|
|
2899
|
+
.glass-steps__item { flex-shrink: 0; }
|
|
2900
|
+
.glass-steps__item--current { flex-shrink: 1; }
|
|
2901
|
+
.glass-steps__line { flex-basis: 0; min-width: 2px; margin-inline: -2px; }
|
|
2671
2902
|
}
|
|
2672
2903
|
|
|
2673
2904
|
|