polish(phase9): sparkline + badge motion and a11y
Sparkline: friendlier aria-label ("3 completed today. 14 total over
the last 7 days." rather than a numeric list), per-bar <title>
tooltips with absolute date + count, 30 ms stagger entrance via
scaleY animation. Badge: 180 ms opacity + translateY entrance on
mount; conditional render means each new badge re-fires the
animation. Both animations respect prefers-reduced-motion.
The earlier draft tabindex=0 on the SVG was correctly flagged by
svelte-check as noninteractive_tabindex; SVG role="img" + aria-label
is sufficient for SR navigation without putting it in the keyboard
tab order.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -298,7 +298,7 @@
|
||||
>
|
||||
{#if todayCount() > 0}
|
||||
<span
|
||||
class="text-[11px] text-text-tertiary"
|
||||
class="text-[11px] text-text-tertiary badge-today"
|
||||
aria-label={`${todayCount()} ${todayCount() === 1 ? "task" : "tasks"} completed today`}
|
||||
>
|
||||
{todayCount()} today
|
||||
@@ -689,3 +689,27 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* Phase 9 polish: gentle entrance animation when the today-count
|
||||
badge mounts (it is conditionally rendered, so each new render
|
||||
re-fires the animation). prefers-reduced-motion disables. */
|
||||
:global(.badge-today) {
|
||||
animation: badge-pop 180ms ease both;
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
:global(.badge-today) {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
@keyframes badge-pop {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(2px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user