aadc1eaac0
- Settings: breathing radiogroup/radio, sound aria-pressed, contrast tokens, placeholder contrast, reset aria-live, abbreviation tags, title tooltips, back button 44px target - MiniTimer: paused text #555→#a8a8a8 for AAA contrast - MicrobreakOverlay: alertdialog role, sr-only heading, aria-describedby - BreakOverlay: alertdialog role, sr-only heading, aria-label - ColorPicker: enlarge swatches 22→28px with 44px hit areas, aria-pressed - ActivityManager: enlarge action buttons to 44px targets, contrast tokens
82 lines
2.8 KiB
Svelte
82 lines
2.8 KiB
Svelte
<script lang="ts">
|
|
import { onMount } from "svelte";
|
|
import { listen } from "@tauri-apps/api/event";
|
|
import { invoke } from "@tauri-apps/api/core";
|
|
import type { TimerSnapshot } from "../stores/timer";
|
|
import { loadConfig, config } from "../stores/config";
|
|
import { pickRandomActivity, getCategoryLabel, type BreakActivity } from "../utils/activities";
|
|
|
|
let timeRemaining = $state(20);
|
|
let totalDuration = $state(20);
|
|
let activity = $state<BreakActivity | null>(null);
|
|
|
|
const progress = $derived(totalDuration > 0 ? 1 - timeRemaining / totalDuration : 0);
|
|
|
|
onMount(async () => {
|
|
await loadConfig();
|
|
|
|
if ($config.microbreak_show_activity) {
|
|
// Pick an eye-focused activity for microbreaks
|
|
activity = pickRandomActivity(undefined, $config);
|
|
}
|
|
|
|
try {
|
|
const snap = await invoke<TimerSnapshot>("get_timer_state");
|
|
timeRemaining = snap.microbreakTimeRemaining;
|
|
totalDuration = snap.microbreakTotalDuration;
|
|
} catch {}
|
|
|
|
await listen<TimerSnapshot>("timer-tick", (event) => {
|
|
const snap = event.payload;
|
|
timeRemaining = snap.microbreakTimeRemaining;
|
|
totalDuration = snap.microbreakTotalDuration;
|
|
});
|
|
|
|
await listen("microbreak-ended", () => {
|
|
// Window will be closed by backend
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<div class="microbreak-card" role="alertdialog" aria-label="Microbreak" aria-describedby="microbreak-msg">
|
|
<h2 class="sr-only">Microbreak</h2>
|
|
<div class="flex items-center gap-3 mb-2">
|
|
<svg aria-hidden="true" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#7c6aef" stroke-width="1.5">
|
|
<path d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"/>
|
|
<circle cx="12" cy="12" r="3"/>
|
|
</svg>
|
|
<span id="microbreak-msg" class="text-[15px] font-medium text-white">Look away — 20 feet for {timeRemaining}s</span>
|
|
</div>
|
|
|
|
{#if activity && $config.microbreak_show_activity}
|
|
<p class="text-[12px] text-text-sec mb-3 ml-[34px]">
|
|
{activity.text}
|
|
</p>
|
|
{/if}
|
|
|
|
<!-- Progress bar -->
|
|
<div class="h-[3px] w-full rounded-full overflow-hidden" style="background: rgba(255,255,255,0.05);">
|
|
<div
|
|
class="h-full transition-[width] duration-1000 ease-linear rounded-full"
|
|
style="width: {progress * 100}%; background: linear-gradient(to right, #7c6aef, #4361ee);"
|
|
></div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.microbreak-card {
|
|
position: fixed;
|
|
top: 16px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 380px;
|
|
background: rgba(12, 12, 12, 0.95);
|
|
backdrop-filter: blur(24px);
|
|
-webkit-backdrop-filter: blur(24px);
|
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
border-radius: 16px;
|
|
padding: 16px 20px;
|
|
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5);
|
|
}
|
|
</style>
|