buster/web/src/components/ui/sidebar/SidebarItem.tsx

110 lines
2.7 KiB
TypeScript
Raw Normal View History

2025-02-28 12:56:52 +08:00
import React from 'react';
import Link from 'next/link';
import { cn } from '@/lib/classMerge';
import { type ISidebarItem } from './interfaces';
2025-03-04 04:33:47 +08:00
import { cva, type VariantProps } from 'class-variance-authority';
2025-03-14 02:50:45 +08:00
import { Xmark } from '../icons';
import { Button } from '../buttons/Button';
2025-02-28 12:56:52 +08:00
const itemVariants = cva(
2025-03-14 02:50:45 +08:00
'flex items-center group justify-between rounded px-1.5 min-h-7 max-h-7 text-base transition-colors cursor-pointer',
2025-02-28 12:56:52 +08:00
{
variants: {
variant: {
2025-02-28 13:53:43 +08:00
default: 'hover:bg-nav-item-hover text-text-default',
2025-02-28 12:56:52 +08:00
emphasized: 'shadow bg-background border border-border text-text-default'
},
active: {
2025-02-28 13:53:43 +08:00
true: 'cursor-default',
2025-02-28 12:56:52 +08:00
false: ''
},
disabled: {
true: 'cursor-not-allowed',
false: ''
}
},
compoundVariants: [
{
active: true,
disabled: false,
variant: 'default',
className: 'bg-nav-item-select hover:bg-nav-item-select'
},
2025-02-28 13:00:13 +08:00
{
active: false,
disabled: true,
variant: 'default',
className: 'text-text-disabled! bg-transparent'
},
2025-02-28 12:56:52 +08:00
{
active: true,
disabled: false,
variant: 'emphasized',
2025-02-28 13:00:13 +08:00
className: 'bg-nav-item-select hover:bg-nav-item-select '
2025-02-28 12:56:52 +08:00
},
{
active: false,
disabled: true,
variant: 'emphasized',
className: 'bg-nav-item-select hover:bg-nav-item-select'
},
{
active: false,
disabled: false,
variant: 'emphasized',
className: 'hover:bg-item-hover '
}
]
}
);
2025-03-14 03:26:33 +08:00
export const SidebarItem: React.FC<
ISidebarItem &
VariantProps<typeof itemVariants> & {
className?: string;
}
> = React.memo(
2025-03-14 02:50:45 +08:00
({
label,
icon,
route,
id,
disabled = false,
active = false,
variant = 'default',
onRemove,
2025-03-14 03:26:33 +08:00
className = '',
2025-03-14 02:50:45 +08:00
onClick
}) => {
2025-03-01 06:02:54 +08:00
const ItemNode = disabled || !route ? 'div' : Link;
2025-02-28 12:56:52 +08:00
return (
2025-03-14 02:50:45 +08:00
<ItemNode
href={route || ''}
2025-03-14 03:26:33 +08:00
className={cn(itemVariants({ active, disabled, variant }), className)}
2025-03-14 02:50:45 +08:00
onClick={onClick}>
<div className="flex items-center gap-2">
<span
className={cn('text-icon-size! text-icon-color', {
'text-text-disabled': disabled,
'pl-4.5': !icon //hmmm... maybe this should be a prop?
})}>
{icon}
</span>
<span className="truncate">{label}</span>
</div>
{onRemove && (
<Button
className="hidden group-hover:flex"
variant="ghost"
size={'small'}
prefix={<Xmark />}
onClick={onRemove}></Button>
)}
2025-02-28 12:56:52 +08:00
</ItemNode>
);
}
);
2025-02-28 13:58:10 +08:00
SidebarItem.displayName = 'SidebarItem';