mirror of
https://github.com/narrrl/holy-flavor-rater.git
synced 2026-11-03 16:41:27 +01:00
116 lines
3.7 KiB
TypeScript
116 lines
3.7 KiB
TypeScript
import { Link, useLocation } from 'react-router-dom';
|
|
import { Box, Button, alpha } from '@mui/material';
|
|
import type { Theme } from '@mui/material';
|
|
import HomeOutlinedIcon from '@mui/icons-material/HomeOutlined';
|
|
import GroupsOutlinedIcon from '@mui/icons-material/GroupsOutlined';
|
|
import CollectionsBookmarkOutlinedIcon from '@mui/icons-material/CollectionsBookmarkOutlined';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useAuth } from '../../hooks/useAuth';
|
|
|
|
export interface CategoryBarProps {
|
|
categories: { name: string; slug: string }[];
|
|
}
|
|
|
|
/**
|
|
* The browse row. Categories are the dominant browse axis, so they get a
|
|
* scrollable row of their own with Home / Community / Dashboard leading it.
|
|
*
|
|
* This renders as the *second row inside* the nav pane (see `GlassAppBar`) —
|
|
* it deliberately carries no sticky positioning or glass of its own, so the
|
|
* two rows share one pane, one rim and one blur pass instead of stacking two
|
|
* translucent bars on top of each other.
|
|
*/
|
|
export const CategoryBar = ({ categories }: CategoryBarProps) => {
|
|
const { t } = useTranslation();
|
|
const location = useLocation();
|
|
const { user } = useAuth();
|
|
|
|
const isActive = (path: string) =>
|
|
path === '/' ? location.pathname === '/' : location.pathname.startsWith(path);
|
|
|
|
const tabSx = (active: boolean) => ({
|
|
flexShrink: 0,
|
|
borderRadius: (theme: Theme) => `${theme.tokens.radius.pill}px`,
|
|
px: 1.75,
|
|
py: 0.75,
|
|
fontWeight: active ? 700 : 500,
|
|
color: active ? 'primary.main' : 'text.secondary',
|
|
bgcolor: active ? (theme: Theme) => alpha(theme.palette.primary.main, 0.14) : 'transparent',
|
|
border: '1px solid',
|
|
borderColor: active ? (theme: Theme) => alpha(theme.palette.primary.main, 0.35) : 'transparent',
|
|
transition: (theme: Theme) =>
|
|
`background-color ${theme.tokens.motion.fast} ${theme.tokens.motion.ease}, border-color ${theme.tokens.motion.fast} ${theme.tokens.motion.ease}`,
|
|
'&:hover': {
|
|
color: 'text.primary',
|
|
bgcolor: 'action.hover',
|
|
},
|
|
});
|
|
|
|
return (
|
|
<Box
|
|
component="nav"
|
|
sx={{
|
|
maxWidth: 1400,
|
|
mx: 'auto',
|
|
px: { xs: 1, sm: 4, md: 6 },
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: { xs: 0.5, md: 1 },
|
|
minHeight: { xs: 46, md: 52 },
|
|
overflowX: 'auto',
|
|
'&::-webkit-scrollbar': { display: 'none' },
|
|
scrollbarWidth: 'none',
|
|
}}
|
|
>
|
|
<Button
|
|
component={Link}
|
|
to="/"
|
|
disableRipple
|
|
sx={{ ...tabSx(isActive('/')), ml: { xs: -0.5, md: -1.75 } }}
|
|
>
|
|
<HomeOutlinedIcon sx={{ fontSize: '1.1rem', mr: 0.75 }} />
|
|
{t('nav.home')}
|
|
</Button>
|
|
|
|
{user && (
|
|
<Button component={Link} to="/community" disableRipple sx={tabSx(isActive('/community'))}>
|
|
<GroupsOutlinedIcon sx={{ fontSize: '1.1rem', mr: 0.75 }} />
|
|
{t('nav.community')}
|
|
</Button>
|
|
)}
|
|
|
|
{user && (
|
|
<Button component={Link} to="/dashboard" disableRipple sx={tabSx(isActive('/dashboard'))}>
|
|
<CollectionsBookmarkOutlinedIcon sx={{ fontSize: '1.1rem', mr: 0.75 }} />
|
|
{t('nav.dashboard')}
|
|
</Button>
|
|
)}
|
|
|
|
<Box
|
|
sx={{
|
|
alignSelf: 'stretch',
|
|
my: 1.25,
|
|
mx: 0.5,
|
|
borderLeft: '1px solid',
|
|
borderColor: 'divider',
|
|
}}
|
|
/>
|
|
|
|
{categories.map((cat) => {
|
|
const path = `/category/${cat.slug}`;
|
|
return (
|
|
<Button
|
|
key={cat.slug}
|
|
component={Link}
|
|
to={path}
|
|
disableRipple
|
|
sx={tabSx(location.pathname === path)}
|
|
>
|
|
{t(`categories.${cat.slug}`, { defaultValue: cat.name })}
|
|
</Button>
|
|
);
|
|
})}
|
|
</Box>
|
|
);
|
|
};
|