@gjsify/adwaita-web 0.31.0 → 0.33.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.
Files changed (183) hide show
  1. package/dist/adwaita-web.css +835 -299
  2. package/dist/adwaita-web.css.map +1 -1
  3. package/lib/types/adw-about-dialog.spec.d.ts +1 -0
  4. package/lib/types/adw-action-rows.spec.d.ts +1 -0
  5. package/lib/types/adw-avatar.spec.d.ts +1 -0
  6. package/lib/types/adw-banner.spec.d.ts +1 -0
  7. package/lib/types/adw-button-content.spec.d.ts +1 -0
  8. package/lib/types/adw-carousel.spec.d.ts +1 -0
  9. package/lib/types/adw-checks.spec.d.ts +1 -0
  10. package/lib/types/adw-header-bar.spec.d.ts +1 -0
  11. package/lib/types/adw-icon.spec.d.ts +1 -0
  12. package/lib/types/adw-progress-bar.spec.d.ts +1 -0
  13. package/lib/types/adw-sidebar.spec.d.ts +1 -0
  14. package/lib/types/adw-switch.spec.d.ts +1 -0
  15. package/lib/types/adw-wrap-box.spec.d.ts +1 -0
  16. package/lib/types/bottom-sheet.spec.d.ts +1 -0
  17. package/lib/types/breakpoints.d.ts +22 -0
  18. package/lib/types/breakpoints.spec.d.ts +1 -0
  19. package/lib/types/chrome.spec.d.ts +1 -0
  20. package/lib/types/elements/adw-about-dialog.d.ts +47 -8
  21. package/lib/types/elements/adw-action-row.d.ts +35 -0
  22. package/lib/types/elements/adw-avatar.d.ts +11 -0
  23. package/lib/types/elements/adw-bottom-sheet.d.ts +33 -4
  24. package/lib/types/elements/adw-button-content.d.ts +12 -0
  25. package/lib/types/elements/adw-button-row.d.ts +10 -1
  26. package/lib/types/elements/adw-carousel.d.ts +111 -8
  27. package/lib/types/elements/adw-checks.d.ts +57 -0
  28. package/lib/types/elements/adw-clamp.d.ts +4 -1
  29. package/lib/types/elements/adw-combo-row.d.ts +10 -0
  30. package/lib/types/elements/adw-data-grid.d.ts +11 -31
  31. package/lib/types/elements/adw-drop-down.d.ts +17 -20
  32. package/lib/types/elements/adw-entry-row.d.ts +93 -3
  33. package/lib/types/elements/adw-expander-row.d.ts +7 -1
  34. package/lib/types/elements/adw-header-bar.d.ts +15 -0
  35. package/lib/types/elements/adw-icon.d.ts +25 -0
  36. package/lib/types/elements/adw-inline-view-switcher.d.ts +73 -11
  37. package/lib/types/elements/adw-menu-button.d.ts +6 -6
  38. package/lib/types/elements/adw-navigation-split-view.d.ts +48 -0
  39. package/lib/types/elements/adw-navigation-view.d.ts +63 -20
  40. package/lib/types/elements/adw-overlay-split-view.d.ts +94 -0
  41. package/lib/types/elements/adw-password-entry-row.d.ts +19 -10
  42. package/lib/types/elements/adw-popover.d.ts +58 -0
  43. package/lib/types/elements/adw-preferences-dialog.d.ts +57 -2
  44. package/lib/types/elements/adw-preferences-group.d.ts +31 -0
  45. package/lib/types/elements/adw-progress-bar.d.ts +38 -0
  46. package/lib/types/elements/adw-sidebar.d.ts +37 -5
  47. package/lib/types/elements/adw-spinner.d.ts +23 -0
  48. package/lib/types/elements/adw-split-button.d.ts +53 -7
  49. package/lib/types/elements/adw-switch-row.d.ts +11 -2
  50. package/lib/types/elements/adw-switch.d.ts +15 -0
  51. package/lib/types/elements/adw-tab-view.d.ts +129 -12
  52. package/lib/types/elements/adw-toolbar-view.d.ts +5 -0
  53. package/lib/types/elements/adw-view-stack.d.ts +39 -19
  54. package/lib/types/elements/adw-view-switcher-bar.d.ts +25 -7
  55. package/lib/types/elements/adw-view-switcher.d.ts +76 -13
  56. package/lib/types/elements/adw-window-title.d.ts +3 -1
  57. package/lib/types/elements/adw-wrap-box.d.ts +58 -3
  58. package/lib/types/elements/view-switcher-dom.d.ts +44 -0
  59. package/lib/types/entry-rows.spec.d.ts +1 -0
  60. package/lib/types/index.d.ts +7 -0
  61. package/lib/types/navigation-view.spec.d.ts +1 -0
  62. package/lib/types/preferences-search.d.ts +20 -0
  63. package/lib/types/preferences.spec.d.ts +1 -0
  64. package/lib/types/split-button.spec.d.ts +1 -0
  65. package/lib/types/split-views.spec.d.ts +1 -0
  66. package/lib/types/styles.generated.d.ts +1 -1
  67. package/lib/types/tab-view.spec.d.ts +1 -0
  68. package/lib/types/view-stack.spec.d.ts +1 -0
  69. package/lib/types/view-switcher.spec.d.ts +1 -0
  70. package/package.json +6 -6
  71. package/scss/_banner.scss +13 -0
  72. package/scss/_bottom_sheet.scss +5 -6
  73. package/scss/_button.scss +3 -26
  74. package/scss/_button_content.scss +28 -0
  75. package/scss/_checks.scss +228 -0
  76. package/scss/_clamp.scss +9 -3
  77. package/scss/_combo_row.scss +19 -0
  78. package/scss/_data_grid.scss +15 -7
  79. package/scss/_drop_down.scss +12 -55
  80. package/scss/_expander_row.scss +5 -50
  81. package/scss/_icon.scss +51 -0
  82. package/scss/_icons.generated.scss +6 -0
  83. package/scss/_inline_view_switcher.scss +34 -0
  84. package/scss/_labels.scss +135 -0
  85. package/scss/_menu_button.scss +10 -70
  86. package/scss/_navigation_split_view.scss +47 -8
  87. package/scss/_overlay_split_view.scss +117 -32
  88. package/scss/_popover.scss +186 -0
  89. package/scss/_preferences.scss +29 -0
  90. package/scss/_preferences_dialog.scss +17 -0
  91. package/scss/_progress_bar.scss +161 -0
  92. package/scss/_reset.scss +18 -7
  93. package/scss/_spinner.scss +37 -19
  94. package/scss/_split_button.scss +6 -50
  95. package/scss/_switch.scss +90 -0
  96. package/scss/_switch_row.scss +6 -52
  97. package/scss/_tab_view.scss +63 -0
  98. package/scss/_theme.scss +10 -0
  99. package/scss/_toolbar_view.scss +74 -0
  100. package/scss/_variables.scss +34 -0
  101. package/scss/_view_switcher.scss +40 -0
  102. package/scss/_view_switcher_bar.scss +37 -0
  103. package/scss/_wrap_box.scss +65 -6
  104. package/scss/adwaita-skin.scss +23 -0
  105. package/src/adw-about-dialog.spec.ts +350 -0
  106. package/src/adw-action-rows.spec.ts +342 -0
  107. package/src/adw-avatar.spec.ts +176 -0
  108. package/src/adw-banner.spec.ts +152 -0
  109. package/src/adw-button-content.spec.ts +207 -0
  110. package/src/adw-button-row.spec.ts +12 -6
  111. package/src/adw-carousel.spec.ts +389 -0
  112. package/src/adw-checks.spec.ts +368 -0
  113. package/src/adw-drop-down.spec.ts +123 -0
  114. package/src/adw-header-bar.spec.ts +83 -0
  115. package/src/adw-icon.spec.ts +167 -0
  116. package/src/adw-progress-bar.spec.ts +173 -0
  117. package/src/adw-row-state.spec.ts +49 -0
  118. package/src/adw-sidebar.spec.ts +332 -0
  119. package/src/adw-switch.spec.ts +242 -0
  120. package/src/adw-tab-view.spec.ts +12 -3
  121. package/src/adw-view-switcher-bar.spec.ts +61 -13
  122. package/src/adw-wrap-box.spec.ts +341 -0
  123. package/src/bottom-sheet.spec.ts +325 -0
  124. package/src/breakpoints.spec.ts +147 -0
  125. package/src/breakpoints.ts +67 -0
  126. package/src/chrome.spec.ts +400 -0
  127. package/src/elements/adw-about-dialog.ts +223 -163
  128. package/src/elements/adw-action-row.ts +131 -11
  129. package/src/elements/adw-avatar.ts +48 -54
  130. package/src/elements/adw-banner.ts +46 -10
  131. package/src/elements/adw-bottom-sheet.ts +145 -60
  132. package/src/elements/adw-button-content.ts +107 -33
  133. package/src/elements/adw-button-row.ts +61 -37
  134. package/src/elements/adw-button.ts +5 -7
  135. package/src/elements/adw-carousel.ts +467 -105
  136. package/src/elements/adw-checks.ts +299 -0
  137. package/src/elements/adw-clamp.ts +80 -10
  138. package/src/elements/adw-combo-row.ts +32 -7
  139. package/src/elements/adw-data-grid.ts +43 -91
  140. package/src/elements/adw-drop-down.ts +117 -128
  141. package/src/elements/adw-entry-row.ts +404 -36
  142. package/src/elements/adw-expander-row.ts +61 -29
  143. package/src/elements/adw-header-bar.ts +31 -6
  144. package/src/elements/adw-icon.ts +148 -0
  145. package/src/elements/adw-inline-view-switcher.ts +325 -131
  146. package/src/elements/adw-menu-button.ts +93 -70
  147. package/src/elements/adw-navigation-split-view.ts +220 -14
  148. package/src/elements/adw-navigation-view.ts +286 -148
  149. package/src/elements/adw-overlay-split-view.ts +536 -28
  150. package/src/elements/adw-password-entry-row.ts +111 -89
  151. package/src/elements/adw-popover.ts +283 -0
  152. package/src/elements/adw-preferences-dialog.ts +120 -21
  153. package/src/elements/adw-preferences-group.ts +128 -22
  154. package/src/elements/adw-progress-bar.ts +189 -0
  155. package/src/elements/adw-sidebar.ts +301 -142
  156. package/src/elements/adw-spin-row.ts +11 -5
  157. package/src/elements/adw-spinner.ts +168 -9
  158. package/src/elements/adw-split-button.ts +371 -92
  159. package/src/elements/adw-status-page.ts +9 -9
  160. package/src/elements/adw-switch-row.ts +100 -30
  161. package/src/elements/adw-switch.ts +129 -0
  162. package/src/elements/adw-tab-view.ts +700 -129
  163. package/src/elements/adw-toggle-group.ts +5 -7
  164. package/src/elements/adw-toolbar-view.ts +84 -21
  165. package/src/elements/adw-view-stack.ts +183 -85
  166. package/src/elements/adw-view-switcher-bar.ts +171 -81
  167. package/src/elements/adw-view-switcher.ts +328 -117
  168. package/src/elements/adw-window-title.ts +44 -11
  169. package/src/elements/adw-wrap-box.ts +329 -78
  170. package/src/elements/view-switcher-dom.ts +108 -0
  171. package/src/entry-rows.spec.ts +391 -0
  172. package/src/index.ts +23 -0
  173. package/src/navigation-view.spec.ts +435 -0
  174. package/src/preferences-search.ts +135 -0
  175. package/src/preferences.spec.ts +250 -0
  176. package/src/source-view/adw-source-view.ts +2 -5
  177. package/src/split-button.spec.ts +470 -0
  178. package/src/split-views.spec.ts +893 -0
  179. package/src/styles.generated.ts +1 -1
  180. package/src/tab-view.spec.ts +451 -0
  181. package/src/test.browser.mts +49 -0
  182. package/src/view-stack.spec.ts +272 -0
  183. package/src/view-switcher.spec.ts +665 -0
