Fix navbar mobile add active page

This commit is contained in:
2025-10-19 18:08:49 +08:00
parent bbf13c1cf7
commit 9055b40769

View File

@@ -5,7 +5,7 @@ import stateNav from "@/state/state-nav";
import { ActionIcon, Box, Burger, Group, Image, Paper, ScrollArea, Stack, Text, Tooltip } from "@mantine/core"; import { ActionIcon, Box, Burger, Group, Image, Paper, ScrollArea, Stack, Text, Tooltip } from "@mantine/core";
import { IconSquareArrowRight } from "@tabler/icons-react"; import { IconSquareArrowRight } from "@tabler/icons-react";
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { useRouter } from "next/navigation"; import { usePathname, useRouter } from "next/navigation";
import { useSnapshot } from "valtio"; import { useSnapshot } from "valtio";
import { MenuItem } from "../../../../types/menu-item"; import { MenuItem } from "../../../../types/menu-item";
import { NavbarMainMenu } from "./NavbarMainMenu"; import { NavbarMainMenu } from "./NavbarMainMenu";
@@ -19,14 +19,18 @@ export function Navbar() {
<Paper <Paper
radius="0" radius="0"
className="glass2" className="glass2"
w="100%" w="100vw"
pos="fixed" pos="fixed"
top={0} top={0}
style={{ zIndex: 100 }} style={{ zIndex: 100 }}
> >
{/* Desktop navbar (muncul mulai 992px ke atas) */}
<Box visibleFrom="md">
<NavbarMainMenu listNavbar={navbarListMenu} /> <NavbarMainMenu listNavbar={navbarListMenu} />
</Box>
<Box hiddenFrom="sm" bg={colors.grey[2]} px="md" py="sm"> {/* Mobile navbar (muncul di bawah 992px, termasuk iPad Mini) */}
<Box hiddenFrom="md" bg={colors.grey[2]} px="md" py="sm">
<Group justify="space-between" wrap="nowrap"> <Group justify="space-between" wrap="nowrap">
<ActionIcon <ActionIcon
variant="transparent" variant="transparent"
@@ -38,10 +42,21 @@ export function Navbar() {
}} }}
> >
<Tooltip label="Go to homepage" position="bottom" withArrow> <Tooltip label="Go to homepage" position="bottom" withArrow>
<Image src="/darmasaba-icon.png" alt="Village Logo" width={48} height={48} loading="lazy"/> <Image
src="/darmasaba-icon.png"
alt="Village Logo"
width={48}
height={48}
loading="lazy"
/>
</Tooltip> </Tooltip>
</ActionIcon> </ActionIcon>
<Tooltip label={mobileOpen ? "Close menu" : "Open menu"} position="bottom" withArrow>
<Tooltip
label={mobileOpen ? "Close menu" : "Open menu"}
position="bottom"
withArrow
>
<Burger <Burger
opened={mobileOpen} opened={mobileOpen}
color={colors["blue-button"]} color={colors["blue-button"]}
@@ -50,12 +65,14 @@ export function Navbar() {
/> />
</Tooltip> </Tooltip>
</Group> </Group>
{mobileOpen && ( {mobileOpen && (
<Paper <Paper
component={motion.div} component={motion.div}
initial={{ x: '100%' }} bg="white"
initial={{ x: "100%" }}
animate={{ x: 0 }} animate={{ x: 0 }}
exit={{ x: '100%' }} exit={{ x: "100%" }}
transition={{ duration: 0.2 }} transition={{ duration: 0.2 }}
pos="absolute" pos="absolute"
left={0} left={0}
@@ -63,12 +80,14 @@ export function Navbar() {
top="100%" top="100%"
m={0} m={0}
radius={0} radius={0}
shadow="md"
> >
<NavbarMobile listNavbar={navbarListMenu} /> <NavbarMobile listNavbar={navbarListMenu} />
</Paper> </Paper>
)} )}
</Box> </Box>
</Paper> </Paper>
{(item || isSearch) && <Box className="glass" />} {(item || isSearch) && <Box className="glass" />}
</Box> </Box>
); );
@@ -76,15 +95,28 @@ export function Navbar() {
function NavbarMobile({ listNavbar }: { listNavbar: MenuItem[] }) { function NavbarMobile({ listNavbar }: { listNavbar: MenuItem[] }) {
const router = useRouter(); const router = useRouter();
const pathname = usePathname(); // 👈 untuk cek path aktif
// fungsi bantu: cek apakah path sekarang sama dengan menu / sub-menu
const isActive = (href?: string) => href && pathname.startsWith(href);
return (
<ScrollArea.Autosize
mah="calc(100dvh - 80px)"
type="auto"
offsetScrollbars
>
<Stack p="sm" gap="xs">
{listNavbar.map((item, k) => {
const active = isActive(item.href);
return ( return (
<ScrollArea.Autosize mah="calc(100vh - 80px)" offsetScrollbars>
<Stack p="md" gap="xs">
{listNavbar.map((item, k) => (
<Box key={k}> <Box key={k}>
<Group <Paper
justify="space-between" shadow={active ? "sm" : "xs"}
align="center" radius="md"
p="xs" p="sm"
withBorder
bg={active ? "blue.0" : "gray.0"}
onClick={() => { onClick={() => {
if (item.href) { if (item.href) {
router.push(item.href); router.push(item.href);
@@ -93,23 +125,75 @@ function NavbarMobile({ listNavbar }: { listNavbar: MenuItem[] }) {
}} }}
style={{ style={{
cursor: item.href ? "pointer" : "default", cursor: item.href ? "pointer" : "default",
opacity: item.href ? 1 : 0.8 transition: "background 0.15s ease",
borderLeft: active ? "4px solid #1e66f5" : "4px solid transparent",
}} }}
> >
<Text c="dark.9" fw={600} fz="md"> <Group justify="space-between" align="center" wrap="nowrap">
<Text
fw={active ? 700 : 600}
fz="md"
c={active ? "blue.7" : "dark.9"}
>
{item.name} {item.name}
</Text> </Text>
<IconSquareArrowRight size={18} /> {item.href && (
<IconSquareArrowRight
size={18}
color={active ? "#1e66f5" : "inherit"}
/>
)}
</Group> </Group>
</Paper>
{/* Submenu */}
{item.children && ( {item.children && (
<Box pl="md"> <Box pl="md" mt={4}>
<NavbarMobile listNavbar={item.children} /> {item.children.map((child, j) => {
const childActive = isActive(child.href);
return (
<Group
key={j}
justify="space-between"
align="center"
p="xs"
onClick={() => {
if (child.href) {
router.push(child.href);
stateNav.mobileOpen = false;
}
}}
style={{
cursor: child.href ? "pointer" : "default",
opacity: child.href ? 1 : 0.8,
borderRadius: "0.5rem",
backgroundColor: childActive ? "#e7f0ff" : "transparent",
borderLeft: childActive ? "3px solid #1e66f5" : "3px solid transparent",
transition: "background 0.15s ease",
}}
>
<Text
fz="sm"
fw={childActive ? 600 : 400}
c={childActive ? "blue.7" : "dark.8"}
>
{child.name}
</Text>
<IconSquareArrowRight
size={14}
color={childActive ? "#1e66f5" : "inherit"}
/>
</Group>
);
})}
</Box> </Box>
)} )}
</Box> </Box>
))} );
})}
</Stack> </Stack>
</ScrollArea.Autosize> </ScrollArea.Autosize>
); );
} }