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> <template>
<div <div
class="border-b border-surface-border px-4 py-3 hover:bg-surface-raised transition-colors" 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 }" :class="{ 'border-l-2 border-l-sev-error': isHighSeverity }"
@click="isLong && (expanded = !expanded)"
> >
<div class="flex items-start gap-3"> <div class="flex items-start gap-3">
<SeverityBadge :severity="entry.severity" class="mt-0.5 shrink-0 w-16 text-center" /> <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> <span v-if="entry.repeat_count > 1" class="text-text-dim text-xs">×{{ entry.repeat_count }}</span>
</div> </div>
<p <p
:id="`entry-text-${entry.entry_id}`"
class="text-text-primary text-sm whitespace-pre-wrap break-words leading-relaxed" class="text-text-primary text-sm whitespace-pre-wrap break-words leading-relaxed"
:class="{ 'line-clamp-3': isLong && !expanded }" :class="{ 'line-clamp-3': isLong && !expanded }"
>{{ entry.text }}</p> >{{ entry.text }}</p>
<button <button
v-if="isLong" 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" 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> </div>
</div> </div>

View file

@ -2,7 +2,9 @@
<div> <div>
<!-- Input row --> <!-- Input row -->
<div class="flex gap-3 mb-6"> <div class="flex gap-3 mb-6">
<label for="qc-query" class="sr-only">Describe the symptom or issue</label>
<input <input
id="qc-query"
v-model="query" v-model="query"
type="text" type="text"
placeholder='e.g. "plex stopped playing audio around 2pm"' placeholder='e.g. "plex stopped playing audio around 2pm"'
@ -14,18 +16,20 @@
@click="run()" @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" 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-if="loading">Searching</span>
<span v-else>Go</span> <span v-else>Search logs</span>
</button> </button>
</div> </div>
<!-- Pipeline status --> <!-- Pipeline status -->
<div <div aria-live="polite" aria-atomic="true">
v-if="loading && statusMsg" <div
class="flex items-center gap-2 mb-3 text-xs text-text-dim" 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>{{ statusMsg }}</span> <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> </div>
<!-- Source scope badge --> <!-- Source scope badge -->
@ -36,11 +40,12 @@
@click="sourceScope = null" @click="sourceScope = null"
class="text-text-dim hover:text-text-primary ml-1" class="text-text-dim hover:text-text-primary ml-1"
title="Clear scope" title="Clear scope"
aria-label="Clear source scope filter"
></button> ></button>
</div> </div>
<!-- Error --> <!-- 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 }} {{ error }}
</div> </div>
@ -61,6 +66,7 @@
v-for="(count, sev) in nonZeroSeverity" v-for="(count, sev) in nonZeroSeverity"
:key="String(sev)" :key="String(sev)"
@click="severityFilter = severityFilter === String(sev) ? null : String(sev)" @click="severityFilter = severityFilter === String(sev) ? null : String(sev)"
:aria-pressed="severityFilter === String(sev)"
:class="[ :class="[
'px-2 py-0.5 rounded text-xs font-medium border transition-colors', 'px-2 py-0.5 rounded text-xs font-medium border transition-colors',
severityFilter === String(sev) severityFilter === String(sev)