mirror of
https://github.com/datahub-project/datahub.git
synced 2025-11-01 11:19:05 +00:00
495 lines
15 KiB
TypeScript
495 lines
15 KiB
TypeScript
import { BADGE } from '@geometricpanda/storybook-addon-badges';
|
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
import React from 'react';
|
|
|
|
import { GridList } from '@components/.docs/mdx-components';
|
|
import { AVAILABLE_ICONS } from '@components/components/Icon';
|
|
import { Select, selectDefaults } from '@components/components/Select/Select';
|
|
import { SimpleSelect } from '@components/components/Select/SimpleSelect';
|
|
import { SelectSizeOptions } from '@components/components/Select/types';
|
|
|
|
// Auto Docs
|
|
const meta: Meta = {
|
|
title: 'Forms / Select',
|
|
component: Select,
|
|
|
|
// Display Properties
|
|
parameters: {
|
|
layout: 'centered',
|
|
badges: [BADGE.STABLE, 'readyForDesignReview'],
|
|
docs: {
|
|
subtitle: 'This component allows users to select one or multiple input options from a dropdown list.',
|
|
},
|
|
},
|
|
|
|
// Component-level argTypes
|
|
argTypes: {
|
|
options: {
|
|
description: 'Array of options for the Select component.',
|
|
control: {
|
|
type: 'object',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: JSON.stringify(selectDefaults.options) },
|
|
},
|
|
},
|
|
label: {
|
|
description: 'Label for the Select component.',
|
|
control: {
|
|
type: 'text',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: selectDefaults.label },
|
|
},
|
|
},
|
|
values: {
|
|
description: 'Selected values for the Select component.',
|
|
control: {
|
|
type: 'object',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: selectDefaults.values?.toString() },
|
|
},
|
|
},
|
|
showSearch: {
|
|
description: 'Whether to show the search input.',
|
|
control: {
|
|
type: 'boolean',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: selectDefaults.showSearch?.toString() },
|
|
},
|
|
},
|
|
isDisabled: {
|
|
description: 'Whether the Select component is disabled.',
|
|
control: {
|
|
type: 'boolean',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: selectDefaults.isDisabled?.toString() },
|
|
},
|
|
},
|
|
isReadOnly: {
|
|
description: 'Whether the Select component is read-only.',
|
|
control: {
|
|
type: 'boolean',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: selectDefaults.isReadOnly?.toString() },
|
|
},
|
|
},
|
|
isRequired: {
|
|
description: 'Whether the Select component is required.',
|
|
control: {
|
|
type: 'boolean',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: selectDefaults.isRequired?.toString() },
|
|
},
|
|
},
|
|
size: {
|
|
description: 'Size of the Select component.',
|
|
control: {
|
|
type: 'select',
|
|
options: ['sm', 'md', 'lg'],
|
|
},
|
|
table: {
|
|
defaultValue: { summary: selectDefaults.size },
|
|
},
|
|
},
|
|
width: {
|
|
description: 'Width of the Select component.',
|
|
control: {
|
|
type: 'number',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: `${selectDefaults.width}` },
|
|
},
|
|
},
|
|
isMultiSelect: {
|
|
description: 'Whether the Select component allows multiple values to be selected.',
|
|
control: {
|
|
type: 'boolean',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: selectDefaults.isMultiSelect?.toString() },
|
|
},
|
|
},
|
|
placeholder: {
|
|
description: 'Placeholder for the Select component.',
|
|
control: {
|
|
type: 'text',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: selectDefaults.placeholder },
|
|
},
|
|
},
|
|
disabledValues: {
|
|
description: 'Disabled values for the multi-select component.',
|
|
control: {
|
|
type: 'object',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: selectDefaults.disabledValues?.toString() },
|
|
},
|
|
},
|
|
showSelectAll: {
|
|
description: 'Whether the multi select component shows Select All button.',
|
|
control: {
|
|
type: 'boolean',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: selectDefaults.showSelectAll?.toString() },
|
|
},
|
|
},
|
|
selectAllLabel: {
|
|
description: 'Label for Select All button.',
|
|
control: {
|
|
type: 'text',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: selectDefaults.selectAllLabel },
|
|
},
|
|
},
|
|
showDescriptions: {
|
|
description: 'Whether to show descriptions with the select options.',
|
|
control: {
|
|
type: 'boolean',
|
|
},
|
|
table: {
|
|
defaultValue: { summary: selectDefaults.showDescriptions?.toString() },
|
|
},
|
|
},
|
|
icon: {
|
|
description: `The name of the icon to display.`,
|
|
type: 'string',
|
|
options: AVAILABLE_ICONS,
|
|
table: {
|
|
defaultValue: { summary: 'undefined' },
|
|
},
|
|
control: {
|
|
type: 'select',
|
|
},
|
|
},
|
|
optionSwitchable: {
|
|
description: 'Set to `true` to uselect option by clicking on it',
|
|
type: 'boolean',
|
|
table: {
|
|
defaultValue: { summary: 'undefined' },
|
|
},
|
|
control: {
|
|
type: 'boolean',
|
|
},
|
|
},
|
|
selectLabelProps: {
|
|
description: 'Additional props for rendering of select label',
|
|
table: {
|
|
defaultValue: { summary: 'undefined' },
|
|
},
|
|
},
|
|
emptyState: {
|
|
description: 'Custom empty state component to render when no options are available',
|
|
table: {
|
|
defaultValue: { summary: 'undefined' },
|
|
},
|
|
},
|
|
},
|
|
|
|
// Define defaults
|
|
args: {
|
|
options: [
|
|
{ label: 'Option 1', value: '1' },
|
|
{ label: 'Option 2', value: '2' },
|
|
{ label: 'Option 3', value: '3' },
|
|
],
|
|
label: 'Select Label',
|
|
values: undefined,
|
|
showSearch: selectDefaults.showSearch,
|
|
isDisabled: selectDefaults.isDisabled,
|
|
isReadOnly: selectDefaults.isReadOnly,
|
|
isRequired: selectDefaults.isRequired,
|
|
onCancel: () => console.log('Cancel clicked'),
|
|
onUpdate: (selectedValues: string[]) => console.log('Update clicked', selectedValues),
|
|
size: 'md', // Default size
|
|
width: 255,
|
|
isMultiSelect: selectDefaults.isMultiSelect,
|
|
placeholder: selectDefaults.placeholder,
|
|
disabledValues: undefined,
|
|
showSelectAll: false,
|
|
selectAllLabel: 'Select All',
|
|
showDescriptions: false,
|
|
},
|
|
} satisfies Meta<typeof Select>;
|
|
|
|
export default meta;
|
|
|
|
// Stories
|
|
|
|
type Story = StoryObj<typeof meta>;
|
|
|
|
const sizeOptions: SelectSizeOptions[] = ['sm', 'md', 'lg'];
|
|
|
|
export const simpleSelectSandbox: Story = {
|
|
tags: ['dev'],
|
|
|
|
render: (props) => (
|
|
<SimpleSelect
|
|
options={props.options}
|
|
label={props.label}
|
|
values={props.values}
|
|
showSearch={props.showSearch}
|
|
isDisabled={props.isDisabled}
|
|
isReadOnly={props.isReadOnly}
|
|
isRequired={props.isRequired}
|
|
size={props.size}
|
|
width={props.width}
|
|
onUpdate={props.onUpdate} // Optional: to log the selected value
|
|
isMultiSelect={props.isMultiSelect}
|
|
placeholder={props.placeholder}
|
|
disabledValues={props.disabledValues}
|
|
icon={props.icon}
|
|
/>
|
|
),
|
|
};
|
|
|
|
export const simpleSelectStates = () => (
|
|
<GridList isVertical>
|
|
<>
|
|
<SimpleSelect options={[{ label: 'Default', value: 'default' }]} label="Default" values={['default']} />
|
|
<SimpleSelect
|
|
options={[{ label: 'Disabled State', value: 'disabled' }]}
|
|
label="Disabled State"
|
|
isDisabled
|
|
values={['disabled']}
|
|
/>
|
|
<SimpleSelect
|
|
options={[{ label: 'Read Only State', value: 'readonly' }]}
|
|
label="Read Only State"
|
|
isReadOnly
|
|
values={['readonly']}
|
|
/>
|
|
</>
|
|
</GridList>
|
|
);
|
|
|
|
export const simpleSelectWithSearch = () => (
|
|
<SimpleSelect
|
|
options={[
|
|
{ label: 'Option 1', value: '1' },
|
|
{ label: 'Option 2', value: '2' },
|
|
{ label: 'Option 3', value: '3' },
|
|
]}
|
|
label="Simple Select with Search"
|
|
showSearch
|
|
values={['2']}
|
|
/>
|
|
);
|
|
|
|
export const simpleSelectWithMultiSelect = () => (
|
|
<SimpleSelect
|
|
options={[
|
|
{ label: 'Option 1', value: '1' },
|
|
{ label: 'Option 2', value: '2' },
|
|
{ label: 'Option 3', value: '3' },
|
|
]}
|
|
label="Simple Select with multi-select"
|
|
showSearch
|
|
values={['2', '3']}
|
|
isMultiSelect
|
|
/>
|
|
);
|
|
|
|
export const simpleSelectWithDisabledValues = () => (
|
|
<SimpleSelect
|
|
options={[
|
|
{ label: 'Option 1', value: '1' },
|
|
{ label: 'Option 2', value: '2' },
|
|
{ label: 'Option 3', value: '3' },
|
|
]}
|
|
label="Simple Select with disabled values"
|
|
values={['2']}
|
|
isMultiSelect
|
|
disabledValues={['2']}
|
|
/>
|
|
);
|
|
|
|
export const simpleSelectWithSelectAll = () => (
|
|
<SimpleSelect
|
|
options={[
|
|
{ label: 'Option 1', value: '1' },
|
|
{ label: 'Option 2', value: '2' },
|
|
{ label: 'Option 3', value: '3' },
|
|
]}
|
|
label="Simple Select with Select All"
|
|
isMultiSelect
|
|
showSelectAll
|
|
/>
|
|
);
|
|
|
|
export const simpleSelectWithDescriptions = () => (
|
|
<SimpleSelect
|
|
options={[
|
|
{ label: 'Option 1', value: '1', description: 'Description of option 1' },
|
|
{ label: 'Option 2', value: '2', description: 'Description of option 2 is longgggggg' },
|
|
{ label: 'Option 3', value: '3', description: 'Description of option 3' },
|
|
]}
|
|
label="Simple Select with descriptions"
|
|
showDescriptions
|
|
/>
|
|
);
|
|
|
|
export const simpleSelectSizes = () => (
|
|
<GridList isVertical>
|
|
{sizeOptions.map((size, index) => (
|
|
<SimpleSelect
|
|
key={`simpleselect-${size}`}
|
|
options={[
|
|
{ label: 'Option 1', value: '1' },
|
|
{ label: 'Option 2', value: '2' },
|
|
{ label: 'Option 3', value: '3' },
|
|
]}
|
|
label={`Simple Select - Font Size: ${size}, Width: ${255 + 50 * index}px`}
|
|
values={['3']}
|
|
size={size}
|
|
width={255 + 50 * index}
|
|
/>
|
|
))}
|
|
</GridList>
|
|
);
|
|
|
|
export const simpleSelectWithIcon = () => (
|
|
<SimpleSelect
|
|
options={[
|
|
{ label: 'Option 1', value: '1' },
|
|
{ label: 'Option 2', value: '2' },
|
|
{ label: 'Option 3', value: '3' },
|
|
]}
|
|
label="Simple Select with icon"
|
|
icon="Search"
|
|
/>
|
|
);
|
|
|
|
// Basic story is what is displayed 1st in storybook & is used as the code sandbox
|
|
// Pass props to this so that it can be customized via the UI props panel
|
|
export const BasicSelectSandbox: Story = {
|
|
tags: ['dev'],
|
|
|
|
render: (props) => (
|
|
<Select
|
|
options={props.options}
|
|
label={props.label}
|
|
values={props.values}
|
|
onCancel={props.onCancel}
|
|
onUpdate={props.onUpdate}
|
|
showSearch={props.showSearch}
|
|
isDisabled={props.isDisabled}
|
|
isReadOnly={props.isReadOnly}
|
|
isRequired={props.isRequired}
|
|
size={props.size}
|
|
width={props.width}
|
|
isMultiSelect={props.isMultiSelect}
|
|
placeholder={props.placeholder}
|
|
icon={props.icon}
|
|
/>
|
|
),
|
|
};
|
|
|
|
export const states = () => (
|
|
<GridList isVertical>
|
|
<>
|
|
<Select options={[{ label: 'Default', value: 'default' }]} label="Default" values={['default']} />
|
|
<Select
|
|
options={[{ label: 'Disabled State', value: 'disabled' }]}
|
|
label="Disabled State"
|
|
isDisabled
|
|
values={['disabled']}
|
|
/>
|
|
<Select
|
|
options={[{ label: 'Read Only State', value: 'readonly' }]}
|
|
label="Read Only State"
|
|
isReadOnly
|
|
values={['readonly']}
|
|
/>
|
|
</>
|
|
</GridList>
|
|
);
|
|
|
|
export const withSearch = () => (
|
|
<Select
|
|
options={[
|
|
{ label: 'Option 1', value: '1' },
|
|
{ label: 'Option 2', value: '2' },
|
|
{ label: 'Option 3', value: '3' },
|
|
]}
|
|
label="Select with Search"
|
|
showSearch
|
|
values={['2']}
|
|
filterResultsByQuery
|
|
/>
|
|
);
|
|
|
|
export const withMultiSelect = () => (
|
|
<Select
|
|
options={[
|
|
{ label: 'Option 1', value: '1' },
|
|
{ label: 'Option 2', value: '2' },
|
|
{ label: 'Option 3', value: '3' },
|
|
]}
|
|
label="Select with multi-select"
|
|
showSearch
|
|
values={['2', '3']}
|
|
isMultiSelect
|
|
/>
|
|
);
|
|
|
|
export const sizes = () => (
|
|
<GridList isVertical>
|
|
{sizeOptions.map((size, index) => (
|
|
<Select
|
|
key={`select-${size}`}
|
|
options={[
|
|
{ label: 'Option 1', value: '1' },
|
|
{ label: 'Option 2', value: '2' },
|
|
{ label: 'Option 3', value: '3' },
|
|
]}
|
|
label={`Select - Font Size: ${size}, Width: ${255 + 50 * index}px`}
|
|
values={['3']}
|
|
onCancel={() => alert('Cancel clicked')}
|
|
onUpdate={(selectedValues) => alert(`Update clicked with values: ${selectedValues}`)}
|
|
size={size}
|
|
width={255 + 50 * index}
|
|
/>
|
|
))}
|
|
</GridList>
|
|
);
|
|
|
|
export const footerActions = () => (
|
|
<GridList isVertical>
|
|
<Select
|
|
options={[
|
|
{ label: 'Option 1', value: '1' },
|
|
{ label: 'Option 2', value: '2' },
|
|
{ label: 'Option 3', value: '3' },
|
|
]}
|
|
label="Select with Footer Actions"
|
|
values={['3']}
|
|
onCancel={() => alert('Cancel clicked')}
|
|
onUpdate={(selectedValues) => alert(`Update clicked with values: ${selectedValues}`)}
|
|
size="md"
|
|
/>
|
|
</GridList>
|
|
);
|
|
|
|
export const withIcon = () => (
|
|
<Select
|
|
options={[
|
|
{ label: 'Option 1', value: '1' },
|
|
{ label: 'Option 2', value: '2' },
|
|
{ label: 'Option 3', value: '3' },
|
|
]}
|
|
label="Select with icon"
|
|
values={['2']}
|
|
icon="Search"
|
|
/>
|
|
);
|