feat(ui): migrate entire UI to "Cozy Home" design
Warm, friendly redesign replacing the generic cold-shadcn look. Built as a swappable token bundle so other presets can be added later; dark mode and the user-tunable accent hue are retained. Foundation - app.css: warm cream (light) + "dusk" (dark) token system; terracotta accent (default hue 16); pastel --room-* palette; vivid --status-* (dots/bars) plus AA-legible --status-*-ink (text); soft warm shadows; --radius 1rem; font tokens - Fonts: Fraunces (display) + Figtree (body), self-hosted in static/fonts (no Google CDN) so offline/LAN installs work; system-ui fallbacks kept - h1/h2/h3 render in Fraunces via base layer Chrome and surfaces - Sidebar, Header, home, AppCard/BoardCard, BoardHeader, sections, favorites - 29 widgets + integration renderers: cozy card shells, room-palette charts - Default background is a static warm "cozy" glow (mesh demoted, rAF gated on prefers-reduced-motion) System-wide - Status colors tokenized (no raw bg/text-*-500 or status hex); success/warning to status tokens, categorical to room palette, errors to destructive - Inputs rounded-xl; buttons rounded-xl; cards/dialogs rounded-[1.4rem]; soft-shadow vocabulary only; focus-visible:ring-primary/30 - Forms, admin tables (now cozy cards), dialogs, popovers, auth screens a11y: reduced-motion guards; darker status "ink" text for AA on cream. Known tradeoff: terracotta primary + white button text ~2.96:1 (signature color, user-tunable). Verified: svelte-check 0/0, build ok, 274 tests pass, eslint 0 errors. Design refs + system sheet in design-mockups/.
This commit is contained in:
@@ -72,7 +72,7 @@
|
||||
let rssShowSummary = $state((initialConfig.showSummary as boolean) ?? true);
|
||||
|
||||
// Calendar
|
||||
let calendarUrlsRaw = $state((initialConfig.icalUrls as Array<{ url: string; color: string; label: string }>) ?? [{ url: '', color: '#6366f1', label: '' }]);
|
||||
let calendarUrlsRaw = $state((initialConfig.icalUrls as Array<{ url: string; color: string; label: string }>) ?? [{ url: '', color: '#e8754f', label: '' }]);
|
||||
let calendarDaysAhead = $state((initialConfig.daysAhead as number) ?? 7);
|
||||
|
||||
// Markdown
|
||||
@@ -155,7 +155,7 @@
|
||||
}
|
||||
|
||||
function addCalendarUrl() {
|
||||
calendarUrlsRaw = [...calendarUrlsRaw, { url: '', color: '#6366f1', label: '' }];
|
||||
calendarUrlsRaw = [...calendarUrlsRaw, { url: '', color: '#e8754f', label: '' }];
|
||||
}
|
||||
|
||||
function removeCalendarUrl(index: number) {
|
||||
@@ -163,7 +163,7 @@
|
||||
}
|
||||
|
||||
// Helper for input styling
|
||||
const inputClass = 'w-full rounded-lg border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground transition-colors focus:border-primary focus:outline-none focus:ring-2 focus:ring-ring/30';
|
||||
const inputClass = 'w-full rounded-xl border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground transition-colors focus:border-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/30';
|
||||
const labelClass = 'mb-1 block text-sm font-medium text-foreground';
|
||||
|
||||
let firstInput: HTMLElement | undefined = $state();
|
||||
@@ -171,7 +171,7 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="rounded-xl border border-border bg-card p-4 shadow-lg"
|
||||
class="rounded-xl border border-border bg-card p-4 shadow-[var(--shadow-soft)]"
|
||||
transition:fade={{ duration: 100 }}
|
||||
onkeydown={handleKeydown}
|
||||
role="dialog"
|
||||
@@ -201,11 +201,11 @@
|
||||
bind:value={appSearchQuery}
|
||||
bind:this={firstInput}
|
||||
placeholder={$t('common.search') ?? 'Search apps...'}
|
||||
class="w-full rounded-lg border border-input bg-background py-1.5 pl-8 pr-3 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-ring/30"
|
||||
class="w-full rounded-xl border border-input bg-background py-1.5 pl-8 pr-3 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/30"
|
||||
/>
|
||||
</div>
|
||||
<!-- App grid -->
|
||||
<div class="max-h-48 overflow-y-auto rounded-lg border border-input bg-background p-1">
|
||||
<div class="max-h-48 overflow-y-auto rounded-xl border border-input bg-background p-1">
|
||||
{#if filteredApps.length === 0}
|
||||
<p class="py-4 text-center text-xs text-muted-foreground">{$t('common.no_results') ?? 'No apps found'}</p>
|
||||
{:else}
|
||||
@@ -548,7 +548,7 @@
|
||||
{$t('common.cancel') ?? 'Cancel'}
|
||||
</button>
|
||||
<button type="button" onclick={handleSave}
|
||||
class="rounded-lg bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90">
|
||||
class="rounded-xl bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90">
|
||||
{mode === 'create' ? ($t('common.add') ?? 'Add') : ($t('common.save') ?? 'Save')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user