- Custom tooltip directive (WCAG AAA) on every button in the app - Two-column timer layout with sticky hero and recent entries sidebar - Timer font selector with 16 monospace Google Fonts and live preview - UI font selector with 15+ Google Fonts - Close-to-tray and minimize-to-tray settings - New app icons (no-glow variants), platform icon set - Mini timer pop-out window - Favorites strip with drag-reorder and inline actions - Comprehensive README with feature documentation - Remove tracked files that belong in gitignore
96 lines
3.0 KiB
Vue
96 lines
3.0 KiB
Vue
<script setup lang="ts">
|
|
import { watch, ref } from 'vue'
|
|
import { useFocusTrap } from '../utils/focusTrap'
|
|
|
|
const props = defineProps<{ show: boolean }>()
|
|
const emit = defineEmits<{ close: [] }>()
|
|
|
|
const { activate, deactivate } = useFocusTrap()
|
|
const dialogRef = ref<HTMLElement | null>(null)
|
|
|
|
watch(() => props.show, (val) => {
|
|
if (val) {
|
|
setTimeout(() => {
|
|
if (dialogRef.value) activate(dialogRef.value, { onDeactivate: () => emit('close') })
|
|
}, 50)
|
|
} else {
|
|
deactivate()
|
|
}
|
|
})
|
|
|
|
const groups = [
|
|
{
|
|
label: 'Global',
|
|
shortcuts: [
|
|
{ keys: '?', description: 'Show keyboard shortcuts' },
|
|
{ keys: 'Ctrl+Shift+T', description: 'Toggle timer' },
|
|
{ keys: 'Ctrl+Shift+Z', description: 'Show/focus app' },
|
|
{ keys: 'Ctrl+Shift+N', description: 'Quick entry' },
|
|
]
|
|
},
|
|
{
|
|
label: 'Timer',
|
|
shortcuts: [
|
|
{ keys: 'Space', description: 'Start/stop timer (when focused)' },
|
|
]
|
|
},
|
|
{
|
|
label: 'Navigation',
|
|
shortcuts: [
|
|
{ keys: 'Arrow keys', description: 'Navigate tabs, calendar, lists' },
|
|
{ keys: 'Enter', description: 'Open/select focused item' },
|
|
{ keys: 'Escape', description: 'Close dialog/popover' },
|
|
]
|
|
},
|
|
]
|
|
</script>
|
|
|
|
<template>
|
|
<Transition name="modal">
|
|
<div
|
|
v-if="show"
|
|
class="fixed inset-0 bg-black/70 backdrop-blur-[4px] flex items-center justify-center p-4 z-50"
|
|
@click.self="emit('close')"
|
|
>
|
|
<div
|
|
ref="dialogRef"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-labelledby="shortcuts-title"
|
|
class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-md p-6"
|
|
>
|
|
<h2 id="shortcuts-title" class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">
|
|
Keyboard Shortcuts
|
|
</h2>
|
|
<div class="space-y-4">
|
|
<div v-for="group in groups" :key="group.label">
|
|
<h3 class="text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium mb-2">
|
|
{{ group.label }}
|
|
</h3>
|
|
<div class="space-y-1.5">
|
|
<div
|
|
v-for="shortcut in group.shortcuts"
|
|
:key="shortcut.keys"
|
|
class="flex items-center justify-between text-[0.8125rem]"
|
|
>
|
|
<span class="text-text-secondary">{{ shortcut.description }}</span>
|
|
<kbd class="px-2 py-0.5 bg-bg-elevated border border-border-subtle rounded text-[0.6875rem] font-mono text-text-primary">
|
|
{{ shortcut.keys }}
|
|
</kbd>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="mt-6 flex justify-end">
|
|
<button
|
|
@click="emit('close')"
|
|
class="px-4 py-2 border border-border-subtle text-text-secondary text-[0.8125rem] rounded-lg hover:bg-bg-elevated transition-colors duration-150"
|
|
>
|
|
Close
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
</template>
|