fix: wrap os tabs, close up stacked table rows

Every OS tab stays on screen at 320 px, stacked cells drop the
16 px sibling margin and push their row down when a label wraps,
short inline code keeps whole, lone card links get a 24 px target
and the card label column fits its longest label.
This commit is contained in:
Abdessamad Derraz committed 2026-10-23 18:39:42 +02:00
1 parent e1d35c3cb4
commit 8e1b49bc0f
4 files changed
+122 -26

No files matched your search

+4 -4
View File
@@ -156,11 +156,11 @@ class ThemeStylesheet(unittest.TestCase):
permalink = next(b for s, b in _blocks(self.css) if s == ".rb-permalink")
self.assertIn("min-height: 24px", permalink)
# 1.10, then round 3 item 1.3: one row that scrolls instead of two rows
# 1.10, then round 4 item 1.1: the row wraps, every tab on screen
def test_os_tabs_stay_reachable(self):
tablist = _rules(self.css, "starlight-tabs [role='tablist']")[0]
self.assertIn("flex-wrap: nowrap", tablist)
self.assertIn("overflow-x: auto", tablist)
self.assertIn("flex-wrap: wrap", tablist)
self.assertIn("overflow-x: visible", tablist)
self.assertIn("white-space: nowrap", _rules(self.css, "starlight-tabs [role='tab']")[0])
# 1.11
@@ -176,7 +176,7 @@ class ThemeStylesheet(unittest.TestCase):
self.assertIn("contain-intrinsic-size: auto 320px", cards)
self.assertIn("--sl-content-width: 54rem", _rules(self.css, "body:has(.rb-sys-file, .rb-file-entry)")[0])
facts = _rules(self.css, "dl.rb-facts")[0]
self.assertIn("grid-template-columns: 9rem minmax(0, 1fr)", facts)
self.assertIn("grid-template-columns: 11rem minmax(0, 1fr)", facts)
self.assertRegex(self.css, r"@media \(max-width: 30rem\) \{\s*\.sl-markdown-content dl\.rb-facts \{ grid-template-columns: minmax\(0, 1fr\)")
# 1.13
+2 -10
View File
@@ -2,7 +2,7 @@
Each test fails on the stylesheet as it was before the fix: commands allowed
to break inside any word on a phone, a sidebar whose top links outsize its
group labels, OS tabs on two rows, badge links cut to a few pixels by the
group labels, badge links cut to a few pixels by the
next row, 12 px hashes, Get your files tables each sizing their own columns.
"""
from __future__ import annotations
@@ -44,18 +44,10 @@ class ThemeStylesheetRound3(unittest.TestCase):
self.assertIn("font-size: var(--sl-text-sm)", links)
self.assertIn("font-weight: 400", links)
# 1.3
def test_os_tabs_on_one_row(self):
tablist = next(b for s, b in _blocks(self.css) if s == "starlight-tabs [role='tablist']")
self.assertIn("flex-wrap: nowrap", tablist)
self.assertIn("overflow-x: auto", tablist)
self.assertIn("scrollbar-width: none", tablist)
self.assertIn("display: none", _rules(self.css, "starlight-tabs [role='tablist']::-webkit-scrollbar")[0])
# 1.4
def test_badge_links_keep_a_24px_target(self):
dd = next(b for s, b in _blocks(self.css) if s == ".sl-markdown-content .rb-facts dd")
self.assertIn("line-height: 1.8", dd)
self.assertIn("line-height: 24px", dd)
badge = _rules(self.css, ".rb-facts :is(.rb-badge:has(> a), a.rb-badge)")[0]
for declaration in ("display: inline-flex", "align-items: center", "min-height: 24px", "margin-block: 2px"):
with self.subTest(declaration=declaration):
+84
View File
@@ -0,0 +1,84 @@
"""Round 4 theme: the stylesheet fixes of package 1, read from its source.
Each test fails on the stylesheet as it was before the fix: OS tabs on one
hidden scrolling row, stacked table cells 16 px apart with labels drawn over
the next row, short flags split across lines, lone card links 19 px high, a
card label column too narrow for its longest label.
"""
from __future__ import annotations
import unittest
from tests.test_site_r2_css import CSS_PATH, _blocks, _rules, _strip_comments
STACK = ".sl-markdown-content table[data-rb-stack] td"
def _block(css: str, selector: str) -> str:
bodies = [b for s, b in _blocks(css) if s == selector]
if not bodies:
raise AssertionError(f"no block {selector}")
return "".join(bodies)
class ThemeStylesheetRound4(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.raw = CSS_PATH.read_text(encoding="utf-8")
cls.css = _strip_comments(cls.raw)
# 1.1
def test_os_tabs_wrap_and_never_hide(self):
tablist = _block(self.css, "starlight-tabs [role='tablist']")
for declaration in ("flex-wrap: wrap", "overflow-x: visible", "row-gap: 0.25rem"):
with self.subTest(declaration=declaration):
self.assertIn(declaration, tablist)
self.assertNotIn("scrollbar-width: none", self.css)
self.assertNotIn("::-webkit-scrollbar", self.css)
# 1.2
def test_stacked_cells_close_up_and_labels_push_rows(self):
cell = _block(self.css, STACK)
for declaration in ("margin-top: 0", "display: flow-root", "line-height: 1.5",
"padding: 0.125rem 0.6rem 0.125rem 8.4rem"):
with self.subTest(declaration=declaration):
self.assertIn(declaration, cell)
label = _block(self.css, STACK + "::before")
self.assertIn("position: static", label)
self.assertIn("float: left", label)
self.assertNotIn("position: absolute", label)
# The label sits in the cell's left padding: 8.4 - 0.6 rem.
self.assertIn("margin-left: -7.8rem", label)
# 1.3
def test_short_inline_code_never_splits(self):
self.assertIn("white-space: pre", _block(self.css, ".sl-markdown-content :not(pre) > code.rb-short"))
self.assertIn("white-space: break-spaces", _block(self.css, ".sl-markdown-content :not(pre) > code"))
self.assertIn("white-space: nowrap", _block(self.css, ".sl-markdown-content table.rb-options td:first-child"))
# A stacked value column is narrow: short code there moves down whole
# and splits only when wider than the column, never pushing the page.
stacked = _block(self.css, STACK + " code.rb-short")
for declaration in ("display: inline-block", "max-width: 100%", "overflow-wrap: anywhere"):
with self.subTest(declaration=declaration):
self.assertIn(declaration, stacked)
# Commands in code blocks keep wrapping on a phone.
self.assertIn("white-space: pre-wrap", _block(self.css, ".sl-markdown-content .expressive-code pre > code"))
# 1.4
def test_lone_card_links_are_24px_targets(self):
dd = _block(self.css, ".sl-markdown-content .rb-facts dd")
self.assertIn("min-height: 24px", dd)
self.assertIn("line-height: 24px", dd)
link = _block(self.css, ".sl-markdown-content .rb-facts dd > a")
self.assertIn("display: inline-block", link)
self.assertIn("min-height: 24px", link)
# 1.5
def test_card_labels_fit_and_lookup_labels_match(self):
facts = _rules(self.css, "dl.rb-facts")[0]
self.assertIn("grid-template-columns: 11rem minmax(0, 1fr)", facts)
self.assertIn("font-weight: 600", _block(self.css, ".sl-markdown-content .rb-file-lookup label"))
if __name__ == "__main__":
unittest.main()
+32 -12
View File
@@ -467,14 +467,16 @@ body:has(.rb-sys-file, .rb-file-entry) { --sl-content-width: 54rem; }
/* The facts of a file card: label column, value column, one column on a phone. */
.sl-markdown-content dl.rb-facts {
display: grid;
grid-template-columns: 9rem minmax(0, 1fr);
grid-template-columns: 11rem minmax(0, 1fr);
gap: 0.2rem 1rem;
margin: 0.4rem 0 0;
font-size: 0.85rem;
}
.sl-markdown-content .rb-facts :is(dt, dd) { margin: 0; padding: 0; }
.sl-markdown-content .rb-facts dt { font-size: 0.8rem; font-weight: 400; color: var(--rb-text-secondary); }
.sl-markdown-content .rb-facts dd { min-width: 0; overflow-wrap: break-word; line-height: 1.8; }
.sl-markdown-content .rb-facts dd { min-width: 0; min-height: 24px; overflow-wrap: break-word; line-height: 24px; }
/* A lone link in a card value is a 24 px target too (WCAG 2.5.8). */
.sl-markdown-content .rb-facts dd > a { display: inline-block; min-height: 24px; }
/* A badge link in a card keeps a 24 px target, rows 4 px apart (WCAG 2.5.8). */
.sl-markdown-content .rb-facts :is(.rb-badge:has(> a), a.rb-badge) {
display: inline-flex;
@@ -577,6 +579,12 @@ abbr.rb-term[data-open]::after {
white-space: normal;
}
/* Inline code: a flag or a name of 30 characters or fewer (marked rb-short
at build time) never splits, longer code wraps at its spaces and keeps them. */
.sl-markdown-content :not(pre) > code { white-space: break-spaces; }
.sl-markdown-content :not(pre) > code.rb-short { white-space: pre; }
.sl-markdown-content table.rb-options td:first-child { white-space: nowrap; }
/* Forms: lookup, picker, table filters */
.rb-file-lookup,
.rb-picker fieldset {
@@ -595,6 +603,8 @@ abbr.rb-term[data-open]::after {
font: inherit;
}
.sl-markdown-content .rb-file-lookup input { flex: 1 1 20rem; font-family: var(--sl-font-mono); }
/* Both lookup labels, the hash and the file chooser, share one weight. */
.sl-markdown-content .rb-file-lookup label { font-weight: 600; }
.sl-markdown-content :is(.rb-file-lookup, .rb-picker) button {
background: var(--rb-link);
color: var(--sl-color-black);
@@ -685,9 +695,8 @@ site-search .pagefind-ui__result-tags { display: none; }
font-weight: 600;
}
/* OS tabs stay on one row and scroll sideways on a narrow phone. */
starlight-tabs [role='tablist'] { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
starlight-tabs [role='tablist']::-webkit-scrollbar { display: none; }
/* OS tabs wrap to a second row on a narrow phone: every tab stays on screen. */
starlight-tabs [role='tablist'] { flex-wrap: wrap; overflow-x: visible; row-gap: 0.25rem; }
starlight-tabs [role='tab'] { white-space: nowrap; }
/* A page without "On this page" keeps the column, and the search box above
@@ -719,21 +728,24 @@ starlight-tabs [role='tab'] { white-space: nowrap; }
}
.sl-markdown-content table[data-rb-stack] :is(tbody, tr) { display: block; }
.sl-markdown-content table[data-rb-stack] tr { padding: 0.5rem 0; border-top: 1px solid var(--rb-border); }
/* A cell holds its label as a float in its left padding: a label on two
lines pushes the row down instead of running into the next one. No
sibling margin between cells. */
.sl-markdown-content table[data-rb-stack] td {
display: block;
position: relative;
min-height: 1.6rem;
padding: 0.25rem 0.6rem 0.25rem 8.4rem;
display: flow-root;
margin-top: 0;
padding: 0.125rem 0.6rem 0.125rem 8.4rem;
border: 0;
line-height: 1.5;
text-align: left !important;
overflow-wrap: anywhere;
}
.sl-markdown-content table[data-rb-stack] td::before {
content: attr(data-label);
position: absolute;
top: 0.25rem;
left: 0.6rem;
position: static;
float: left;
width: 7.4rem;
margin-left: -7.8rem;
font-weight: 600;
color: var(--rb-text-secondary);
}
@@ -748,6 +760,14 @@ starlight-tabs [role='tab'] { white-space: nowrap; }
font-weight: 600;
color: var(--rb-text-secondary);
}
/* A stacked value column is about 14rem wide: short code moves to the
next line whole, and splits only when it is wider than the column. */
.sl-markdown-content table[data-rb-stack] td code.rb-short {
display: inline-block;
max-width: 100%;
white-space: pre-wrap;
overflow-wrap: anywhere;
}
/* On a phone every command wraps: the end of a one-liner is never
off-screen. A word is cut only when it cannot fit on a line. */