whisper-money/resources/js/components/nav-footer.tsx

59 lines
1.9 KiB
TypeScript

import { Icon } from '@/components/icon';
import {
SidebarGroup,
SidebarGroupContent,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from '@/components/ui/sidebar';
import { resolveUrl } from '@/lib/utils';
import { type NavItem } from '@/types';
import { __ } from '@/utils/i18n';
import { LucideIcon } from 'lucide-react';
import { isValidElement, type ComponentPropsWithoutRef } from 'react';
export function NavFooter({
items,
className,
...props
}: ComponentPropsWithoutRef<typeof SidebarGroup> & {
items: NavItem[];
}) {
return (
<SidebarGroup
{...props}
className={`group-data-[collapsible=icon]:p-0 ${className || ''}`}
>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton
asChild
className="text-neutral-600 hover:text-neutral-800 dark:text-neutral-300 dark:hover:text-neutral-100"
>
<a
href={resolveUrl(item.href)}
target="_blank"
rel="noopener noreferrer"
>
<IconOrComponent icon={item.icon} />
<span>{__(item.title)}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
);
}
function IconOrComponent({ icon }: { icon: React.ReactNode | LucideIcon }) {
if (isValidElement(icon)) {
return icon;
}
return <Icon iconNode={icon as LucideIcon} />;
}