@@ -0,0 +1,186 @@
1
+ // _popover.scss — <adw-popover>, the one popover surface in this package.
2
+ //
3
+ // It replaces three hand-rolled copies (`.adw-menu-button-popover`,
4
+ // `.adw-drop-down-popover`, `.adw-split-button-menu`) that disagreed with
5
+ // libadwaita AND with each other: 12px / 12px / 9px radius against libadwaita's
6
+ // 15px, two correct three-layer shadows and one invented two-layer one. Nothing
7
+ // compared any of them to the vendored stylesheet, so all three shipped.
8
+ //
9
+ // GROUND TRUTH, AND THE SELECTOR THAT WINS THE CASCADE
10
+ //
11
+ // `popover > contents` is `padding: 8px; border-radius: $popover_radius` plus a
12
+ // three-layer shadow (_popovers.scss:13-21), with a `prefers-contrast: more`
13
+ // variant that swaps the innermost layer for a hairline border (:23-27).
14
+ // `$popover_radius` is `$menu_radius + 6` = 15px (_common.scss:10,13) — not
15
+ // `$card_radius` (12px) and not `$button_radius` (9px), the two tokens the
16
+ // copies reached for.
17
+ //
18
+ // The PADDING has a second, more specific rule: `popover.menu > contents`
19
+ // re-declares `padding: 0` and moves the inset onto the item box as
20
+ // `$menu_margin` (6px) at _menus.scss:58-66. Two element selectors plus a class
21
+ // beats one element selector plus a child, so a MENU popover renders a 6px inset
22
+ // and a plain one an 8px inset. The three copies all used 6px — they were right
23
+ // about the inset for the menus they drew, and wrong only about the radius.
24
+ //
25
+ // We reproduce the menu inset with ONE node instead of GTK's contents+box pair:
26
+ // `[menu]` puts the 6px directly on the surface. Same rendered geometry, and
27
+ // there is no separate box element to hang it on in the DOM.
28
+ //
29
+ // Reference: refs/libadwaita/src/stylesheet/widgets/_popovers.scss:7-28
30
+ // Reference: refs/libadwaita/src/stylesheet/widgets/_menus.scss:58-66, :134-156
31
+ // Reference: refs/libadwaita/src/stylesheet/_common.scss:10-13 ($menu_radius, $menu_margin, $popover_radius)
32
+ // Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
33
+ // Modifications: Adapted for the @gjsify/adwaita-web light-DOM custom elements.
34
+
35
+ // Distance between the anchor and the surface. GTK gets this gap from the
36
+ // popover's arrow, which this port does not draw (`has-arrow` is not modelled —
37
+ // GtkPopover's C is not vendored here). 6px is what the menu button and the
38
+ // drop-down already used; the split button's 4px was the odd one out.
39
+ $popover-gap: 6px;
40
+
41
+ adw-popover {
42
+ // $popover_radius = $menu_radius + 6 (_common.scss:10,13). Exposed as a token
43
+ // so consumers re-theme it the same way as the rest (ADR 0010), with the
44
+ // libadwaita value as the fallback.
45
+ --popover-radius: 15px;
46
+
47
+ position: absolute;
48
+ z-index: 10;
49
+ display: flex;
50
+ flex-direction: column;
51
+ box-sizing: border-box;
52
+ min-width: 120px; // popover.menu > contents (_menus.scss:2-4)
53
+ padding: 8px; // popover > contents (_popovers.scss:14)
54
+ border-radius: var(--popover-radius);
55
+ background-color: var(--popover-bg-color, var(--window-bg-color, #fff));
56
+ color: var(--popover-fg-color, var(--window-fg-color));
57
+
58
+ // The exact three layers of _popovers.scss:18-20. The COUNT is load-bearing:
59
+ // the split button shipped two.
60
+ box-shadow:
61
+ 0 0 0 1px rgba(0, 0, 0, 0.05),
62
+ 0 1px 5px 1px rgba(0, 0, 0, 0.09),
63
+ 0 2px 14px 3px rgba(0, 0, 0, 0.05);
64
+
65
+ // _popovers.scss:23-27 — the innermost layer becomes a real hairline so the
66
+ // surface has a visible edge when the shadow alone is not enough. Missing
67
+ // from all three copies.
68
+ @media (prefers-contrast: more) {
69
+ box-shadow:
70
+ 0 0 0 1px var(--separator-color),
71
+ 0 1px 5px 1px rgba(0, 0, 0, 0.09),
72
+ 0 2px 14px 3px rgba(0, 0, 0, 0.05);
73
+ }
74
+
75
+ // `popover.menu > contents { padding: 0 }` + `$menu_margin` on the item box
76
+ // (_menus.scss:58-66), flattened onto the single surface node.
77
+ &[menu] {
78
+ padding: 6px;
79
+ }
80
+
81
+ // --- Placement. Pure CSS, as it always was: nothing measures a rect and
82
+ // --- nothing flips on overflow, in either the element or the core.
83
+ &[data-position='bottom'] {
84
+ top: calc(100% + #{$popover-gap});
85
+ }
86
+
87
+ &[data-position='top'] {
88
+ bottom: calc(100% + #{$popover-gap});
89
+ }
90
+
91
+ &[data-position='start'] {
92
+ top: 0;
93
+ right: calc(100% + #{$popover-gap});
94
+ }
95
+
96
+ &[data-position='end'] {
97
+ top: 0;
98
+ left: calc(100% + #{$popover-gap});
99
+ }
100
+
101
+ // `align` picks the edge the surface lines up with, and only applies on the
102
+ // vertical axis — a start/end popover is already pinned horizontally.
103
+ &[data-position='bottom'],
104
+ &[data-position='top'] {
105
+ &[data-align='start'] {
106
+ left: 0;
107
+ }
108
+
109
+ &[data-align='end'] {
110
+ right: 0;
111
+ }
112
+ }
113
+ }
114
+
115
+ // A popover row — libadwaita's `modelbutton` (_menus.scss:134-156).
116
+ .adw-popover-item {
117
+ box-sizing: border-box;
118
+ display: flex;
119
+ align-items: center;
120
+ gap: var(--spacing-xs);
121
+ width: 100%;
122
+ min-height: 32px; // :135
123
+ min-width: 40px; // :136
124
+ margin: 0;
125
+ // `padding: 0 $menu_padding` (:137) — $menu_padding is 12px (_common.scss:12),
126
+ // and the vertical inset comes from min-height, not from padding. No 12px
127
+ // spacing token exists in this port, so the value is literal like the radius.
128
+ padding: 0 12px;
129
+ border: none;
130
+ border-radius: 9px; // $menu_radius (:138) — NOT calc(--button-radius - 2px), which two copies invented
131
+ background-color: transparent; // :139
132
+ color: inherit;
133
+ font-family: var(--font-family);
134
+ font-size: var(--font-size-base);
135
+ text-align: start;
136
+ cursor: pointer;
137
+ transition: background-color 0.1s ease;
138
+
139
+ // `&:hover, &:selected { background-color: $selected_color }` (:141-144).
140
+ // `:selected` is GTK's keyboard-highlight pseudo-class; in the DOM that state
141
+ // is focus, so `.selected` (the drop-down's chosen row) and `:focus` share it.
142
+ &:hover,
143
+ &:focus,
144
+ &.selected {
145
+ background-color: var(--button-hover-color);
146
+ }
147
+
148
+ &:active {
149
+ background-color: var(--button-active-color); // $selected_active_color (:146-148)
150
+ }
151
+
152
+ // :150-156 — a contrast-mode ring on the same three states.
153
+ @media (prefers-contrast: more) {
154
+ &:hover,
155
+ &:focus,
156
+ &.selected,
157
+ &:active {
158
+ box-shadow: inset 0 0 0 1px var(--separator-color);
159
+ }
160
+ }
161
+
162
+ &:focus-visible {
163
+ outline: 2px solid var(--accent-color);
164
+ outline-offset: -2px;
165
+ }
166
+
167
+ &[disabled] {
168
+ // `--disabled-opacity` is libadwaita's own variable (_colors.scss:320,
169
+ // 50%); this port does not define it yet, so the fallback carries the value.
170
+ opacity: var(--disabled-opacity, 0.5);
171
+ pointer-events: none;
172
+ }
173
+ }
174
+
175
+ // Optional heading atop a menu. libadwaita's `label.title` is `font-weight: bold`
176
+ // + `padding: 4px ($menu_padding + 20px)` (_menus.scss:180-183) — 32px of
177
+ // horizontal padding to centre the title over icon-indented rows, which
178
+ // libadwaita's own comment calls out as fragile. This port keeps the tighter
179
+ // inset `.adw-menu-button-title` already shipped rather than changing how the
180
+ // existing menus look; only the class name moved here. A DELIBERATE deviation,
181
+ // not a reading of :180-183.
182
+ .adw-popover-title {
183
+ padding: 4px var(--spacing-s) 6px;
184
+ font-weight: 700;
185
+ opacity: var(--dim-opacity);
186
+ }
@@ -8,6 +8,14 @@
8
8
  adw-preferences-group {
9
9
  display: block;
10
10
 
11
+ // An author `display` beats the UA `[hidden] { display: none }` regardless of
12
+ // specificity, so without this a group hidden through the DOM `hidden`
13
+ // property would keep rendering — the search treats it as invisible
14
+ // (`is_visible_group`), and the two must agree.
15
+ &[hidden] {
16
+ display: none;
17
+ }
18
+
11
19
  // The header is a flex row: a title/description label column on the left
12
20
  // (stretches to fill) and the optional header-suffix on the trailing edge.
13
21
  .adw-preferences-group-header {
@@ -15,6 +23,27 @@ adw-preferences-group {
15
23
  align-items: center;
16
24
  gap: var(--spacing-s);
17
25
  padding: var(--spacing-xs) 2px;
26
+
27
+ // An author `display` beats the UA `[hidden] { display: none }` no matter
28
+ // the specificity, so `headerEl.hidden = true` did NOTHING here: an empty
29
+ // group kept its header box and its padding.
30
+ &[hidden] {
31
+ display: none;
32
+ }
33
+
34
+ // libadwaita's own metrics, keyed off `is_single_line`:
35
+ // `> box.header:not(.single-line) { margin-bottom: 6px }` and
36
+ // `> box.single-line { min-height: 34px }`
37
+ // (refs/libadwaita/src/stylesheet/widgets/_preferences.scss:6-13). A
38
+ // title-only or suffix-only header is one line tall and needs the height
39
+ // floor instead of the gap below it.
40
+ &:not(.single-line) {
41
+ margin-bottom: 6px;
42
+ }
43
+
44
+ &.single-line {
45
+ min-height: 34px;
46
+ }
18
47
  }
19
48
 
20
49
  .adw-preferences-group-labels {
@@ -150,5 +150,22 @@ adw-preferences-dialog {
150
150
  max-width: 600px;
151
151
  margin: 0 auto;
152
152
  padding: var(--spacing-xl) var(--spacing-m);
153
+
154
+ // The dialog keeps the <adw-preferences-page> ELEMENTS rather than hoisting
155
+ // their children out — the page's title / name / icon-name are what a
156
+ // search-result subtitle and a view switcher read. The page therefore has
157
+ // to be layout-transparent so its groups stay flex items of this column;
158
+ // a custom element's default `display: inline` would collapse it.
159
+ > adw-preferences-page {
160
+ display: contents;
161
+
162
+ // `display: contents` above beats the UA `[hidden] { display: none }`, so
163
+ // a page hidden through the DOM `hidden` property would keep rendering
164
+ // its groups while the search (which reads the same flag) had already
165
+ // dropped it from the corpus.
166
+ &[hidden] {
167
+ display: none;
168
+ }
169
+ }
153
170
  }
154
171
  }
@@ -0,0 +1,161 @@
1
+ // _progress_bar.scss — <adw-progress-bar>, the determinate partner to
2
+ // <adw-spinner>.
3
+ //
4
+ // TWO SOURCES, AND WHICH HALF CAME FROM WHICH — the two disagree, so this is not
5
+ // bookkeeping:
6
+ //
7
+ // GEOMETRY + COLOUR + THE OSD VARIANT come from
8
+ // `refs/libadwaita/src/stylesheet/widgets/_progress-bar.scss`: an 8px trough
9
+ // (:6), the 99px `$_progress-radius` (:33-35), the `%scale_trough` /
10
+ // `%scale_highlight` placeholders it shares with the scale
11
+ // (`_scale.scss:1-17`), the `> trough.empty > progress { all: unset }` rule
12
+ // that makes a zero fraction draw NOTHING rather than a 0px sliver (:85), and
13
+ // the `.osd` variant — a 2px bar with no trough, for under a header bar
14
+ // (:59-83).
15
+ //
16
+ // THE INDETERMINATE ANIMATION comes from
17
+ // `refs/adwaita-web/adwaita-web/scss/_progressbar.scss:25-66`, because
18
+ // libadwaita has NO CSS equivalent: GTK animates a pulsing block from C
19
+ // (`gtk_progress_bar_pulse`), so the stylesheet has nothing to copy. Its
20
+ // keyframes and its `prefers-reduced-motion` fallback are the only parts taken
21
+ // from there. Its GEOMETRY is NOT: it draws a 6px bar with a 3px radius and
22
+ // has no trough placeholder, no OSD variant and no text node, so copying its
23
+ // numbers would put a bar in this package that matches neither source.
24
+ //
25
+ // NOT PORTED, deliberately: `progressbar.vertical` (:10-15) and the four
26
+ // `progress.{left,right,top,bottom}` corner-radius rules (:37-55). Both exist
27
+ // for orientations and trough-splitting `<adw-progress-bar>` does not expose —
28
+ // there is no `orientation` attribute — and a rule nothing can ever select is a
29
+ // rule that rots.
30
+ //
31
+ // Reference: refs/libadwaita/src/stylesheet/widgets/_progress-bar.scss:5-6,17-21,23-25,27-35,59-85
32
+ // Reference: refs/libadwaita/src/stylesheet/_scale.scss:1-17 (%scale_trough, %scale_highlight)
33
+ // Reference: refs/libadwaita/src/stylesheet/_colors.scss:280-286 (the trough colours)
34
+ // Reference: refs/adwaita-web/adwaita-web/scss/_progressbar.scss:25-66 (indeterminate keyframes + reduced-motion fallback ONLY)
35
+ // Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
36
+ // Copyright (c) 2025 csm (adwaita-web). MIT License.
37
+ // Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
38
+
39
+ // `.dimmed` / `.numeric`, which the text node @extends exactly as upstream does.
40
+ @use 'labels';
41
+
42
+ adw-progress-bar {
43
+ display: flex;
44
+ flex-direction: column;
45
+ gap: var(--spacing-xs);
46
+ // `progressbar.horizontal > trough { min-width: 150px }` (:5) is a WIDGET
47
+ // minimum in GTK, so it belongs on the element rather than on the trough.
48
+ min-width: 150px;
49
+
50
+ .adw-progress-bar-trough {
51
+ // %scale_trough (_scale.scss:1-10)
52
+ position: relative;
53
+ display: flex;
54
+ overflow: hidden;
55
+ height: 8px; // :6 — `&, > progress { min-height: 8px }`
56
+ border-radius: 99px;
57
+ background-color: color-mix(in srgb, currentColor 15%, transparent);
58
+ transition: background 200ms ease-out;
59
+
60
+ @media (prefers-contrast: more) {
61
+ // $trough_color_hc (_colors.scss:284)
62
+ background-color: color-mix(in srgb, currentColor 30%, transparent);
63
+ }
64
+ }
65
+
66
+ .adw-progress-bar-progress {
67
+ // %scale_highlight (_scale.scss:12-17) + $_progress-radius (:33-35)
68
+ height: 100%;
69
+ border-radius: 99px;
70
+ background-color: var(--accent-bg-color);
71
+ color: var(--accent-fg-color);
72
+ transition:
73
+ width 200ms ease-out,
74
+ background 200ms ease-out;
75
+ }
76
+
77
+ // `> text { @extend .dimmed; @extend .numeric; font-size: smaller; }` (:17-21)
78
+ // — literally upstream's three lines, now that `.dimmed` and `.numeric` exist
79
+ // here as the same utility classes they are there.
80
+ .adw-progress-bar-text {
81
+ @extend .dimmed;
82
+ @extend .numeric;
83
+
84
+ font-size: smaller;
85
+ }
86
+
87
+ // `&:disabled { filter: Opacity(var(--disabled-opacity)) }` (:23-25). This
88
+ // package defines no `--disabled-opacity`, so `--dim-opacity` stands in — the
89
+ // same substitution `_switch.scss` documents, not a fourth invented token.
90
+ &[disabled] {
91
+ opacity: var(--dim-opacity);
92
+ }
93
+
94
+ // Fill from the far end. GTK spells this `:inverted`; flexbox handles the
95
+ // writing direction, so nothing here needs an RTL branch.
96
+ &[inverted] .adw-progress-bar-trough {
97
+ justify-content: flex-end;
98
+ }
99
+
100
+ // `> trough.empty > progress { all: unset }` (:85) — at fraction 0 the
101
+ // indicator DISAPPEARS instead of drawing a rounded 0px stub.
102
+ .adw-progress-bar-trough.empty .adw-progress-bar-progress {
103
+ all: unset;
104
+ }
105
+
106
+ // The `.osd` variant (:59-83): a hairline bar with no trough at all, the way
107
+ // it is drawn under a header bar.
108
+ &[osd] {
109
+ min-width: 2px;
110
+
111
+ .adw-progress-bar-trough {
112
+ height: 2px;
113
+ border-radius: 0;
114
+ background-color: transparent;
115
+ box-shadow: none;
116
+ }
117
+
118
+ .adw-progress-bar-progress {
119
+ border-radius: 0;
120
+ }
121
+ }
122
+
123
+ // Indeterminate. The block leaves the flex flow and bounces across the trough;
124
+ // this is the ONLY part of the widget taken from the vendored web port, since
125
+ // GTK pulses from C and its stylesheet has no equivalent to copy.
126
+ &[pulsing] .adw-progress-bar-progress {
127
+ position: absolute;
128
+ inset-block: 0;
129
+ width: 30%;
130
+ animation: adw-progress-bar-indeterminate 1.5s infinite ease-in-out;
131
+
132
+ // `_progressbar.scss:42-49` — with motion suppressed the block stops moving
133
+ // and fills the trough, so the bar still reads as "busy" and not as "0%".
134
+ @media (prefers-reduced-motion: reduce) {
135
+ left: 0;
136
+ width: 100%;
137
+ animation: none;
138
+ }
139
+ }
140
+ }
141
+
142
+ // refs/adwaita-web/adwaita-web/scss/_progressbar.scss:53-66, verbatim offsets.
143
+ // `left` rather than `inset-inline-start`: the port animates a physical offset,
144
+ // and a keyframe that flipped with the writing direction would no longer be the
145
+ // animation being cited.
146
+ @keyframes adw-progress-bar-indeterminate {
147
+ 0% {
148
+ left: -35%;
149
+ width: 30%;
150
+ }
151
+
152
+ 50% {
153
+ left: 50%;
154
+ width: 40%;
155
+ }
156
+
157
+ 100% {
158
+ left: 105%;
159
+ width: 30%;
160
+ }
161
+ }
package/scss/_reset.scss CHANGED
@@ -17,20 +17,31 @@
17
17
  // inherited typography + a host `* {}` box-sizing reset, which is what this
18
18
  // neutralises.
19
19
 
20
- // Every custom element adwaita-web defines. Keep in sync with
21
- // `src/elements/*` (the `customElements.define('adw-…')` calls).
20
+ // Every custom element adwaita-web defines — one entry per `customElements
21
+ // .define('adw-…')` call under `src/`.
22
+ //
23
+ // DERIVED, NOT REMEMBERED: `scripts/check-adwaita-reset-components.mjs` walks
24
+ // those calls and fails on any tag missing from this list (and on any entry with
25
+ // no call behind it). A hand-kept list is a second copy of the registry, and it
26
+ // had already drifted — `adw-source-view` was defined for its whole life and
27
+ // never listed, so it silently ran without the isolation floor. Nothing noticed,
28
+ // because the only spec touching this file instantiates `adw-switch-row`.
22
29
  $adw-components:
23
30
  adw-about-dialog, adw-action-row, adw-alert-dialog, adw-alert-response,
24
31
  adw-avatar, adw-banner, adw-bottom-sheet, adw-bottom-sheet-content,
25
32
  adw-bottom-sheet-sheet, adw-button, adw-button-content, adw-button-row,
26
33
  adw-card, adw-carousel, adw-carousel-indicator-dots,
27
- adw-carousel-indicator-lines, adw-clamp, adw-combo-row, adw-data-grid,
34
+ adw-carousel-indicator-lines, adw-checkbox, adw-clamp, adw-combo-row,
35
+ adw-data-grid,
28
36
  adw-dialog, adw-drop-down, adw-entry, adw-entry-row, adw-expander-row,
29
- adw-header-bar, adw-inline-view-switcher, adw-menu-button, adw-navigation-page,
37
+ adw-header-bar, adw-icon, adw-inline-view-switcher, adw-menu-button,
38
+ adw-navigation-page,
30
39
  adw-navigation-split-view, adw-navigation-view, adw-overlay-split-view,
31
- adw-password-entry-row, adw-preferences-dialog, adw-preferences-group,
32
- adw-preferences-page, adw-sidebar, adw-sidebar-item, adw-sidebar-section,
33
- adw-spinner, adw-spin-row, adw-split-button, adw-status-page, adw-switch-row,
40
+ adw-password-entry-row, adw-popover, adw-preferences-dialog,
41
+ adw-preferences-group, adw-preferences-page, adw-progress-bar, adw-radio,
42
+ adw-sidebar, adw-sidebar-item,
43
+ adw-sidebar-section, adw-source-view, adw-spinner, adw-spin-row,
44
+ adw-split-button, adw-status-page, adw-switch, adw-switch-row,
34
45
  adw-tab-page, adw-tab-view, adw-toast-overlay, adw-toggle, adw-toggle-group,
35
46
  adw-toolbar-view, adw-view-stack, adw-view-stack-page, adw-view-switcher,
36
47
  adw-view-switcher-bar, adw-view-switcher-page, adw-window, adw-window-title,
@@ -1,28 +1,46 @@
1
- // _spinner.scss — adw-spinner styling (ring with a spinning arc).
1
+ // _spinner.scss — adw-spinner styling.
2
+ //
3
+ // Almost nothing is left here on purpose. The ring is an SVG the element draws
4
+ // per frame from `@gjsify/adwaita-core`'s `spinnerArc`, because the arc BREATHES
5
+ // (2.7 to 102.8 degrees) and CSS cannot express that: the `border-top-color`
6
+ // chase this file used to carry was a fixed 90-degree quarter-circle at 0.8s
7
+ // against libadwaita's 1.2s, with a hardcoded grey track and square-cut ends.
8
+ //
9
+ // What CSS still owns is the box: the element is `size × size` and the ring is
10
+ // centred inside it, which is how a 200px spinner shows a 64px ring
11
+ // (adw-spinner.c:95-99 hands the widget's real size to the paintable, which caps
12
+ // only the radius).
13
+ //
14
+ // There is deliberately NO `prefers-reduced-motion` rule. The C opts out of the
15
+ // animation setting explicitly (`adw_animation_set_follow_enable_animations_setting
16
+ // (…, FALSE)`, adw-spinner-paintable.c:537) — a frozen busy indicator reads as a
17
+ // hang. This file used to stop the animation there.
18
+ //
19
+ // Reference: refs/libadwaita/src/adw-spinner.c
20
+ // Reference: refs/libadwaita/src/adw-spinner-paintable.c
2
21
  // Reference: refs/adwaita-web/adwaita-web/scss/_spinner.scss
3
- // Reference: refs/libadwaita (Adw.Spinner)
4
22
  // Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
5
23
  // Modifications: Adapted for @gjsify/adwaita-web Web Components.
6
24
 
7
25
  adw-spinner {
8
- display: inline-block;
26
+ // The element writes the measured box onto `style` when it upgrades; these are
27
+ // the values in force until then, which are Adwaita's own minimum
28
+ // (adw-spinner.c:14, reported as both minimum and natural at :78-81).
29
+ display: inline-flex;
30
+ align-items: center;
31
+ justify-content: center;
9
32
  box-sizing: border-box;
10
- width: 24px;
11
- height: 24px;
12
- // Neutral arc (currentColor, theme-aware) over a faint track — Adw.Spinner
13
- // is a neutral indicator, NOT accent-coloured.
14
- border: 3px solid rgba(127, 127, 127, 0.25);
15
- border-top-color: currentColor;
16
- border-radius: 50%;
17
- animation: adw-spinner-spin 0.8s linear infinite;
33
+ width: 16px;
34
+ height: 16px;
35
+ // The arc strokes `currentColor` — `gtk_widget_get_color` (:432), the widget's
36
+ // TEXT colour, never the accent. The track is the same colour at 15%, which
37
+ // the SVG applies as `stroke-opacity`.
38
+ color: inherit;
18
39
 
19
- @media (prefers-reduced-motion: reduce) {
20
- animation: none;
21
- }
22
- }
23
-
24
- @keyframes adw-spinner-spin {
25
- to {
26
- transform: rotate(360deg);
40
+ svg {
41
+ display: block;
42
+ // The ring never grows past its own diameter, so an over-large box centres
43
+ // it rather than stretching it.
44
+ flex: none;
27
45
  }
28
46
  }
@@ -111,56 +111,12 @@
111
111
  }
112
112
  }
113
113
 
114
- // --- Dropdown menu (popover) ---
115
- .adw-split-button-menu {
116
- position: absolute;
117
- top: calc(100% + 4px);
118
- right: 0;
119
- z-index: 10;
120
- display: flex;
121
- flex-direction: column;
122
- min-width: 160px;
123
- padding: var(--spacing-xs);
124
- border-radius: var(--button-radius);
125
- background-color: var(--popover-bg-color, var(--window-bg-color, #fff));
126
- color: var(--window-fg-color);
127
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 0 0 1px var(--separator-color);
128
-
129
- &[hidden] {
130
- display: none;
131
- }
132
- }
133
-
134
- .adw-split-button-menu-item {
135
- box-sizing: border-box;
136
- display: flex;
137
- align-items: center;
138
- width: 100%;
139
- min-height: 32px;
140
- margin: 0;
141
- padding: var(--spacing-xs) var(--spacing-s);
142
- border: none;
143
- border-radius: calc(var(--button-radius) - 2px);
144
- background-color: transparent;
145
- color: inherit;
146
- font: inherit;
147
- text-align: start;
148
- cursor: pointer;
149
- transition: background-color 0.1s ease;
150
-
151
- &:hover {
152
- background-color: var(--button-hover-color);
153
- }
154
-
155
- &:active {
156
- background-color: var(--button-active-color);
157
- }
158
-
159
- &:focus-visible {
160
- outline: 2px solid var(--accent-color);
161
- outline-offset: -2px;
162
- }
163
- }
114
+ // The dropdown menu is `<adw-popover>` (`_popover.scss`), and this was the
115
+ // WORST of the three hand-rolled surfaces: `--button-radius` (9px) where
116
+ // libadwaita's popover is 15px, under a two-layer shadow that exists nowhere
117
+ // in the vendored stylesheet (`popover > contents` has three,
118
+ // _popovers.scss:18-20), and a `calc(var(--button-radius) - 2px)` (7px) row
119
+ // where `modelbutton` is 9px. Nothing element-specific was left to keep.
164
120
 
165
121
  // --- Suggested action — accent-coloured whole control ---
166
122
  &.suggested-action {
@@ -0,0 +1,90 @@
1
+ // _switch.scss — the <adw-switch> control: a track, a hidden checkbox and a
2
+ // sliding knob. UNSCOPED, which is the whole point of the partial.
3
+ //
4
+ // WHY IT IS ITS OWN FILE. These rules used to live inside `_switch_row.scss`,
5
+ // nested under `adw-switch-row { … }` — so `.adw-switch` did not exist anywhere
6
+ // else, and the moment a second widget needed a toggle it could not use it.
7
+ // `_expander_row.scss` therefore carried a character-for-character copy of the
8
+ // whole block (same 44×24 box, same hidden input, same 20px knob, same
9
+ // `translateX(20px)`, same focus ring) under a different class name. Two copies
10
+ // of a control is how a hover state gets fixed in one of them.
11
+ //
12
+ // FIDELITY, RECORDED RATHER THAN "FIXED": the 44×24 track with the 20px knob is
13
+ // `refs/adwaita-web/adwaita-web/scss/_switch.scss`'s geometry, NOT libadwaita's.
14
+ // libadwaita draws `switch` as a 3px-padded trough around a 20px slider with
15
+ // `border-radius: 14px` (refs/libadwaita/src/stylesheet/widgets/_switch.scss:3-4,
16
+ // :24-26) — about 26px tall, not 24, and correspondingly narrower. What ships
17
+ // here is the vendored web port's box, unchanged by the extraction; changing the
18
+ // geometry is a visual decision for a separate change, and citing libadwaita for
19
+ // numbers that came from somewhere else would be the misreading the conformance
20
+ // header warns about.
21
+ //
22
+ // Reference: refs/adwaita-web/adwaita-web/scss/_switch.scss (the geometry that ships)
23
+ // Reference: refs/libadwaita/src/stylesheet/widgets/_switch.scss:3-4,20-26 (the geometry that does not, + the disabled treatment)
24
+ // Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
25
+ // Copyright (c) 2025 csm (adwaita-web). MIT License.
26
+ // Modifications: Adapted for @gjsify/adwaita-web Web Components; lifted out of
27
+ // `adw-switch-row {}` so <adw-switch> is usable anywhere.
28
+
29
+ .adw-switch {
30
+ position: relative;
31
+ display: inline-block;
32
+ width: 44px;
33
+ height: 24px;
34
+ flex-shrink: 0;
35
+
36
+ // The real control: focusable and keyboard-toggleable, but never painted —
37
+ // the slider below is what the user sees and clicks.
38
+ input {
39
+ opacity: 0;
40
+ width: 0;
41
+ height: 0;
42
+ position: absolute;
43
+ }
44
+ }
45
+
46
+ .adw-switch-slider {
47
+ position: absolute;
48
+ cursor: pointer;
49
+ inset: 0;
50
+ background-color: var(--switch-off-bg);
51
+ border-radius: 12px;
52
+ transition: background-color 0.15s ease-out;
53
+
54
+ &::before {
55
+ content: "";
56
+ position: absolute;
57
+ height: 20px;
58
+ width: 20px;
59
+ left: 2px;
60
+ bottom: 2px;
61
+ background-color: var(--switch-knob-bg);
62
+ border-radius: 50%;
63
+ transition: transform 0.15s ease-out;
64
+ box-shadow: 0 1px 2px rgb(0 0 0 / 20%);
65
+ }
66
+ }
67
+
68
+ .adw-switch input:checked + .adw-switch-slider {
69
+ background-color: var(--accent-bg-color);
70
+
71
+ &::before {
72
+ transform: translateX(20px);
73
+ }
74
+ }
75
+
76
+ .adw-switch input:focus-visible + .adw-switch-slider {
77
+ outline: 2px solid var(--accent-color);
78
+ outline-offset: 2px;
79
+ }
80
+
81
+ // libadwaita dims the whole widget (`filter: Opacity(var(--disabled-opacity))`,
82
+ // _switch.scss:20-22). This package has no `--disabled-opacity` token, so the
83
+ // existing `--dim-opacity` stands in rather than a fourth invented colour.
84
+ .adw-switch.disabled {
85
+ opacity: var(--dim-opacity);
86
+
87
+ .adw-switch-slider {
88
+ cursor: not-allowed;
89
+ }
90
+ }