web: the icon nav is a top bar at every width !428

merged merged by cmc on 2026-09-19 05:40 UTC · krz/gitbay:nav-topbar into main

3 files changed, +19 −50

Layout: unified · split

internal/web/static/img/mr-dark.png

Binary file not shown.

internal/web/static/img/mr-light.png

Binary file not shown.

internal/web/static/style.css +19 −50
@@ -120,7 +120,6 @@
120 --sp-7: 48px; 120 --sp-7: 48px;
121 121
122 /* the rail: a column the width of one hit target, a row one tall */ 122 /* the rail: a column the width of one hit target, a row one tall */
123 --rail-w: 3.5rem;
124 --rail-hit: 40px; 123 --rail-hit: 40px;
125 --rail-strip-h: 48px; 124 --rail-strip-h: 48px;
126 --rail-mark: 24px; 125 --rail-mark: 24px;
@@ -251,33 +250,28 @@ a.skip {
251} 250}
252a.skip:focus { top: var(--sp-3); text-decoration: none; } 251a.skip:focus { top: var(--sp-3); text-decoration: none; }
253 252
254/* ---- rail: one glyph per destination, no labels ---- 253/* ---- rail: one row of glyphs across the top, no labels ----
255 The column is the width of a hit target and nothing else. Every item is 254 One strip the height of a hit target, at every width: fixed squares,
256 a square link carrying an inline svg, its name in an aria-label and in a 255 no wrapping and no scrolling. Every item is a square link carrying an
257 visually hidden span, so the nav reads the same to a screen reader as 256 inline svg, its name in an aria-label and in a visually hidden span, so
258 the old text list did. */ 257 the nav reads the same to a screen reader as the old text list did. */
259.rail { 258.rail {
260 flex: none; 259 height: var(--rail-strip-h);
261 width: var(--rail-w);
262 background: var(--shell-bg); 260 background: var(--shell-bg);
263 color: var(--shell-fg); 261 color: var(--shell-fg);
264 border-right: 1px solid var(--shell-line); 262 border-bottom: 1px solid var(--shell-line);
265 position: sticky;
266 top: 0;
267 height: 100vh;
268 display: flex; 263 display: flex;
269 flex-direction: column; 264 flex-direction: row;
270 align-items: center; 265 align-items: center;
271 gap: var(--sp-1); 266 padding: 0 var(--sp-1);
272 padding: var(--sp-3) 0;
273} 267}
274a.brand { 268a.brand {
275 display: flex; 269 display: flex;
276 align-items: center; 270 align-items: center;
277 justify-content: center; 271 justify-content: center;
278 flex: none; 272 flex: none;
279 width: var(--rail-hit); 273 width: var(--rail-mark-box);
280 height: var(--rail-hit); 274 height: var(--rail-strip-h);
281 color: var(--shell-fg); 275 color: var(--shell-fg);
282} 276}
283a.brand:hover { text-decoration: none; } 277a.brand:hover { text-decoration: none; }
@@ -288,13 +282,11 @@ ul.raillist {
288 margin: 0; 282 margin: 0;
289 padding: 0; 283 padding: 0;
290 display: flex; 284 display: flex;
291 flex-direction: column;
292 align-items: center; 285 align-items: center;
293 gap: var(--sp-1);
294 min-width: 0; 286 min-width: 0;
295} 287}
296/* the spacer that holds settings, admin and the account cell at the far 288/* the spacer that holds settings, admin and the account cell at the far
297 end of the rail in either orientation */ 289 end of the row */
298.railgap { flex: 1; } 290.railgap { flex: 1; }
299.railicon { 291.railicon {
300 position: relative; 292 position: relative;
@@ -303,19 +295,18 @@ ul.raillist {
303 justify-content: center; 295 justify-content: center;
304 flex: none; 296 flex: none;
305 width: var(--rail-hit); 297 width: var(--rail-hit);
306 height: var(--rail-hit); 298 height: var(--rail-strip-h);
307 padding: 0; 299 padding: 0;
308 border: 0; 300 border: 0;
309 background: none; 301 background: none;
310 color: var(--shell-fg); 302 color: var(--shell-fg);
311 border-radius: var(--r-ctl);
312 cursor: pointer; 303 cursor: pointer;
313} 304}
314.railicon:hover { background: var(--shell-hover); text-decoration: none; } 305.railicon:hover { background: var(--shell-hover); text-decoration: none; }
315/* orange marks position — the rail's only accent */ 306/* orange marks position along the bottom edge — the rail's only accent */
316.railicon[aria-current] { 307.railicon[aria-current] {
317 background: var(--shell-hover); 308 background: var(--shell-hover);
318 box-shadow: inset 3px 0 0 var(--shell-mark); 309 box-shadow: inset 0 -2px 0 var(--shell-mark);
319} 310}
320.count { 311.count {
321 font-size: var(--fs-0); 312 font-size: var(--fs-0);
@@ -339,9 +330,7 @@ ul.raillist {
339.railfoot { 330.railfoot {
340 flex: none; 331 flex: none;
341 display: flex; 332 display: flex;
342 flex-direction: column;
343 align-items: center; 333 align-items: center;
344 gap: var(--sp-1);
345 min-width: 0; 334 min-width: 0;
346} 335}
347.railfoot a { color: var(--shell-fg); } 336.railfoot a { color: var(--shell-fg); }
@@ -352,7 +341,7 @@ a.railuser {
352 justify-content: center; 341 justify-content: center;
353 flex: none; 342 flex: none;
354 width: var(--rail-hit); 343 width: var(--rail-hit);
355 height: var(--rail-hit); 344 height: var(--rail-strip-h);
356} 345}
357a.railuser:hover { text-decoration: none; } 346a.railuser:hover { text-decoration: none; }
358a.railuser .avatar { width: var(--rail-mark); height: var(--rail-mark); } 347a.railuser .avatar { width: var(--rail-mark); height: var(--rail-mark); }
@@ -368,8 +357,9 @@ a.railuser .avatar { width: var(--rail-mark); height: var(--rail-mark); }
368 font-weight: 600; 357 font-weight: 600;
369} 358}
370 359
371/* ---- shell ---- */ 360/* ---- shell: the rail above, then the pane, which fills the rest of the
372.shell { display: flex; align-items: stretch; min-height: 100vh; } 361 viewport so the footer sits at the bottom of a short page ---- */
362.shell { display: flex; flex-direction: column; min-height: 100vh; }
373.pane { flex: 1; min-width: 0; display: flex; flex-direction: column; } 363.pane { flex: 1; min-width: 0; display: flex; flex-direction: column; }
374main.content { 364main.content {
375 flex: 1; 365 flex: 1;
@@ -1476,27 +1466,6 @@ svg.icon { vertical-align: -0.125em; }
1476} 1466}
1477 1467
1478@media (max-width: 52rem) { 1468@media (max-width: 52rem) {
1479 /* the rail becomes one row of the same glyphs: fixed squares, no
1480 wrapping and no scrolling. The squares narrow a step further below
1481 30rem, where eleven of them would not otherwise fit a phone. */
1482 .shell { display: block; }
1483 .rail {
1484 width: auto;
1485 height: var(--rail-strip-h);
1486 position: static;
1487 flex-direction: row;
1488 align-items: center;
1489 gap: 0;
1490 padding: 0 var(--sp-1);
1491 border-right: 0;
1492 border-bottom: 1px solid var(--shell-line);
1493 overflow: visible;
1494 }
1495 a.brand { width: var(--rail-mark-box); height: var(--rail-strip-h); }
1496 ul.raillist, .railfoot { flex-direction: row; gap: 0; }
1497 .railicon, a.railuser { height: var(--rail-strip-h); border-radius: 0; }
1498 /* the current item is marked along the bottom edge in a row */
1499 .railicon[aria-current] { box-shadow: inset 0 -2px 0 var(--shell-mark); }
1500 main.content { padding: var(--sp-4) var(--sp-4) var(--sp-5); } 1469 main.content { padding: var(--sp-4) var(--sp-4) var(--sp-5); }
1501 footer { padding: var(--sp-4); } 1470 footer { padding: var(--sp-4); }
1502 .repohead { padding: var(--sp-3) var(--sp-4) 0; } 1471 .repohead { padding: var(--sp-3) var(--sp-4) 0; }