@jungherz-de/glasskit 1.19.0 → 1.20.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.19.0
3
+ Jungherz GmbH – v1.20.0
4
4
 
5
5
  Features:
6
6
  - Scoped Reset (box-sizing fix)
@@ -68,6 +68,8 @@
68
68
  --gl-color-text-muted: rgba(255, 255, 255, 0.60);
69
69
  --gl-color-text-on-light: #1a3a4a;
70
70
  --gl-color-text-heading: #ffffff;
71
+ /* The select's chevron, drawn in the muted text colour of each theme. */
72
+ --gl-select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='rgba(255,255,255,0.6)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
71
73
  --gl-color-success: #34c759;
72
74
  --gl-color-error: #ff3b30;
73
75
  --gl-color-warning: #ffcc00;
@@ -219,6 +221,8 @@
219
221
 
220
222
  /* ---- Tab-Bar ---- */
221
223
  --gl-tab-bar-height: 82px;
224
+ /* Widest a .glass-modal grows; dialogs with a form or a table can take more. */
225
+ --gl-modal-max-width: 340px;
222
226
 
223
227
  /* ---- Tab-Bar Floating ---- */
224
228
  --gl-tab-bar-floating-bottom: 16px;
@@ -261,6 +265,7 @@
261
265
  --gl-color-text-muted: rgba(26, 42, 54, 0.55);
262
266
  --gl-color-text-on-light: #1a3a4a;
263
267
  --gl-color-text-heading: #0f1f2a;
268
+ --gl-select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='rgba(26,42,54,0.55)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
264
269
  --gl-color-success: #28a745;
265
270
  --gl-color-error: #dc3545;
266
271
  --gl-color-warning: #e6a800;
@@ -643,7 +648,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
643
648
  font-size: var(--gl-font-size-sm);
644
649
  font-weight: var(--gl-font-weight-medium);
645
650
  color: var(--gl-icon-strong);
646
- padding-left: var(--gl-space-2xs);
651
+ padding-inline-start: var(--gl-space-2xs);
647
652
  }
648
653
 
649
654
  .glass-input {
@@ -697,7 +702,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
697
702
  .glass-hint {
698
703
  font-size: var(--gl-font-size-xs);
699
704
  color: var(--gl-color-text-muted);
700
- padding-left: var(--gl-space-2xs);
705
+ padding-inline-start: var(--gl-space-2xs);
701
706
  }
702
707
  .glass-hint--error { color: var(--gl-color-error); }
703
708
 
@@ -745,10 +750,16 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
745
750
  box-shadow: var(--gl-inset-subtle);
746
751
  cursor: pointer;
747
752
  appearance: none; -webkit-appearance: none;
748
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='rgba(255,255,255,0.6)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
753
+ background-image: var(--gl-select-chevron, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='rgba(255,255,255,0.6)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"));
749
754
  background-repeat: no-repeat;
750
755
  background-position: right 16px center;
751
756
  }
757
+ /* Right to left: the chevron and the room kept for it move to the left —
758
+ together, under :dir(), so a browser without it keeps both on the right. */
759
+ .glass-select:dir(rtl) {
760
+ padding: 0 var(--gl-space-md) 0 var(--gl-space-3xl);
761
+ background-position: left 16px center;
762
+ }
752
763
  .glass-select:focus {
753
764
  border-color: var(--gl-border-focus);
754
765
  box-shadow: var(--gl-shadow-focus), var(--gl-inset-medium);
@@ -764,7 +775,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
764
775
  }
765
776
 
766
777
  .glass-search__icon {
767
- position: absolute; left: var(--gl-space-md);
778
+ position: absolute; inset-inline-start: var(--gl-space-md);
768
779
  width: 18px; height: 18px;
769
780
  stroke: var(--gl-icon-muted) !important;
770
781
  stroke-width: 2 !important;
@@ -776,7 +787,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
776
787
  }
777
788
 
778
789
  .glass-search .glass-input {
779
- padding-left: 44px;
790
+ padding-inline-start: 44px;
780
791
  border-radius: var(--gl-radius-full);
781
792
  }
782
793
 
@@ -791,12 +802,18 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
791
802
  -webkit-tap-highlight-color: transparent;
792
803
  }
