fix: Beschreibung und Kurz-Fakten im Tooltip trennen
Bisher hing alles an derselben ` · `-Aufzählung: Auf die letzte Zeile des Fließtexts folgte unmittelbar `· #cms · geplant · Alt+Klick: …`. Der Übergang war nicht zu sehen, obwohl dort die Art der Aussage wechselt — vorn ein Satz, den jemand geschrieben hat, hinten Metadaten, die das Werkzeug kennt. Jetzt: Leerzeile plus Trennstrich dazwischen. Der Strich ist aus `─` (U+2500) gebaut, nicht aus Bindestrichen — das Box-Drawing-Zeichen stößt gapless aneinander und liest sich als Linie, `---` liest sich als Text; mehr kann ein `title` nicht, dort gibt es kein Markup. Zwei Randbedingungen: Der Strich steht nur, wenn beide Teile da sind (ohne Beschreibung bleibt der Tooltip unverändert), und mit 24 Zeichen ist er schmaler als die Fakten-Zeile mit dem Sprung-Hinweis — er verbreitert den Tooltip also nie. Nicht in den aria-label: Ein Screenreader läse vierundzwanzig Striche einzeln vor, und die Kommaliste dort ist ohnehin schon gegliedert. 2 neue Tests (199 gesamt), der bestehende Tooltip-Test nachgezogen. SPEC §9 und D40 (Nachtrag) ebenso. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
037db30d96
commit
e223734d58
+21
-8
@@ -42,6 +42,10 @@ export function esc(s){
|
||||
}
|
||||
/* Escaping für Attributwerte (zusätzlich " -> "). */
|
||||
function attr(s){ return esc(String(s)).replace(/"/g,'"'); }
|
||||
/* Trennstrich im Knoten-Tooltip zwischen Beschreibung und Kurz-Fakten (D40).
|
||||
Box-Drawing-Zeichen statt Bindestrichen: `─` stößt gapless aneinander und
|
||||
liest sich als Linie, `---` als Text. */
|
||||
const TIP_RULE = '─'.repeat(24);
|
||||
|
||||
/* Barrierefreier Name eines Knotens: Label + Status + Aufwand + Zuständige +
|
||||
Link. Die visuellen Badges (Größe, Tags, ↗) sind aria-hidden — ihre
|
||||
@@ -95,15 +99,24 @@ function nodeHtml(n, extra, opts, fold){
|
||||
Querverbindungs-Ebene und den Export — beide arbeiten auf dem DOM. */
|
||||
const idAttr = n.id ? ` data-id="${attr(n.id)}"` : '';
|
||||
const depsAttr = n.deps && n.deps.length ? ` data-deps="${attr(n.deps.join(' '))}"` : '';
|
||||
/* Beschreibung zuerst im Tooltip (mehrzeilig, D40), dann die Kurz-Fakten. */
|
||||
const tip = [n.desc || '',
|
||||
n.id ? '#' + n.id : '',
|
||||
n.deps && n.deps.length ? '→ ' + n.deps.map(d => '#' + d).join(', ') : '',
|
||||
effKey
|
||||
? t('heldTooltip', {eff: t('st_' + effKey), own: t('st_' + n.status.key)})
|
||||
: (n.status ? t('st_' + n.status.key) : ''),
|
||||
n.optional ? t('a11yOptional') : '', t('jumpHint')]
|
||||
/* Tooltip: erst die Beschreibung (mehrzeilig, D40), dann die Kurz-Fakten.
|
||||
Die Fakten hängen NICHT mit ` · ` an den Fließtext an — sie sind eine
|
||||
andere Art von Aussage, und in der einen Zeile ging der Übergang unter
|
||||
(„hinten drangeklatscht"). Deshalb Leerzeile plus Trennstrich dazwischen.
|
||||
Ein `title` kann nur Text, keine Linie — der Strich ist deshalb aus
|
||||
`─` gebaut. Er steht nur, wenn es wirklich etwas zu trennen gibt, und
|
||||
bleibt schmaler als die Fakten-Zeile (die den Sprung-Hinweis enthält),
|
||||
verbreitert den Tooltip also nicht. Der `aria-label` bekommt ihn NICHT:
|
||||
ein Screenreader läse die Striche einzeln vor (nodeAria oben). */
|
||||
const facts = [n.id ? '#' + n.id : '',
|
||||
n.deps && n.deps.length ? '→ ' + n.deps.map(d => '#' + d).join(', ') : '',
|
||||
effKey
|
||||
? t('heldTooltip', {eff: t('st_' + effKey), own: t('st_' + n.status.key)})
|
||||
: (n.status ? t('st_' + n.status.key) : ''),
|
||||
n.optional ? t('a11yOptional') : '', t('jumpHint')]
|
||||
.filter(Boolean).join(' · ');
|
||||
const tip = n.desc && facts ? n.desc + '\n\n' + TIP_RULE + '\n' + facts
|
||||
: (n.desc || facts);
|
||||
const title = ` title="${attr(tip)}"`;
|
||||
const tagsHtml = n.tags && n.tags.length
|
||||
? `<span class="tags" aria-hidden="true">${n.tags.map(tag => `<span class="tag">${esc(tag)}</span>`).join('')}</span>`
|
||||
|
||||
@@ -102,11 +102,28 @@ describe('Langform — ID-Blöcke hinter `---`', () => {
|
||||
describe('Darstellung — Tooltip, ”-Marke, aria', () => {
|
||||
it('stellt die Beschreibung an den Anfang des Tooltips und setzt die Marke', () => {
|
||||
const {html} = render(`[ ] Auth #auth\n " Kapselt Login.`);
|
||||
expect(html).toContain('title="Kapselt Login. · #auth · st_geplant · jumpHint"');
|
||||
expect(html).toContain('title="Kapselt Login.\n\n' + '─'.repeat(24)
|
||||
+ '\n#auth · st_geplant · jumpHint"');
|
||||
expect(html).toContain('<span class="desc-mark" aria-hidden="true">”</span>');
|
||||
expect(html).toContain('aria-label="Auth, a11yStatus, a11yId, Kapselt Login."');
|
||||
});
|
||||
|
||||
/* Die Kurz-Fakten hingen früher mit ` · ` am Fließtext — in einer Zeile ging
|
||||
der Übergang unter. Getrennt wird nur, wenn es etwas zu trennen gibt. */
|
||||
it('trennt Beschreibung und Kurz-Fakten durch Leerzeile und Strich', () => {
|
||||
const {html} = render(`[ ] Auth #auth\n " Erste Zeile.\n " Zweite Zeile.`);
|
||||
const tip = html.match(/title="([^"]*)"/)[1];
|
||||
const [text, rest] = tip.split('\n\n');
|
||||
expect(text).toBe('Erste Zeile.\nZweite Zeile.'); /* Fließtext bleibt zusammen */
|
||||
expect(rest.split('\n')[0]).toMatch(/^─+$/); /* Trennstrich als eigene Zeile */
|
||||
expect(rest.split('\n')[1]).toContain('#auth'); /* danach die Fakten */
|
||||
});
|
||||
|
||||
it('setzt keinen Trennstrich, wenn es keine Beschreibung gibt', () => {
|
||||
const {html} = render(`[ ] Ohne #auth`);
|
||||
expect(html.match(/title="([^"]*)"/)[1]).not.toContain('─');
|
||||
});
|
||||
|
||||
it('ändert Knoten ohne Beschreibung nicht', () => {
|
||||
const {html} = render(`[ ] Ohne`);
|
||||
expect(html).not.toContain('desc-mark');
|
||||
|
||||
Reference in New Issue
Block a user