Skip to content

Commit c6680d4

Browse files
committed
feat: add new themes (Gruvbox Dark, Tokyo Night, Nord) and enhance accessibility in GuardianPanel
1 parent b233d49 commit c6680d4

File tree

3 files changed

+167
-45
lines changed

3 files changed

+167
-45
lines changed

src/app.css

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,72 @@
2626
--petalytics-border: #3d484d;
2727
}
2828

29+
/* Gruvbox Dark */
30+
.gruvbox {
31+
--petalytics-bg: #282828;
32+
--petalytics-fg: #ebdbb2;
33+
--petalytics-surface: #3c3836;
34+
--petalytics-overlay: #504945;
35+
--petalytics-muted: #928374;
36+
--petalytics-subtle: #a89984;
37+
--petalytics-text: #ebdbb2;
38+
--petalytics-love: #fb4934; /* red */
39+
--petalytics-gold: #fabd2f; /* yellow */
40+
--petalytics-rose: #d3869b; /* purple-ish */
41+
--petalytics-pine: #b8bb26; /* green */
42+
--petalytics-foam: #83a598; /* blue */
43+
--petalytics-iris: #8ec07c; /* aqua */
44+
--petalytics-highlight-low: #32302f;
45+
--petalytics-highlight-med: #3c3836;
46+
--petalytics-highlight-high: #504945;
47+
--petalytics-accent: #b8bb26;
48+
--petalytics-border: #504945;
49+
}
50+
51+
/* Tokyo Night */
52+
.tokyo-night {
53+
--petalytics-bg: #1a1b26;
54+
--petalytics-fg: #c0caf5;
55+
--petalytics-surface: #24283b;
56+
--petalytics-overlay: #2f334d;
57+
--petalytics-muted: #565f89;
58+
--petalytics-subtle: #737aa2;
59+
--petalytics-text: #c0caf5;
60+
--petalytics-love: #f7768e; /* red */
61+
--petalytics-gold: #e0af68; /* yellow */
62+
--petalytics-rose: #bb9af7; /* magenta */
63+
--petalytics-pine: #9ece6a; /* green */
64+
--petalytics-foam: #7dcfff; /* cyan */
65+
--petalytics-iris: #2ac3de; /* teal */
66+
--petalytics-highlight-low: #1f2335;
67+
--petalytics-highlight-med: #24283b;
68+
--petalytics-highlight-high: #2f334d;
69+
--petalytics-accent: #7dcfff;
70+
--petalytics-border: #2f334d;
71+
}
72+
73+
/* Nord */
74+
.nord {
75+
--petalytics-bg: #2e3440;
76+
--petalytics-fg: #d8dee9;
77+
--petalytics-surface: #3b4252;
78+
--petalytics-overlay: #434c5e;
79+
--petalytics-muted: #4c566a;
80+
--petalytics-subtle: #81a1c1;
81+
--petalytics-text: #d8dee9;
82+
--petalytics-love: #bf616a;
83+
--petalytics-gold: #ebcb8b;
84+
--petalytics-rose: #b48ead;
85+
--petalytics-pine: #a3be8c;
86+
--petalytics-foam: #88c0d0;
87+
--petalytics-iris: #5e81ac;
88+
--petalytics-highlight-low: #353b49;
89+
--petalytics-highlight-med: #3b4252;
90+
--petalytics-highlight-high: #434c5e;
91+
--petalytics-accent: #88c0d0;
92+
--petalytics-border: #434c5e;
93+
}
94+
2995
html,
3096
body {
3197
margin: 0;

src/lib/components/panels/GuardianPanel.svelte

Lines changed: 100 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,14 @@
123123
preferences[key] = !preferences[key];
124124
saveGuardianInfo();
125125
}
126+
127+
// Keyboard activate handler for elements with role="button"
128+
function handleActivate(e: KeyboardEvent, action: () => void) {
129+
if (e.key === 'Enter' || e.key === ' ') {
130+
e.preventDefault();
131+
action();
132+
}
133+
}
126134
</script>
127135

