feat: add theme selection toggle to AccountSwitcher component

This commit is contained in:
2025-12-28 15:04:30 +01:00
parent 0f145d556d
commit 3ca5966d03
2 changed files with 121 additions and 101 deletions

View File

@@ -1,7 +1,7 @@
// NOTE: This file is stable and usually should not be modified.
// It is important that all functionality in this file is preserved, and should only be modified if explicitly requested.
import { ChevronDown, LayoutDashboard, LogOut, UserIcon, UserPlus, Wallet, Wifi, X } from 'lucide-react';
import { ChevronDown, LayoutDashboard, LogOut, Monitor, Moon, Sun, UserIcon, UserPlus, Wallet, Wifi, X } from 'lucide-react';
import { useNavigate } from 'react-router-dom';
import {
DropdownMenu,
@@ -25,6 +25,8 @@ import { Button } from '@/components/ui/button';
import { useLoggedInAccounts, type Account } from '@/hooks/useLoggedInAccounts';
import { genUserName } from '@/lib/genUserName';
import { RelayListManager } from '@/components/RelayListManager';
import { useTheme } from '@/hooks/useTheme';
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
interface AccountSwitcherProps {
onAddAccountClick: () => void;
@@ -32,6 +34,7 @@ interface AccountSwitcherProps {
export function AccountSwitcher({ onAddAccountClick }: AccountSwitcherProps) {
const { currentUser, otherUsers, setLogin, removeLogin } = useLoggedInAccounts();
const { theme, setTheme } = useTheme();
const navigate = useNavigate();
if (!currentUser) return null;
@@ -40,6 +43,12 @@ export function AccountSwitcher({ onAddAccountClick }: AccountSwitcherProps) {
return account.metadata.name ?? genUserName(account.pubkey);
}
const handleThemeChange = (value: string) => {
if (value === 'light' || value === 'dark' || value === 'system') {
setTheme(value);
}
};
return (
<DropdownMenu modal={false}>
<DropdownMenuTrigger asChild>
@@ -129,6 +138,39 @@ export function AccountSwitcher({ onAddAccountClick }: AccountSwitcherProps) {
<UserPlus className='w-4 h-4' />
<span>Add another account</span>
</DropdownMenuItem>
<DropdownMenuSeparator />
<div className='px-2 py-2 space-y-2'>
<p className='text-xs font-medium text-muted-foreground'>Theme</p>
<ToggleGroup
type='single'
value={theme}
onValueChange={handleThemeChange}
aria-label='Select theme'
className='w-full justify-start'
>
<ToggleGroupItem
value='light'
aria-label='Light theme'
className='flex-1 flex items-center justify-center gap-1'
>
<Sun className='h-4 w-4' />
</ToggleGroupItem>
<ToggleGroupItem
value='system'
aria-label='System theme'
className='flex-1 flex items-center justify-center gap-1'
>
<Monitor className='h-4 w-4' />
</ToggleGroupItem>
<ToggleGroupItem
value='dark'
aria-label='Dark theme'
className='flex-1 flex items-center justify-center gap-1'
>
<Moon className='h-4 w-4' />
</ToggleGroupItem>
</ToggleGroup>
</div>
<DropdownMenuItem
onClick={() => removeLogin(currentUser.id)}
className='flex items-center gap-2 cursor-pointer p-2 rounded-md text-red-500'

View File

@@ -4,111 +4,89 @@
@layer base {
:root {
--background: 0 0% 97.6471%;
--foreground: 0 0% 12.5490%;
--card: 0 0% 98.8235%;
--card-foreground: 0 0% 12.5490%;
--popover: 0 0% 98.8235%;
--popover-foreground: 0 0% 12.5490%;
--primary: 16.6667 21.9512% 32.1569%;
--primary-foreground: 0 0% 100%;
--secondary: 34.0541 100.0000% 85.4902%;
--secondary-foreground: 16.2712 50.4274% 22.9412%;
--muted: 0 0% 93.7255%;
--muted-foreground: 0 0% 39.2157%;
--accent: 0 0% 90.9804%;
--accent-foreground: 0 0% 12.5490%;
--destructive: 10.1639 77.8723% 53.9216%;
--destructive-foreground: 0 0% 100%;
--border: 0 0% 84.7059%;
--input: 0 0% 84.7059%;
--ring: 16.6667 21.9512% 32.1569%;
--chart-1: rgb(100, 74, 64);
--chart-2: rgb(255, 223, 181);
--chart-3: rgb(232, 232, 232);
--chart-4: rgb(255, 230, 196);
--chart-5: rgb(102, 73, 62);
--sidebar: 0 0% 98.4314%;
--sidebar-foreground: 0 0% 14.5098%;
--sidebar-primary: 0 0% 20.3922%;
--sidebar-primary-foreground: 0 0% 98.4314%;
--sidebar-accent: 0 0% 96.8627%;
--sidebar-accent-foreground: 0 0% 20.3922%;
--sidebar-border: 0 0% 92.1569%;
--sidebar-ring: 0 0% 70.9804%;
--font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
--radius: 0.5rem;
--shadow-x: 0;
--shadow-y: 1px;
--shadow-blur: 3px;
--shadow-spread: 0px;
--shadow-opacity: 0.1;
--shadow-color: oklch(0 0 0);
--shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);
--shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);
--shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 2px 4px -1px hsl(0 0% 0% / 0.10);
--shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 4px 6px -1px hsl(0 0% 0% / 0.10);
--shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 8px 10px -1px hsl(0 0% 0% / 0.10);
--shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);
--tracking-normal: 0em;
--spacing: 0.25rem;
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--background: 0 0% 6.6667%;
--foreground: 0 0% 93.3333%;
--card: 0 0% 9.8039%;
--card-foreground: 0 0% 93.3333%;
--popover: 0 0% 9.8039%;
--popover-foreground: 0 0% 93.3333%;
--primary: 29.5082 100% 88.0392%;
--primary-foreground: 183.1579 54.2857% 6.8627%;
--secondary: 28.2353 17.5258% 19.0196%;
--secondary-foreground: 29.5082 100% 88.0392%;
--muted: 0 0% 13.3333%;
--muted-foreground: 0 0% 70.5882%;
--accent: 0 0% 16.4706%;
--accent-foreground: 0 0% 93.3333%;
--destructive: 10.1639 77.8723% 53.9216%;
--destructive-foreground: 0 0% 100%;
--border: 45 14.2857% 10.9804%;
--input: 0 0% 28.2353%;
--ring: 29.5082 100% 88.0392%;
--chart-1: rgb(255, 224, 194);
--chart-2: rgb(57, 48, 40);
--chart-3: rgb(42, 42, 42);
--chart-4: rgb(66, 56, 46);
--chart-5: rgb(255, 224, 193);
--sidebar: 240 5.8824% 10%;
--sidebar-foreground: 240 4.7619% 95.8824%;
--sidebar-primary: 224.2781 76.3265% 48.0392%;
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7037% 15.8824%;
--sidebar-accent-foreground: 240 4.7619% 95.8824%;
--sidebar-border: 240 3.7037% 15.8824%;
--sidebar-ring: 240 4.8780% 83.9216%;
--font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--radius: 0.5rem;
--shadow-x: 0;
--shadow-y: 1px;
--shadow-blur: 3px;
--shadow-spread: 0px;
--shadow-opacity: 0.1;
--shadow-color: oklch(0 0 0);
--shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);
--shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);
--shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 2px 4px -1px hsl(0 0% 0% / 0.10);
--shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 4px 6px -1px hsl(0 0% 0% / 0.10);
--shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 8px 10px -1px hsl(0 0% 0% / 0.10);
--shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}