fix(stijl): de gebundelde profielen halen hun eigen contrastondergrens (#1818) #1820

Merged
brenno merged 2 commits from fix/checklist-contrast-default into main 2026-08-27 18:13:17 +00:00
Owner

Het standaardthema zakte door de contrasteis die de app zelf hanteert, zodra je een van zijn eigen diatypes gebruikte.

Wat er misging

checklistUncheckedColor: '#CBD5E1' op een witte dia is een verhouding van 1,48, tegen de 3,0 die SlideQualityAnalyzer._checkChecklistContrast eist (WCAG 1.4.11). Elk deck met een checklist-dia opende dus meteen op een waarschuwing die de auteur vanuit de .md niet kón oplossen — styling staat bewust niet in het bestand (FILE_FORMAT §3.2).

Gemeten op main, alle gebundelde profielen door de analyzer met een deck van titel/sectie/checklist/tabel/code:

profiel vóór na
Standaard 1 0
LibreKAT 0 0
Security 1 0
Vigilis 4 1 (benoemde uitzondering)

De kleur is nagerekend, niet gekozen

#94A3B8 — de voor de hand liggende volgende stap in de slate-ramp — haalt 2,56 en zou het dus niet hebben opgelost. De lichtste tint die 3,0 raakt ligt rond #8695AA (3,05): te weinig marge.

#64748B haalt 4,76 op wit. Belangrijker: het is de klasse kleur die op beide uitersten werkt — 3,90 / 3,75 / 3,07 op de donkere tinten die deze repo elders voert, waar het oude lichte grijs juist op wit faalde. Een midden-grijs is de enige keuze die 3:1 haalt ongeacht hoe de auteur zijn achtergrond zet.

Vier kopieën van dezelfde standaard moesten mee: de constructor, security, vigilis en — bijna vergeten — de terugval in ThemeProfile.fromJson. Was die laatste blijven staan, dan had een profiel dat zónder deze sleutel uit de instellingen komt de oude kleur teruggekregen, bij precies de gebruiker die er niets aan veranderd had. Er staat nu een test op dat die twee gelijk zijn.

Het bleek breder dan gemeld

Vigilis droeg er nog drie bij. Twee daarvan zijn dezelfde fout: de sectiedia tekent titleTextColor (wit) op het merkgeel #FFB8001,73, onleesbaar, bevestigd in de renderer (text_previews.dart, _titleColor), niet alleen in de analyzer.

Die achtergrond is nu het merkzwart #111318 (wit erop: 18,6). Het geel kón daar niet blijven zolang de sectie zijn tekstkleur deelt met de titeldia, en die moet wit blijven voor de bijna-zwarte titelachtergrond. Het merkaccent zelf is ongemoeid: accentColor is nog steeds #FFB800.

De botsing, hardop

Toegankelijkheid tegen merkidentiteit. Bij de sectie laat ik toegankelijkheid voorgaan: wit op geel is geen merkbesluit maar onleesbaar, en er was een reparatie die het geel als accent intact laat.

Bij de vierde bevinding niet. Datzelfde geel wordt óók als linkColor doorgegeven (bullets_previews.dart, table_preview.dart), en haalt op wit 1,73 waar 4,5 nodig is. Om dat te repareren moet het accent naar ongeveer #96690F, en dan verandert het zichtbare merk overal. Dat is een besluit van de merkeigenaar, niet van een reparatiebeurt — expliciet zo besloten. Het blijft dus staan, maar zichtbaar: als benoemde uitzondering in de test, met #1819 erbij. Van gedachten veranderen we zodra dat issue een kant op valt; de uitzondering gaat er dan uit, en de test dwingt dat af (zie hieronder).

Dat een Vigilis-deck vandaag onleesbare links heeft, is een echte toegankelijkheidsschuld. Hij is nu opgeschreven in plaats van onopgemerkt.

De poort die er niet was

Dat is het eigenlijke gat: niets hield de standaardwaarden aan hun eigen ondergrens. test/theme_profile_contrast_test.dart haalt nu elk gebundeld profiel door dezelfde SlideQualityAnalyzer als het kwaliteitspaneel, over een deck dat elk contrastpaar aanraakt dat de analyzer kent, en eist nul bevindingen.

Uitzonderingen staan in één expliciete map mét reden en issuenummer. En een tweede test faalt zodra een uitzondering niet meer nodig is — anders blijft hij staan nadat de kleur gerepareerd is en dekt hij stilletjes de volgende fout op datzelfde veld.

De test stond eerst rood: 4 van 7 faalden tegen de onherstelde waarden.

Bewust buiten scope

Het aangevinkte #2E7D64 haalt op #1E293B 2,95 — nét onder 3,0. Dat is een bestaand geval op een achtergrond die geen enkel gebundeld profiel voert, en repareren zou de standaard-accentkleur veranderen. Staat opgeschreven in de test, niet stilzwijgend meegenomen.

Gedraaid

  • make check — groen, exitcode 0 (niet door tail gepijpt)
  • make check-secrets — 0 bevindingen
  • make sast — 0 bevindingen
  • DAST (ZAP) niet gedraaid: dit raakt geen geserveerd weboppervlak.
  • Bewaker-blik gedaan. Er komt niets in het .md — styling staat daar bewust niet in — dus uitwisselbaarheid is niet in het geding. Wat wél geraakt wordt is een publieke belofte (waarde 4, en waarde 7): de app meet contrast bij de gebruiker, dus moeten zijn eigen profielen die lat halen. ACCESSIBILITY.md zei daar niets over en zegt het nu wel.

Closes #1818

Het standaardthema zakte door de contrasteis die de app zelf hanteert, zodra je een van zijn eigen diatypes gebruikte. ## Wat er misging `checklistUncheckedColor: '#CBD5E1'` op een witte dia is een verhouding van **1,48**, tegen de **3,0** die `SlideQualityAnalyzer._checkChecklistContrast` eist (WCAG 1.4.11). Elk deck met een checklist-dia opende dus meteen op een waarschuwing die de auteur vanuit de `.md` niet kón oplossen — styling staat bewust niet in het bestand (FILE_FORMAT §3.2). Gemeten op `main`, alle gebundelde profielen door de analyzer met een deck van titel/sectie/checklist/tabel/code: | profiel | vóór | na | | --- | --- | --- | | Standaard | 1 | 0 | | LibreKAT | 0 | 0 | | Security | 1 | 0 | | Vigilis | 4 | 1 (benoemde uitzondering) | ## De kleur is nagerekend, niet gekozen `#94A3B8` — de voor de hand liggende volgende stap in de slate-ramp — haalt **2,56** en zou het dus niet hebben opgelost. De lichtste tint die 3,0 raakt ligt rond `#8695AA` (3,05): te weinig marge. **`#64748B`** haalt **4,76** op wit. Belangrijker: het is de klasse kleur die op *beide* uitersten werkt — 3,90 / 3,75 / 3,07 op de donkere tinten die deze repo elders voert, waar het oude lichte grijs juist op wit faalde. Een midden-grijs is de enige keuze die 3:1 haalt ongeacht hoe de auteur zijn achtergrond zet. Vier kopieën van dezelfde standaard moesten mee: de constructor, `security`, `vigilis` en — bijna vergeten — de terugval in `ThemeProfile.fromJson`. Was die laatste blijven staan, dan had een profiel dat zónder deze sleutel uit de instellingen komt de oude kleur teruggekregen, bij precies de gebruiker die er niets aan veranderd had. Er staat nu een test op dat die twee gelijk zijn. ## Het bleek breder dan gemeld Vigilis droeg er nog drie bij. Twee daarvan zijn dezelfde fout: de sectiedia tekent `titleTextColor` (wit) op het merkgeel `#FFB800` — **1,73**, onleesbaar, bevestigd in de renderer (`text_previews.dart`, `_titleColor`), niet alleen in de analyzer. Die achtergrond is nu het merkzwart `#111318` (wit erop: 18,6). Het geel kón daar niet blijven zolang de sectie zijn tekstkleur deelt met de titeldia, en die moet wit blijven voor de bijna-zwarte titelachtergrond. **Het merkaccent zelf is ongemoeid**: `accentColor` is nog steeds `#FFB800`. ## De botsing, hardop **Toegankelijkheid tegen merkidentiteit.** Bij de sectie laat ik toegankelijkheid voorgaan: wit op geel is geen merkbesluit maar onleesbaar, en er was een reparatie die het geel als accent intact laat. Bij de vierde bevinding niet. Datzelfde geel wordt óók als `linkColor` doorgegeven (`bullets_previews.dart`, `table_preview.dart`), en haalt op wit 1,73 waar 4,5 nodig is. Om dat te repareren moet het accent naar ongeveer `#96690F`, en dan verandert het zichtbare merk overal. Dat is een besluit van de merkeigenaar, niet van een reparatiebeurt — expliciet zo besloten. Het blijft dus staan, maar **zichtbaar**: als benoemde uitzondering in de test, met [#1819](https://pawprint.vigilis.online/LibreKAT/Ocideck/issues/1819) erbij. Van gedachten veranderen we zodra dat issue een kant op valt; de uitzondering gaat er dan uit, en de test dwingt dat af (zie hieronder). Dat een Vigilis-deck vandaag onleesbare links heeft, is een echte toegankelijkheidsschuld. Hij is nu opgeschreven in plaats van onopgemerkt. ## De poort die er niet was Dat is het eigenlijke gat: niets hield de standaardwaarden aan hun eigen ondergrens. `test/theme_profile_contrast_test.dart` haalt nu elk gebundeld profiel door dezelfde `SlideQualityAnalyzer` als het kwaliteitspaneel, over een deck dat elk contrastpaar aanraakt dat de analyzer kent, en eist nul bevindingen. Uitzonderingen staan in één expliciete map mét reden en issuenummer. En een tweede test faalt zodra een uitzondering **niet meer nodig** is — anders blijft hij staan nadat de kleur gerepareerd is en dekt hij stilletjes de volgende fout op datzelfde veld. De test stond eerst rood: 4 van 7 faalden tegen de onherstelde waarden. ## Bewust buiten scope Het aangevinkte `#2E7D64` haalt op `#1E293B` **2,95** — nét onder 3,0. Dat is een bestaand geval op een achtergrond die geen enkel gebundeld profiel voert, en repareren zou de standaard-accentkleur veranderen. Staat opgeschreven in de test, niet stilzwijgend meegenomen. ## Gedraaid - `make check` — groen, exitcode 0 (niet door `tail` gepijpt) - `make check-secrets` — 0 bevindingen - `make sast` — 0 bevindingen - DAST (ZAP) niet gedraaid: dit raakt geen geserveerd weboppervlak. - **Bewaker-blik gedaan.** Er komt niets in het `.md` — styling staat daar bewust niet in — dus uitwisselbaarheid is niet in het geding. Wat wél geraakt wordt is een publieke belofte (waarde 4, en waarde 7): de app meet contrast bij de gebruiker, dus moeten zijn eigen profielen die lat halen. ACCESSIBILITY.md zei daar niets over en zegt het nu wel. Closes #1818
`checklistUncheckedColor: '#CBD5E1'` op wit is 1,48, tegen de 3,0 die
`SlideQualityAnalyzer` zelf eist. Elk deck met een checklist-dia opende dus op
een waarschuwing die de auteur vanuit de `.md` niet kón oplossen — styling
staat daar bewust niet in.

De nieuwe waarde is nagerekend, niet gekozen. `#94A3B8` haalt 2,56 en zou het
niet hebben opgelost; de lichtste tint die 3,0 raakt ligt rond `#8695AA` (3,05),
te weinig marge. `#64748B` haalt 4,76 op wit, en is de klasse kleur die op béide
uitersten werkt: 3,90 / 3,75 / 3,07 op de donkere tinten die deze repo elders
voert, waar het oude grijs juist op wit faalde.

Vier kopieën van dezelfde standaard: de constructor, security, vigilis en de
terugval in `fromJson` — die laatste bijna vergeten, en dan had een profiel dat
zonder deze sleutel uit de instellingen komt de oude kleur teruggekregen.

Vigilis droeg er nog twee bij uit dezelfde fout: de sectiedia tekende wit op het
merkgeel (1,73, onleesbaar). Die achtergrond is nu het merkzwart; `accentColor`
blijft #FFB800. Het geel als linkkleur is een merkbesluit en blijft staan als
benoemde uitzondering — zie #1819.

De test haalt elk gebundeld profiel door dezelfde analyzer als het
kwaliteitspaneel en eist nul bevindingen; een tweede test faalt zodra een
uitzondering niet meer nodig is, zodat hij wordt opgeruimd in plaats van
stilletjes de volgende fout te dekken. Stond eerst rood: 4 van 7.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
docs(toegankelijkheid): de app houdt nu ook zijn eigen profielen aan de lat (#1818)
All checks were successful
scans / scans (pull_request) Successful in 2m1s
static-gate / static-gate (pull_request) Successful in 4m56s
98bee9f8f7
ACCESSIBILITY.md beschreef dat het kwaliteitspaneel het deck van de gebruiker
meet, maar zei niets over de kleuren die de app zelf uitlevert. Precies daar zat
het gat: standaarden die dezelfde lat niet halen, terwijl de auteur er vanuit de
`.md` niets aan kan doen. Dat staat er nu, met de uitzonderingsregeling en het
ene geval dat vandaag openstaat.

FILE_FORMAT §3.2 noemt de nieuwe standaardwaarde met de reden erbij, in beide
talen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
brenno merged commit 1a50646e51 into main 2026-08-27 18:13:17 +00:00
Sign in to join this conversation.
No description provided.