@gjsify/adwaita-web 0.40.0 → 0.41.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/adwaita-web",
3
- "version": "0.40.0",
3
+ "version": "0.41.0",
4
4
  "description": "Adwaita/Libadwaita web components for browser targets",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -41,14 +41,14 @@
41
41
  "@codemirror/language": "^6.12.4",
42
42
  "@codemirror/state": "^6.7.0",
43
43
  "@codemirror/view": "^6.43.4",
44
- "@gjsify/adwaita-core": "^0.40.0",
45
- "@gjsify/adwaita-fonts": "^0.40.0",
46
- "@gjsify/adwaita-icons": "^0.40.0",
44
+ "@gjsify/adwaita-core": "^0.41.0",
45
+ "@gjsify/adwaita-fonts": "^0.41.0",
46
+ "@gjsify/adwaita-icons": "^0.41.0",
47
47
  "@lezer/highlight": "^1.2.3"
48
48
  },
49
49
  "devDependencies": {
50
- "@gjsify/cli": "^0.40.0",
51
- "@gjsify/unit": "^0.40.0",
50
+ "@gjsify/cli": "^0.41.0",
51
+ "@gjsify/unit": "^0.41.0",
52
52
  "sass": "^1.101.0",
53
53
  "typescript": "^6.0.3"
54
54
  },
@@ -36,13 +36,27 @@ adw-carousel {
36
36
  }
37
37
  }
38
38
 
39
+ // `100%` is the FALLBACK basis, used until the element has measured its pages:
40
+ // libadwaita gives every page the largest natural size capped at the carousel
41
+ // (adw-carousel.c:748-765), which is only 100% when a page asks for it all. The
42
+ // element narrows `flex-basis` to the measured size and pads the track by the
43
+ // half-gap that leaves, so the neighbours peek in as they do in GTK.
44
+ //
45
+ // `center` and not `start` for the same reason: the strip is drawn centred
46
+ // (:801), and centre-snapping is what makes the track padding cancel out of the
47
+ // scroll offset, leaving `scrollLeft = position * distance` exactly true.
48
+ //
49
+ // `min-width: 0` because a flex item floors at its own min-content size: without
50
+ // it a page whose content is wider than the carousel keeps that width instead of
51
+ // being capped at it, and GTK allocates the capped one (:754) and clips.
39
52
  .adw-carousel-page {
40
53
  flex: 0 0 100%;
54
+ min-width: 0;
41
55
  box-sizing: border-box;
42
56
  display: flex;
43
57
  align-items: center;
44
58
  justify-content: center;
45
- scroll-snap-align: start;
59
+ scroll-snap-align: center;
46
60
  scroll-snap-stop: always;
47
61
  }
48
62
  }
@@ -5,8 +5,23 @@
5
5
  // Copyright (c) 2025 csm (adwaita-web). MIT License.
6
6
  // Modifications: Adapted for @gjsify/adwaita-web Web Components.
7
7
 
8
+ // A GRID, not a flex row, because `Adw.HeaderBar` puts its three sections in a
9
+ // `GtkCenterBox` (adw-header-bar.c:992) — and a center box centres its middle
10
+ // child in the WHOLE box, not in whatever space the sides left over. As a flex
11
+ // row with `flex: 1` on the centre, the title was centred between the buttons
12
+ // instead: any bar whose two sides differ in width — which is most of them, e.g.
13
+ // a storybook preview header with no start buttons and two end buttons — drew its
14
+ // title visibly off-centre.
15
+ //
16
+ // `1fr` is `minmax(auto, 1fr)`, and that auto floor is what makes this the LOOSE
17
+ // centering policy (the default) rather than STRICT: the side tracks share the
18
+ // free space equally, so the title sits dead centre while both sides fit, but a
19
+ // side whose content is wider than its share pushes the title off centre rather
20
+ // than truncating itself. STRICT — `adw_header_bar_set_centering_policy`, which
21
+ // size-groups the two sides — would instead keep the title centred at all cost.
8
22
  adw-header-bar {
9
- display: flex;
23
+ display: grid;
24
+ grid-template-columns: 1fr minmax(0, auto) 1fr;
10
25
  align-items: center;
11
26
  min-height: 47px;
12
27
  padding: 0 6px;
@@ -18,10 +33,26 @@ adw-header-bar {
18
33
  flex-shrink: 0;
19
34
 
20
35
  .adw-header-bar-center {
21
- flex: 1;
36
+ // STRETCHED into its track, never `justify-self: center`. A grid item that is
37
+ // centred is sized `fit-content`, whose floor is the item's own MIN-CONTENT —
38
+ // and a `nowrap` title's min-content is the whole string. Centred, a 260px bar
39
+ // with a back button and two end buttons therefore drew a 277px centre section
40
+ // starting 6.6px OUTSIDE the bar and running straight over all three buttons,
41
+ // with the ellipsis never reached. Stretched, the item is exactly its track,
42
+ // and the track is what is left once both sides have their natural width.
43
+ //
44
+ // That leftover is the rule `gtk_center_layout_distribute` applies while
45
+ // `shrink-center-last` is FALSE (gtkcenterlayout.c:155-157): the centre is
46
+ // CLAMPed to `size - spacing - (start.natural + end.natural)` and then pushed
47
+ // in from either side, so it cannot overlap them. The centring above still
48
+ // holds wherever the bar HAS room, because the two `1fr` side tracks split the
49
+ // free space evenly and `justify-content: center` centres the title in the
50
+ // middle track.
22
51
  display: flex;
23
52
  justify-content: center;
24
53
  // min-width: 0 prevents the title from pushing the end buttons off-screen.
54
+ // `shrink-center-last` is FALSE on the center box, so the TITLE is what gives
55
+ // way when the bar runs out of room, not the buttons.
25
56
  min-width: 0;
26
57
  }
27
58
 
@@ -34,15 +65,15 @@ adw-header-bar {
34
65
  }
35
66
 
36
67
  .adw-header-bar-start {
68
+ justify-self: start;
37
69
  display: flex;
38
70
  align-items: center;
39
71
  padding: 0 6px;
40
72
  gap: 4px;
41
- // flex-shrink: 0 keeps the start buttons visible when the window is narrow.
42
- flex-shrink: 0;
43
73
  }
44
74
 
45
75
  .adw-header-bar-end {
76
+ justify-self: end;
46
77
  display: flex;
47
78
  align-items: center;
48
79
  // justify-content: flex-end aligns end buttons to the right edge of the
@@ -50,8 +81,6 @@ adw-header-bar {
50
81
  justify-content: flex-end;
51
82
  padding: 0 6px;
52
83
  gap: 4px;
53
- // flex-shrink: 0 keeps the end buttons visible when the window is narrow.
54
- flex-shrink: 0;
55
84
  }
56
85
 
57
86
  .adw-header-btn {
@@ -38,6 +38,9 @@
38
38
  --icon-emblem-system: url("data:image/svg+xml,%3Csvg%20height%3D'16px'%20viewBox%3D'0%200%2016%2016'%20width%3D'16px'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%20%3Cpath%20d%3D'm%208%200%20c%20-0.550781%200%20-1%200.449219%20-1%201%20v%200.238281%20c%200%200.464844%20-0.378906%200.902344%20-0.820312%201.046875%20c%20-0.023438%200.007813%20-0.042969%200.011719%20-0.0625%200.019532%20c%20-0.445313%200.148437%20-1.007813%200.015624%20-1.28125%20-0.359376%20l%20-0.140626%20-0.195312%20c%20-0.15625%20-0.214844%20-0.390624%20-0.359375%20-0.652343%20-0.398438%20c%20-0.261719%20-0.042968%20-0.53125%200.019532%20-0.742188%200.175782%20c%20-0.449219%200.324218%20-0.550781%200.949218%20-0.222656%201.398437%20l%200.140625%200.199219%20c%200.277344%200.375%200.226562%200.953125%20-0.050781%201.328125%20c%20-0.011719%200.015625%20-0.023438%200.035156%20-0.035157%200.050781%20c%20-0.273437%200.378906%20-0.804687%200.601563%20-1.25%200.457032%20l%20-0.230468%20-0.074219%20c%20-0.523438%20-0.171875%20-1.089844%200.117187%20-1.257813%200.640625%20c%20-0.171875%200.527344%200.113281%201.089844%200.640625%201.261718%20l%200.222656%200.074219%20c%200.445313%200.144531%200.738282%200.636719%200.75%201.101563%20v%200.070312%20c%200.015626%200.464844%20-0.304687%200.960938%20-0.746093%201.105469%20l%20-0.226563%200.070313%20c%20-0.527344%200.171874%20-0.8125%200.738281%20-0.640625%201.261718%20c%200.167969%200.523438%200.734375%200.8125%201.257813%200.640625%20l%200.230468%20-0.074219%20c%200.445313%20-0.144531%200.976563%200.078126%201.25%200.457032%20c%200.011719%200.015625%200.027344%200.035156%200.039063%200.050781%20c%200.277344%200.375%200.324219%200.953125%200.050781%201.328125%20l%20-0.144531%200.203125%20c%20-0.324219%200.445313%20-0.226563%201.070313%200.222656%201.394531%20c%200.445313%200.324219%201.070313%200.226563%201.394531%20-0.21875%20l%200.144532%20-0.199218%20c%200.273437%20-0.378907%200.835937%20-0.507813%201.277344%20-0.359376%20c%200.019531%200.007813%200.042968%200.011719%200.0625%200.019532%20c%200.445312%200.140625%200.820312%200.578125%200.820312%201.046875%20v%200.238281%20c%200%200.550781%200.449219%201%201%201%20s%201%20-0.449219%201%20-1%20v%20-0.238281%20c%200%20-0.46875%200.378906%20-0.90625%200.820312%20-1.046875%20c%200.023438%20-0.007813%200.042969%20-0.015625%200.066407%20-0.023438%20c%200.441406%20-0.144531%201.003906%20-0.015625%201.277343%200.363282%20l%200.144532%200.199218%20c%200.324218%200.445313%200.949218%200.542969%201.394531%200.21875%20c%200.445313%20-0.324218%200.546875%20-0.949218%200.222656%20-1.394531%20l%20-0.148437%20-0.203125%20c%20-0.273438%20-0.375%20-0.226563%20-0.953125%200.050781%20-1.328125%20c%200.015625%20-0.015625%200.027344%20-0.035156%200.039063%20-0.050781%20c%200.273437%20-0.378906%200.804687%20-0.601563%201.25%20-0.457032%20l%200.234374%200.078126%20c%200.523438%200.167968%201.085938%20-0.121094%201.257813%20-0.644532%20c%200.171875%20-0.523437%20-0.117187%20-1.089844%20-0.640625%20-1.257812%20l%20-0.230469%20-0.074219%20c%20-0.445312%20-0.144531%20-0.734375%20-0.640625%20-0.746093%20-1.105469%20c%200%20-0.023437%200%20-0.046875%200%20-0.070312%20c%20-0.015626%20-0.464844%200.300781%20-0.957032%200.746093%20-1.101563%20l%200.230469%20-0.074219%20c%200.523438%20-0.171874%200.8125%20-0.734374%200.640625%20-1.261718%20c%20-0.171875%20-0.523438%20-0.734375%20-0.8125%20-1.257813%20-0.640625%20l%20-0.230468%200.074219%20c%20-0.445313%200.144531%20-0.980469%20-0.078126%20-1.253906%20-0.457032%20c%20-0.011719%20-0.015625%20-0.023438%20-0.035156%20-0.035157%20-0.050781%20c%20-0.277343%20-0.375%20-0.324219%20-0.953125%20-0.050781%20-1.328125%20l%200.144531%20-0.199219%20c%200.324219%20-0.445312%200.226563%20-1.074219%20-0.222656%20-1.398437%20c%20-0.214844%20-0.15625%20-0.480469%20-0.21875%20-0.742187%20-0.179688%20c%20-0.265626%200.042969%20-0.5%200.1875%20-0.652344%200.402344%20l%20-0.144532%200.195312%20c%20-0.273437%200.378907%20-0.835937%200.507813%20-1.28125%200.363282%20c%20-0.019531%20-0.007813%20-0.039062%20-0.015625%20-0.0625%20-0.023438%20c%20-0.441406%20-0.140625%20-0.820312%20-0.578125%20-0.820312%20-1.046875%20v%20-0.238281%20c%200%20-0.550781%20-0.449219%20-1%20-1%20-1%20z%20m%200%204%20c%200.871094%200%201.675781%200.273438%202.332031%200.742188%20c%200.003907%200.007812%200.011719%200.015624%200.019531%200.023437%20c%200.011719%200.003906%200.019532%200.007813%200.03125%200.015625%20c%200.660157%200.484375%201.160157%201.171875%201.421876%201.976562%20v%200.007813%20s%200.003906%200.003906%200.003906%200.007813%20c%200.292968%200.851562%200.15625%201.65625%200%202.457031%20c%200%200%20-0.003906%200.003906%20-0.003906%200.007812%20v%200.003907%20c%20-0.261719%200.800781%20-0.757813%201.488281%20-1.414063%201.976562%20c%20-0.015625%200.003906%20-0.027344%200.011719%20-0.039063%200.019531%20c%20-0.007812%200.003907%20-0.015624%200.011719%20-0.019531%200.019531%20c%20-0.65625%200.46875%20-1.460937%200.742188%20-2.332031%200.742188%20c%20-0.855469%200%20-1.644531%20-0.265625%20-2.289062%20-0.714844%20c%20-0.019532%20-0.015625%20-0.042969%20-0.035156%20-0.0625%20-0.046875%20c%20-0.011719%20-0.007812%20-0.023438%20-0.015625%20-0.035157%20-0.019531%20c%20-0.652343%20-0.484375%20-1.148437%20-1.160156%20-1.40625%20-1.945312%20c%20-0.003906%20-0.015626%20-0.007812%20-0.023438%20-0.011719%20-0.035157%20c%20-0.003906%20-0.007812%20-0.007812%20-0.015625%20-0.011718%20-0.019531%20c%20-0.285156%20-0.847656%20-0.148438%20-1.644531%200%20-2.4375%20c%200.003906%20-0.007812%200.007812%20-0.011719%200.011718%20-0.019531%20c%200.003907%20-0.011719%200.007813%20-0.023438%200.011719%20-0.039063%20c%200.261719%20-0.785156%200.757813%20-1.460937%201.414063%20-1.945312%20c%200.007812%20-0.003906%200.019531%20-0.007813%200.027344%20-0.015625%20c%200.019531%20-0.011719%200.042968%20-0.03125%200.058593%20-0.046875%20c%200.648438%20-0.449219%201.4375%20-0.714844%202.292969%20-0.714844%20z%20m%200%200'%20fill%3D'currentColor'%2F%3E%20%3C%2Fsvg%3E");
39
39
  --icon-preferences-system: url("data:image/svg+xml,%3Csvg%20height%3D'16px'%20viewBox%3D'0%200%2016%2016'%20width%3D'16px'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%20%3Cpath%20d%3D'm%2013.855469%200%20l%20-1.539063%201.4375%20c%20-0.453125%200.421875%20-0.53125%201.148438%20-0.269531%201.707031%20l%20-5.886719%205.996094%20c%20-0.011718%200%20-0.019531%200%20-0.03125%200%20c%20-0.257812%20-0.128906%20-0.550781%20-0.183594%20-0.839844%20-0.148437%20c%20-0.328124%200.046874%20-0.632812%200.199218%20-0.867187%200.441406%20l%20-3.945313%203.996094%20c%20-0.3906245%200.375%20-0.5468745%200.933593%20-0.4062495%201.457031%20c%200.1406255%200.523437%200.5546875%200.929687%201.0820315%201.058593%20c%200.527344%200.132813%201.082031%20-0.03125%201.453125%20-0.425781%20l%203.945312%20-3.996093%20c%200.472657%20-0.453126%200.59375%20-1.15625%200.296875%20-1.738282%20l%205.890625%20-5.964844%20c%200.558594%200.25%201.273438%200.148438%201.707031%20-0.289062%20l%201.414063%20-1.5625%20z%20m%20-10.308594%200.0898438%20c%20-0.398437%200%20-0.785156%200.0937502%20-1.140625%200.2187502%20l%201.882812%201.878906%20c%200.390626%200.382812%200.390626%201%200%201.386719%20l%20-0.710937%200.707031%20c%20-0.386719%200.386719%20-1%200.386719%20-1.390625%200%20l%20-1.882812%20-1.878906%20c%20-0.125%200.355468%20-0.2187505%200.742187%20-0.2187505%201.140625%20c%200%201.90625%201.5507815%203.453125%203.4609375%203.453125%20c%200.402344%200%200.789063%20-0.09375%201.144531%20-0.21875%20l%201.175782%201.171875%20h%200.058593%20l%202.070313%20-2.0625%20l%20-1.203125%20-1.203125%20c%200.125%20-0.359375%200.214843%20-0.742188%200.214843%20-1.140625%20c%200%20-1.90625%20-1.546874%20-3.4531252%20-3.460937%20-3.4531252%20z%20m%206.550781%207.8906252%20l%20-2.070312%202.066406%20c%200.011718%200.027344%200.023437%200.058594%200.03125%200.089844%20l%201.144531%201.140625%20c%20-0.125%200.355468%20-0.21875%200.742187%20-0.21875%201.140625%20c%200%201.902343%201.550781%203.449219%203.460937%203.449219%20c%200.433594%200%200.855469%20-0.101563%201.238282%20-0.246094%20l%20-2.007813%20-2%20c%20-0.386719%20-0.386719%20-0.386719%20-1.035156%200%20-1.417969%20l%200.679688%20-0.679687%20c%200.195312%20-0.191407%200.457031%20-0.308594%200.710937%20-0.308594%20s%200.515625%200.117187%200.710938%200.308594%20l%201.945312%201.941406%20c%200.105469%20-0.328125%200.183594%20-0.683594%200.183594%20-1.046875%20c%200%20-1.90625%20-1.546875%20-3.453125%20-3.460938%20-3.453125%20c%20-0.398437%200%20-0.785156%200.09375%20-1.140624%200.21875%20z%20m%200%200'%20fill%3D'currentColor'%2F%3E%20%3C%2Fsvg%3E");
40
40
  --icon-application-x-executable: url("data:image/svg+xml,%3Csvg%20height%3D'16px'%20viewBox%3D'0%200%2016%2016'%20width%3D'16px'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%20%3Cpath%20d%3D'm%208.015625%200.015625%20c%20-0.769531%200%20-1.539063%200.292969%20-2.121094%200.875%20l%20-5.003906%205.003906%20c%20-1.164063%201.164063%20-1.164063%203.078125%200%204.242188%20l%205.003906%205.003906%20c%201.164063%201.164063%203.078125%201.164063%204.242188%200%20l%205.007812%20-5.003906%20c%201.164063%20-1.164063%201.164063%20-3.078125%200%20-4.242188%20l%20-5.007812%20-5.003906%20c%20-0.582031%20-0.582031%20-1.351563%20-0.875%20-2.121094%20-0.875%20z%20m%200.101563%201.988281%20c%200.210937%200.023438%200.414062%200.117188%200.585937%200.28125%20l%20-0.339844%200.113282%20c%20-0.074219%20-0.136719%20-0.15625%20-0.269532%20-0.246093%20-0.394532%20z%20m%20-1.570313%201.058594%20c%200.300781%200.421875%200.464844%200.929688%200.46875%201.453125%20c%200%201.378906%20-1.121094%202.5%20-2.5%202.5%20c%20-0.523437%20-0.003906%20-1.03125%20-0.171875%20-1.449219%20-0.472656%20z%20m%203.441406%200.503906%20l%203.742188%203.742188%20c%200.402343%200.402344%200.402343%201.011718%200%201.414062%20l%20-0.253907%200.25%20c%20-0.039062%20-0.046875%20-0.074218%20-0.09375%20-0.117187%20-0.140625%20l%200.621094%20-0.855469%20l%20-0.808594%20-0.585937%20l%20-0.621094%200.851563%20c%20-0.167969%20-0.078126%20-0.347656%20-0.136719%20-0.535156%20-0.175782%20v%20-1.050781%20h%20-1%20v%201.050781%20c%20-0.183594%200.039063%20-0.363281%200.097656%20-0.53125%200.175782%20l%20-0.621094%20-0.851563%20l%20-0.804687%200.585937%20l%200.617187%200.855469%20c%20-0.125%200.136719%20-0.238281%200.289063%20-0.332031%200.453125%20l%20-1%20-0.324218%20l%20-0.308594%200.949218%20l%201%200.324219%20c%20-0.011718%200.09375%20-0.019531%200.1875%20-0.019531%200.28125%20s%200.007813%200.1875%200.019531%200.28125%20l%20-1%200.324219%20l%200.308594%200.949218%20l%201%20-0.324218%20c%200.09375%200.164062%200.207031%200.316406%200.332031%200.453125%20l%20-0.617187%200.855469%20l%200.195312%200.140624%20l%20-0.53125%200.53125%20c%20-0.402344%200.40625%20-1.011718%200.40625%20-1.414062%200%20l%20-4.902344%20-4.902343%20l%200.027344%20-0.039063%20l%200.210937%20-0.289062%20c%200.328125%200.152344%200.679688%200.269531%201.046875%200.339844%20v%201.179687%20h%201.648438%20v%20-1.179687%20c%200.363281%20-0.070313%200.714844%20-0.1875%201.046875%20-0.339844%20l%200.207031%200.289062%20l%200.484375%200.667969%20l%201.335937%20-0.972656%20l%20-0.484374%20-0.667969%20l%20-0.210938%20-0.289062%20c%200.25%20-0.269532%200.46875%20-0.566407%200.648438%20-0.890626%20l%200.339843%200.113282%20l%200.785157%200.253906%20l%200.507812%20-1.566406%20l%20-0.785156%20-0.257813%20l%20-0.335938%20-0.109375%20c%200.019532%20-0.179687%200.035156%20-0.363281%200.035156%20-0.550781%20s%20-0.015624%20-0.371094%20-0.035156%20-0.550781%20l%200.335938%20-0.109375%20l%200.785156%20-0.257813%20z%20m%201.527344%205.449219%20c%200.527344%200%200.984375%200.265625%201.25%200.667969%20l%20-2.078125%202.082031%20c%20-0.40625%20-0.269531%20-0.671875%20-0.722656%20-0.671875%20-1.25%20c%200%20-0.835937%200.667969%20-1.5%201.5%20-1.5%20z%20m%200%200'%20fill%3D'currentColor'%2F%3E%20%3Cpath%20d%3D'm%204.039062%20-18.988281%20c%20-1.449218%200%20-2.679687%201.046875%20-2.964843%202.421875%20c%20-0.019531%200.097656%20-0.035157%200.199218%20-0.046875%200.300781%20c%20-0.007813%200.101563%20-0.015625%200.203125%20-0.015625%200.304687%20v%207.910157%20c%200%201.660156%201.367187%203.027343%203.027343%203.027343%20h%207.949219%20c%201.660157%200%203.027344%20-1.367187%203.027344%20-3.027343%20v%20-7.910157%20c%200%20-0.105468%20-0.003906%20-0.207031%20-0.015625%20-0.304687%20c%20-0.011719%20-0.101563%20-0.027344%20-0.203125%20-0.046875%20-0.300781%20c%20-0.285156%20-1.375%20-1.511719%20-2.421875%20-2.964844%20-2.421875%20z%20m%200%202.003906%20h%202.976563%20v%203%20h%20-2.976563%20c%20-0.585937%200%20-1.027343%20-0.441406%20-1.027343%20-1.027344%20v%20-0.949219%20c%200.003906%20-0.035156%200.003906%20-0.070312%200.007812%20-0.105468%20c%200.003907%20-0.035156%200.007813%20-0.070313%200.011719%20-0.105469%20c%200.007812%20-0.035156%200.019531%20-0.066406%200.027344%20-0.097656%20c%200.125%20-0.421875%200.503906%20-0.714844%200.980468%20-0.714844%20z%20m%204.976563%200%20h%202.972656%20c%200.585938%200%201.023438%200.4375%201.027344%201.023437%20v%200.949219%20c%200%200.585938%20-0.441406%201.027344%20-1.027344%201.027344%20h%20-2.972656%20z%20m%204%203.71875%20v%205.214844%20c%200%200.585937%20-0.441406%201.027343%20-1.027344%201.027343%20h%20-7.949219%20c%20-0.585937%200%20-1.027343%20-0.441406%20-1.027343%20-1.027343%20v%20-5.175781%20c%200.324219%200.148437%200.671875%200.246093%201.027343%200.246093%20h%202.976563%20v%203.035157%20l%202%200.992187%20v%20-4.027344%20h%202.972656%20c%200.34375%200%200.695313%20-0.113281%201.027344%20-0.285156%20z%20m%20-5%2033.28125%20c%20-0.851563%200%20-1.699219%200.328125%20-2.351563%200.976563%20l%20-4.671874%204.671874%20c%20-1.300782%201.300782%20-1.300782%203.402344%200%204.703126%20l%204.671874%204.671874%20c%201.300782%201.300782%203.402344%201.300782%204.699219%200%20l%204.675781%20-4.671874%20c%201.300782%20-1.300782%201.300782%20-3.402344%200%20-4.703126%20l%20-4.675781%20-4.671874%20c%20-0.648437%20-0.648438%20-1.496093%20-0.976563%20-2.347656%20-0.976563%20z%20m%200%201.984375%20c%200.335937%200%200.675781%200.132812%200.941406%200.402344%20l%203.03125%203.027344%20c%20-0.066406%200.039062%20-0.136719%200.070312%20-0.210937%200.09375%20c%20-0.019532%200.003906%20-0.039063%200.011718%20-0.0625%200.015624%20c%20-0.441406%200.148438%20-1.003906%200.019532%20-1.277344%20-0.359374%20l%20-0.140625%20-0.195313%20c%20-0.15625%20-0.210937%20-0.390625%20-0.355469%20-0.652344%20-0.398437%20c%20-0.066406%20-0.011719%20-0.132812%20-0.015626%20-0.199219%20-0.011719%20c%20-0.195312%200.007812%20-0.382812%200.074219%20-0.542968%200.191406%20c%20-0.449219%200.324219%20-0.550782%200.949219%20-0.226563%201.394531%20l%200.144531%200.199219%20c%200.273438%200.378906%200.226563%200.953125%20-0.050781%201.332031%20c%20-0.011719%200.015625%20-0.023437%200.03125%20-0.035156%200.050782%20c%20-0.273437%200.378906%20-0.808594%200.597656%20-1.253906%200.453124%20l%20-0.226563%20-0.074218%20c%20-0.523437%20-0.167969%20-1.089844%200.117187%20-1.257812%200.644531%20c%20-0.171875%200.523437%200.113281%201.089844%200.636718%201.261719%20l%200.226563%200.070312%20c%200.445313%200.144532%200.738281%200.640625%200.746094%201.105469%20c%200.003906%200.023437%200.003906%200.042969%200.003906%200.066406%20c%200.015625%200.464844%20-0.304687%200.960938%20-0.75%201.105469%20l%20-0.226563%200.074219%20c%20-0.179687%200.058593%20-0.332031%200.164062%20-0.445312%200.296875%20l%20-3.785156%20-3.785156%20c%20-0.535156%20-0.535157%20-0.535156%20-1.355469%200%20-1.890626%20l%204.667968%20-4.667968%20c%200.269532%20-0.269532%200.609376%20-0.402344%200.945313%20-0.402344%20z%20m%205.585937%205.234375%20c%200.058594%200%200.117188%200.003906%200.175782%200.007813%20c%200.382812%200.523437%200.335937%201.234374%20-0.144532%201.71875%20l%20-3.753906%203.75%20c%20-0.027344%20-0.066407%20-0.050781%20-0.136719%20-0.070312%20-0.203126%20c%20-0.003906%20-0.011718%20-0.007813%20-0.023437%20-0.011719%20-0.035156%20c%20-0.003906%20-0.007812%20-0.007813%20-0.011718%20-0.011719%20-0.019531%20c%20-0.285156%20-0.84375%20-0.152344%20-1.644531%200%20-2.4375%20c%200.003906%20-0.003906%200.007813%20-0.007813%200.011719%20-0.015625%20c%200.003906%20-0.011719%200.007813%20-0.027344%200.011719%20-0.039062%20c%200.261718%20-0.789063%200.757812%20-1.464844%201.410156%20-1.945313%20c%200.011719%20-0.003906%200.023438%20-0.011719%200.03125%20-0.015625%20c%200.019531%20-0.015625%200.042969%20-0.03125%200.058594%20-0.046875%20c%200.648437%20-0.453125%201.4375%20-0.71875%202.292968%20-0.71875%20z%20m%200%200'%20fill%3D'currentColor'%2F%3E%20%3C%2Fsvg%3E");
41
+ --icon-window-close: url("data:image/svg+xml,%3Csvg%20height%3D'16px'%20viewBox%3D'0%200%2016%2016'%20width%3D'16px'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%20%3Cpath%20d%3D'm%204%204%20h%201%20h%200.03125%20c%200.253906%200.011719%200.511719%200.128906%200.6875%200.3125%20l%202.28125%202.28125%20l%202.3125%20-2.28125%20c%200.265625%20-0.230469%200.445312%20-0.304688%200.6875%20-0.3125%20h%201%20v%201%20c%200%200.285156%20-0.035156%200.550781%20-0.25%200.75%20l%20-2.28125%202.28125%20l%202.25%202.25%20c%200.1875%200.1875%200.28125%200.453125%200.28125%200.71875%20v%201%20h%20-1%20c%20-0.265625%200%20-0.53125%20-0.09375%20-0.71875%20-0.28125%20l%20-2.28125%20-2.28125%20l%20-2.28125%202.28125%20c%20-0.1875%200.1875%20-0.453125%200.28125%20-0.71875%200.28125%20h%20-1%20v%20-1%20c%200%20-0.265625%200.09375%20-0.53125%200.28125%20-0.71875%20l%202.28125%20-2.25%20l%20-2.28125%20-2.28125%20c%20-0.210938%20-0.195312%20-0.304688%20-0.46875%20-0.28125%20-0.75%20z%20m%200%200'%20fill%3D'currentColor'%2F%3E%20%3C%2Fsvg%3E");
42
+ --icon-window-minimize: url("data:image/svg+xml,%3Csvg%20height%3D'16px'%20viewBox%3D'0%200%2016%2016'%20width%3D'16px'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%20%3Cpath%20d%3D'm%204%2010.007812%20h%208%20v%201.988282%20h%20-8%20z%20m%200%200'%20fill%3D'currentColor'%2F%3E%20%3C%2Fsvg%3E");
43
+ --icon-window-maximize: url("data:image/svg+xml,%3Csvg%20height%3D'16px'%20viewBox%3D'0%200%2016%2016'%20width%3D'16px'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%20%3Cpath%20d%3D'm%203.988281%203.992188%20v%208.011718%20h%208.011719%20v%20-8.011718%20z%20m%202%202%20h%204.011719%20v%204.011718%20h%20-4.011719%20z%20m%200%200'%20fill%3D'currentColor'%2F%3E%20%3C%2Fsvg%3E");
41
44
  --icon-image-missing: url("data:image/svg+xml,%3Csvg%20height%3D'16px'%20viewBox%3D'0%200%2016%2016'%20width%3D'16px'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%20%3Cpath%20d%3D'm%204.015625%201.03125%20c%20-1.644531%200%20-3%201.355469%20-3%203%20v%201%20h%201%20v%20-1%20c%200%20-1.109375%200.890625%20-2%202%20-2%20h%201%20v%20-1%20z%20m%202%200%20v%201%20h%204%20v%20-1%20z%20m%205%200%20v%201%20h%201%20c%201.109375%200%202%200.890625%202%202%20v%201%20h%201%20v%20-1%20c%200%20-1.644531%20-1.355469%20-3%20-3%20-3%20z%20m%20-5%204%20c%20-0.550781%200%20-1%200.449219%20-1%201%20s%200.449219%201%201%201%20s%201%20-0.449219%201%20-1%20s%20-0.449219%20-1%20-1%20-1%20z%20m%20-5%201%20v%204%20h%201%20v%20-4%20z%20m%2013%200%20v%204%20h%201%20v%20-4%20z%20m%20-4.5%202%20l%20-2%202%20l%20-1.5%20-1%20l%20-2%202%20v%200.5%20c%200%200.5%200.5%200.5%200.5%200.5%20h%207%20s%200.472656%20-0.035156%200.5%20-0.5%20v%20-1%20z%20m%20-8.5%203%20v%201%20c%200%201.644531%201.355469%203%203%203%20h%201%20v%20-1%20h%20-1%20c%20-1.109375%200%20-2%20-0.890625%20-2%20-2%20v%20-1%20z%20m%2013%200%20v%201%20c%200%201.109375%20-0.890625%202%20-2%202%20h%20-1%20v%201%20h%201%20c%201.644531%200%203%20-1.355469%203%20-3%20v%20-1%20z%20m%20-8%203%20v%201%20h%204%20v%20-1%20z%20m%200%200'%20fill%3D'currentColor'%20fill-opacity%3D'0.34902'%2F%3E%20%3C%2Fsvg%3E");
42
45
  }
43
46
 
@@ -221,6 +224,21 @@
221
224
  -webkit-mask-image: var(--icon-application-x-executable);
222
225
  }
223
226
 
227
+ .adw-icon--window-close {
228
+ mask-image: var(--icon-window-close);
229
+ -webkit-mask-image: var(--icon-window-close);
230
+ }
231
+
232
+ .adw-icon--window-minimize {
233
+ mask-image: var(--icon-window-minimize);
234
+ -webkit-mask-image: var(--icon-window-minimize);
235
+ }
236
+
237
+ .adw-icon--window-maximize {
238
+ mask-image: var(--icon-window-maximize);
239
+ -webkit-mask-image: var(--icon-window-maximize);
240
+ }
241
+
224
242
  .adw-icon--image-missing {
225
243
  mask-image: var(--icon-image-missing);
226
244
  -webkit-mask-image: var(--icon-image-missing);
@@ -0,0 +1,107 @@
1
+ // _scrolling.scss — GtkScrolledWindow's edge indicators.
2
+ //
3
+ // The two states are drawn by ONE pseudo-element per edge, because they cannot be
4
+ // live at once: an undershoot means content is hidden past the edge, an overshoot
5
+ // means the position is past it. `src/scroll-shading.ts` decides which, and carries
6
+ // the overshoot's size in `--adw-overshoot`.
7
+ //
8
+ // Both boxes are sticky with a negative margin of their own height, so they weld to
9
+ // the scrollport edge and consume no layout — an absolutely positioned child of a
10
+ // scroll container scrolls away with the content instead of staying at the edge.
11
+ //
12
+ // Reference: refs/libadwaita/src/stylesheet/_drawing.scss (undershoot/overshoot mixins)
13
+ // Reference: refs/libadwaita/src/stylesheet/widgets/_scrolling.scss
14
+ // Reference: refs/gtk/gtk/gtkscrolledwindow.c (UNDERSHOOT_SIZE, MAX_OVERSHOOT_DISTANCE)
15
+ // Copyright (c) GNOME contributors (GTK, libadwaita). LGPLv2.1+.
16
+ // Modifications: Adapted for @gjsify/adwaita-web.
17
+
18
+ // `UNDERSHOOT_SIZE` — the band the node is allocated. Mostly transparent: the
19
+ // gradient over it is done after 4px.
20
+ $undershoot_size: 40px;
21
+
22
+ // The shade both gradients start from — `color-mix(… var(--shade-color) 75% …)`.
23
+ $undershoot_shade: color-mix(in srgb, var(--shade-color) 75%, transparent);
24
+
25
+ .adw-scroll-shaded {
26
+ // The two indicator boxes exist for every shaded scroller and stay invisible
27
+ // until a state class turns them on, so nothing has to be inserted or removed
28
+ // while scrolling.
29
+ &::before,
30
+ &::after {
31
+ content: '';
32
+ display: block;
33
+ position: sticky;
34
+ z-index: 1;
35
+ flex-shrink: 0;
36
+ pointer-events: none;
37
+ height: 0;
38
+ background: none;
39
+ box-shadow: none;
40
+ }
41
+
42
+ &::before {
43
+ top: 0;
44
+ }
45
+
46
+ &::after {
47
+ bottom: 0;
48
+ }
49
+
50
+ // --- Undershoot: "there is content past this edge" ---
51
+ //
52
+ // A 1px line at the very edge plus a 4px fade, both at 75% of the shade colour.
53
+ // Constant size: it says THAT content is hidden, never how much.
54
+ &.undershoot-top::before {
55
+ height: $undershoot_size;
56
+ margin-bottom: -$undershoot_size;
57
+ box-shadow: inset 0 1px $undershoot_shade;
58
+ background: linear-gradient(to bottom, $undershoot_shade, transparent 4px);
59
+ }
60
+
61
+ &.undershoot-bottom::after {
62
+ height: $undershoot_size;
63
+ margin-top: -$undershoot_size;
64
+ box-shadow: inset 0 -1px $undershoot_shade;
65
+ background: linear-gradient(to top, $undershoot_shade, transparent 4px);
66
+ }
67
+
68
+ // --- Overshoot: "there is nothing past this edge" ---
69
+ //
70
+ // Two stacked radial gradients in the CURRENT text colour — a tight 3% band at
71
+ // the edge over a soft 50% wash — sized to how far past the edge the position
72
+ // was pushed. `--adw-overshoot` is set per scroller by the shading controller.
73
+ &.overshoot-top::before,
74
+ &.overshoot-bottom::after {
75
+ height: var(--adw-overshoot, 0px);
76
+ background-repeat: no-repeat;
77
+ box-shadow: none;
78
+ // The spring-back: the size is driven from JS, the fade rides the transition
79
+ // so releasing the wheel eases out instead of cutting.
80
+ transition: height 200ms ease-out, opacity 200ms ease-out;
81
+ }
82
+
83
+ &.overshoot-top::before {
84
+ margin-bottom: calc(var(--adw-overshoot, 0px) * -1);
85
+ background-image:
86
+ radial-gradient(farthest-side at top, color-mix(in srgb, currentColor 12%, transparent) 85%, transparent),
87
+ radial-gradient(farthest-side at top, color-mix(in srgb, currentColor 5%, transparent), transparent);
88
+ background-size: 100% 3%, 100% 50%;
89
+ background-position: top;
90
+ }
91
+
92
+ &.overshoot-bottom::after {
93
+ margin-top: calc(var(--adw-overshoot, 0px) * -1);
94
+ background-image:
95
+ radial-gradient(farthest-side at bottom, color-mix(in srgb, currentColor 12%, transparent) 85%, transparent),
96
+ radial-gradient(farthest-side at bottom, color-mix(in srgb, currentColor 5%, transparent), transparent);
97
+ background-size: 100% 3%, 100% 50%;
98
+ background-position: bottom;
99
+ }
100
+
101
+ @media (prefers-reduced-motion: reduce) {
102
+ &.overshoot-top::before,
103
+ &.overshoot-bottom::after {
104
+ transition: none;
105
+ }
106
+ }
107
+ }
@@ -372,21 +372,34 @@ $_linked-nodes: '.adw-button', '.adw-entry';
372
372
  // `-start`/`-end` follow text direction, same as `margin-start`/`margin-end`,
373
373
  // which `:dir()` expresses directly.
374
374
  //
375
- // `adw-toolbar-view` carries the same two class names for its OWN top/bottom
376
- // indicators, drawn on its content node against the header shade
377
- // (`_toolbar_view.scss:67-86`) — so it is excluded here rather than getting both
378
- // a host shadow and a content gradient.
375
+ // THESE FOUR NAMES HAVE TWO WRITERS, so both of them are excluded here and this
376
+ // rule is left to the third: an author applying the documented style class by
377
+ // hand to markup adwaita-web does not drive.
378
+ //
379
+ // - `adw-toolbar-view` carries `undershoot-top`/`-bottom` as its own STATE
380
+ // (`update_undershoots`), and hands the two flags down to the scrollers.
381
+ // - `src/scroll-shading.ts` stamps all four onto every scroller under a toolbar
382
+ // view and marks it `.adw-scroll-shaded`; `_scrolling.scss` draws that one,
383
+ // per scroller, as the 1px line + 4px fade GTK paints on a `scrolledwindow`.
384
+ //
385
+ // Without the second exclusion each shaded scroller drew BOTH — a 6px blurred
386
+ // host shadow under the new gradient — and on the horizontal axis, which
387
+ // `_scrolling.scss` deliberately leaves unpainted because neither AdwTabBox nor
388
+ // AdwCarousel has a `scrolledwindow` node, this rule was the only thing drawing
389
+ // at all: an overflowing tab strip lost its own `inset 0 -1px` bottom hairline to
390
+ // this more specific `box-shadow` and gained an edge shadow libadwaita never
391
+ // draws there.
379
392
  $undershoot-color: color-mix(in srgb, currentColor 6%, transparent);
380
393
 
381
- .undershoot-top:not(adw-toolbar-view) {
394
+ .undershoot-top:not(adw-toolbar-view):not(.adw-scroll-shaded) {
382
395
  box-shadow: inset 0 6px 6px -6px $undershoot-color;
383
396
  }
384
397
 
385
- .undershoot-bottom:not(adw-toolbar-view) {
398
+ .undershoot-bottom:not(adw-toolbar-view):not(.adw-scroll-shaded) {
386
399
  box-shadow: inset 0 -6px 6px -6px $undershoot-color;
387
400
  }
388
401
 
389
- .undershoot-start {
402
+ .undershoot-start:not(.adw-scroll-shaded) {
390
403
  &:dir(ltr) {
391
404
  box-shadow: inset 6px 0 6px -6px $undershoot-color;
392
405
  }
@@ -396,7 +409,7 @@ $undershoot-color: color-mix(in srgb, currentColor 6%, transparent);
396
409
  }
397
410
  }
398
411
 
399
- .undershoot-end {
412
+ .undershoot-end:not(.adw-scroll-shaded) {
400
413
  &:dir(ltr) {
401
414
  box-shadow: inset -6px 0 6px -6px $undershoot-color;
402
415
  }
package/scss/_theme.scss CHANGED
@@ -17,6 +17,7 @@
17
17
  --headerbar-fg-color: #ffffff;
18
18
  --headerbar-shade-color: rgba(0, 0, 6, 0.36);
19
19
  --separator-color: rgba(255, 255, 255, 0.08);
20
+ --shade-color: rgba(0, 0, 6, 0.25);
20
21
  --sidebar-bg-color: #2e2e32;
21
22
  --sidebar-fg-color: #ffffff;
22
23
  --sidebar-backdrop-color: #28282c;
@@ -31,6 +31,35 @@ adw-toolbar-view {
31
31
  background-color: var(--window-bg-color);
32
32
  }
33
33
 
34
+ // THE CONTENT WIDGET FILLS THE CONTENT RECT. `adw_toolbar_view_size_allocate`
35
+ // (adw-toolbar-view.c:390-397) hands `self->content` the whole rect between the
36
+ // bars, and a GTK widget that wants less of it says so through its own
37
+ // alignment. This port collects the content into a flex COLUMN, where an item
38
+ // declaring no `flex-grow` is content-sized instead, so the child stopped
39
+ // wherever its content did and the pane below it stayed empty. Measured on the
40
+ // docs Navigation Split View preview: a 293px sidebar pane holding a 176px
41
+ // `adw-sidebar`, i.e. 117px of window-coloured dead strip under the last row,
42
+ // and beside it a status page top-aligned in a pane it was supposed to centre in.
43
+ // The web storybook had been papering over it in its own sheet
44
+ // (`.sb-sidebar-scroll { flex: 1 1 auto }`), deleted now that the widget carries
45
+ // it: a per-consumer copy is what a missing widget rule looks like from the
46
+ // outside, and it keeps the widget green while the next consumer hits the same
47
+ // wall.
48
+ //
49
+ // `:only-child` because Adw.ToolbarView HAS one content widget. Several stacked
50
+ // children are this port's own extension, and GTK defines no distribution for
51
+ // them, so inventing one here would be a claim rather than a copy.
52
+ //
53
+ // NO `min-height: 0` alongside it, deliberately: the automatic minimum size is
54
+ // already the right answer per child. A scroller (`adw-sidebar`, any
55
+ // `overflow: auto` box) gets an automatic minimum of 0 and shrinks to scroll
56
+ // itself, as its GtkScrolledWindow would; a status page keeps its content-based
57
+ // minimum, so a pane too short to hold it scrolls THIS box instead of crushing a
58
+ // centred column into overflow its reader cannot scroll back up to.
59
+ .adw-toolbar-view-content > :only-child {
60
+ flex: 1 1 auto;
61
+ }
62
+
34
63
  // top-bar-style / bottom-bar-style: an opaque background plus a persistent
35
64
  // shadow, which `.border` swaps for a hairline (adw-toolbar-view.c:1011-1024,
36
65
  // _toolbars.scss `> .top-bar.raised`).
@@ -60,30 +89,31 @@ adw-toolbar-view {
60
89
  }
61
90
  }
62
91
 
63
- // The scroll fade under a FLAT bar. libadwaita paints it on the scrolled
64
- // window; the browser equivalent is a non-interactive gradient stuck to the
65
- // scrollport edge, taking no space of its own — a NEGATIVE margin equal to its
66
- // height (_toolbars.scss :342-343, _scrolling.scss :150-157).
67
- &.undershoot-top .adw-toolbar-view-content::before,
68
- &.undershoot-bottom .adw-toolbar-view-content::after {
69
- content: '';
70
- position: sticky;
71
- height: 6px;
72
- flex-shrink: 0;
73
- pointer-events: none;
74
- }
75
-
76
- &.undershoot-top .adw-toolbar-view-content::before {
77
- top: 0;
78
- margin-bottom: -6px;
79
- background: linear-gradient(to bottom, var(--headerbar-shade-color), transparent);
92
+ // A bar in a toolbar view is INLINE — `%headerbar-inline` → `%headerbar-flat`:
93
+ // no background of its own, no separator, the content's foreground
94
+ // (_toolbars.scss :313-317, _header-bar.scss :110-147). That is what makes a
95
+ // flat-style view read as ONE surface with the bar sitting in it rather than as
96
+ // a bar bolted on top of a pane, and it is why the shading below is the ONLY
97
+ // thing that ever draws a line between them.
98
+ //
99
+ // Not folded into `%headerbar` itself: a header bar used as a WINDOW titlebar
100
+ // keeps its own background and shade, which is what `adw-header-bar` outside a
101
+ // toolbar view still renders.
102
+ .adw-toolbar-view-top,
103
+ .adw-toolbar-view-bottom {
104
+ &:not(.raised) adw-header-bar {
105
+ background: none;
106
+ color: inherit;
107
+ box-shadow: none;
108
+ }
80
109
  }
81
110
 
82
- &.undershoot-bottom .adw-toolbar-view-content::after {
83
- bottom: 0;
84
- margin-top: -6px;
85
- background: linear-gradient(to top, var(--headerbar-shade-color), transparent);
86
- }
111
+ // The scroll shading under a FLAT bar belongs to the SCROLLER, not to the view:
112
+ // upstream's selector is `toolbarview.undershoot-top scrolledwindow`, and GTK
113
+ // draws that node only while the scroller is off the edge. Drawn from the view
114
+ // instead — which is what this did — the fade is unconditional, so every flat
115
+ // bar sat behind a permanent hairline that native shows only after scrolling.
116
+ // `_scrolling.scss` + `src/scroll-shading.ts` now own it, per scroller.
87
117
  }
88
118
 
89
119
  // extend-content-to-*-edge: the content spans the full height and the bar is
@@ -24,6 +24,13 @@
24
24
  // draws separators, instead of a harsh near-black line on a dark surface.
25
25
  --separator-color: rgba(0, 0, 6, 0.1);
26
26
 
27
+ // The GENERIC shade the whole `*-shade-color` family below specialises
28
+ // (`_colors.scss:79,141`). Scroll undershoots are drawn from it, and it belongs
29
+ // to the palette rather than to any one widget: a scroller can sit on a window,
30
+ // a view, a sidebar or a card, and reading its neighbour's shade would make the
31
+ // same indicator four different colours.
32
+ --shade-color: rgba(0, 0, 6, 0.07);
33
+
27
34
  // Sidebar / split panes. libadwaita defines the whole family, not just the
28
35
  // background (_colors.scss:47-58), and only the background was here — so
29
36
  // `.sidebar-pane` had no foreground to name, and an app overriding
@@ -22,12 +22,19 @@ adw-view-switcher {
22
22
  min-height: 34px;
23
23
  }
24
24
 
25
- // Each tab is a flat, transparent toggle that lights up with a subtle fill
26
- // when hovered and shows the active page with an accent-tinted background.
25
+ // Each tab is a flat, transparent toggle that lights up with a subtle
26
+ // neutral fill when hovered and a slightly stronger one while selected.
27
27
  .adw-view-switcher-button {
28
28
  box-sizing: border-box;
29
29
  display: inline-flex;
30
30
  flex: 1 1 0; // homogeneous — every tab gets equal width
31
+ // `min-width: auto` is the flex-item default, and it floors every tab at
32
+ // its own min-content width, so a long title made ITS tab wider than the
33
+ // others and homogeneity silently stopped holding at exactly the widths
34
+ // where it matters. GTK's homogeneous box has no such floor
35
+ // (adw-view-switcher.c:475) and the labels ellipsize instead
36
+ // (adw-view-switcher-button.ui:42), which is what the 0 restores.
37
+ min-width: 0;
31
38
  align-items: center;
32
39
  justify-content: center;
33
40
  margin: 0;
@@ -63,6 +70,10 @@ adw-view-switcher {
63
70
  }
64
71
 
65
72
  .adw-view-switcher-label {
73
+ // Same min-content floor as the button, one level down: without it the
74
+ // `overflow: hidden` box never shrinks, so the ellipsis never appears
75
+ // and the label pushes its tab wide instead.
76
+ min-width: 0;
66
77
  white-space: nowrap;
67
78
  overflow: hidden;
68
79
  text-overflow: ellipsis;
@@ -99,12 +110,27 @@ adw-view-switcher {
99
110
  }
100
111
  }
101
112
 
113
+ // AdwViewSwitcherButton is a `.flat` GtkToggleButton
114
+ // (adw-view-switcher-button.ui:5-7), so its five states are
115
+ // `%button_basic_flat`'s currentColor alpha ladder, NOT the filled-button
116
+ // tokens: hover 7% / pressed 16%, and checked 10% / 13% / 19%
117
+ // (_buttons.scss:250-269 over _colors.scss:268-272). The same ladder the
118
+ // tab bar and the sidebar rows already spell out.
119
+ //
120
+ // It used to spend the FILLED-button tokens here: `--button-active-color`
121
+ // (.19 light / .22 dark) for the selected tab AND for its hover, and
122
+ // `--button-hover-color` (.13 / .15) for an unselected hover. Two defects
123
+ // in one rule. The selected tab sat at the shade upstream keeps for HELD
124
+ // DOWN, so it read as permanently pressed; and pinning its hover to that
125
+ // same value left the selected tab answering the pointer with nothing.
126
+ // Those tokens are also a FIXED rgba, so unlike the ladder they do not
127
+ // follow the foreground of whatever bar the switcher was dropped into.
102
128
  &:hover {
103
- background-color: var(--button-hover-color);
129
+ background-color: color-mix(in srgb, currentColor 7%, transparent);
104
130
  }
105
131
 
106
132
  &:active {
107
- background-color: var(--button-active-color);
133
+ background-color: color-mix(in srgb, currentColor 16%, transparent);
108
134
  }
109
135
 
110
136
  &:focus-visible {
@@ -112,15 +138,17 @@ adw-view-switcher {
112
138
  outline-offset: -2px;
113
139
  }
114
140
 
115
- // The selected view — a neutral filled chip (libadwaita darkens the
116
- // whole button; the icon/label keep the normal foreground colour
117
- // rather than turning accent).
141
+ // The selected view: a neutral fill over the whole tab. libadwaita leaves
142
+ // the foreground alone here, so no accent recolouring of icon or label.
118
143
  &.active {
119
- background-color: var(--button-active-color);
120
- color: var(--window-fg-color);
144
+ background-color: color-mix(in srgb, currentColor 10%, transparent);
121
145
 
122
146
  &:hover {
123
- background-color: var(--button-active-color);
147
+ background-color: color-mix(in srgb, currentColor 13%, transparent);
148
+ }
149
+
150
+ &:active {
151
+ background-color: color-mix(in srgb, currentColor 19%, transparent);
124
152
  }
125
153
  }
126
154
  }
@@ -141,8 +169,15 @@ adw-view-switcher {
141
169
  .adw-view-switcher-button {
142
170
  flex-direction: column;
143
171
  gap: 1px;
144
- padding-top: 4px;
145
- padding-bottom: 2px;
172
+ // The narrow box carries NO horizontal padding upstream: only
173
+ // `padding-top: 4px`, and the 3px per side plus the 2px below sit on
174
+ // the LABEL (_view-switcher.scss:15-24). Aggregated onto the button
175
+ // here because this port has no separate box node between button and
176
+ // label, which is the same geometry for every label at least as wide
177
+ // as the 16px icon. Overriding only the vertical halves left the wide
178
+ // policy's `2px 12px` standing, so a narrow tab spent 24px on side
179
+ // padding where libadwaita spends 6px.
180
+ padding: 4px 3px 2px;
146
181
  font-size: 0.75rem;
147
182
 
148
183
  .adw-view-switcher-label {
@@ -152,22 +187,47 @@ adw-view-switcher {
152
187
  }
153
188
  }
154
189
 
155
- // The paired content area showing the active page — a card-like surface
156
- // below the switcher (the web stand-in for the Adw.ViewStack body).
190
+ // The paired content area showing the active page: the Adw.ViewStack half of
191
+ // this composite, and it draws NOTHING. libadwaita's recommended arrangement
192
+ // is an AdwToolbarView whose top bar holds the switcher and whose `content`
193
+ // is the bare AdwViewStack (adw-view-switcher.c:41-73); no rule in
194
+ // `_view-switcher.scss`, `_toolbars.scss` or `_views.scss` frames that stack,
195
+ // and the standalone `adw-view-stack` element here says the same in its own
196
+ // words.
197
+ //
198
+ // It used to be a card: a 1px separator outline, a 12px radius, a 9px gap
199
+ // under the row and 12px of padding inside. On a page that gives the switcher
200
+ // its full width, that outline runs down the container's own left and right
201
+ // edges with its corners curling away from them, which reads as a broken
202
+ // frame rather than as a view. libadwaita has no line between the row and the
203
+ // content at all: a FLAT top bar (the default, adw-toolbar-view.c:731) has no
204
+ // background and no shade, and the only shading that ever appears is the
205
+ // scroller's undershoot, which `_scrolling.scss` owns per scroller for the
206
+ // reason `_toolbar_view.scss` records.
207
+ //
208
+ // `display: flex` is load-bearing, not decoration: this box is the stack, and
209
+ // `adw-view-stack` is a flex COLUMN for the same reason. Without it the box
210
+ // stays block-level, its child's `flex: 1 1 auto` below has no flex container
211
+ // to answer and is silently inert, and the visible page keeps stopping at its
212
+ // own text in a pane many times its height.
157
213
  .adw-view-switcher-content {
214
+ display: flex;
215
+ flex-direction: column;
158
216
  flex: 1 1 auto;
159
- margin-top: var(--spacing-s);
160
- padding: var(--spacing-m);
161
- background-color: var(--view-bg-color);
162
- border: 1px solid var(--separator-color);
163
- border-radius: var(--card-radius);
217
+ min-height: 0;
164
218
  }
165
219
 
220
+ // Mirrors `.adw-view-stack-child`: the visible page is handed the whole
221
+ // content area, which is what lets a status page centre itself in it the way
222
+ // AdwViewStack allocates to its visible child.
166
223
  .adw-view-switcher-page {
167
224
  display: none;
168
225
 
169
226
  &.active-view {
170
- display: block;
227
+ display: flex;
228
+ flex-direction: column;
229
+ flex: 1 1 auto;
230
+ min-height: 0;
171
231
  }
172
232
  }
173
233
  }