793
804
 
794
- /* Visually hidden but keeps the control's area: zero-size inputs make the
795
- browser suppress the native validation bubble on required fields
796
- (silent submit block). pointer-events: none — the label handles clicks. */
805
+ /* Visually hidden, but it keeps the control's area and lies on top of it.
806
+ Zero-size inputs make the browser suppress the native validation bubble
807
+ on required fields (silent submit block). On top, a pointer — or a test
808
+ tool that clicks the switch by its role — reaches the input itself; the
809
+ track drew over it before and took the click. It covers the track only:
810
+ the label text, which may hold a link, stays the label's. margin-top is
811
+ the track's first-line offset, from the label's font; a browser without
812
+ the lh unit drops it and keeps margin: 0, as the track does. */
797
813
  .glass-toggle__input {
798
- position: absolute; opacity: 0; margin: 0;
799
- width: 52px; height: 30px; pointer-events: none;
814
+ position: absolute; z-index: 1; opacity: 0; cursor: inherit;
815
+ width: 52px; height: 30px; margin: 0; font: inherit;
816
+ margin-top: max(0px, calc((1lh - 30px) / 2));
800
817
  }
801
818
 
802
819
  .glass-toggle__track {
@@ -831,6 +848,12 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
831
848
  .glass-toggle__input:checked + .glass-toggle__track .glass-toggle__thumb {
832
849
  transform: translateX(22px);
833
850
  }
851
+ /* Right to left the thumb starts on the right and travels left — both
852
+ under :dir(), so a browser without it keeps the left-to-right switch. */
853
+ .glass-toggle__thumb:dir(rtl) { left: auto; right: 3px; }
854
+ .glass-toggle__input:checked + .glass-toggle__track .glass-toggle__thumb:dir(rtl) {
855
+ transform: translateX(-22px);
856
+ }
834
857
 
835
858
  .glass-toggle__input:focus-visible + .glass-toggle__track { box-shadow: var(--gl-shadow-focus); }
836
859
 
@@ -840,6 +863,10 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
840
863
  user-select: none;
841
864
  margin-top: max(0px, calc((30px - 1lh) / 2));
842
865
  }
866
+ /* A control without a label keeps no gap for one. */
867
+ .glass-toggle__label:empty,
868
+ .glass-checkbox__label:empty,
869
+ .glass-radio__label:empty { display: none; }
843
870
 
844
871
 
845
872
  /* ============================================================
@@ -857,10 +884,11 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
857
884
  gap: var(--gl-space-sm); cursor: pointer;
858
885
  -webkit-tap-highlight-color: transparent;
859
886
  }
860
- /* See .glass-toggle__input: keep area so native validation bubbles anchor */
887
+ /* On top of the box, covering it only — see .glass-toggle__input. */
861
888
  .glass-checkbox__input {
862
- position: absolute; opacity: 0; margin: 0;
863
- width: 24px; height: 24px; pointer-events: none;
889
+ position: absolute; z-index: 1; opacity: 0; cursor: inherit;
890
+ width: 24px; height: 24px; margin: 0; font: inherit;
891
+ margin-top: max(0px, calc((1lh - 24px) / 2));
864
892
  }
865
893
 
866
894
  .glass-checkbox__box {
@@ -910,10 +938,11 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
910
938
  gap: var(--gl-space-sm); cursor: pointer;
911
939
  -webkit-tap-highlight-color: transparent;
912
940
  }
