mirror of https://github.com/buster-so/buster.git
sidebar group
This commit is contained in:
parent
60b6bc9e5b
commit
5169b4eb92
|
@ -0,0 +1,49 @@
|
|||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { SidebarGroup } from './SidebarCollapsible';
|
||||
//import { Home, Settings, User } from 'lucide-react';
|
||||
import { HouseModern, MapSettings, User } from '../icons/NucleoIconOutlined';
|
||||
import { BusterRoutes } from '@/routes';
|
||||
|
||||
const meta: Meta<typeof SidebarGroup> = {
|
||||
title: 'UI/Sidebar/SidebarGroup',
|
||||
component: SidebarGroup,
|
||||
parameters: {
|
||||
layout: 'centered'
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div className="bg-background min-w-[270px]">
|
||||
<Story />
|
||||
</div>
|
||||
)
|
||||
]
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof SidebarGroup>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
label: 'Settings',
|
||||
items: [
|
||||
{
|
||||
id: '1',
|
||||
label: 'Profile',
|
||||
icon: <User />,
|
||||
route: BusterRoutes.SETTINGS
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
label: 'Account',
|
||||
icon: <MapSettings />,
|
||||
route: BusterRoutes.APP_CHAT
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
label: 'Dashboard',
|
||||
icon: <HouseModern />,
|
||||
route: BusterRoutes.APP_METRIC
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
|
@ -6,7 +6,52 @@ import {
|
|||
} from '../collapsible/CollapsibleBase';
|
||||
import { type ISidebarGroup } from './interfaces';
|
||||
import { SidebarItem } from './SidebarItem';
|
||||
import { CaretDown } from '../icons/NucleoIconFilled';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
|
||||
interface SidebarTriggerProps {
|
||||
label: string;
|
||||
isOpen: boolean;
|
||||
}
|
||||
|
||||
const SidebarTrigger: React.FC<SidebarTriggerProps> = React.memo(({ label, isOpen }) => {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center gap-1 rounded px-1.5 py-1 text-sm transition-colors',
|
||||
'hover:text-text-default text-text-secondary',
|
||||
'group cursor-pointer'
|
||||
)}>
|
||||
<span className="">{label}</span>
|
||||
<div
|
||||
className={cn(
|
||||
'text-icon-color text-2xs -rotate-90 transition-transform duration-200',
|
||||
isOpen && 'rotate-0',
|
||||
'group-hover:text-text-default'
|
||||
)}>
|
||||
<CaretDown />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export const SidebarGroup: React.FC<ISidebarGroup> = React.memo(({ label, items }) => {
|
||||
return <></>;
|
||||
const [isOpen, setIsOpen] = React.useState(false);
|
||||
|
||||
return (
|
||||
<Collapsible open={isOpen} onOpenChange={setIsOpen} className="space-y-0.5">
|
||||
<CollapsibleTrigger asChild className="w-full">
|
||||
<button className="w-full text-left">
|
||||
<SidebarTrigger label={label} isOpen={isOpen} />
|
||||
</button>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent className="data-[state=open]:animate-collapsible-down data-[state=closed]:animate-collapsible-up pl-0">
|
||||
<div className="space-y-0.5">
|
||||
{items.map((item) => (
|
||||
<SidebarItem key={item.id} {...item} />
|
||||
))}
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@ import { type ISidebarItem } from './interfaces';
|
|||
import { cva, VariantProps } from 'class-variance-authority';
|
||||
|
||||
const itemVariants = cva(
|
||||
'flex items-center gap-2.5 rounded px-1.5 py-1.5 text-sm transition-colors',
|
||||
'flex items-center gap-2 rounded px-1.5 py-1.5 text-sm transition-colors',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
@theme {
|
||||
/* animations */
|
||||
--animate-indeterminate-progress-bar: indeterminate-progress-bar 1s infinite linear;
|
||||
--animate-collapsible-down: collapsible-down 0.12s ease-out;
|
||||
--animate-collapsible-up: collapsible-up 0.12s ease-out;
|
||||
|
||||
@keyframes indeterminate-progress-bar {
|
||||
0% {
|
||||
transform: translateX(0) scaleX(0);
|
||||
|
@ -12,4 +15,26 @@
|
|||
transform: translateX(100%) scaleX(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes collapsible-down {
|
||||
from {
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
height: var(--radix-collapsible-content-height);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes collapsible-up {
|
||||
from {
|
||||
height: var(--radix-collapsible-content-height);
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue