mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-23 20:29:06 -05:00
fix: round 3 theme
This commit is contained in:
commit
f59217e645
4 files changed
+147
-15
No files matched your search
@@ -156,9 +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
|
||||
def test_os_tabs_wrap(self):
|
||||
self.assertIn("flex-wrap: wrap", _rules(self.css, "starlight-tabs [role='tablist']")[0])
|
||||
# 1.10, then round 3 item 1.3: one row that scrolls instead of two rows
|
||||
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("white-space: nowrap", _rules(self.css, "starlight-tabs [role='tab']")[0])
|
||||
|
||||
# 1.11
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
"""Round 3 theme: the stylesheet fixes of package 1, read from its source.
|
||||
|
||||
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
|
||||
next row, 12 px hashes, Get your files tables each sizing their own columns.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
|
||||
from tests.test_site_r2_css import CSS_PATH, PAGE_BG, _blocks, _ratio, _rules, _strip_comments, _theme_tokens
|
||||
|
||||
PACKS = "table.rb-packs"
|
||||
|
||||
|
||||
class ThemeStylesheetRound3(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None:
|
||||
cls.css = _strip_comments(CSS_PATH.read_text(encoding="utf-8"))
|
||||
dark = _theme_tokens(cls.css, ":root")
|
||||
light = {**dark, **_theme_tokens(cls.css, ":root[data-theme='light']")}
|
||||
cls.tokens = {"dark": dark, "light": light}
|
||||
|
||||
# 1.1
|
||||
def test_commands_never_break_inside_a_word(self):
|
||||
blocks = _rules(self.css, ".expressive-code pre > code")
|
||||
self.assertTrue(blocks)
|
||||
for body in blocks:
|
||||
self.assertIn("white-space: pre-wrap", body, "commands keep wrapping")
|
||||
self.assertNotIn("overflow-wrap: anywhere", body)
|
||||
for selector in (".rb-facts code", ".rb-hash code", ".rb-meta-card td code"):
|
||||
with self.subTest(selector=selector):
|
||||
self.assertIn("overflow-wrap: anywhere", _rules(self.css, selector)[0])
|
||||
|
||||
# 1.2
|
||||
def test_sidebar_labels_above_links(self):
|
||||
label = _rules(self.css, ".top-level summary .large")[0]
|
||||
# 13 px grey semibold, no uppercase: the house style refuses small caps.
|
||||
for declaration in ("font-size: var(--sl-text-xs)", "font-weight: 600", "color: var(--rb-text-secondary)"):
|
||||
with self.subTest(declaration=declaration):
|
||||
self.assertIn(declaration, label)
|
||||
links = next(b for s, b in _blocks(self.css) if s == "#starlight__sidebar .top-level a")
|
||||
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)
|
||||
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):
|
||||
self.assertIn(declaration, badge)
|
||||
|
||||
# 1.5
|
||||
def test_hashes_are_13px_at_every_width(self):
|
||||
hashes = [b for s, b in _blocks(self.css) if ".rb-hash" in s and "font-size" in b]
|
||||
self.assertEqual(len(hashes), 1, "a second size for .rb-hash, on phones")
|
||||
self.assertIn("font-size: 0.8125rem", hashes[0])
|
||||
short = _rules(self.css, "td code[title]")[0]
|
||||
self.assertIn("white-space: nowrap", short)
|
||||
self.assertIn("underline dotted", short)
|
||||
self.assertIn("min-width: 12rem", _rules(self.css, "td.rb-reason")[0])
|
||||
|
||||
# 1.6
|
||||
def test_pack_tables_share_their_columns(self):
|
||||
base = next(b for s, b in _blocks(self.css) if PACKS in s and "table-layout" in b)
|
||||
self.assertIn("table-layout: fixed", base)
|
||||
self.assertIn("width: 100%", base)
|
||||
widths = {s.rsplit("th:nth-child(", 1)[1].split(")")[0]: b for s, b in _blocks(self.css)
|
||||
if PACKS in s and "th:nth-child(" in s}
|
||||
self.assertEqual({k: v.strip() for k, v in widths.items()},
|
||||
{"1": "width: 18%;", "2": "width: 20%;", "3": "width: 40%;", "4": "width: 22%;"})
|
||||
parts = next(b for s, b in _blocks(self.css) if PACKS in s and s.endswith(":is(a, .rb-button)"))
|
||||
self.assertIn("white-space: nowrap", parts)
|
||||
|
||||
def test_secondary_text_on_the_sidebar_meets_aa(self):
|
||||
for theme in ("light", "dark"):
|
||||
with self.subTest(theme=theme):
|
||||
fg = self.tokens[theme]["--rb-text-secondary"].strip()
|
||||
self.assertGreaterEqual(_ratio(fg, PAGE_BG[theme]), 4.5)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -333,6 +333,32 @@
|
||||
.sl-markdown-content table { font-variant-numeric: tabular-nums; }
|
||||
.sl-markdown-content table th { font-weight: 600; }
|
||||
.sl-markdown-content table[role='region']:focus-visible { outline: 2px solid var(--rb-link); outline-offset: 2px; }
|
||||
/* A hash in a table cell is its first 12 characters, the full value in the
|
||||
title: one line, dotted to say there is more on hover. */
|
||||
.sl-markdown-content td code[title] {
|
||||
white-space: nowrap;
|
||||
text-decoration: underline dotted;
|
||||
text-underline-offset: 0.2em;
|
||||
cursor: help;
|
||||
}
|
||||
@media (min-width: 50rem) {
|
||||
/* The reason a file is listed reads as a sentence, not a word per line. */
|
||||
.sl-markdown-content :is(td.rb-reason, td[data-label='Reason']) { min-width: 12rem; }
|
||||
|
||||
/* Get your files: every group table shares one set of columns. */
|
||||
.sl-markdown-content :is(table.rb-packs, table:has(td[data-label='Runs on']):has(td[data-label='ZIP'])) {
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
.sl-markdown-content :is(table.rb-packs, table:has(td[data-label='Runs on']):has(td[data-label='ZIP'])) th:nth-child(1) { width: 18%; }
|
||||
.sl-markdown-content :is(table.rb-packs, table:has(td[data-label='Runs on']):has(td[data-label='ZIP'])) th:nth-child(2) { width: 20%; }
|
||||
.sl-markdown-content :is(table.rb-packs, table:has(td[data-label='Runs on']):has(td[data-label='ZIP'])) th:nth-child(3) { width: 40%; }
|
||||
.sl-markdown-content :is(table.rb-packs, table:has(td[data-label='Runs on']):has(td[data-label='ZIP'])) th:nth-child(4) { width: 22%; }
|
||||
.sl-markdown-content :is(table.rb-packs, table:has(td[data-label='Runs on']):has(td[data-label='ZIP'])) td { overflow-wrap: break-word; }
|
||||
}
|
||||
/* A ZIP part link or button never breaks across two lines. */
|
||||
.sl-markdown-content :is(table.rb-packs, table:has(td[data-label='Runs on']):has(td[data-label='ZIP'])) td:last-child :is(a, .rb-button) { white-space: nowrap; }
|
||||
|
||||
/* Key and value cards: the empty header row is not drawn */
|
||||
.rb-meta-card thead,
|
||||
@@ -416,7 +442,7 @@ body:has(.rb-sys-file, .rb-file-entry) { --sl-content-width: 54rem; }
|
||||
.sl-markdown-content :is(.rb-sys-file, .rb-file-entry) li { margin: 0.1rem 0; }
|
||||
.rb-hash {
|
||||
font-family: var(--sl-font-mono);
|
||||
font-size: 0.78rem;
|
||||
font-size: 0.8125rem;
|
||||
color: var(--rb-text-secondary);
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
@@ -448,7 +474,15 @@ body:has(.rb-sys-file, .rb-file-entry) { --sl-content-width: 54rem; }
|
||||
}
|
||||
.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; }
|
||||
.sl-markdown-content .rb-facts dd { min-width: 0; overflow-wrap: break-word; line-height: 1.8; }
|
||||
/* 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;
|
||||
align-items: center;
|
||||
min-height: 24px;
|
||||
margin-block: 2px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.sl-markdown-content .rb-facts code { overflow-wrap: anywhere; }
|
||||
@media (max-width: 30rem) {
|
||||
.sl-markdown-content dl.rb-facts { grid-template-columns: minmax(0, 1fr); gap: 0; }
|
||||
@@ -636,22 +670,24 @@ site-search .pagefind-ui__result-tags { display: none; }
|
||||
}
|
||||
.sl-menu-button:has(~ :popover-open) { box-shadow: none; background: var(--sl-color-accent-low); }
|
||||
|
||||
/* Sidebar: small grey group labels, regular links, the current page on a
|
||||
tinted background with no bar or rule beside it. */
|
||||
/* Sidebar: small grey group labels above 14 px links, top-level links as
|
||||
large as the children, the current page on a tinted background with no
|
||||
bar or rule beside it. */
|
||||
#starlight__sidebar .top-level summary .large {
|
||||
font-size: var(--sl-text-xs);
|
||||
font-weight: 600;
|
||||
color: var(--rb-text-secondary);
|
||||
}
|
||||
#starlight__sidebar .top-level a { font-weight: 400; }
|
||||
#starlight__sidebar .top-level a { font-size: var(--sl-text-sm); font-weight: 400; }
|
||||
#starlight__sidebar .top-level a[aria-current='page'] {
|
||||
background: var(--sl-color-accent-low);
|
||||
color: var(--sl-color-accent-high);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* OS tabs wrap on a narrow phone instead of hiding the last one. */
|
||||
starlight-tabs [role='tablist'] { flex-wrap: wrap; }
|
||||
/* 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; }
|
||||
starlight-tabs [role='tab'] { white-space: nowrap; }
|
||||
|
||||
/* A page without "On this page" keeps the column, and the search box above
|
||||
@@ -713,10 +749,10 @@ starlight-tabs [role='tab'] { white-space: nowrap; }
|
||||
color: var(--rb-text-secondary);
|
||||
}
|
||||
|
||||
/* On a phone every command wraps: the end of a one-liner is never off-screen. */
|
||||
.sl-markdown-content .expressive-code pre > code { white-space: pre-wrap; overflow-wrap: anywhere; }
|
||||
.sl-markdown-content :is(.rb-sys-file, .rb-file-entry) ul,
|
||||
.rb-hash { font-size: 0.75rem; }
|
||||
/* 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. */
|
||||
.sl-markdown-content .expressive-code pre > code { white-space: pre-wrap; }
|
||||
.sl-markdown-content :is(.rb-sys-file, .rb-file-entry) ul { font-size: 0.75rem; }
|
||||
}
|
||||
|
||||
@media (max-width: 50rem) {
|
||||
|
||||
@@ -54,7 +54,7 @@ Every module in `tests/`, by the area it guards.
|
||||
| Installer and downloads | loopback server | `test_check_release`, `test_download`, `test_install`, `test_install_cores`, `test_install_experience`, `test_install_offline`, `test_install_selection` |
|
||||
| Handheld port | stubbed PortMaster dialogs, fake installer | `test_port` |
|
||||
| Truth and native export | synthetic + cached originals | `test_export_counts`, `test_export_native_layer`, `test_export_report`, `test_exporters`, `test_truth_data_dir_readers`, `test_truth_diff`, `test_truth_layout` |
|
||||
| Scrapers, upstream and provenance | inline sources, synthetic | `test_batocera_md5_list`, `test_check_freshness`, `test_contributing_text`, `test_coverage_cache`, `test_data_dir_refs`, `test_dataclass_defaults`, `test_dedup`, `test_doc_pages`, `test_doc_surfaces`, `test_elec_scrapers`, `test_fbneo_parser`, `test_find_pinned_revision`, `test_hash_merge`, `test_launchers`, `test_launchers_emudeck`, `test_launchers_recalbox`, `test_launchers_retrobat`, `test_launchers_retrodeck`, `test_launchers_retropie`, `test_launchers_rocknix`, `test_mame_devices`, `test_mame_parser`, `test_mame_ref_audit`, `test_optional_dependencies`, `test_profile_sync`, `test_prose_style`, `test_provenance`, `test_refresh_data_dirs`, `test_refresh_failures`, `test_refresh_stale`, `test_retrodeck_scraper_errors`, `test_romset_recipes`, `test_schema_semantic_gate`, `test_scraper_contract`, `test_site_availability`, `test_site_content_data`, `test_site_copy`, `test_site_cores`, `test_site_emulator_page`, `test_site_exports`, `test_site_funnel`, `test_site_images`, `test_site_picker`, `test_site_platform_hashes`, `test_site_r2_components`, `test_site_r2_css`, `test_site_r2_emulators`, `test_site_r2_entry`, `test_site_r2_gate`, `test_site_r2_nav`, `test_site_r2_p0`, `test_site_r2_reference`, `test_site_r2_systems`, `test_site_r2_wiki`, `test_site_r3_collection`, `test_site_r3_p0`, `test_site_render`, `test_site_system_links`, `test_site_validation`, `test_site_weight`, `test_site_write`, `test_upstream`, `test_upstream_index`, `test_validate_pr`, `test_validate_pr_flow`, `test_validate_pr_hashes`, `test_workflow_paths` |
|
||||
| Scrapers, upstream and provenance | inline sources, synthetic | `test_batocera_md5_list`, `test_check_freshness`, `test_contributing_text`, `test_coverage_cache`, `test_data_dir_refs`, `test_dataclass_defaults`, `test_dedup`, `test_doc_pages`, `test_doc_surfaces`, `test_elec_scrapers`, `test_fbneo_parser`, `test_find_pinned_revision`, `test_hash_merge`, `test_launchers`, `test_launchers_emudeck`, `test_launchers_recalbox`, `test_launchers_retrobat`, `test_launchers_retrodeck`, `test_launchers_retropie`, `test_launchers_rocknix`, `test_mame_devices`, `test_mame_parser`, `test_mame_ref_audit`, `test_optional_dependencies`, `test_profile_sync`, `test_prose_style`, `test_provenance`, `test_refresh_data_dirs`, `test_refresh_failures`, `test_refresh_stale`, `test_retrodeck_scraper_errors`, `test_romset_recipes`, `test_schema_semantic_gate`, `test_scraper_contract`, `test_site_availability`, `test_site_content_data`, `test_site_copy`, `test_site_cores`, `test_site_emulator_page`, `test_site_exports`, `test_site_funnel`, `test_site_images`, `test_site_picker`, `test_site_platform_hashes`, `test_site_r2_components`, `test_site_r2_css`, `test_site_r2_emulators`, `test_site_r2_entry`, `test_site_r2_gate`, `test_site_r2_nav`, `test_site_r2_p0`, `test_site_r2_reference`, `test_site_r2_systems`, `test_site_r2_wiki`, `test_site_r3_collection`, `test_site_r3_css`, `test_site_r3_p0`, `test_site_render`, `test_site_system_links`, `test_site_validation`, `test_site_weight`, `test_site_write`, `test_upstream`, `test_upstream_index`, `test_validate_pr`, `test_validate_pr_flow`, `test_validate_pr_hashes`, `test_workflow_paths` |
|
||||
|
||||
## Test architecture
|
||||
|
||||
|
||||
Reference in new issue
Block a user