2
1
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2023-12-13 21:00:40 +01:00

Added multiselect to AdminX Design System

refs. https://github.com/TryGhost/Team/issues/3318
This commit is contained in:
Peter Zimon 2023-06-02 10:53:47 +02:00
parent e9ed7dfb64
commit 6900fd9eb0
4 changed files with 169 additions and 1 deletions

View file

@ -76,6 +76,7 @@
"postcss": "8.4.24",
"postcss-import": "^15.1.0",
"prop-types": "15.8.1",
"react-select": "^5.7.3",
"rollup-plugin-node-builtins": "2.1.2",
"storybook": "7.0.18",
"stylelint": "15.6.1",

View file

@ -0,0 +1,72 @@
import type {Meta, StoryObj} from '@storybook/react';
import MultiSelect, {MultiSelectOption} from './MultiSelect';
import {MultiValue} from 'react-select';
const meta = {
title: 'Global / Select / Multiselect',
component: MultiSelect,
tags: ['autodocs']
} satisfies Meta<typeof MultiSelect>;
export default meta;
type Story = StoryObj<typeof MultiSelect>;
const options = [
{value: 'steph', label: 'Steph Curry'},
{value: 'klay', label: 'Klay Thompson'},
{value: 'dray', label: 'Draymond Green'}
];
export const Default: Story = {
args: {
options: options,
placeholder: 'Select your players'
}
};
export const Clear: Story = {
args: {
options: options,
clearBg: true
}
};
export const Black: Story = {
args: {
options: options,
color: 'black'
}
};
export const WithTitle: Story = {
args: {
title: 'Choose your players',
options: options,
color: 'black'
}
};
export const WithTitleAndHint: Story = {
args: {
title: 'Choose your players',
options: options,
color: 'black',
hint: 'I knew you\'d choose all'
}
};
export const WithDefaultValue: Story = {
args: {
title: 'Choose your players',
options: options,
color: 'black',
hint: 'I knew you\'d choose all',
defaultValues: [options[0]],
onChange: (selected: MultiValue<MultiSelectOption>) => {
selected?.map(o => (
alert(`${o.label} (${o.value})`)
));
}
}
};

View file

@ -0,0 +1,95 @@
import Heading from './Heading';
import Hint from './Hint';
import React from 'react';
import {MultiValue, default as ReactSelect, components} from 'react-select';
export type MultiSelectColor = 'grey' | 'black' | string;
export type MultiSelectOption = {
value: string;
label: string;
}
interface MultiSelectProps {
options: MultiSelectOption[];
defaultValues?: MultiSelectOption[];
title?: string;
clearBg?: boolean;
error?: boolean;
placeholder?: string;
color?: MultiSelectColor
hint?: string;
onChange: (selected: MultiValue<MultiSelectOption>) => void
}
const MultiSelect: React.FC<MultiSelectProps> = ({
title = '',
clearBg = false,
error = false,
placeholder,
color = 'grey',
hint = '',
options,
defaultValues,
onChange,
...props
}) => {
let multiValueColor;
switch (color) {
case 'black':
multiValueColor = 'bg-black text-white';
break;
case 'grey':
multiValueColor = 'bg-grey-300 text-black';
break;
default:
break;
}
const customClasses = {
control: `w-full cursor-pointer appearance-none min-h-[40px] border-b ${!clearBg && 'bg-grey-75 px-[10px]'} py-2 outline-none ${error ? 'border-red' : 'border-grey-500 hover:border-grey-700'} ${title && 'mt-2'}`,
valueContainer: 'gap-1',
placeHolder: 'text-grey-600',
menu: 'shadow py-2 rounded-b z-50 bg-white',
option: 'hover:cursor-pointer hover:bg-grey-100 px-3 py-[6px]',
multiValue: `rounded-sm items-center text-[14px] py-px pl-2 pr-1 gap-1.5 ${multiValueColor}`,
noOptionsMessage: 'p-3 text-grey-600'
};
const DropdownIndicator: React.FC<any> = ddiProps => (
<components.DropdownIndicator {...ddiProps}>
<div className={`absolute top-[14px] block h-2 w-2 rotate-45 border-[1px] border-l-0 border-t-0 border-grey-900 content-[''] ${clearBg ? 'right-0' : 'right-4'} `}></div>
</components.DropdownIndicator>
);
return (
<div className='flex flex-col'>
{title && <Heading useLabelTag={true}>{title}</Heading>}
<ReactSelect
classNames={{
menuList: () => 'z-50',
valueContainer: () => customClasses.valueContainer,
control: () => customClasses.control,
placeholder: () => customClasses.placeHolder,
menu: () => customClasses.menu,
option: () => customClasses.option,
multiValue: () => customClasses.multiValue,
noOptionsMessage: () => customClasses.noOptionsMessage
}}
components={{DropdownIndicator}}
defaultValue={defaultValues}
isClearable={false}
options={options}
placeholder={placeholder ? placeholder : ''}
isMulti
unstyled
onChange={onChange}
{...props}
/>
{hint && <Hint color={error ? 'red' : ''}>{hint}</Hint>}
</div>
);
};
export default MultiSelect;

View file

@ -4,7 +4,7 @@ import Select from './Select';
import {SelectOption} from './Select';
const meta = {
title: 'Global / Select',
title: 'Global / Select / Simple select',
component: Select,
tags: ['autodocs'],
decorators: [(_story: any) => (<div style={{maxWidth: '400px'}}>{_story()}</div>)],