Update theme selector and optimize button styling

Updated the theme selector to display the currently selected theme more clearly and enhance user-friendliness. Further, the button style is modernized with a class ensuring rounded edges for a sleeker appearance. These changes are applicable to the "ghost" button variant used for mode selection. Finally, the mode selection options utilize the MODES array for a dynamic approach, moving away from a fixed, hard-coded selection.
This commit is contained in:
giancarlo
2024-04-04 10:27:43 +08:00
parent 0b374c558a
commit ca2c3ebbbd
2 changed files with 39 additions and 19 deletions

View File

@@ -2,7 +2,7 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import { CheckCircle, Moon, Sun } from 'lucide-react'; import { Computer, Moon, Sun } from 'lucide-react';
import { useTheme } from 'next-themes'; import { useTheme } from 'next-themes';
import { Button } from '../shadcn/button'; import { Button } from '../shadcn/button';
@@ -15,39 +15,49 @@ import {
DropdownMenuSubTrigger, DropdownMenuSubTrigger,
DropdownMenuTrigger, DropdownMenuTrigger,
} from '../shadcn/dropdown-menu'; } from '../shadcn/dropdown-menu';
import { If } from './if'; import { cn } from '../utils';
import { Trans } from './trans'; import { Trans } from './trans';
const MODES = ['light', 'dark', 'system']; const MODES = ['light', 'dark', 'system'];
export function ModeToggle() { export function ModeToggle() {
const { setTheme } = useTheme(); const { setTheme, theme } = useTheme();
const Items = useMemo(() => { const Items = useMemo(() => {
return MODES.map((mode) => { return MODES.map((mode) => {
const isSelected = theme === mode;
return ( return (
<DropdownMenuItem <DropdownMenuItem
className={cn('space-x-2', {
'bg-muted': isSelected,
})}
key={mode} key={mode}
onClick={() => { onClick={() => {
setTheme(mode); setTheme(mode);
setCookeTheme(mode); setCookeTheme(mode);
}} }}
> >
<Icon theme={mode} />
<span>
<Trans i18nKey={`common:${mode}Theme`} /> <Trans i18nKey={`common:${mode}Theme`} />
</span>
</DropdownMenuItem> </DropdownMenuItem>
); );
}); });
}, [setTheme]); }, [setTheme, theme]);
return ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon"> <Button variant="ghost" size="icon" className="rounded-full">
<Sun className="h-[1rem] w-[1rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" /> <Sun className="h-[1rem] w-[1rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1rem] w-[1rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" /> <Moon className="absolute h-[1rem] w-[1rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span> <span className="sr-only">Toggle theme</span>
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end">{Items}</DropdownMenuContent> <DropdownMenuContent align="end">{Items}</DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
); );
@@ -58,21 +68,25 @@ export function SubMenuModeToggle() {
const MenuItems = useMemo( const MenuItems = useMemo(
() => () =>
['light', 'dark', 'system'].map((mode) => { MODES.map((mode) => {
const isSelected = theme === mode;
return ( return (
<DropdownMenuItem <DropdownMenuItem
className={'justify-between'} className={cn('flex items-center space-x-2', {
'bg-muted': isSelected,
})}
key={mode} key={mode}
onClick={() => { onClick={() => {
setTheme(mode); setTheme(mode);
setCookeTheme(mode); setCookeTheme(mode);
}} }}
> >
<Trans i18nKey={`common:${mode}Theme`} /> <Icon theme={mode} />
<If condition={theme === mode}> <span>
<CheckCircle className={'mr-2 h-3'} /> <Trans i18nKey={`common:${mode}Theme`} />
</If> </span>
</DropdownMenuItem> </DropdownMenuItem>
); );
}), }),
@@ -83,11 +97,7 @@ export function SubMenuModeToggle() {
<DropdownMenuSub> <DropdownMenuSub>
<DropdownMenuSubTrigger> <DropdownMenuSubTrigger>
<span className={'flex w-full items-center space-x-2'}> <span className={'flex w-full items-center space-x-2'}>
{resolvedTheme === 'light' ? ( <Icon theme={resolvedTheme} />
<Sun className={'h-5'} />
) : (
<Moon className={'h-5'} />
)}
<span> <span>
<Trans i18nKey={'common:theme'} /> <Trans i18nKey={'common:theme'} />
@@ -103,3 +113,14 @@ export function SubMenuModeToggle() {
function setCookeTheme(theme: string) { function setCookeTheme(theme: string) {
document.cookie = `theme=${theme}; path=/; max-age=31536000`; document.cookie = `theme=${theme}; path=/; max-age=31536000`;
} }
function Icon({ theme }: { theme: string | undefined }) {
switch (theme) {
case 'light':
return <Sun className="h-4" />;
case 'dark':
return <Moon className="h-4" />;
case 'system':
return <Computer className="h-4" />;
}
}

View File

@@ -16,10 +16,9 @@ import {
TooltipProvider, TooltipProvider,
TooltipTrigger, TooltipTrigger,
} from '../shadcn/tooltip'; } from '../shadcn/tooltip';
import { cn } from '../utils'; import { cn, isRouteActive } from '../utils';
import { SidebarContext } from './context/sidebar.context'; import { SidebarContext } from './context/sidebar.context';
import { If } from './if'; import { If } from './if';
import isRouteActive from './is-route-active';
import { SidebarConfigSchema } from './sidebar-schema'; import { SidebarConfigSchema } from './sidebar-schema';
import { Trans } from './trans'; import { Trans } from './trans';