Added basic list to Admin Design System

refs. https://github.com/TryGhost/Team/issues/3150
This commit is contained in:
Peter Zimon 2023-05-22 16:56:07 +02:00
parent 2e0073f9ec
commit 950fc832e4
5 changed files with 165 additions and 1 deletions

View File

@ -0,0 +1,40 @@
import type {Meta, StoryObj} from '@storybook/react';
import * as ListItemStories from './ListItem.stories';
import List from './List';
import ListItem from './ListItem';
const meta = {
title: 'Global / List',
component: List,
tags: ['autodocs'],
decorators: [(_story: any) => (<div style={{maxWidth: '600px'}}>{_story()}</div>)]
} satisfies Meta<typeof List>;
export default meta;
type Story = StoryObj<typeof List>;
const listItemProps = {
title: ListItemStories.HiddenActions.args?.title,
detail: ListItemStories.HiddenActions.args?.detail,
action: ListItemStories.HiddenActions.args?.action,
hideActions: ListItemStories.HiddenActions.args?.hideActions,
separator: true,
onClick: ListItemStories.HiddenActions.args?.onClick
};
const listItems = (
<>
<ListItem id='list-item-1' {...listItemProps}/>
<ListItem id='list-item-2' {...listItemProps}/>
<ListItem id='list-item-3' {...listItemProps}/>
</>
);
export const Default: Story = {
args: {
title: 'This is a list',
children: listItems,
hint: 'And here is a hint for the whole list'
}
};

View File

@ -0,0 +1,39 @@
import Heading from './Heading';
import Hint from './Hint';
import React from 'react';
import Separator from './Separator';
interface ListProps {
title?: React.ReactNode;
titleSeparator?: boolean;
children?: React.ReactNode;
hint?: React.ReactNode;
hintSeparator?: boolean;
}
const List: React.FC<ListProps> = ({title, titleSeparator, children, hint, hintSeparator}) => {
titleSeparator = (titleSeparator === undefined) ? true : titleSeparator;
hintSeparator = (hintSeparator === undefined) ? true : hintSeparator;
return (
<section>
{title &&
<div className='flex flex-col gap-1'>
<Heading grey={true} level={6}>{title}</Heading>
{titleSeparator && <Separator />}
</div>
}
<div className='flex flex-col'>
{children}
</div>
{hint &&
<>
{hintSeparator && <Separator />}
<Hint>{hint}</Hint>
</>
}
</section>
);
};
export default List;

View File

@ -0,0 +1,48 @@
import React from 'react';
import type {Meta, StoryObj} from '@storybook/react';
import Button from './Button';
import ListItem from './ListItem';
const meta = {
title: 'Global / List / List Item',
component: ListItem,
tags: ['autodocs'],
decorators: [(_story: any) => (<div style={{maxWidth: '600px'}}>{_story()}</div>)],
argTypes: {
title: {control: 'text'},
detail: {control: 'text'}
}
} satisfies Meta<typeof ListItem>;
export default meta;
type Story = StoryObj<typeof ListItem>;
export const Default: Story = {
args: {
id: 'list-item',
title: 'A list item',
detail: 'Some details',
action: <Button color='green' label='Edit' link={true} />,
separator: true,
onClick: (e: React.MouseEvent<HTMLDivElement>) => {
const clickedDiv = e.currentTarget;
alert(`Clicked on "${clickedDiv.id}"`);
}
}
};
export const HiddenActions: Story = {
args: {
id: 'list-item',
title: 'A list item',
detail: 'Some details',
action: <Button color='green' label='Edit' link={true} />,
separator: true,
hideActions: true,
onClick: (e: React.MouseEvent<HTMLDivElement>) => {
const clickedDiv = e.currentTarget;
alert(`Clicked on "${clickedDiv.id}"`);
}
}
};

View File

@ -0,0 +1,37 @@
import React from 'react';
interface ListItemProps {
id: string;
title?: React.ReactNode;
detail?: React.ReactNode;
action?: React.ReactNode;
hideActions?: boolean;
/**
* Hidden for the last item in the list
*/
separator?: boolean;
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
}
const ListItem: React.FC<ListItemProps> = ({id, title, detail, action, hideActions, separator, onClick}) => {
const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
onClick?.(e);
};
return (
<div className={`group flex items-center justify-between hover:bg-gradient-to-r hover:from-white hover:to-grey-50 ${separator ? 'border-b border-grey-100 last-of-type:border-none' : ''}`}>
<div className={`flex grow flex-col pr-6 ${separator ? 'py-3' : 'py-2'} ${onClick && 'cursor-pointer'}`} id={id} onClick={handleClick}>
<span>{title}</span>
{detail && <span className='text-xs text-grey-700'>{detail}</span>}
</div>
{action &&
<div className={`px-3 ${separator ? 'py-3' : 'py-2'} ${hideActions ? 'invisible group-hover:visible' : ''}`}>
{action}
</div>
}
</div>
);
};
export default ListItem;

View File

@ -186,7 +186,7 @@ module.exports = {
supertight: '1.1em'
},
transition: {
basic: 'all 0.4 ease'
basic: 'all 0.4s ease'
}
}
}