913
- /* See .glass-toggle__input: keep area so native validation bubbles anchor */
941
+ /* On top of the circle, covering it only — see .glass-toggle__input. */
914
942
  .glass-radio__input {
915
- position: absolute; opacity: 0; margin: 0;
916
- width: 24px; height: 24px; pointer-events: none;
943
+ position: absolute; z-index: 1; opacity: 0; cursor: inherit;
944
+ width: 24px; height: 24px; margin: 0; font: inherit;
945
+ margin-top: max(0px, calc((1lh - 24px) / 2));
917
946
  }
918
947
 
919
948
  .glass-radio__circle {
@@ -1071,6 +1100,9 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
1071
1100
  );
1072
1101
  box-shadow: 0 0 8px color-mix(in srgb, var(--gl-color-error) 30%, transparent), var(--gl-inset-strong);
1073
1102
  }
1103
+ /* The fill grows from the inline start; right to left its gradient turns
1104
+ round so the darker end still leads. */
1105
+ .glass-progress__fill:dir(rtl) { scale: -1 1; }
1074
1106
 
1075
1107
 
1076
1108
  /* ============================================================
@@ -1089,9 +1121,20 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
1089
1121
  -webkit-font-smoothing: antialiased;
1090
1122
  }
1091
1123
  .glass-modal-overlay.is-active { opacity: 1; pointer-events: auto; }
1124
+ /* The overlay may be a native <dialog>: opened with showModal() it lies in
1125
+ the top layer, the page behind it is inert, focus moves in and Escape
1126
+ closes it. These rules undo the dialog's own box and backdrop; the
1127
+ overlay above paints the dimmed, blurred layer. GlassKit Elements'
1128
+ <glk-modal> uses exactly this. */
1129
+ dialog.glass-modal-overlay {
1130
+ width: auto; height: auto; max-width: none; max-height: none;
1131
+ margin: 0; border: 0; color: inherit;
1132
+ }
1133
+ dialog.glass-modal-overlay:not([open]) { display: none; }
1134
+ dialog.glass-modal-overlay::backdrop { background: transparent; }
1092
1135
 
1093
1136
  .glass-modal {
1094
- width: 100%; max-width: 340px;
1137
+ width: 100%; max-width: var(--gl-modal-max-width, 340px);
1095
1138
  background: linear-gradient(to bottom,
1096
1139
  var(--gl-card-glow-top) 0%, var(--gl-card-glow-bottom) 100%
1097
1140
  );
@@ -1132,7 +1175,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
1132
1175
  cursor: pointer; transition: var(--gl-transition-fast); outline: none;
1133
1176
  }
1134
1177
  .glass-modal__action:hover { background: var(--gl-surface-1); }
1135
- .glass-modal__action + .glass-modal__action { border-left: 1px solid var(--gl-border-subtle); }
1178
+ .glass-modal__action + .glass-modal__action { border-inline-start: 1px solid var(--gl-border-subtle); }
1136
1179
  .glass-modal__action--primary { color: var(--gl-color-primary); font-weight: var(--gl-font-weight-semibold); }
1137
1180
  .glass-modal__action--danger { color: var(--gl-color-error); font-weight: var(--gl-font-weight-semibold); }
1138
1181
 
@@ -1243,7 +1286,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
1243
1286
  }
1244
1287
  .glass-toast__action:active { transform: scale(0.96); }
