feat(ux): PR 1.3 — replace 0→100 hover-reveals with calm baseline

Affordances on MicroSteps rows (thumbs/edit/speaker/just-start) and
transcript-viewer segments (star, copy, delete) used opacity-0 →
opacity-100 on group-hover, which (a) hid them from keyboard users
until focus and (b) violated the "always-visible affordance" line in
the Kon design audit.

Replace with opacity-30 baseline + group-hover:opacity-100 +
focus-visible:opacity-100 (MicroSteps) / focus-within:opacity-100
(viewer, since the actions sit inside an interactive segment row).
Result: affordances are calm but visible at rest, lift on hover or
keyboard focus, never invisible.

HistoryPage was checked — its row checkbox at line 757 is already
opacity-50 → opacity-100 on hover, the pattern this PR is moving
toward, so no change needed there.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-26 18:20:34 +01:00
parent 6e663a3625
commit 07925cf360
2 changed files with 7 additions and 7 deletions

View File

@@ -277,7 +277,7 @@
route into record_feedback and feed the prompt-conditioning
loop. See docs/roadmap/2026-04-23-... Phase 2. -->
<button
class="opacity-0 group-hover:opacity-100 p-0.5 text-text-tertiary hover:text-success
class="opacity-30 group-hover:opacity-100 focus-visible:opacity-100 p-0.5 text-text-tertiary hover:text-success
{rating[step.id] === 1 ? '!opacity-100 text-success' : ''}"
onclick={() => recordThumb(step, 1)}
aria-label={rating[step.id] === 1 ? 'Remove thumbs up' : 'Thumbs up — this is a good step'}
@@ -287,7 +287,7 @@
<ThumbsUp size={10} aria-hidden="true" />
</button>
<button
class="opacity-0 group-hover:opacity-100 p-0.5 text-text-tertiary hover:text-danger
class="opacity-30 group-hover:opacity-100 focus-visible:opacity-100 p-0.5 text-text-tertiary hover:text-danger
{rating[step.id] === -1 ? '!opacity-100 text-danger' : ''}"
onclick={() => recordThumb(step, -1)}
aria-label={rating[step.id] === -1 ? 'Remove thumbs down' : 'Thumbs down — this misses the mark'}
@@ -297,7 +297,7 @@
<ThumbsDown size={10} aria-hidden="true" />
</button>
<button
class="opacity-0 group-hover:opacity-100 p-0.5 text-text-tertiary hover:text-accent"
class="opacity-30 group-hover:opacity-100 focus-visible:opacity-100 p-0.5 text-text-tertiary hover:text-accent"
onclick={() => startEdit(step)}
aria-label="Edit this step (the correction trains future suggestions)"
title="Edit — this is the strongest training signal"
@@ -306,13 +306,13 @@
<Pencil size={10} aria-hidden="true" />
</button>
<span
class="opacity-0 group-hover:opacity-100"
class="opacity-30 group-hover:opacity-100 focus-visible:opacity-100"
style={reduceMotion ? '' : 'transition: opacity var(--duration-ui)'}
>
<SpeakerButton text={step.text} label="Read this step aloud" size={10} />
</span>
<button
class="opacity-0 group-hover:opacity-100 flex items-center gap-1 text-[10px] text-text-tertiary hover:text-accent"
class="opacity-30 group-hover:opacity-100 focus-visible:opacity-100 flex items-center gap-1 text-[10px] text-text-tertiary hover:text-accent"
onclick={() => startTimer(step.id)}
aria-label="Start 2-minute timer for this step"
style={reduceMotion ? '' : 'transition: opacity var(--duration-ui)'}

View File

@@ -534,7 +534,7 @@
>
<!-- Star -->
<button
class="mt-0.5 flex-shrink-0 {seg.starred ? 'text-accent' : 'text-text-tertiary opacity-0 group-hover:opacity-100'}"
class="mt-0.5 flex-shrink-0 {seg.starred ? 'text-accent' : 'text-text-tertiary opacity-30 group-hover:opacity-100 focus-within:opacity-100'}"
onclick={(e) => { e.stopPropagation(); toggleStar(seg._idx); }}
aria-label={seg.starred ? "Unstar" : "Star"}
>
@@ -570,7 +570,7 @@
</p>
{/if}
<!-- Actions (hover reveal) -->
<div class="flex items-center gap-1 opacity-0 group-hover:opacity-100 flex-shrink-0">
<div class="flex items-center gap-1 opacity-30 group-hover:opacity-100 focus-within:opacity-100 flex-shrink-0">
<button
class="text-text-tertiary hover:text-accent"
onclick={(e) => { e.stopPropagation(); copySegment(seg._idx); }}