feat: add user avatar menu (#80)
This commit is contained in:
@@ -1,11 +1,14 @@
|
|||||||
import { UnstyledButton } from "@homarr/ui";
|
import { UnstyledButton } from "@homarr/ui";
|
||||||
|
|
||||||
import { UserAvatar } from "~/components/user-avatar";
|
import { UserAvatar } from "~/components/user-avatar";
|
||||||
|
import { UserAvatarMenu } from "~/components/user-avatar-menu";
|
||||||
|
|
||||||
export const UserButton = () => {
|
export const UserButton = () => {
|
||||||
return (
|
return (
|
||||||
<UnstyledButton>
|
<UserAvatarMenu>
|
||||||
<UserAvatar size="md" />
|
<UnstyledButton>
|
||||||
</UnstyledButton>
|
<UserAvatar size="md" />
|
||||||
|
</UnstyledButton>
|
||||||
|
</UserAvatarMenu>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
61
apps/nextjs/src/components/user-avatar-menu.tsx
Normal file
61
apps/nextjs/src/components/user-avatar-menu.tsx
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
import { useScopedI18n } from "@homarr/translation/client";
|
||||||
|
import {
|
||||||
|
IconDashboard,
|
||||||
|
IconLogout,
|
||||||
|
IconMoon,
|
||||||
|
IconSun,
|
||||||
|
IconTool,
|
||||||
|
Menu,
|
||||||
|
useMantineColorScheme,
|
||||||
|
} from "@homarr/ui";
|
||||||
|
|
||||||
|
interface UserAvatarMenuProps {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const UserAvatarMenu = ({ children }: UserAvatarMenuProps) => {
|
||||||
|
const t = useScopedI18n("common.userAvatar.menu");
|
||||||
|
const { colorScheme, toggleColorScheme } = useMantineColorScheme();
|
||||||
|
|
||||||
|
const ColorSchemeIcon = colorScheme === "dark" ? IconSun : IconMoon;
|
||||||
|
|
||||||
|
const colorSchemeText =
|
||||||
|
colorScheme === "dark" ? t("switchToLightMode") : t("switchToDarkMode");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Menu width={200} withArrow withinPortal>
|
||||||
|
<Menu.Dropdown>
|
||||||
|
<Menu.Item
|
||||||
|
onClick={toggleColorScheme}
|
||||||
|
leftSection={<ColorSchemeIcon size="1rem" />}
|
||||||
|
>
|
||||||
|
{colorSchemeText}
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
component={Link}
|
||||||
|
href="/boards"
|
||||||
|
leftSection={<IconDashboard size="1rem" />}
|
||||||
|
>
|
||||||
|
{t("navigateDefaultBoard")}
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
component={Link}
|
||||||
|
href="/manage"
|
||||||
|
leftSection={<IconTool size="1rem" />}
|
||||||
|
>
|
||||||
|
{t("management")}
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Divider />
|
||||||
|
<Menu.Item leftSection={<IconLogout size="1rem" />} color="red">
|
||||||
|
{t("logout")}
|
||||||
|
</Menu.Item>
|
||||||
|
</Menu.Dropdown>
|
||||||
|
<Menu.Target>{children}</Menu.Target>
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -155,6 +155,15 @@ export default {
|
|||||||
placeholder: "Search for anything...",
|
placeholder: "Search for anything...",
|
||||||
nothingFound: "Nothing found",
|
nothingFound: "Nothing found",
|
||||||
},
|
},
|
||||||
|
userAvatar: {
|
||||||
|
menu: {
|
||||||
|
switchToDarkMode: "Switch to dark mode",
|
||||||
|
switchToLightMode: "Switch to light mode",
|
||||||
|
management: "Management",
|
||||||
|
logout: "Logout",
|
||||||
|
navigateDefaultBoard: "Navigate to default board",
|
||||||
|
},
|
||||||
|
},
|
||||||
noResults: "No results found",
|
noResults: "No results found",
|
||||||
},
|
},
|
||||||
section: {
|
section: {
|
||||||
|
|||||||
Reference in New Issue
Block a user