Give every fastext destination a distinct mark; add skip-link, fix aria-label
All checks were successful
Deploy / deploy (push) Successful in 23s
All checks were successful
Deploy / deploy (push) Successful in 23s
Colours: "if the intent is to have them all different colors than lets have them all different colors." The locked eight only give five safe as full text (blue fails contrast, black's invisible on black), so the other three get their own treatments instead of sharing plain ink: Watch gets blue as a swatch-only accent (the button cap's colour, not the label), Activity gets an ordered-dither swatch (the other legal way to mark something without a ninth colour), and Settings alone keeps plain ink deliberately, as the one page with no live status of its own. Accessibility (items 1 and 3 from the design review, item 2 skipped per request — the header's download figure stays live and unmuted): - Added a skip-link, off-screen until focused, jumping past the 8-item top nav straight to each page's #main-content. - Renamed the nav's aria-label from "Fastext" (meaningless without the visual teletext context) to "Page navigation".
This commit is contained in:
parent
15936027de
commit
5dd49c505c
4 changed files with 79 additions and 28 deletions
28
CLAUDE.md
28
CLAUDE.md
|
|
@ -105,18 +105,22 @@ the user's Unraid home server. Server-side project directory is still named
|
|||
under the header on every page but the index — those pages carry no
|
||||
other nav, so it needs no scroll to reach. The index overrides it
|
||||
with `HOME_FASTEXT`, the original four-entry row, as its own closing
|
||||
line, since its body already lists every destination once. The
|
||||
original four (Index/Library/Discover/System) keep their `r`/`g`/
|
||||
`y`/`c` keyboard shortcut and colour; Requests also gets a colour
|
||||
(magenta, `--pending`) without a shortcut — a deliberate fit, not
|
||||
an arbitrary fifth pick, since Requests already is "waiting on a
|
||||
human" everywhere else magenta appears. That's the ceiling: the
|
||||
locked eight colours leave exactly five that read as legible text
|
||||
on black (blue fails contrast there, black is invisible), so Watch/
|
||||
Activity/Settings share plain ink rather than a sixth colour that
|
||||
doesn't exist in this palette. Whichever entry matches the current
|
||||
page renders as a `.fastext-here` span instead of a link — a page
|
||||
linking to itself did nothing, so it isn't offered as a click.
|
||||
line, since its body already lists every destination once. Every
|
||||
destination gets its own distinct mark — the locked eight colours
|
||||
only give five that read as legible text on black, so getting to
|
||||
eight took three treatments: five flat colours as text+swatch
|
||||
(Index/Library/Discover/System keep their `r`/`g`/`y`/`c` shortcut;
|
||||
Requests gets magenta/`--pending` with no shortcut — a deliberate
|
||||
fit, since Requests already is "waiting on a human" everywhere else
|
||||
magenta appears); Watch gets blue as a swatch-only accent (`.k-blue`
|
||||
— blue fails contrast as body text, so only the small cell carries
|
||||
it, not the row's own label); Activity gets an ordered-dither swatch
|
||||
(`.k-dither`, same mechanism as `--dither-mid`) rather than a flat
|
||||
colour. Settings alone keeps plain ink with no swatch treatment —
|
||||
deliberately, as the one page with no live status of its own.
|
||||
Whichever entry matches the current page renders as a
|
||||
`.fastext-here` span instead of a link — a page linking to itself
|
||||
did nothing, so it isn't offered as a click.
|
||||
- **Nothing is clipped, hidden, or sticky.** All seven page numbers and
|
||||
every fastext entry stay visible at every width, reflowing to another
|
||||
row rather than scrolling, truncating, or folding into a menu. No
|
||||
|
|
|
|||
34
app.py
34
app.py
|
|
@ -1303,24 +1303,34 @@ def service_urls():
|
|||
}
|
||||
|
||||
|
||||
# Every destination, for the top of every page but the index. Order
|
||||
# matches nav_items. The locked eight teletext colours leave exactly
|
||||
# five that read as text on black without inventing a ninth tone or
|
||||
# borrowing a colour that already means something else here: the four
|
||||
# with a real keyboard shortcut (r/g/y/c), plus magenta for Requests —
|
||||
# not arbitrary, it's the same --pending magenta a request already
|
||||
# shows once approved elsewhere, and Requests IS "waiting on a human".
|
||||
# Blue fails contrast as text and black is invisible on black, so the
|
||||
# three destinations left over (Watch/Activity/Settings) share plain
|
||||
# ink rather than a sixth colour that doesn't exist in this palette.
|
||||
# Every destination, for the top of every page but the index, each
|
||||
# with its own distinct treatment. Order matches nav_items. The
|
||||
# locked eight teletext colours only give five that read as full-
|
||||
# saturation text on black (blue fails contrast there), so getting all
|
||||
# eight distinct without inventing a ninth colour takes three
|
||||
# treatments, not one:
|
||||
# - Five flat colours, text and swatch both: the four with a real
|
||||
# keyboard shortcut (r/g/y/c), plus magenta for Requests — not
|
||||
# arbitrary, it's the same --pending magenta a request already
|
||||
# shows once approved elsewhere, and Requests IS "waiting on a
|
||||
# human".
|
||||
# - Blue as a swatch-only accent (Watch): legible as a small solid
|
||||
# cell — "the physical coloured button on the remote" — but not as
|
||||
# the row's own text colour, where it fails contrast.
|
||||
# - An ordered dither swatch (Activity): the one other legal way to
|
||||
# get a distinct mark out of this palette per base.css's own first
|
||||
# discipline, without smuggling in a ninth hue.
|
||||
# Settings keeps plain ink deliberately — the one purely administrative
|
||||
# destination with no live status of its own, so it's the one page
|
||||
# that gets no colour at all rather than an arbitrary last one.
|
||||
FULL_FASTEXT = [
|
||||
("k-red", "r", "100", "Index", "/"),
|
||||
("", "", "101", "Watch", "/watch"),
|
||||
("k-blue", "", "101", "Watch", "/watch"),
|
||||
("k-green", "g", "102", "Library", "/library"),
|
||||
("k-yellow", "y", "103", "Discover", "/discover"),
|
||||
("k-magenta", "", "104", "Requests", "/requests"),
|
||||
("k-cyan", "c", "105", "System", "/system"),
|
||||
("", "", "106", "Activity", "/activity"),
|
||||
("k-dither", "", "106", "Activity", "/activity"),
|
||||
("", "", "900", "Settings", "/settings"),
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,26 @@
|
|||
RULER (every bar is --bar-cells wide, no exceptions).
|
||||
═══════════════════════════════════════════════════════ */
|
||||
|
||||
/* ── Skip-link ──────────────────────────────────────────
|
||||
Off-screen until it receives focus, then it's a plain field row
|
||||
like any other — a solid colour ground, no border — sitting above
|
||||
everything else so tabbing past it reaches the header next. */
|
||||
.skip-link {
|
||||
position: absolute;
|
||||
top: -999px;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
padding: 0.5em 1ch;
|
||||
background: var(--field);
|
||||
color: var(--ink);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.16em;
|
||||
}
|
||||
.skip-link:focus {
|
||||
top: 0;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* ── Header row ─────────────────────────────────────────
|
||||
Teletext's top line, unchanged for forty years: the page
|
||||
number you are on, who is transmitting, and the clock. It
|
||||
|
|
@ -512,8 +532,10 @@ a.tt-row:focus-visible .tt-row-sub { color: var(--tt-black); }
|
|||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
/* The key's colour is carried by a solid cell at its head — the
|
||||
physical coloured button on the remote. */
|
||||
/* The key's identity is carried by a cell at its head — the physical
|
||||
coloured button on the remote. Solid for most; k-blue and k-dither
|
||||
override its background below, since a flat swatch can't carry
|
||||
every one of the eight destinations without repeating a colour. */
|
||||
.fastext a > span, .fastext-here > span {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
|
|
@ -538,6 +560,15 @@ a.tt-row:focus-visible .tt-row-sub { color: var(--tt-black); }
|
|||
.fastext .k-yellow { color: var(--voice); }
|
||||
.fastext .k-cyan { color: var(--live); }
|
||||
.fastext .k-magenta { color: var(--pending); }
|
||||
/* Blue fails contrast as body text on black, so it marks the swatch
|
||||
only — the button cap's colour, not the printed label — while the
|
||||
row's own text stays legible ink. */
|
||||
.fastext .k-blue::before { background: var(--field); }
|
||||
.fastext .k-blue:hover, .fastext .k-blue:focus-visible { background: var(--field); }
|
||||
/* The one other legal way to get a distinct mark out of eight colours
|
||||
without a ninth: an ordered dither, same mechanism as --dither-mid,
|
||||
in place of a flat swatch. */
|
||||
.fastext .k-dither::before { background: var(--dither-mid); }
|
||||
.fastext a:hover, .fastext a:focus-visible {
|
||||
background: currentColor;
|
||||
outline: none;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,12 @@
|
|||
</head>
|
||||
<body data-timezone="{{ timezone }}" data-url-base="{{ request.script_root }}"
|
||||
data-pages='{{ nav_items | tojson }}'>
|
||||
{#- Skip-link: every page but the index now opens with a full nav
|
||||
block before any real content — a keyboard or screen-reader visitor
|
||||
would otherwise tab through all eight destinations on every single
|
||||
visit. Off-screen until focused, then it's the first thing tabbing
|
||||
into the page reaches. -#}
|
||||
<a class="skip-link" href="#main-content">Skip to content</a>
|
||||
<!--
|
||||
THESIS: Media Centre is a broadcast information service, not a dashboard. It
|
||||
refuses the bordered-card grid every self-hosted dashboard ships, this one
|
||||
|
|
@ -56,7 +62,7 @@ provenance.
|
|||
index's own body already is the full nav. Everywhere else it leads,
|
||||
right under the header, since it's the only nav those pages carry. -#}
|
||||
{% set fastext_nav %}
|
||||
<nav class="fastext{{ '' if page == 'home' else ' fastext-top' }}" aria-label="Fastext">
|
||||
<nav class="fastext{{ '' if page == 'home' else ' fastext-top' }}" aria-label="Page navigation">
|
||||
{% for cls, key, num, label, href in fastext %}
|
||||
{% if num == here[1] %}
|
||||
<span class="fastext-here" aria-current="page"><span>{{ num }} {{ label }}</span></span>
|
||||
|
|
@ -71,7 +77,7 @@ provenance.
|
|||
|
||||
{% if page != 'home' %}{{ fastext_nav }}{% endif %}
|
||||
|
||||
<main class="tt-page">
|
||||
<main class="tt-page" id="main-content">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue