Spaces:
Sleeping
Sleeping
File size: 3,020 Bytes
b64de39 75fda81 b64de39 75fda81 b64de39 c5a7b7d b64de39 c5a7b7d b64de39 75fda81 b64de39 75fda81 b64de39 fc91a5e b64de39 75fda81 b64de39 fc91a5e b64de39 75fda81 b64de39 75fda81 b64de39 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | /**
* BottomNav - Mobile bottom navigation bar.
*
* Fixed to the bottom of the viewport on mobile screens.
* Hidden on desktop via className prop (default usage in Layout).
*/
import { useMemo } from "react";
import { Link, useLocation } from "react-router-dom";
import { useTranslation } from "react-i18next";
import PropTypes from "prop-types";
import {
HomeIcon,
CameraIcon,
CloudIcon,
CurrencyRupeeIcon,
DocumentTextIcon,
} from "@heroicons/react/24/outline";
import {
HomeIcon as HomeIconSolid,
CameraIcon as CameraIconSolid,
CloudIcon as CloudIconSolid,
CurrencyRupeeIcon as CurrencyRupeeIconSolid,
DocumentTextIcon as DocumentTextIconSolid,
} from "@heroicons/react/24/solid";
import { ROUTES } from "@utils/constants";
function BottomNav({ className = "" }) {
const { t } = useTranslation();
const location = useLocation();
const NAV_ITEMS = useMemo(() => [
{
labelKey: "nav.home",
path: ROUTES.HOME,
Icon: HomeIcon,
ActiveIcon: HomeIconSolid,
},
{
labelKey: "nav.diseaseDetection",
path: ROUTES.DISEASE_DETECTION,
Icon: CameraIcon,
ActiveIcon: CameraIconSolid,
},
{
labelKey: "nav.weather",
path: ROUTES.WEATHER,
Icon: CloudIcon,
ActiveIcon: CloudIconSolid,
},
{
labelKey: "nav.apmcPrice",
path: ROUTES.APMC,
Icon: CurrencyRupeeIcon,
ActiveIcon: CurrencyRupeeIconSolid,
},
{
labelKey: "nav.schemes",
path: ROUTES.SCHEMES,
Icon: DocumentTextIcon,
ActiveIcon: DocumentTextIconSolid,
},
], []);
return (
<nav
className={`fixed bottom-0 inset-x-0 z-30 border-t border-neutral-200 bg-white/95 backdrop-blur-sm safe-area-bottom ${className}`}
aria-label="Bottom navigation"
>
<div className="flex items-center justify-around h-16">
{NAV_ITEMS.map((item) => {
const isActive = location.pathname === item.path;
const IconComponent = isActive ? item.ActiveIcon : item.Icon;
const label = t(item.labelKey);
return (
<Link
key={item.path}
to={item.path}
className={[
"flex flex-col items-center justify-center gap-0.5 px-3 py-1 rounded-lg min-w-[4rem]",
"transition-colors focus:outline-none focus:ring-2 focus:ring-primary-500",
isActive
? "text-primary-700"
: "text-neutral-500 hover:text-neutral-700",
].join(" ")}
aria-current={isActive ? "page" : undefined}
aria-label={label}
>
<IconComponent className="h-6 w-6" aria-hidden="true" />
<span className="text-[10px] font-medium leading-tight truncate max-w-[4rem]">
{label}
</span>
</Link>
);
})}
</div>
</nav>
);
}
BottomNav.propTypes = {
className: PropTypes.string,
};
export default BottomNav;
|