mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Added basic dropdown component to Admin X DS
refs. https://github.com/TryGhost/Team/issues/3150
This commit is contained in:
parent
e6d289da4a
commit
9cdc31350d
5 changed files with 93 additions and 4 deletions
|
@ -0,0 +1,43 @@
|
||||||
|
import type {Meta, StoryObj} from '@storybook/react';
|
||||||
|
|
||||||
|
import Dropdown from './Dropdown';
|
||||||
|
import {DropdownOption} from './Dropdown';
|
||||||
|
|
||||||
|
const meta = {
|
||||||
|
title: 'Global / Input / Dropdown',
|
||||||
|
component: Dropdown,
|
||||||
|
tags: ['autodocs'],
|
||||||
|
decorators: [(_story: any) => (<div style={{maxWidth: '400px'}}>{_story()}</div>)]
|
||||||
|
} satisfies Meta<typeof Dropdown>;
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof Dropdown>;
|
||||||
|
|
||||||
|
const dropdownOptions: DropdownOption[] = [
|
||||||
|
{value: 'Option 1', label: 'option-1'},
|
||||||
|
{value: 'Option 2', label: 'option-2'},
|
||||||
|
{value: 'Option 3', label: 'option-3'},
|
||||||
|
{value: 'Option 4', label: 'option-4'},
|
||||||
|
{value: 'Option 5', label: 'option-5'}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
options: dropdownOptions
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WithHeading: Story = {
|
||||||
|
args: {
|
||||||
|
title: 'Title',
|
||||||
|
options: dropdownOptions
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WithHelp: Story = {
|
||||||
|
args: {
|
||||||
|
title: 'Title',
|
||||||
|
options: dropdownOptions,
|
||||||
|
help: 'Here\'s some help'
|
||||||
|
}
|
||||||
|
};
|
45
ghost/admin-x-settings/src/admin-x-ds/global/Dropdown.tsx
Normal file
45
ghost/admin-x-settings/src/admin-x-ds/global/Dropdown.tsx
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import React, {useState} from 'react';
|
||||||
|
|
||||||
|
import Heading from './Heading';
|
||||||
|
|
||||||
|
export interface DropdownOption {
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DropdownProps {
|
||||||
|
title?: string;
|
||||||
|
options: DropdownOption[];
|
||||||
|
onSelect: (value: string) => void;
|
||||||
|
help?: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Dropdown: React.FC<DropdownProps> = ({title, options, onSelect, help}) => {
|
||||||
|
const [selectedOption, setSelectedOption] = useState('');
|
||||||
|
|
||||||
|
const handleOptionChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||||
|
const selectedValue = event.target.value;
|
||||||
|
setSelectedOption(selectedValue);
|
||||||
|
onSelect(selectedValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='flex flex-col'>
|
||||||
|
{title && <Heading formLabel={true} grey={true}>{title}</Heading>}
|
||||||
|
<select className={`-m-1 h-10 border-b border-grey-300 py-2 focus:border-grey-900 ${title && `mt-1`}`} value={selectedOption} onChange={handleOptionChange}>
|
||||||
|
<option value="">Select an option</option>
|
||||||
|
{options.map(option => (
|
||||||
|
<option
|
||||||
|
key={option.value}
|
||||||
|
value={option.value}
|
||||||
|
>
|
||||||
|
{option.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
<span className='mt-2 inline-block text-xs text-grey-700'>{help}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Dropdown;
|
|
@ -5,7 +5,8 @@ import TextField from './TextField';
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Global / Input / Textfield',
|
title: 'Global / Input / Textfield',
|
||||||
component: TextField,
|
component: TextField,
|
||||||
tags: ['autodocs']
|
tags: ['autodocs'],
|
||||||
|
decorators: [(_story: any) => (<div style={{maxWidth: '400px'}}>{_story()}</div>)]
|
||||||
} satisfies Meta<typeof TextField>;
|
} satisfies Meta<typeof TextField>;
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
|
@ -17,7 +17,7 @@ const TextField: React.FC<ITextField> = ({inputRef, title, value, placeholder, h
|
||||||
{title && <Heading formLabel={true} grey={true}>{title}</Heading>}
|
{title && <Heading formLabel={true} grey={true}>{title}</Heading>}
|
||||||
<input
|
<input
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className='-m-1 border-b border-grey-300 px-1 py-2 focus:border-grey-900'
|
className={`-m-1 h-10 border-b border-grey-300 px-1 py-2 focus:border-grey-900 ${title && `mt-1`}`}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
type='text'
|
type='text'
|
||||||
value={value}
|
value={value}
|
||||||
|
|
|
@ -12,11 +12,11 @@ const SettingGroup: React.FC<SettingGroupProps> = ({state, children}) => {
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 'edit':
|
case 'edit':
|
||||||
styles = 'border-grey-400';
|
styles = 'border-grey-500';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'unsaved':
|
case 'unsaved':
|
||||||
styles = 'border-yellow';
|
styles = 'border-green';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'error':
|
case 'error':
|
||||||
|
|
Loading…
Add table
Reference in a new issue