mirror of https://github.com/buster-so/buster.git
added sidebar variant
This commit is contained in:
parent
1d934c6cde
commit
ba62cb4e25
|
@ -19,6 +19,7 @@
|
|||
"@monaco-editor/react": "^4.7.0",
|
||||
"@radix-ui/react-avatar": "^1.1.3",
|
||||
"@radix-ui/react-checkbox": "^1.1.4",
|
||||
"@radix-ui/react-collapsible": "^1.1.3",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
||||
"@radix-ui/react-popover": "^1.1.6",
|
||||
"@radix-ui/react-select": "^2.1.6",
|
||||
|
@ -2426,6 +2427,7 @@
|
|||
},
|
||||
"node_modules/@clack/prompts/node_modules/is-unicode-supported": {
|
||||
"version": "1.3.0",
|
||||
"extraneous": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
@ -5683,6 +5685,36 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-collapsible": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.3.tgz",
|
||||
"integrity": "sha512-jFSerheto1X03MUC0g6R7LedNW9EEGWdg9W1+MlpkMLwGkgkbUXLPBH/KIuWKXUoeYRVY11llqbTBDzuLg7qrw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/primitive": "1.1.1",
|
||||
"@radix-ui/react-compose-refs": "1.1.1",
|
||||
"@radix-ui/react-context": "1.1.1",
|
||||
"@radix-ui/react-id": "1.1.0",
|
||||
"@radix-ui/react-presence": "1.1.2",
|
||||
"@radix-ui/react-primitive": "2.0.2",
|
||||
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-collection": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.2.tgz",
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
"@monaco-editor/react": "^4.7.0",
|
||||
"@radix-ui/react-avatar": "^1.1.3",
|
||||
"@radix-ui/react-checkbox": "^1.1.4",
|
||||
"@radix-ui/react-collapsible": "^1.1.3",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
||||
"@radix-ui/react-popover": "^1.1.6",
|
||||
"@radix-ui/react-select": "^2.1.6",
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
'use client';
|
||||
|
||||
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
||||
|
||||
const Collapsible = CollapsiblePrimitive.Root;
|
||||
|
||||
const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;
|
||||
|
||||
const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;
|
||||
|
||||
export { Collapsible, CollapsibleTrigger, CollapsibleContent };
|
|
@ -0,0 +1,11 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger
|
||||
} from '../collapsible/CollapsibleBase';
|
||||
import { type ISidebarGroup } from './interfaces';
|
||||
|
||||
export const SidebarGroup: React.FC<ISidebarGroup> = React.memo(({ label, items }) => {
|
||||
return <></>;
|
||||
});
|
|
@ -0,0 +1,84 @@
|
|||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { SidebarItem } from './SidebarItem';
|
||||
import { HouseModern } from '@/components/ui/icons';
|
||||
import { BusterRoutes } from '@/routes';
|
||||
|
||||
const meta: Meta<typeof SidebarItem> = {
|
||||
title: 'UI/Sidebar/SidebarItem',
|
||||
component: SidebarItem,
|
||||
parameters: {
|
||||
layout: 'centered'
|
||||
},
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: 'select',
|
||||
options: ['default', 'emphasized']
|
||||
},
|
||||
active: {
|
||||
control: 'boolean'
|
||||
},
|
||||
disabled: {
|
||||
control: 'boolean'
|
||||
}
|
||||
},
|
||||
tags: ['autodocs'],
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div className="min-w-[300px]">
|
||||
<Story />
|
||||
</div>
|
||||
)
|
||||
]
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof SidebarItem>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
label: 'Home',
|
||||
icon: <HouseModern />,
|
||||
route: BusterRoutes.APP_ROOT,
|
||||
id: 'home'
|
||||
}
|
||||
};
|
||||
|
||||
export const Emphasized: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'emphasized',
|
||||
id: 'home-emphasized'
|
||||
}
|
||||
};
|
||||
|
||||
export const Active: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
id: 'home-active',
|
||||
active: true
|
||||
}
|
||||
};
|
||||
|
||||
export const Disabled: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
disabled: true,
|
||||
id: 'home-disabled'
|
||||
}
|
||||
};
|
||||
|
||||
export const LongText: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
label:
|
||||
'This is a very long sidebar item label that should demonstrate text truncation behavior in the component',
|
||||
id: 'long-text'
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div className="max-w-[200px]">
|
||||
<Story />
|
||||
</div>
|
||||
)
|
||||
]
|
||||
};
|
|
@ -0,0 +1,64 @@
|
|||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
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',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'hover:bg-item-hover text-text-default',
|
||||
emphasized: 'shadow bg-background border border-border text-text-default'
|
||||
},
|
||||
active: {
|
||||
true: '',
|
||||
false: ''
|
||||
},
|
||||
disabled: {
|
||||
true: 'cursor-not-allowed',
|
||||
false: ''
|
||||
}
|
||||
},
|
||||
compoundVariants: [
|
||||
{
|
||||
active: true,
|
||||
disabled: false,
|
||||
variant: 'default',
|
||||
className: 'bg-nav-item-select hover:bg-nav-item-select'
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
disabled: false,
|
||||
variant: 'emphasized',
|
||||
className: 'bg-nav-item-select hover:bg-nav-item-select'
|
||||
},
|
||||
{
|
||||
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 '
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
|
||||
export const SidebarItem: React.FC<ISidebarItem & VariantProps<typeof itemVariants>> = React.memo(
|
||||
({ label, icon, route, id, disabled = false, active = false, variant = 'default' }) => {
|
||||
const ItemNode = disabled ? 'div' : Link;
|
||||
|
||||
return (
|
||||
<ItemNode href={route} className={cn(itemVariants({ active, disabled, variant }))}>
|
||||
<span className="text-icon-size text-icon-color">{icon}</span>
|
||||
<span className="text-foreground truncate">{label}</span>
|
||||
</ItemNode>
|
||||
);
|
||||
}
|
||||
);
|
|
@ -0,0 +1,29 @@
|
|||
import { BusterRoutes } from '@/routes';
|
||||
|
||||
export interface ISidebarItem {
|
||||
label: string;
|
||||
icon: React.ReactNode;
|
||||
route: BusterRoutes;
|
||||
id: string;
|
||||
disabled?: boolean;
|
||||
active?: boolean;
|
||||
onRemove?: () => void;
|
||||
}
|
||||
|
||||
export interface ISidebarGroup {
|
||||
label: string;
|
||||
items: ISidebarItem[];
|
||||
}
|
||||
|
||||
export interface ISidebarList {
|
||||
items: ISidebarItem[];
|
||||
}
|
||||
|
||||
type SidebarContent = ISidebarGroup | ISidebarList;
|
||||
|
||||
export interface SidebarProps {
|
||||
header: React.ReactNode;
|
||||
content: SidebarContent[];
|
||||
footer?: React.ReactNode;
|
||||
activeItem: string;
|
||||
}
|
|
@ -24,7 +24,7 @@ export const BusterReactQueryProvider = ({ children }: { children: React.ReactEl
|
|||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{children}
|
||||
{/* <ReactQueryDevtoolsPanel /> */}
|
||||
<ReactQueryDevtoolsPanel />
|
||||
</QueryClientProvider>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue