feat(frontend): replace emoji with inline Material Symbols icon system
Add a self-contained icon system: vendored Material Symbols registry, an <Icon> component that references a single <symbol> sprite via <use>, plus IconButton/IconSprite. Replace every emoji/Unicode glyph (logo, theme switcher, cover placeholder, like/comment counts, lightbox controls, back links) and add leading icons to key controls. Decorative icons are aria-hidden; icon-only buttons get labels; theme toggles expose aria-pressed; counters get accessible names. Recorded in openspec change material-icons-ui (all tasks complete).
This commit is contained in:
@@ -1,27 +1,29 @@
|
||||
<script lang="ts">
|
||||
import IconButton from './IconButton.svelte';
|
||||
import type { IconName } from '$lib/icons/registry';
|
||||
import { theme, type Theme } from '$lib/stores/theme.svelte';
|
||||
|
||||
const options: { value: Theme; label: string; icon: string }[] = [
|
||||
{ value: 'light', label: 'Light', icon: '☀️' },
|
||||
{ value: 'dark', label: 'Dark', icon: '🌙' },
|
||||
{ value: 'neutral', label: 'Neutral', icon: '🌾' },
|
||||
{ value: 'system', label: 'System', icon: '💻' }
|
||||
const options: { value: Theme; label: string; icon: IconName }[] = [
|
||||
{ value: 'light', label: 'Light', icon: 'light_mode' },
|
||||
{ value: 'dark', label: 'Dark', icon: 'dark_mode' },
|
||||
{ value: 'neutral', label: 'Neutral', icon: 'palette' },
|
||||
{ value: 'system', label: 'System', icon: 'brightness_auto' }
|
||||
];
|
||||
</script>
|
||||
|
||||
<div class="border-border bg-bg-elevated inline-flex gap-1 rounded-lg border p-1" role="group" aria-label="Theme">
|
||||
<div
|
||||
class="border-border bg-bg-elevated inline-flex gap-1 rounded-lg border p-1"
|
||||
role="group"
|
||||
aria-label="Theme"
|
||||
>
|
||||
{#each options as option (option.value)}
|
||||
<button
|
||||
type="button"
|
||||
title={option.label}
|
||||
aria-label={option.label}
|
||||
aria-pressed={theme.current === option.value}
|
||||
<IconButton
|
||||
name={option.icon}
|
||||
label={option.label}
|
||||
active={theme.current === option.value}
|
||||
pressed={theme.current === option.value}
|
||||
class="px-2 py-1 text-sm"
|
||||
onclick={() => theme.set(option.value)}
|
||||
class="rounded-md px-2 py-1 text-sm transition-colors {theme.current === option.value
|
||||
? 'bg-primary text-primary-fg'
|
||||
: 'text-text-muted hover:bg-bg-muted'}"
|
||||
>
|
||||
{option.icon}
|
||||
</button>
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user