fix: a11y — QuickCapture label/role/aria-live/spinner, LogEntryRow expand button

This commit is contained in:
pyr0ball 2026-05-13 16:42:46 -07:00
parent e0bfa11642
commit b7e71b0e78
2 changed files with 24 additions and 13 deletions

View file

@ -1,8 +1,7 @@
<template>
<div
class="border-b border-surface-border px-4 py-3 hover:bg-surface-raised transition-colors"
:class="{ 'border-l-2 border-l-sev-error': isHighSeverity, 'cursor-pointer': isLong }"
@click="isLong && (expanded = !expanded)"
:class="{ 'border-l-2 border-l-sev-error': isHighSeverity }"
>
<div class="flex items-start gap-3">
<SeverityBadge :severity="entry.severity" class="mt-0.5 shrink-0 w-16 text-center" />
@ -18,14 +17,20 @@
<span v-if="entry.repeat_count > 1" class="text-text-dim text-xs">×{{ entry.repeat_count }}</span>
</div>
<p
:id="`entry-text-${entry.entry_id}`"
class="text-text-primary text-sm whitespace-pre-wrap break-words leading-relaxed"
:class="{ 'line-clamp-3': isLong && !expanded }"
>{{ entry.text }}</p>
<button
v-if="isLong"
@click="expanded = !expanded"
:aria-expanded="expanded"
:aria-controls="`entry-text-${entry.entry_id}`"
class="mt-1 text-text-dim hover:text-accent text-xs transition-colors"
@click.stop="expanded = !expanded"
>{{ expanded ? '▲ collapse' : '▼ expand' }}</button>
>
<span aria-hidden="true">{{ expanded ? '▲' : '▼' }}</span>
{{ expanded ? 'Collapse entry' : 'Expand entry' }}
</button>
</div>
</div>
</div>

View file

@ -2,7 +2,9 @@
<div>
<!-- Input row -->
<div class="flex gap-3 mb-6">
<label for="qc-query" class="sr-only">Describe the symptom or issue</label>
<input
id="qc-query"
v-model="query"
type="text"
placeholder='e.g. "plex stopped playing audio around 2pm"'
@ -14,19 +16,21 @@
@click="run()"
class="px-6 py-2.5 rounded bg-accent text-white text-sm font-semibold hover:bg-blue-400 transition-colors disabled:opacity-50"
>
<span v-if="loading">Go</span>
<span v-else>Go</span>
<span v-if="loading">Searching</span>
<span v-else>Search logs</span>
</button>
</div>
<!-- Pipeline status -->
<div aria-live="polite" aria-atomic="true">
<div
v-if="loading && statusMsg"
class="flex items-center gap-2 mb-3 text-xs text-text-dim"
>
<span class="inline-block w-3 h-3 rounded-full border-2 border-accent border-t-transparent animate-spin" />
<span class="inline-block w-3 h-3 rounded-full border-2 border-accent border-t-transparent animate-spin motion-reduce:animate-none" aria-hidden="true" />
<span>{{ statusMsg }}</span>
</div>
</div>
<!-- Source scope badge -->
<div v-if="sourceScope" class="flex items-center gap-2 mb-4 text-xs">
@ -36,11 +40,12 @@
@click="sourceScope = null"
class="text-text-dim hover:text-text-primary ml-1"
title="Clear scope"
aria-label="Clear source scope filter"
></button>
</div>
<!-- Error -->
<div v-if="error" class="mb-4 p-3 rounded bg-red-900/30 border border-red-700/40 text-sev-error text-sm">
<div v-if="error" role="alert" class="mb-4 p-3 rounded bg-red-900/30 border border-red-700/40 text-sev-error text-sm">
{{ error }}
</div>
@ -61,6 +66,7 @@
v-for="(count, sev) in nonZeroSeverity"
:key="String(sev)"
@click="severityFilter = severityFilter === String(sev) ? null : String(sev)"
:aria-pressed="severityFilter === String(sev)"
:class="[
'px-2 py-0.5 rounded text-xs font-medium border transition-colors',
severityFilter === String(sev)