@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/glasskit.css CHANGED
@@ -1,6 +1,6 @@
1
1
  /* ============================================================
2
2
  GLASSKIT COMPONENT LIBRARY
3
- Jungherz GmbH – v1.26.0
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, 8px);
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: var(--gl-icon-muted); stroke-width: 1.8;
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
- .glass-tab-bar__item.is-active .glass-tab-bar__icon svg {
1719
- stroke: var(--gl-tab-bar-active-color, var(--gl-color-primary-text));
1720
- filter: drop-shadow(0 0 6px color-mix(in srgb, var(--gl-color-primary) 35%, transparent));
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 svg { stroke: var(--gl-icon-default); }
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: var(--gl-icon-default); stroke-width: 1.8;
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 rules at their specificity while leaving a
1840
- disabled accessory out of them — a reset could not restore the icon
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 { transform: translateY(-1px); }
1843
- .glass-tab-bar__accessory:where(:not(:disabled, [aria-disabled="true"])):hover svg,
1844
- .glass-tab-bar__accessory:where(:not(:disabled, [aria-disabled="true"])):hover ::slotted(svg) { stroke: var(--gl-icon-strong); }
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 svg,
1867
- .glass-tab-bar__accessory--accent ::slotted(svg) { stroke: var(--gl-color-on-primary, #ffffff); }
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 svg,
1882
- .glass-tab-bar__accessory--success ::slotted(svg) { stroke: var(--gl-color-on-success, #ffffff); }
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 svg,
1895
- .glass-tab-bar__accessory--error ::slotted(svg) { stroke: var(--gl-color-on-error, #ffffff); }
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