Skip to main content

max / goingson

The two filter rows are runs, and the toolbars can shrink again The contacts and email filter rows were grids of `auto` tracks, which cannot fall back. At 560 and below the contacts row's two `auto` tracks resolved to 0px and its tag select painted outside its track; the email row, five members against four declared tracks, put its folder and label selects on top of each other, 134px of overlap at 320. Both are `.run.run-wrap` now: the field carries the basis that decides where the row breaks, and the controls wrap under it at every width with no breakpoint. Two Compact rules went with them, both written for the grid: the search inputs' `grid-column: 1 / -1` and the `min-width: 0 !important; flex: 1` on the email selects, which squashed both to 29px at 320 and is this file's own smell test. `.page-header[data-for=...]` also came out of four `flex-shrink: 0` rules. Those keep a subview's column from squashing its fixed parts, and the toolbar left that column in 5fa511a to join the tab row's run, where the same declaration read as "never give horizontal room" and pinned the run 81px wider than the viewport. Census of what remains, and the two findings that are not defects: wiki `goingson-overlap-census`.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-18 21:24 UTC
Signed with PGP, not checked
Commit: e01dfe2e9677ac23dad7b557d914267598a2ab4d
Parent: d83e7ce
2 files changed, +47 insertions, -48 deletions
@@ -544,7 +544,7 @@
544 544 </div>
545 545 <div class="page-header subview-head hidden" data-for="contacts">
546 546 <h2 class="page-title">Contacts</h2>
547 - <div class="contacts-filter-row">
547 + <div class="run run-wrap contacts-filter-row">
548 548 <input type="text" class="field" id="contacts-search" placeholder="Search contacts..." data-input="contacts.filterBySearch">
549 549 <select class="filter-select" id="contacts-tag-filter" data-change="contacts.filterByTag">
550 550 <option value="">All Tags</option>
@@ -564,7 +564,7 @@
564 564 <!-- Emails Sub-View -->
565 565 <div id="emails-view" class="subview" role="tabpanel" aria-labelledby="emails-tab">
566 566
567 - <div class="email-filter-row mb-peer">
567 + <div class="run run-wrap email-filter-row mb-peer">
568 568 <input type="text" class="field" id="email-search" placeholder="Search emails..." data-input="emails.search">
569 569 <select class="field" id="email-folder-filter" data-change="emails.filterByFolder">
570 570 <option value="">All folders</option>
@@ -31,8 +31,9 @@
31 31 whose intrinsic-min-content sizing fights `flex: 1`. Smell test: if you
32 32 find yourself reaching for `.field--compact`, `style="width: auto;"`,
33 33 or `min-width: 0 !important` to make a row lay out right, the layout
34 - itself wants a name. See `.email-filter-row`, `.contacts-filter-row`, and
35 - `.work-hours-row` (all 2026-05-24) for the canonical form.
34 + itself wants a name. See `.work-hours-row` (2026-05-24) for the canonical
35 + form, and `.email-filter-row` / `.contacts-filter-row`, which took the same
36 + naming to a declared run with a fallback on 2026-08-18.
36 37
37 38 FILE STRUCTURE: search by BAND name (uppercase anchors) to navigate.
38 39 Per-section titles use numbered CSS-comment headers ("3. Design System
@@ -5228,7 +5229,12 @@
5228 5229 min-height: 0;
5229 5230 }
5230 5231
5231 - .page-header[data-for="tasks"],
5232 + /* No `.page-header[data-for="tasks"]` here. These `flex-shrink: 0` rules keep the
5233 + subview's own column from squashing its fixed parts, and the toolbar left that
5234 + column on 2026-08-18 (5fa511a) to become a member of the tab row's run. In a row
5235 + it read as "never give horizontal room", which pinned the run wider than its
5236 + container -- cause 3 of wiki `goingson-overlap-census` arriving at the site of
5237 + cause 2. */
5232 5238 #tasks-view .bulk-actions-bar,
5233 5239 #tasks-view .mobile-sort-bar,
5234 5240 #tasks-view .filter-bar,
@@ -5252,7 +5258,8 @@
5252 5258 min-height: 0;
5253 5259 }
5254 5260
5255 - .page-header[data-for="events"],
5261 + /* No `.page-header[data-for="events"]` here; it is a member of the tab row's run
5262 + now, not of this column. See the note on the tasks rule above. */
5256 5263 #events-view .filter-bar,
5257 5264 #events-view .bulk-actions-bar {
5258 5265 flex-shrink: 0;
@@ -5273,40 +5280,33 @@
5273 5280 min-height: 0;
5274 5281 }
5275 5282
5276 - /* Email filter row: search input flexes; selects + count are content-sized.
5277 - Grid columns make the geometry explicit and immune to <select> intrinsic
5278 - min-content shenanigans that flex layout exposes. */
5279 - .email-filter-row {
5280 - display: grid;
5281 - grid-template-columns: minmax(0, 1fr) auto auto auto;
5282 - gap: var(--gap-peer);
5283 - align-items: center;
5284 - }
5285 - .email-filter-row > .field {
5286 - width: 100%;
5287 - min-width: 0;
5288 - }
5289 - .email-filter-row > select.field {
5290 - width: 9rem;
5291 - }
5283 + /* The two filter rows, one shape: a search field leads and the controls
5284 + beside it follow. Both are runs (`.run.run-wrap`), not grids.
5292 5285
5293 - /* Contacts filter row: same shape as .email-filter-row (search fills,
5294 - filter sizes to content, action button sizes to content). Tag filter
5295 - uses .filter-select rather than .field, but the layout rule is
5296 - identical. */
5286 + They were `display: grid` with `auto` tracks until 2026-08-18, and a grid
5287 + of `auto` tracks cannot fall back: at 560 and below the contacts row's two
5288 + `auto` tracks resolved to 0px and its tag select painted outside its track,
5289 + and the email row -- five members against four declared tracks -- put its
5290 + folder and label selects on top of each other, 134px of overlap at 320.
5291 + Wrap is the fallback the ruling asks for: the field keeps the first line,
5292 + the controls move under it, no breakpoint and no member leaving the row.
5293 + Rule 3, relief resolving inside-out, one level in from the tab row above.
5294 + See wiki `layout-room-and-fallback` and `goingson-overlap-census` cause 2.
5295 +
5296 + The basis is what decides where it wraps: the field asks for 12rem and
5297 + grows, so the run breaks when the field would drop under a searchable
5298 + width rather than when the last control happens not to fit. */
5299 + .email-filter-row,
5297 5300 .contacts-filter-row {
5298 - display: grid;
5299 - grid-template-columns: minmax(0, 1fr) auto auto;
5300 5301 gap: var(--gap-peer);
5301 - align-items: center;
5302 5302 }
5303 - .contacts-filter-row > .field {
5304 - width: 100%;
5305 - min-width: 0;
5303 + .email-filter-row > input.field,
5304 + .contacts-filter-row > input.field {
5305 + flex: 1 1 12rem;
5306 5306 }
5307 + .email-filter-row > select.field,
5307 5308 .contacts-filter-row > .filter-select {
5308 - width: 9rem;
5309 - min-width: 0;
5309 + flex: 0 0 9rem;
5310 5310 }
5311 5311
5312 5312 /* Work-hours row in Settings: two small selects with a "to" label
@@ -5322,7 +5322,8 @@
5322 5322 width: auto;
5323 5323 }
5324 5324
5325 - .page-header[data-for="emails"],
5325 + /* No `.page-header[data-for="emails"]` here; it is a member of the tab row's run
5326 + now, not of this column. See the note on the tasks rule above. */
5326 5327 #emails-view .email-filter-row,
5327 5328 #emails-view .bulk-actions-bar,
5328 5329 #email-pagination {
@@ -5338,7 +5339,8 @@
5338 5339 min-height: 0;
5339 5340 }
5340 5341
5341 - .page-header[data-for="contacts"],
5342 + /* No `.page-header[data-for="contacts"]` here; it is a member of the tab row's run
5343 + now, not of this column. See the note on the tasks rule above. */
5342 5344 #contacts-view .bulk-actions-bar {
5343 5345 flex-shrink: 0;
5344 5346 }
@@ -7423,13 +7425,11 @@
7423 7425 display: none;
7424 7426 }
7425 7427
7426 - /* Search inputs always span the full grid row. */
7427 - #email-search,
7428 - #contacts-search {
7429 - grid-column: 1 / -1;
7430 - width: 100%;
7431 - min-width: 0;
7432 - }
7428 + /* No `#email-search` / `#contacts-search` rule here. It set `grid-column:
7429 + 1 / -1` plus `min-width: 0`, which was the two filter rows' grid asking
7430 + for the whole row at Compact. They are runs now and the field's own
7431 + basis decides where they break, in one declaration for every width, so a
7432 + breakpoint restating it can only disagree. */
7433 7433
7434 7434 /* The email-count span ("48 threads") is inside the grid row, hide
7435 7435 on mobile; will get a tidier home in layer-2 trims. */
@@ -7527,11 +7527,10 @@
7527 7527 margin-left: auto;
7528 7528 }
7529 7529
7530 - /* Email filter row: let selects shrink and wrap instead of forcing 120px. */
7531 - #emails-view select.field[id^="email-"] {
7532 - min-width: 0 !important;
7533 - flex: 1;
7534 - }
7530 + /* No `#emails-view select.field[id^="email-"]` rule here. It was
7531 + `min-width: 0 !important; flex: 1` -- this file's own smell test in the
7532 + header, and it squashed both selects to 29px at 320. The run wraps them
7533 + whole instead. */
7535 7534
7536 7535 textarea.field {
7537 7536 min-height: 72px;