1245
1288
  .glass-toast__close {
1246
- width: 28px; height: 28px; margin: 0 -8px 0 -4px; padding: 0;
1289
+ width: 28px; height: 28px; margin-block: 0; margin-inline: -4px -8px; padding: 0;
1247
1290
  display: inline-flex; align-items: center; justify-content: center;
1248
1291
  border: 0; border-radius: 50%;
1249
1292
  background: transparent;
@@ -1327,7 +1370,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
1327
1370
  .glass-tab-bar__item:not(.is-active):hover .glass-tab-bar__label { color: var(--gl-icon-default); }
1328
1371
 
1329
1372
  .glass-tab-bar__badge {
1330
- position: absolute; top: -4px; right: -8px;
1373
+ position: absolute; top: -4px; inset-inline-end: -8px;
1331
1374
  min-width: 16px; height: 16px; padding: 0 4px;
1332
1375
  border-radius: var(--gl-radius-full);
1333
1376
  /* 10px text needs 4.5:1 – white on the plain error red only reaches 3.55:1
@@ -1513,7 +1556,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
1513
1556
  font-family: var(--gl-font-family);
1514
1557
  font-size: var(--gl-font-size-base);
1515
1558
  font-weight: var(--gl-font-weight-semibold);
1516
- color: var(--gl-color-text); text-align: left;
1559
+ color: var(--gl-color-text); text-align: start;
1517
1560
  outline: none; transition: var(--gl-transition);
1518
1561
  -webkit-tap-highlight-color: transparent;
1519
1562
  }
@@ -1782,18 +1825,19 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
1782
1825
  transform-origin: bottom center;
1783
1826
  }
1784
1827
  .glass-popover--start {
1785
- left: 0;
1828
+ inset-inline-start: 0; inset-inline-end: auto;
1786
1829
  transform: translateY(-4px) scale(0.96);
1787
1830
  transform-origin: top left;
1788
1831
  }
1832
+ .glass-popover--start:dir(rtl) { transform-origin: top right; }
1789
1833
  .glass-popover--start.is-open { transform: translateY(0) scale(1); }
1790
1834
 
1791
1835
  .glass-popover--end {
1792
- left: auto;
1793
- right: 0;
1836
+ inset-inline-start: auto; inset-inline-end: 0;
1794
1837
  transform: translateY(-4px) scale(0.96);
1795
1838
  transform-origin: top right;
1796
1839
  }
1840
+ .glass-popover--end:dir(rtl) { transform-origin: top left; }
1797
1841
  .glass-popover--end.is-open { transform: translateY(0) scale(1); }
1798
1842
 
1799
1843
 
@@ -1858,7 +1902,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
1858
1902
  background: transparent;
1859
1903
  border: none;
1860
1904
  width: 100%;
1861
- text-align: left;
1905
+ text-align: start;
1862
1906
  font-family: inherit;
1863
1907
  list-style: none;
1864
1908
  }
@@ -1866,20 +1910,20 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
1866
1910
  .glass-list__item:not(:last-child)::after {
1867
1911
  content: '';
1868
1912
  position: absolute;
1869
- left: calc(var(--gl-space-lg) + 28px + var(--gl-space-sm));
1870
- right: var(--gl-space-lg);
1913
+ inset-inline-start: calc(var(--gl-space-lg) + 28px + var(--gl-space-sm));
1914
+ inset-inline-end: var(--gl-space-lg);
1871
1915
  bottom: 0;
1872
1916
  height: 1px;
1873
1917
  background: var(--gl-border-subtle);
1874
1918
  pointer-events: none;
1875
1919
  }
1876
- /* Items without a leading icon: divider follows the standard horizontal
1877
- padding instead of the (non-existent) icon slot. */
1878
- .glass-list__item:not(:has(.glass-list__leading)):not(:last-child)::after {
1879
- left: var(--gl-space-lg);
1920
+ /* Items without a leading icon — no slot, or a hidden one: divider follows
1921
+ the standard horizontal padding instead of the icon slot. */
1922
+ .glass-list__item:not(:has(.glass-list__leading:not([hidden]))):not(:last-child)::after {
1923
+ inset-inline-start: var(--gl-space-lg);
1880
1924
  }
1881
- .glass-list__item:has(.glass-list__leading--lg):not(:last-child)::after {
1882
- left: calc(var(--gl-space-lg) + 40px + var(--gl-space-sm));
1925
+ .glass-list__item:has(.glass-list__leading--lg:not([hidden])):not(:last-child)::after {
1926
+ inset-inline-start: calc(var(--gl-space-lg) + 40px + var(--gl-space-sm));
1883
1927
  }
1884
1928
 
1885
1929
  .glass-list__item--center {
@@ -1925,6 +1969,10 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
1925
1969
  justify-content: center;
1926
1970
  color: var(--gl-icon-strong);
1927
1971
  }
1972
+ /* display: flex above beats the hidden attribute's own rule: an empty slot
1973
+ hidden by script kept its 28px and its gap. */
1974
+ .glass-list__leading[hidden],
1975
+ .glass-list__trailing[hidden] { display: none; }
1928
1976
  .glass-list__leading svg,
1929
1977
  .glass-list__leading ::slotted(svg) {
1930
1978
  width: 24px;
@@ -2049,7 +2097,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
2049
2097
  font-size: var(--gl-font-size-sm); color: var(--gl-color-text);
2050
2098
  }
2051
2099
  .glass-table th {
2052
- text-align: left; padding: 8px 10px; white-space: nowrap;
2100
+ text-align: start; padding: 8px 10px; white-space: nowrap;
2053
2101
  font-weight: var(--gl-font-weight-medium); color: var(--gl-color-text-muted);
2054
2102
  border-bottom: 1px solid var(--gl-border-medium);
2055
2103
  }
@@ -2059,7 +2107,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
2059
2107
  }
2060
2108
  .glass-table tbody tr:last-child td { border-bottom: 0; }
2061
2109
  .glass-table tbody tr:hover td { background: var(--gl-surface-1); }
2062
- .glass-table__num { text-align: right; font-variant-numeric: tabular-nums; }
2110
+ .glass-table__num { text-align: end; font-variant-numeric: tabular-nums; }
2063
2111
  .glass-table__muted { color: var(--gl-color-text-muted); }
2064
2112
 
2065
2113
 
@@ -2085,7 +2133,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
2085
2133
  .glass-prose h3 { font-size: var(--gl-font-size-lg); }
2086
2134
  .glass-prose p, .glass-prose ul, .glass-prose ol, .glass-prose pre,
2087
2135
  .glass-prose blockquote, .glass-prose table { margin: 0 0 0.9em; }
2088
- .glass-prose ul, .glass-prose ol { padding-left: 1.3em; }
2136
+ .glass-prose ul, .glass-prose ol { padding-inline-start: 1.3em; }
2089
2137
  .glass-prose strong { color: var(--gl-color-text-heading); }
2090
2138
  /* Links in running text are underlined: colour alone does not mark them. */
2091
2139
  .glass-prose a { color: var(--gl-color-primary); text-decoration: underline; text-underline-offset: 2px; }
@@ -2100,15 +2148,16 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
2100
2148
  .glass-prose pre code { background: none; padding: 0; }
2101
2149
  .glass-prose blockquote {
2102
2150
  padding: 8px 14px;
2103
- border-left: 3px solid var(--gl-color-primary);
2151
+ border-inline-start: 3px solid var(--gl-color-primary);
2104
2152
  background: var(--gl-surface-1);
2105
- border-radius: 0 var(--gl-radius-xs) var(--gl-radius-xs) 0;
2153
+ border-start-start-radius: 0; border-end-start-radius: 0;
2154
+ border-start-end-radius: var(--gl-radius-xs); border-end-end-radius: var(--gl-radius-xs);
2106
2155
  }
2107
2156
  .glass-prose img { max-width: 100%; height: auto; border-radius: var(--gl-radius-sm); }
2108
2157
  .glass-prose hr { height: 1px; border: 0; margin: 1.2em 0; background: var(--gl-border-subtle); }
2109
2158
  .glass-prose table { width: 100%; border-collapse: collapse; }
2110
2159
  .glass-prose th, .glass-prose td {
2111
- padding: 6px 8px; text-align: left;
2160
+ padding: 6px 8px; text-align: start;
2112
2161
  border-bottom: 1px solid var(--gl-border-subtle);
2113
2162
  }
2114
2163