128136
<div class="guardian-panel h-full" style="background: var(--petalytics-bg);">
@@ -137,19 +145,17 @@
137145
<div class="cli-content p-3 font-mono text-sm overflow-y-auto" style="color: var(--petalytics-text);">
138146

139147
<!-- Guardian name row -->
140-
<div class="cli-row flex items-center hover:bg-gray-800/20 px-2 py-1 rounded transition-colors cursor-pointer" on:click={() => startEdit('guardian')}>
141-
<span style="color: var(--petalytics-subtle);">></span>
142-
<span style="color: var(--petalytics-foam);">guardian</span>
143-
<span class="flex-1 text-right" style="color: var(--petalytics-text);">
148+
<div class="cli-row px-2 py-1" role="button" tabindex="0" onclick={() => startEdit('guardian')} onkeydown={(e) => handleActivate(e, () => startEdit('guardian'))}>
149+
<span class="label" style="color: var(--petalytics-foam);">guardian</span>
150+
<span class="value" style="color: var(--petalytics-text);">
144151
{#if editingField === 'guardian'}
145152
<input
146153
bind:value={guardianName}
147-
on:blur={stopEdit}
148-
on:keydown={(e) => handleKeydown(e, 'guardian')}
149-
class="bg-transparent border-none outline-none w-full text-right"
154+
onblur={stopEdit}
155+
onkeydown={(e) => handleKeydown(e, 'guardian')}
156+
class="bg-transparent border-none outline-none w-full text-right input-inline"
150157
style="color: var(--petalytics-text);"
151158
placeholder="Pet Guardian Name"
152-
autofocus
153159
/>
154160
{:else}
155161
{guardianName || 'Not set'}
@@ -158,20 +164,18 @@
158164
</div>
159165

160166
<!-- API Key row -->
161-
<div class="cli-row flex items-center hover:bg-gray-800/20 px-2 py-1 rounded transition-colors cursor-pointer" on:click={() => startEdit('apiKey')}>
162-
<span style="color: var(--petalytics-subtle);">></span>
163-
<span style="color: var(--petalytics-foam);">api_key</span>
164-
<span class="flex-1 text-right" style="color: var(--petalytics-text);">
167+
<div class="cli-row px-2 py-1" role="button" tabindex="0" onclick={() => startEdit('apiKey')} onkeydown={(e) => handleActivate(e, () => startEdit('apiKey'))}>
168+
<span class="label" style="color: var(--petalytics-foam);">api_key</span>
169+
<span class="value" style="color: var(--petalytics-text);">
165170
{#if editingField === 'apiKey'}
166171
<input
167172
type="password"
168173
bind:value={apiKeyInput}
169-
on:blur={stopEdit}
170-
on:keydown={(e) => handleKeydown(e, 'apiKey')}
171-
class="bg-transparent border-none outline-none w-full text-right"
174+
onblur={stopEdit}
175+
onkeydown={(e) => handleKeydown(e, 'apiKey')}
176+
class="bg-transparent border-none outline-none w-full text-right input-inline"
172177
style="color: var(--petalytics-text);"
173178
placeholder="sk-or-..."
174-
autofocus
175179
/>
176180
{:else}
177181
{apiKeyInput ? `${apiKeyInput.slice(0, 8)}****` : 'Not set'}
@@ -191,19 +195,14 @@
191195
</div>
192196

193197
<!-- Theme row -->
194-
<div class="cli-row flex items-center hover:bg-gray-800/20 px-2 py-1 rounded transition-colors">
195-
<span style="color: var(--petalytics-subtle);">></span>
196-
<span style="color: var(--petalytics-foam);">theme</span>
197-
<span class="flex-1 text-right" style="color: var(--petalytics-text);">
198+
<div class="cli-row px-2 py-1">
199+
<span class="label" style="color: var(--petalytics-foam);">theme</span>
200+
<span class="value" style="color: var(--petalytics-text);">
198201
{currentTheme}
199202
</span>
200203
<div class="ml-2 flex items-center space-x-1">
201-
<button on:click={() => toggleTheme('prev')} class="hover:opacity-70">
202-
<ChevronLeft size={14} style="color: var(--petalytics-subtle);" />
203-
</button>
204-
<button on:click={() => toggleTheme('next')} class="hover:opacity-70">
205-
<ChevronRight size={14} style="color: var(--petalytics-subtle);" />
206-
</button>
204+
<button type="button" class="arrow-btn" onclick={() => toggleTheme('prev')} aria-label="Previous theme">&lt;</button>
205+
<button type="button" class="arrow-btn" onclick={() => toggleTheme('next')} aria-label="Next theme">&gt;</button>
207206
</div>
208207
</div>
209208

@@ -213,37 +212,34 @@
213212
</div>
214213

215214
<!-- Preferences section header -->
216-
<div class="cli-row flex items-center px-2 py-1">
215+
<div class="cli-row px-2 py-1">
217216
<span style="color: var(--petalytics-subtle);">#</span>
218217
<span class="ml-2" style="color: var(--petalytics-gold);">preferences</span>
219218
</div>
220219

221-
<div class="cli-row flex items-center hover:bg-gray-800/20 px-2 py-1 rounded transition-colors cursor-pointer" on:click={() => togglePreference('dailyReminders')}>
222-
<span style="color: var(--petalytics-subtle);">></span>
223-
<span style="color: var(--petalytics-foam);">daily_reminders</span>
224-
<span class="flex-1 text-right" style="color: var(--petalytics-text);">
220+
<div class="cli-row px-2 py-1" role="button" tabindex="0" aria-pressed={preferences.dailyReminders} onclick={() => togglePreference('dailyReminders')} onkeydown={(e) => handleActivate(e, () => togglePreference('dailyReminders'))}>
221+
<span class="label" style="color: var(--petalytics-foam);">daily_reminders</span>
222+
<span class="value" style="color: var(--petalytics-text);">
225223
{preferences.dailyReminders ? 'enabled' : 'disabled'}
226224
</span>
227225
<span class="ml-2" style="color: {preferences.dailyReminders ? 'var(--petalytics-pine)' : 'var(--petalytics-subtle)'};">
228226
{preferences.dailyReminders ? '' : ''}
229227
</span>
230228
</div>
231229

232-
<div class="cli-row flex items-center hover:bg-gray-800/20 px-2 py-1 rounded transition-colors cursor-pointer" on:click={() => togglePreference('aiInsights')}>
233-
<span style="color: var(--petalytics-subtle);">></span>
234-
<span style="color: var(--petalytics-foam);">ai_insights</span>
235-
<span class="flex-1 text-right" style="color: var(--petalytics-text);">
230+
<div class="cli-row px-2 py-1" role="button" tabindex="0" aria-pressed={preferences.aiInsights} onclick={() => togglePreference('aiInsights')} onkeydown={(e) => handleActivate(e, () => togglePreference('aiInsights'))}>
231+
<span class="label" style="color: var(--petalytics-foam);">ai_insights</span>
232+
<span class="value" style="color: var(--petalytics-text);">
236233
{preferences.aiInsights ? 'enabled' : 'disabled'}
237234
</span>
238235
<span class="ml-2" style="color: {preferences.aiInsights ? 'var(--petalytics-pine)' : 'var(--petalytics-subtle)'};">
239236
{preferences.aiInsights ? '' : ''}
240237
</span>
241238
</div>
242239

243-
<div class="cli-row flex items-center hover:bg-gray-800/20 px-2 py-1 rounded transition-colors cursor-pointer" on:click={() => togglePreference('notifications')}>
244-
<span style="color: var(--petalytics-subtle);">></span>
245-
<span style="color: var(--petalytics-foam);">notifications</span>
246-
<span class="flex-1 text-right" style="color: var(--petalytics-text);">
240+
<div class="cli-row px-2 py-1" role="button" tabindex="0" aria-pressed={preferences.notifications} onclick={() => togglePreference('notifications')} onkeydown={(e) => handleActivate(e, () => togglePreference('notifications'))}>
241+
<span class="label" style="color: var(--petalytics-foam);">notifications</span>
242+
<span class="value" style="color: var(--petalytics-text);">
247243
{preferences.notifications ? 'enabled' : 'disabled'}
248244
</span>
249245
<span class="ml-2" style="color: {preferences.notifications ? 'var(--petalytics-pine)' : 'var(--petalytics-subtle)'};">
@@ -257,7 +253,7 @@
257253
</div>
258254

259255
<!-- Status section header -->
260-
<div class="cli-row flex items-center px-2 py-1">
256+
<div class="cli-row px-2 py-1">
261257
<span style="color: var(--petalytics-subtle);">#</span>
262258
<span class="ml-2" style="color: var(--petalytics-gold);">status</span>
263259
</div>
@@ -271,10 +267,9 @@
271267
</div>
272268

273269
<!-- Data management toggle -->
274-
<div class="cli-row flex items-center hover:bg-gray-800/20 px-2 py-1 rounded transition-colors cursor-pointer" on:click={() => showDataManager = !showDataManager}>
275-
<span style="color: var(--petalytics-subtle);">></span>
276-
<span style="color: var(--petalytics-foam);">data_manager</span>
277-
<span class="flex-1 text-right" style="color: var(--petalytics-text);">
270+
<div class="cli-row px-2 py-1" role="button" tabindex="0" aria-expanded={showDataManager} onclick={() => showDataManager = !showDataManager} onkeydown={(e) => handleActivate(e, () => (showDataManager = !showDataManager))}>
271+
<span class="label" style="color: var(--petalytics-foam);">data_manager</span>
272+
<span class="value" style="color: var(--petalytics-text);">
278273
{showDataManager ? 'show' : 'hidden'}
279274
</span>
280275
<ChevronRight
@@ -291,3 +286,64 @@
291286
{/if}
292287
</div>
293288
</div>
289+
290+
<style>
291+
/* Alacritty-inspired interactive rows */
292+
.cli-row {
293+
display: flex;
294+
align-items: center;
295+
border: 1px solid transparent;
296+
border-radius: 6px;
297+
transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
298+
}
299+
.cli-row[role="button"] {
300+
cursor: pointer;
301+
}
302+
.cli-row:hover {
303+
background: var(--petalytics-highlight-low);
304+
border-color: var(--petalytics-border);
305+
}
306+
.cli-row:focus-within,
307+
.cli-row[role="button"]:focus-visible {
308+
outline: none;
309+
background: var(--petalytics-highlight-med);
310+
border-color: var(--petalytics-accent);
311+
box-shadow: 0 0 0 2px color-mix(in oklab, var(--petalytics-accent) 40%, transparent);
312+
}
313+
.cli-row[aria-pressed="true"],
314+
.cli-row[aria-expanded="true"] {
315+
background: var(--petalytics-highlight-high);
316+
border-color: var(--petalytics-accent);
317+
}
318+
.label {
319+
color: var(--petalytics-foam);
320+
}
321+
.value {
322+
margin-left: auto;
323+
text-align: right;
324+
flex: 1 1 auto;
325+
}
326+
.input-inline {
327+
padding: 0;
328+
}
329+
.arrow-btn {
330+
font-family: 'JetBrains Mono', monospace;
331+
font-size: 0.85rem;
332+
line-height: 1rem;
333+
background: transparent;
334+
border: 1px solid var(--petalytics-border);
335+
color: var(--petalytics-subtle);
336+
padding: 0.15rem 0.4rem;
337+
border-radius: 4px;
338+
cursor: pointer;
339+
}
340+
.arrow-btn:hover {
341+
background: var(--petalytics-highlight-low);
342+
color: var(--petalytics-text);
343+
}
344+
.arrow-btn:focus-visible {
345+
outline: none;
346+
border-color: var(--petalytics-accent);
347+
box-shadow: 0 0 0 2px color-mix(in oklab, var(--petalytics-accent) 35%, transparent);
348+
}
349+
</style>

src/lib/components/ui/EmptyState.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
{#if actionText && onAction}
4646
<button
47-
on:click={onAction}
47+
onclick={onAction}
4848
class="button flex items-center space-x-2 mx-auto"
4949
>
5050
<IconComponent size={16} />

0 commit comments

Comments
 (0)