feat: menu styles
This commit is contained in:
5
bun.lock
5
bun.lock
@@ -4,6 +4,7 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "anti-hvost",
|
"name": "anti-hvost",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@heroicons/react": "^2.2.0",
|
||||||
"@preact/signals": "^2.0.2",
|
"@preact/signals": "^2.0.2",
|
||||||
"@tailwindcss/postcss": "^4.0.17",
|
"@tailwindcss/postcss": "^4.0.17",
|
||||||
"@tailwindcss/vite": "^4.0.17",
|
"@tailwindcss/vite": "^4.0.17",
|
||||||
@@ -147,6 +148,8 @@
|
|||||||
|
|
||||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.7", "", { "dependencies": { "@eslint/core": "^0.12.0", "levn": "^0.4.1" } }, "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g=="],
|
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.7", "", { "dependencies": { "@eslint/core": "^0.12.0", "levn": "^0.4.1" } }, "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g=="],
|
||||||
|
|
||||||
|
"@heroicons/react": ["@heroicons/react@2.2.0", "", { "peerDependencies": { "react": ">= 16 || ^19.0.0-rc" } }, "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ=="],
|
||||||
|
|
||||||
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
||||||
|
|
||||||
"@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="],
|
"@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="],
|
||||||
@@ -583,6 +586,8 @@
|
|||||||
|
|
||||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||||
|
|
||||||
|
"react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="],
|
||||||
|
|
||||||
"react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
"react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
||||||
|
|
||||||
"require-relative": ["require-relative@0.8.7", "", {}, "sha512-AKGr4qvHiryxRb19m3PsLRGuKVAbJLUD7E6eOaHkfKhwc+vSgVOCY5xNvm9EkolBKTOf0GrQAZKLimOCz81Khg=="],
|
"require-relative": ["require-relative@0.8.7", "", {}, "sha512-AKGr4qvHiryxRb19m3PsLRGuKVAbJLUD7E6eOaHkfKhwc+vSgVOCY5xNvm9EkolBKTOf0GrQAZKLimOCz81Khg=="],
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@heroicons/react": "^2.2.0",
|
||||||
"@preact/signals": "^2.0.2",
|
"@preact/signals": "^2.0.2",
|
||||||
"@tailwindcss/postcss": "^4.0.17",
|
"@tailwindcss/postcss": "^4.0.17",
|
||||||
"@tailwindcss/vite": "^4.0.17",
|
"@tailwindcss/vite": "^4.0.17",
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
@reference "../index.scss";
|
@reference "../index.scss";
|
||||||
|
|
||||||
|
#container {
|
||||||
|
@apply flex min-h-auto w-screen flex-col items-center gap-4 px-2 py-3 md:min-h-screen md:w-[30rem];
|
||||||
|
}
|
||||||
|
|
||||||
.menu_container {
|
.menu_container {
|
||||||
@apply fixed right-0 bottom-0 left-0 flex min-h-auto flex-row items-center gap-1 border-t border-t-gray-500 bg-white px-1 py-5 md:sticky md:top-0 md:right-0 md:bottom-auto md:left-auto md:min-h-screen md:w-auto md:flex-col md:gap-4 md:border-t-0 md:border-l md:border-l-gray-500 md:px-5 md:py-5;
|
@apply fixed right-0 bottom-0 left-0 flex h-[4rem] w-full flex-1 flex-row items-center gap-1 rounded-[44px] bg-[rgba(167,213,246,0.3)] px-1 py-5 md:sticky md:top-0 md:right-0 md:bottom-auto md:left-auto md:h-full md:flex-col md:gap-4 md:border-t-0 md:px-5 md:py-5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu_item {
|
.menu_item {
|
||||||
@apply w-full cursor-pointer rounded-md px-3 py-2 text-center hover:bg-gray-200 md:px-6;
|
@apply flex w-full cursor-pointer flex-row items-center gap-3 rounded-full px-3 py-2 text-center hover:bg-gray-200 md:px-6;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { FunctionComponent } from "preact";
|
import { cn } from "@/utils/class-merge";
|
||||||
|
import { CalendarDaysIcon, ListBulletIcon, UserIcon } from "@heroicons/react/24/solid";
|
||||||
|
import { FunctionComponent, h } from "preact";
|
||||||
import { useLocation } from "preact-iso";
|
import { useLocation } from "preact-iso";
|
||||||
import { tv } from "tailwind-variants";
|
import { tv } from "tailwind-variants";
|
||||||
import classes from "./menu.module.scss";
|
import classes from "./menu.module.scss";
|
||||||
@@ -6,9 +8,10 @@ import classes from "./menu.module.scss";
|
|||||||
interface MenuItemProps {
|
interface MenuItemProps {
|
||||||
title: string;
|
title: string;
|
||||||
link: string;
|
link: string;
|
||||||
|
icon: h.JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MenuItem: FunctionComponent<MenuItemProps> = ({ title, link }: MenuItemProps) => {
|
const MenuItem: FunctionComponent<MenuItemProps> = ({ title, link, icon }: MenuItemProps) => {
|
||||||
const { route, path } = useLocation();
|
const { route, path } = useLocation();
|
||||||
const active = path === link;
|
const active = path === link;
|
||||||
const menuItemClasses = tv({
|
const menuItemClasses = tv({
|
||||||
@@ -16,7 +19,7 @@ const MenuItem: FunctionComponent<MenuItemProps> = ({ title, link }: MenuItemPro
|
|||||||
variants: {
|
variants: {
|
||||||
activity: {
|
activity: {
|
||||||
active: "bg-gray-200",
|
active: "bg-gray-200",
|
||||||
inactive: "bg-gray-100",
|
inactive: "bg-white",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
@@ -25,36 +28,70 @@ const MenuItem: FunctionComponent<MenuItemProps> = ({ title, link }: MenuItemPro
|
|||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<div class={menuItemClasses({ activity: active ? "active" : "inactive" })} onClick={() => route(link, true)}>
|
<div class={menuItemClasses({ activity: active ? "active" : "inactive" })} onClick={() => route(link, true)}>
|
||||||
|
{icon}
|
||||||
{title}
|
{title}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Avatar: FunctionComponent = () => {
|
||||||
|
const { route, path } = useLocation();
|
||||||
|
//TODO: Move styles to scss module
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
onClick={() => route("/profile/settings")}
|
||||||
|
class={cn("hidden h-32 w-full cursor-pointer overflow-hidden transition-[height] md:block", {
|
||||||
|
"h-0": path === "/profile/settings",
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class={cn(
|
||||||
|
"h-full flex-row items-center justify-around rounded-[44px] bg-[linear-gradient(180.00deg,rgba(249,134,143,0.5)_3.053%,rgb(228,242,252)_96.183%)] px-5 py-5 md:flex"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div class="my-5 aspect-square h-full rounded-full bg-white"></div>
|
||||||
|
<div class="flex flex-col items-center justify-center">
|
||||||
|
<p class="text-3xl font-semibold">Никнейм</p>
|
||||||
|
<p class="text-xl font-light">Статус</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
interface MenuItems {
|
interface MenuItems {
|
||||||
title: string;
|
title: string;
|
||||||
link: string;
|
link: string;
|
||||||
|
icon: h.JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Menu: FunctionComponent = () => {
|
const Menu: FunctionComponent = () => {
|
||||||
|
//TODO: Move links to enum
|
||||||
const menu_items: MenuItems[] = [
|
const menu_items: MenuItems[] = [
|
||||||
{
|
|
||||||
title: "Профиль",
|
|
||||||
link: "/profile/settings",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "Задачи",
|
title: "Задачи",
|
||||||
link: "/profile/tasks",
|
link: "/profile/tasks",
|
||||||
|
icon: <ListBulletIcon class="size-10" />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Календарь",
|
title: "Календарь",
|
||||||
link: "/profile/calendar",
|
link: "/profile/calendar",
|
||||||
|
icon: <CalendarDaysIcon class="size-10" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Профиль",
|
||||||
|
link: "/profile/settings",
|
||||||
|
icon: <UserIcon class="size-10" />,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<div class={classes.menu_container}>
|
<div id={classes.container}>
|
||||||
{menu_items.map(({ title, link }) => (
|
<Avatar />
|
||||||
<MenuItem title={title} link={link} />
|
<div class={classes.menu_container}>
|
||||||
))}
|
{menu_items.map(({ title, link, icon }) => (
|
||||||
|
<MenuItem title={title} link={link} icon={icon} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user