2025-02-25 02:38:28 +08:00
|
|
|
import type { Meta, StoryObj } from '@storybook/react';
|
2025-02-26 07:24:53 +08:00
|
|
|
import { Dropdown, DropdownItems } from './Dropdown';
|
2025-02-25 02:38:28 +08:00
|
|
|
import { Button } from '../buttons/Button';
|
2025-02-26 04:58:01 +08:00
|
|
|
import { PaintRoller, Star, Storage } from '../icons';
|
2025-02-26 05:59:21 +08:00
|
|
|
import { faker } from '@faker-js/faker';
|
2025-02-26 07:24:53 +08:00
|
|
|
import React from 'react';
|
2025-02-26 04:58:01 +08:00
|
|
|
|
2025-02-25 02:38:28 +08:00
|
|
|
const meta: Meta<typeof Dropdown> = {
|
2025-02-27 23:40:07 +08:00
|
|
|
title: 'UI/Dropdowns/Dropdown',
|
2025-02-25 02:38:28 +08:00
|
|
|
component: Dropdown,
|
|
|
|
parameters: {
|
|
|
|
layout: 'centered'
|
|
|
|
},
|
2025-02-25 03:55:35 +08:00
|
|
|
argTypes: {
|
|
|
|
closeOnSelect: {
|
|
|
|
control: 'boolean',
|
|
|
|
defaultValue: true
|
2025-02-25 04:12:02 +08:00
|
|
|
},
|
|
|
|
align: {
|
|
|
|
control: 'select',
|
|
|
|
options: ['start', 'center', 'end'],
|
|
|
|
defaultValue: 'start'
|
2025-02-25 03:55:35 +08:00
|
|
|
}
|
|
|
|
},
|
2025-02-25 02:38:28 +08:00
|
|
|
tags: ['autodocs']
|
|
|
|
};
|
|
|
|
|
|
|
|
export default meta;
|
|
|
|
type Story = StoryObj<typeof Dropdown>;
|
|
|
|
|
|
|
|
// Basic example with simple items
|
|
|
|
export const Basic: Story = {
|
|
|
|
args: {
|
|
|
|
items: [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Profile',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Profile clicked'),
|
2025-02-25 03:55:35 +08:00
|
|
|
loading: false,
|
|
|
|
icon: <PaintRoller />
|
2025-02-25 02:38:28 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Settings',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Settings clicked'),
|
2025-02-25 02:38:28 +08:00
|
|
|
shortcut: '⌘S'
|
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '3',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Logout',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Logout clicked'),
|
2025-02-25 03:06:10 +08:00
|
|
|
items: [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '3-1',
|
2025-02-25 03:55:35 +08:00
|
|
|
label: 'Testing 123'
|
2025-02-25 03:06:10 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '3-2',
|
2025-02-25 03:55:35 +08:00
|
|
|
label: 'Testing 456'
|
2025-02-25 03:06:10 +08:00
|
|
|
}
|
|
|
|
]
|
2025-02-25 02:38:28 +08:00
|
|
|
}
|
|
|
|
],
|
|
|
|
children: <Button>Open Menu</Button>
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Example with icons and shortcuts
|
|
|
|
export const WithIconsAndShortcuts: Story = {
|
|
|
|
args: {
|
2025-02-26 05:18:42 +08:00
|
|
|
menuHeader: 'Menu Options',
|
2025-02-25 02:38:28 +08:00
|
|
|
items: [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Profile',
|
|
|
|
icon: '👤',
|
|
|
|
shortcut: '⌘P',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Profile clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Settings',
|
|
|
|
icon: '⚙️',
|
|
|
|
shortcut: '⌘S',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Settings clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '3',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Logout',
|
|
|
|
icon: '🚪',
|
|
|
|
shortcut: '⌘L',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Logout clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
}
|
|
|
|
],
|
|
|
|
children: <Button>Menu with Icons</Button>
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Example with nested items
|
|
|
|
export const WithNestedItems: Story = {
|
|
|
|
args: {
|
2025-02-26 05:18:42 +08:00
|
|
|
menuHeader: 'Nested Menu',
|
2025-02-25 02:38:28 +08:00
|
|
|
items: [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Main Options',
|
|
|
|
items: [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1-1',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Option 1',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Option 1 clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1-2',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Option 2',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Option 2 clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'More Options',
|
|
|
|
items: [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2-1',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Sub Option 1',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Sub Option 1 clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2-2',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Sub Option 2',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Sub Option 2 clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
],
|
|
|
|
children: <Button>Nested Menu</Button>
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Example with disabled items
|
|
|
|
export const WithDisabledItems: Story = {
|
|
|
|
args: {
|
|
|
|
items: [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Available Option',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Available clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Disabled Option',
|
|
|
|
disabled: true,
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Should not be called')
|
2025-02-25 02:38:28 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '3',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Another Available',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Another clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
}
|
|
|
|
],
|
|
|
|
children: <Button>Menu with Disabled Items</Button>
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Example with custom widths
|
|
|
|
export const CustomWidth: Story = {
|
|
|
|
args: {
|
2025-02-26 05:18:42 +08:00
|
|
|
menuHeader: 'Custom Width Menu',
|
2025-02-25 02:38:28 +08:00
|
|
|
minWidth: 300,
|
|
|
|
maxWidth: 400,
|
|
|
|
items: [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'This is a very long menu item that might need wrapping',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Long item clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Short item',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Short item clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
}
|
|
|
|
],
|
|
|
|
children: <Button>Wide Menu</Button>
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Example with loading state
|
|
|
|
export const WithLoadingItems: Story = {
|
|
|
|
args: {
|
|
|
|
items: [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Normal Item',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Normal clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Loading Item',
|
|
|
|
loading: true,
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Loading clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '3',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Another Normal',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Another clicked')
|
2025-02-26 07:24:53 +08:00
|
|
|
},
|
|
|
|
{ type: 'divider' },
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '4',
|
2025-02-26 07:24:53 +08:00
|
|
|
label: 'Option 4',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Option 4 clicked')
|
2025-02-26 07:24:53 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '5',
|
2025-02-26 07:24:53 +08:00
|
|
|
label: 'Option 5',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Option 5 clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
}
|
|
|
|
],
|
|
|
|
children: <Button>Menu with Loading</Button>
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Example with selection
|
2025-02-26 07:24:53 +08:00
|
|
|
export const WithSelectionSingle: Story = {
|
2025-02-25 02:38:28 +08:00
|
|
|
args: {
|
2025-02-26 07:24:53 +08:00
|
|
|
selectType: 'single',
|
2025-02-25 02:38:28 +08:00
|
|
|
items: [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Option 1',
|
2025-02-25 04:00:53 +08:00
|
|
|
selected: false,
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Option 1 clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2',
|
2025-02-25 02:38:28 +08:00
|
|
|
label: 'Option 2',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Option 2 clicked')
|
2025-02-25 02:38:28 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '3',
|
2025-02-25 04:00:53 +08:00
|
|
|
label: 'Option 3 - Selected',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Option 3 clicked'),
|
2025-02-25 04:00:53 +08:00
|
|
|
selected: true
|
2025-02-25 02:38:28 +08:00
|
|
|
}
|
|
|
|
],
|
|
|
|
children: <Button>Selection Menu</Button>
|
|
|
|
}
|
|
|
|
};
|
2025-02-26 04:58:01 +08:00
|
|
|
|
2025-02-26 07:24:53 +08:00
|
|
|
export const WithSelectionMultiple: Story = {
|
|
|
|
render: () => {
|
|
|
|
const [selectedIds, setSelectedIds] = React.useState<Set<string>>(new Set(['3']));
|
|
|
|
|
|
|
|
const items: DropdownItems = [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1',
|
2025-02-26 07:24:53 +08:00
|
|
|
label: 'Option 1',
|
|
|
|
selected: selectedIds.has('1'),
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Option 1 clicked')
|
2025-02-26 07:24:53 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2',
|
2025-02-26 07:24:53 +08:00
|
|
|
label: 'Option 2',
|
|
|
|
selected: selectedIds.has('2'),
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Option 2 clicked')
|
2025-02-26 07:24:53 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '3',
|
2025-02-26 07:24:53 +08:00
|
|
|
label: 'Option 3',
|
|
|
|
selected: selectedIds.has('3'),
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Option 3 clicked')
|
2025-02-26 07:24:53 +08:00
|
|
|
},
|
|
|
|
{ type: 'divider' as const },
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '4',
|
2025-02-26 07:24:53 +08:00
|
|
|
label: 'Option 4',
|
|
|
|
selected: selectedIds.has('4'),
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Option 4 clicked')
|
2025-02-26 07:24:53 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '5',
|
2025-02-26 07:24:53 +08:00
|
|
|
label: 'Option 5',
|
|
|
|
selected: selectedIds.has('5'),
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Option 5 clicked')
|
2025-02-26 07:24:53 +08:00
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
const handleSelect = (itemId: string) => {
|
|
|
|
setSelectedIds((prev) => {
|
|
|
|
const newSet = new Set(prev);
|
|
|
|
if (newSet.has(itemId)) {
|
|
|
|
newSet.delete(itemId);
|
|
|
|
} else {
|
|
|
|
newSet.add(itemId);
|
|
|
|
}
|
|
|
|
return newSet;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Dropdown
|
|
|
|
selectType="multiple"
|
|
|
|
items={items}
|
2025-02-27 14:25:53 +08:00
|
|
|
menuHeader={'Search items...'}
|
2025-02-26 07:24:53 +08:00
|
|
|
onSelect={handleSelect}
|
|
|
|
children={<Button>Selection Menu</Button>}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2025-02-26 04:58:01 +08:00
|
|
|
// Example with secondary labels
|
|
|
|
export const WithSecondaryLabel: Story = {
|
|
|
|
args: {
|
2025-02-26 05:18:42 +08:00
|
|
|
menuHeader: 'Items with Secondary Labels',
|
2025-02-26 04:58:01 +08:00
|
|
|
items: [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1',
|
2025-02-26 04:58:01 +08:00
|
|
|
label: 'Profile Settings',
|
|
|
|
secondaryLabel: 'User preferences',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Profile clicked'),
|
2025-02-26 04:58:01 +08:00
|
|
|
icon: <PaintRoller />
|
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2',
|
2025-02-26 04:58:01 +08:00
|
|
|
label: 'Storage',
|
|
|
|
secondaryLabel: '45GB used',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Storage clicked'),
|
2025-02-26 04:58:01 +08:00
|
|
|
icon: <Storage />
|
|
|
|
},
|
|
|
|
{ type: 'divider' },
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '3',
|
2025-02-26 04:58:01 +08:00
|
|
|
label: 'Subscription',
|
|
|
|
secondaryLabel: 'Pro Plan',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Subscription clicked'),
|
2025-02-26 04:58:01 +08:00
|
|
|
icon: <Star />
|
|
|
|
}
|
|
|
|
],
|
|
|
|
children: <Button>Menu with Secondary Labels</Button>
|
|
|
|
}
|
|
|
|
};
|
2025-02-26 05:18:42 +08:00
|
|
|
|
|
|
|
// Example with search header
|
|
|
|
export const WithSearchHeader: Story = {
|
|
|
|
args: {
|
2025-02-27 14:25:53 +08:00
|
|
|
menuHeader: 'Search items...',
|
2025-02-26 05:18:42 +08:00
|
|
|
items: [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1',
|
2025-02-26 05:18:42 +08:00
|
|
|
label: 'Profile Settings',
|
|
|
|
searchLabel: 'profile settings user preferences account',
|
|
|
|
secondaryLabel: 'User preferences',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Profile clicked'),
|
2025-02-26 05:18:42 +08:00
|
|
|
icon: <PaintRoller />
|
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2',
|
2025-02-26 05:18:42 +08:00
|
|
|
label: 'Storage Options',
|
|
|
|
searchLabel: 'storage disk space memory',
|
|
|
|
secondaryLabel: 'Manage storage space',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Storage clicked'),
|
2025-02-26 05:18:42 +08:00
|
|
|
icon: <Storage />
|
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '3',
|
2025-02-26 05:18:42 +08:00
|
|
|
label: 'Favorites',
|
|
|
|
searchLabel: 'favorites starred items bookmarks',
|
|
|
|
secondaryLabel: 'View starred items',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Favorites clicked'),
|
2025-02-26 05:18:42 +08:00
|
|
|
icon: <Star />
|
2025-02-26 05:59:21 +08:00
|
|
|
},
|
|
|
|
{ type: 'divider' },
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '4',
|
2025-02-26 05:59:21 +08:00
|
|
|
label: 'Logout',
|
|
|
|
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Logout clicked')
|
2025-02-26 05:59:21 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '5',
|
2025-02-26 05:59:21 +08:00
|
|
|
label: 'Invite User',
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Invite User clicked')
|
2025-02-26 05:18:42 +08:00
|
|
|
}
|
|
|
|
],
|
|
|
|
children: <Button>Searchable Menu</Button>
|
|
|
|
}
|
|
|
|
};
|
2025-02-26 05:59:21 +08:00
|
|
|
|
|
|
|
// Example with long text to test truncation
|
|
|
|
export const WithLongText: Story = {
|
|
|
|
args: {
|
2025-02-27 14:25:53 +08:00
|
|
|
menuHeader: 'Search items...',
|
2025-02-26 05:59:21 +08:00
|
|
|
items: [
|
|
|
|
...Array.from({ length: 100 }).map(() => {
|
|
|
|
const label = faker.commerce.product();
|
|
|
|
const secondaryLabel = faker.commerce.productDescription();
|
|
|
|
return {
|
2025-02-26 13:16:50 +08:00
|
|
|
value: faker.string.uuid(),
|
2025-02-26 05:59:21 +08:00
|
|
|
label,
|
|
|
|
secondaryLabel,
|
|
|
|
searchLabel: label + ' ' + secondaryLabel,
|
2025-02-26 07:47:49 +08:00
|
|
|
onClick: () => alert('Long text clicked'),
|
2025-02-26 05:59:21 +08:00
|
|
|
truncate: true
|
|
|
|
};
|
|
|
|
})
|
|
|
|
],
|
|
|
|
children: <Button>Long Text Menu</Button>
|
|
|
|
}
|
|
|
|
};
|
2025-02-26 07:47:49 +08:00
|
|
|
|
|
|
|
// Example with links
|
|
|
|
export const WithLinks: Story = {
|
|
|
|
args: {
|
|
|
|
menuHeader: 'Navigation Links',
|
|
|
|
items: [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1',
|
2025-02-26 07:47:49 +08:00
|
|
|
label: 'Documentation',
|
|
|
|
link: '/docs',
|
|
|
|
icon: <Storage />,
|
|
|
|
onClick: () => alert('Documentation clicked')
|
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2',
|
2025-02-26 07:47:49 +08:00
|
|
|
label: 'GitHub Repository',
|
|
|
|
link: 'https://github.com/example/repo',
|
|
|
|
icon: <Star />,
|
|
|
|
secondaryLabel: 'External Link'
|
|
|
|
},
|
|
|
|
{ type: 'divider' },
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '3',
|
2025-02-26 07:47:49 +08:00
|
|
|
label: 'Settings Page',
|
|
|
|
link: '/settings',
|
|
|
|
icon: <PaintRoller />
|
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '4',
|
2025-02-26 07:47:49 +08:00
|
|
|
label: 'Help Center',
|
|
|
|
link: '/help',
|
|
|
|
secondaryLabel: 'Get Support'
|
|
|
|
}
|
|
|
|
],
|
|
|
|
children: <Button>Menu with Links</Button>
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Interactive example with links and multiple selection
|
|
|
|
export const WithLinksAndMultipleSelection: Story = {
|
|
|
|
render: () => {
|
|
|
|
const [selectedIds, setSelectedIds] = React.useState<Set<string>>(new Set(['2']));
|
|
|
|
|
|
|
|
const items: DropdownItems = [
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '1',
|
2025-02-26 07:47:49 +08:00
|
|
|
label: 'Documentation Home',
|
|
|
|
link: '/docs',
|
|
|
|
selected: selectedIds.has('1'),
|
|
|
|
icon: <Storage />,
|
|
|
|
secondaryLabel: 'Main documentation'
|
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '2',
|
2025-02-26 07:47:49 +08:00
|
|
|
label: 'API Reference',
|
|
|
|
link: '/docs/api',
|
|
|
|
selected: selectedIds.has('2'),
|
|
|
|
icon: <Star />,
|
|
|
|
secondaryLabel: 'API documentation'
|
|
|
|
},
|
|
|
|
{ type: 'divider' as const },
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '3',
|
2025-02-26 07:47:49 +08:00
|
|
|
label: 'Tutorials',
|
|
|
|
link: '/docs/tutorials',
|
|
|
|
selected: selectedIds.has('3'),
|
|
|
|
icon: <PaintRoller />,
|
|
|
|
secondaryLabel: 'Learn step by step'
|
|
|
|
},
|
|
|
|
{
|
2025-02-26 13:16:50 +08:00
|
|
|
value: '4',
|
2025-02-26 07:47:49 +08:00
|
|
|
label: 'Examples',
|
|
|
|
link: '/docs/examples',
|
|
|
|
selected: selectedIds.has('4'),
|
|
|
|
secondaryLabel: 'Code examples'
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
const handleSelect = (itemId: string) => {
|
|
|
|
setSelectedIds((prev) => {
|
|
|
|
const newSet = new Set(prev);
|
|
|
|
if (newSet.has(itemId)) {
|
|
|
|
newSet.delete(itemId);
|
|
|
|
} else {
|
|
|
|
newSet.add(itemId);
|
|
|
|
}
|
|
|
|
return newSet;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Dropdown
|
|
|
|
open
|
|
|
|
selectType="multiple"
|
|
|
|
items={items}
|
2025-02-27 14:25:53 +08:00
|
|
|
menuHeader="Search documentation..."
|
2025-02-26 07:47:49 +08:00
|
|
|
onSelect={handleSelect}
|
|
|
|
children={<Button>Documentation Sections</Button>}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
2025-02-27 14:25:53 +08:00
|
|
|
|
|
|
|
export const WithFooterContent: Story = {
|
|
|
|
args: {
|
|
|
|
items: [
|
|
|
|
{
|
|
|
|
value: '1',
|
|
|
|
label: 'Option 1',
|
|
|
|
onClick: () => alert('Option 1 clicked')
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: '2',
|
|
|
|
label: 'Option 2',
|
|
|
|
onClick: () => alert('Option 2 clicked')
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: '3',
|
|
|
|
label: 'Option 3',
|
|
|
|
onClick: () => alert('Option 3 clicked')
|
|
|
|
}
|
|
|
|
],
|
|
|
|
footerContent: (
|
|
|
|
<Button variant={'black'} block>
|
|
|
|
Footer Content
|
|
|
|
</Button>
|
|
|
|
),
|
|
|
|
children: <Button>Menu with Footer Content</Button>
|
|
|
|
}
|
|
|
|
};
|