feat: new dropdown-menu

This commit is contained in:
hamster1963 2024-11-14 16:25:16 +08:00
parent e6d2916402
commit f931a9c487
3 changed files with 43 additions and 18 deletions

View File

@ -9,16 +9,17 @@ import {
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { localeItems } from "@/i18n-metadata"; import { localeItems } from "@/i18n-metadata";
import { setUserLocale } from "@/i18n/locale"; import { setUserLocale } from "@/i18n/locale";
import { CheckCircleIcon } from "@heroicons/react/20/solid";
import { useLocale } from "next-intl"; import { useLocale } from "next-intl";
import * as React from "react"; import * as React from "react";
export function LanguageSwitcher() { export function LanguageSwitcher() {
const locale = useLocale(); const locale = useLocale();
function onChange(value: string) { const handleSelect = (e: Event, newLocale: string) => {
const locale = value; e.preventDefault(); // 阻止默认的关闭行为
setUserLocale(locale); setUserLocale(newLocale);
} };
return ( return (
<DropdownMenu> <DropdownMenu>
@ -32,10 +33,15 @@ export function LanguageSwitcher() {
<span className="sr-only">Change language</span> <span className="sr-only">Change language</span>
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end"> <DropdownMenuContent className="flex flex-col gap-0.5" align="end">
{localeItems.map((item) => ( {localeItems.map((item) => (
<DropdownMenuItem key={item.code} onClick={() => onChange(item.code)}> <DropdownMenuItem
{item.name} key={item.code}
onSelect={(e) => handleSelect(e, item.code)}
className={locale === item.code ? "bg-muted gap-3" : ""}
>
{item.name}{" "}
{locale === item.code && <CheckCircleIcon className="size-4" />}
</DropdownMenuItem> </DropdownMenuItem>
))} ))}
</DropdownMenuContent> </DropdownMenuContent>

View File

@ -7,14 +7,21 @@ import {
DropdownMenuItem, DropdownMenuItem,
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { cn } from "@/lib/utils";
import { CheckCircleIcon } from "@heroicons/react/20/solid";
import { Moon, Sun } from "lucide-react"; import { Moon, Sun } from "lucide-react";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useTheme } from "next-themes"; import { useTheme } from "next-themes";
import * as React from "react";
export function ModeToggle() { export function ModeToggle() {
const { setTheme } = useTheme(); const { setTheme, theme } = useTheme();
const t = useTranslations("ThemeSwitcher"); const t = useTranslations("ThemeSwitcher");
const handleSelect = (e: Event, newTheme: string) => {
e.preventDefault();
setTheme(newTheme);
};
return ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
@ -28,15 +35,27 @@ export function ModeToggle() {
<span className="sr-only">Toggle theme</span> <span className="sr-only">Toggle theme</span>
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end"> <DropdownMenuContent className="flex flex-col gap-0.5" align="end">
<DropdownMenuItem onClick={() => setTheme("light")}> <DropdownMenuItem
{t("Light")} className={cn({ "gap-3 bg-muted": theme === "light" })}
onSelect={(e) => handleSelect(e, "light")}
>
{t("Light")}{" "}
{theme === "light" && <CheckCircleIcon className="size-4" />}
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("dark")}> <DropdownMenuItem
{t("Dark")} className={cn({ "gap-3 bg-muted": theme === "dark" })}
onSelect={(e) => handleSelect(e, "dark")}
>
{t("Dark")}{" "}
{theme === "dark" && <CheckCircleIcon className="size-4" />}
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("system")}> <DropdownMenuItem
{t("System")} className={cn({ "gap-3 bg-muted": theme === "system" })}
onSelect={(e) => handleSelect(e, "system")}
>
{t("System")}{" "}
{theme === "system" && <CheckCircleIcon className="size-4" />}
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>

View File

@ -64,7 +64,7 @@ const DropdownMenuContent = React.forwardRef<
ref={ref} ref={ref}
sideOffset={sideOffset} sideOffset={sideOffset}
className={cn( className={cn(
"z-50 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg shadow-neutral-200/50 dark:shadow-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", "z-50 overflow-hidden rounded-md border bg-popover p-1.5 text-popover-foreground shadow-2xl dark:shadow-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className, className,
)} )}
{...props} {...props}
@ -82,7 +82,7 @@ const DropdownMenuItem = React.forwardRef<
<DropdownMenuPrimitive.Item <DropdownMenuPrimitive.Item
ref={ref} ref={ref}
className={cn( className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-xs font-medium outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", "relative flex cursor-default select-none items-center rounded-[10px] px-2 py-1.5 text-xs font-medium outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8", inset && "pl-8",
className, className,
)} )}