diff --git a/public/neu/ansichten.css b/public/neu/ansichten.css index 3a19372..7a48c8e 100644 --- a/public/neu/ansichten.css +++ b/public/neu/ansichten.css @@ -125,7 +125,6 @@ .kn-az-balken li { position: relative; flex: 1; height: 4px; } .kn-az-balken li::before { content: ""; position: absolute; inset: 0; border-radius: 2px; background: var(--kn-line); } /* die Fläche liegt im Pseudo-Element: der Lesetext darunter bleibt auf Weiß */ .kn-az-balken li.is-done::before { background: var(--kn-accent); } -.kn-nur-lesen { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; } .kn-az-zeitleiste { margin: 14px 0 0; } .kn-az-zeilen { list-style: none; margin: 0 0 0 3px; padding: 0; border-left: 1px solid var(--kn-line-strong); } .kn-az-zeilen li { position: relative; display: flex; gap: 10px; padding: 4px 0 4px 16px; font-size: 14px; line-height: 20px; } diff --git a/public/neu/auftrags-zeitleiste.js b/public/neu/auftrags-zeitleiste.js index 529adb3..c17d5c9 100644 --- a/public/neu/auftrags-zeitleiste.js +++ b/public/neu/auftrags-zeitleiste.js @@ -143,7 +143,7 @@ function baueBalken(status) { if (!stufen.some((stufe) => stufe.erreicht)) return null return h('ol', { class: 'kn-az-balken', 'aria-label': 'Fortschritt des Auftrags' }, stufen.map((stufe) => h('li', { class: stufe.erreicht ? 'is-done' : null, 'aria-current': stufe.aktuell ? 'step' : null }, - h('span', { class: 'kn-nur-lesen' }, `${stufe.name}, ${zustandText(stufe)}`)))) + h('span', { class: 'kn-nur-leser' }, `${stufe.name}, ${zustandText(stufe)}`)))) } let listenNummer = 0 // Ids der Listen für aria-controls: eindeutig je Seite, auch wenn die Ansicht mehrmals gezeichnet wird diff --git a/test/knAnsichtStil.test.js b/test/knAnsichtStil.test.js index 6d23fc4..ab18198 100644 --- a/test/knAnsichtStil.test.js +++ b/test/knAnsichtStil.test.js @@ -19,7 +19,7 @@ test('Stil: Farbliterale nur in Custom-Property-Deklarationen, jedes benutzte To test('Stil: jede kn-Klasse der P2-Module hat eine Regel', () => { const klassen = new Set(); for (const n of MODULE.filter(existiert)) for (const m of lies(n).matchAll(/class:\s*'([^']+)'/g)) m[1].split(/\s+/).filter((k) => k.startsWith('kn-')).forEach((k) => klassen.add(k)) for (const wert of Object.values(K).flatMap((v) => (typeof v === 'string' ? [v] : Object.values(v)))) wert.split(/\s+/).filter((k) => k.startsWith('kn-')).forEach((k) => klassen.add(k)) - for (const k of klassen) assert.match(BASIS + A, new RegExp(`\\.${k}(?![\\w-])`), `Klasse ohne Regel: ${k}`) + for (const k of klassen) assert.match(BASIS + A + css('huelle.css'), new RegExp(`\\.${k}(?![\\w-])`), `Klasse ohne Regel: ${k}`) // huelle.css trägt .kn-nur-leser (Text nur für Vorlesegeräte) }) test('Stil: Aufträge-Abschnitt, Chat-Variablen, hidden und Handy-Abfrage', () => { const ab = new Set([...(lese('auftrag-dom.js') + lese('auftrag-portal.js')).matchAll(/\bab-[a-z0-9]+(?:-[a-z0-9]+)*/g)].map((m) => m[0])) diff --git a/test/knAuftragsZeitleisteDom.test.js b/test/knAuftragsZeitleisteDom.test.js index 140968b..f85e9ad 100644 --- a/test/knAuftragsZeitleisteDom.test.js +++ b/test/knAuftragsZeitleisteDom.test.js @@ -53,8 +53,8 @@ test('Aktivität: schmaler Balken mit vier Abschnitten, Stufennamen als Text fü assert.deepEqual(stand(pruefung), [[true, null], [true, null], [true, 'step'], [false, null]]) assert.deepEqual(stand(fertig), [[true, null], [true, null], [true, null], [true, 'step']]) const balken = fx.finde(wartet, '.kn-az-balken'); assert.equal(balken.tagName, 'OL'); assert.equal(balken.getAttribute('aria-label'), 'Fortschritt des Auftrags') - assert.deepEqual(fx.alle(balken, '.kn-nur-lesen').map((s) => s.textContent), ['Eingegangen, erreicht', 'In Arbeit, aktueller Stand', 'Prüfung, noch offen', 'Erledigt, noch offen']) - assert.deepEqual(fx.alle(fertig, '.kn-nur-lesen').map((s) => s.textContent), ['Eingegangen, erreicht', 'In Arbeit, erreicht', 'Prüfung, erreicht', 'Erledigt, aktueller Stand']) + assert.deepEqual(fx.alle(balken, '.kn-nur-leser').map((s) => s.textContent), ['Eingegangen, erreicht', 'In Arbeit, aktueller Stand', 'Prüfung, noch offen', 'Erledigt, noch offen']) + assert.deepEqual(fx.alle(fertig, '.kn-nur-leser').map((s) => s.textContent), ['Eingegangen, erreicht', 'In Arbeit, erreicht', 'Prüfung, erreicht', 'Erledigt, aktueller Stand']) })) test('Aktivität: Stufe 0 (pausiert, storniert) zeigt keinen Balken, nur die Pille', () => mitDom((fx) => { @@ -99,6 +99,17 @@ test('Aktivität: Zeitleiste mit Datum und Kurztext, drei sichtbar, „mehr anze assert.equal(fx.alle(el, '[data-mehr]').length, 1) })) +// Eine Klasse für Text nur für Vorlesegeräte: die vorhandene .kn-nur-leser (huelle.css). Die zweite, .kn-nur-lesen (ansichten.css), ist entfallen. +test('Nur für Vorlesegeräte: die Zeitleiste nutzt .kn-nur-leser aus huelle.css, .kn-nur-lesen gibt es in keinem Stil und keiner Ansicht mehr', () => mitDom((fx) => { + const css = (name) => readFileSync(new URL(`../public/neu/${name}`, import.meta.url), 'utf8') + assert.match(css('huelle.css'), /\n\.kn-nur-leser \{[^}]*position: absolute;[^}]*\}/) + assert.doesNotMatch(css('ansichten.css'), /kn-nur-lesen\b/) + assert.doesNotMatch(readFileSync(new URL('../public/neu/auftrags-zeitleiste.js', import.meta.url), 'utf8'), /kn-nur-lesen\b/) + const balken = fx.finde(baueAktivitaet(dreiAuftraege(), JETZT), '.kn-az-balken') + assert.equal(fx.alle(balken, 'li > .kn-nur-leser').length, 4) + assert.equal(fx.alle(balken, '.kn-nur-lesen').length, 0) +})) + // Barrierefreiheit: Mehrere Knöpfe „mehr anzeigen“ auf einer Seite sind für Screenreader nicht zu unterscheiden. Der Name nennt darum den Auftrag (und enthält den sichtbaren // Text, WCAG 2.5.3), aria-controls zeigt auf die Liste, die der Knopf aufklappt. test('Zeitleiste: „mehr anzeigen“ trägt aria-label mit dem Auftragstitel und aria-controls auf die eigene Liste, auch nach dem Umschalten', () => mitDom((fx) => {