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:
@@ -277,7 +277,7 @@
|
|||||||
route into record_feedback and feed the prompt-conditioning
|
route into record_feedback and feed the prompt-conditioning
|
||||||
loop. See docs/roadmap/2026-04-23-... Phase 2. -->
|
loop. See docs/roadmap/2026-04-23-... Phase 2. -->
|
||||||
<button
|
<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' : ''}"
|
{rating[step.id] === 1 ? '!opacity-100 text-success' : ''}"
|
||||||
onclick={() => recordThumb(step, 1)}
|
onclick={() => recordThumb(step, 1)}
|
||||||
aria-label={rating[step.id] === 1 ? 'Remove thumbs up' : 'Thumbs up — this is a good step'}
|
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" />
|
<ThumbsUp size={10} aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<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' : ''}"
|
{rating[step.id] === -1 ? '!opacity-100 text-danger' : ''}"
|
||||||
onclick={() => recordThumb(step, -1)}
|
onclick={() => recordThumb(step, -1)}
|
||||||
aria-label={rating[step.id] === -1 ? 'Remove thumbs down' : 'Thumbs down — this misses the mark'}
|
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" />
|
<ThumbsDown size={10} aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<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)}
|
onclick={() => startEdit(step)}
|
||||||
aria-label="Edit this step (the correction trains future suggestions)"
|
aria-label="Edit this step (the correction trains future suggestions)"
|
||||||
title="Edit — this is the strongest training signal"
|
title="Edit — this is the strongest training signal"
|
||||||
@@ -306,13 +306,13 @@
|
|||||||
<Pencil size={10} aria-hidden="true" />
|
<Pencil size={10} aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<span
|
<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)'}
|
style={reduceMotion ? '' : 'transition: opacity var(--duration-ui)'}
|
||||||
>
|
>
|
||||||
<SpeakerButton text={step.text} label="Read this step aloud" size={10} />
|
<SpeakerButton text={step.text} label="Read this step aloud" size={10} />
|
||||||
</span>
|
</span>
|
||||||
<button
|
<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)}
|
onclick={() => startTimer(step.id)}
|
||||||
aria-label="Start 2-minute timer for this step"
|
aria-label="Start 2-minute timer for this step"
|
||||||
style={reduceMotion ? '' : 'transition: opacity var(--duration-ui)'}
|
style={reduceMotion ? '' : 'transition: opacity var(--duration-ui)'}
|
||||||
|
|||||||
@@ -534,7 +534,7 @@
|
|||||||
>
|
>
|
||||||
<!-- Star -->
|
<!-- Star -->
|
||||||
<button
|
<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); }}
|
onclick={(e) => { e.stopPropagation(); toggleStar(seg._idx); }}
|
||||||
aria-label={seg.starred ? "Unstar" : "Star"}
|
aria-label={seg.starred ? "Unstar" : "Star"}
|
||||||
>
|
>
|
||||||
@@ -570,7 +570,7 @@
|
|||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
<!-- Actions (hover reveal) -->
|
<!-- 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
|
<button
|
||||||
class="text-text-tertiary hover:text-accent"
|
class="text-text-tertiary hover:text-accent"
|
||||||
onclick={(e) => { e.stopPropagation(); copySegment(seg._idx); }}
|
onclick={(e) => { e.stopPropagation(); copySegment(seg._idx); }}
|
||||||
|
|||||||
Reference in New Issue
Block a user