mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Changed NewsletterList to use new Table
component (#17458)
refs https://github.com/TryGhost/Product/issues/3601 - `NewsletterList` now uses the new `Table` component, along with its subcomponents `TableRow` and `TableCell` to be able to show more relevant data
This commit is contained in:
parent
0aa5815b26
commit
5d5d33b930
5 changed files with 261 additions and 14 deletions
|
@ -0,0 +1,38 @@
|
|||
import type {Meta, StoryObj} from '@storybook/react';
|
||||
|
||||
import Table from './Table';
|
||||
import TableCell from './TableCell';
|
||||
import TableRow from './TableRow';
|
||||
|
||||
const meta = {
|
||||
title: 'Global / Table',
|
||||
component: Table,
|
||||
tags: ['autodocs']
|
||||
} satisfies Meta<typeof Table>;
|
||||
|
||||
const tableRows = (
|
||||
<>
|
||||
<TableRow>
|
||||
<TableCell>Jamie Larson</TableCell>
|
||||
<TableCell>jamie@example.com</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>Jamie Larson</TableCell>
|
||||
<TableCell>jamie@example.com</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>Jamie Larson</TableCell>
|
||||
<TableCell>jamie@example.com</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Table>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
children: tableRows
|
||||
},
|
||||
decorators: [(_story: any) => (<div style={{maxWidth: '600px'}}>{_story()}</div>)]
|
||||
};
|
35
apps/admin-x-settings/src/admin-x-ds/global/Table.tsx
Normal file
35
apps/admin-x-settings/src/admin-x-ds/global/Table.tsx
Normal file
|
@ -0,0 +1,35 @@
|
|||
import Heading from './Heading';
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
|
||||
interface TableProps {
|
||||
/**
|
||||
* If the table is the primary content on a page (e.g. Members table) then you can set a pagetitle to be consistent
|
||||
*/
|
||||
pageTitle?: string;
|
||||
children?: React.ReactNode;
|
||||
borderTop?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const Table: React.FC<TableProps> = ({children, borderTop, pageTitle, className}) => {
|
||||
const tableClasses = clsx(
|
||||
(borderTop || pageTitle) && 'border-t border-grey-300',
|
||||
'w-full',
|
||||
pageTitle ? 'mb-0 mt-14' : 'my-0',
|
||||
className
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{pageTitle && <Heading>{pageTitle}</Heading>}
|
||||
<table className={tableClasses}>
|
||||
<tbody>
|
||||
{children}
|
||||
</tbody>
|
||||
</table>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Table;
|
22
apps/admin-x-settings/src/admin-x-ds/global/TableCell.tsx
Normal file
22
apps/admin-x-settings/src/admin-x-ds/global/TableCell.tsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
|
||||
interface TableCellProps {
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const TableCell: React.FC<TableCellProps> = ({className, children}) => {
|
||||
const tableCellClasses = clsx(
|
||||
'!py-3 !pl-0 !pr-6 align-top',
|
||||
className
|
||||
);
|
||||
|
||||
return (
|
||||
<td className={tableCellClasses}>
|
||||
{children}
|
||||
</td>
|
||||
);
|
||||
};
|
||||
|
||||
export default TableCell;
|
47
apps/admin-x-settings/src/admin-x-ds/global/TableRow.tsx
Normal file
47
apps/admin-x-settings/src/admin-x-ds/global/TableRow.tsx
Normal file
|
@ -0,0 +1,47 @@
|
|||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
|
||||
interface TableRowProps {
|
||||
id?: string;
|
||||
action?: React.ReactNode;
|
||||
hideActions?: boolean;
|
||||
className?: string;
|
||||
testId?: string;
|
||||
|
||||
/**
|
||||
* Hidden for the last item in the table
|
||||
*/
|
||||
separator?: boolean;
|
||||
|
||||
bgOnHover?: boolean;
|
||||
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const TableRow: React.FC<TableRowProps> = ({id, action, hideActions, className, testId, separator, bgOnHover = true, onClick, children}) => {
|
||||
const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
onClick?.(e);
|
||||
};
|
||||
|
||||
separator = (separator === undefined) ? true : separator;
|
||||
const tableRowClasses = clsx(
|
||||
'group',
|
||||
bgOnHover && 'hover:bg-gradient-to-r hover:from-white hover:to-grey-50',
|
||||
onClick && 'cursor-pointer',
|
||||
separator ? 'border-b border-grey-100 last-of-type:border-b-transparent hover:border-grey-200' : 'border-y border-transparent hover:border-grey-200 first-of-type:hover:border-t-transparent',
|
||||
className
|
||||
);
|
||||
|
||||
return (
|
||||
<tr className={tableRowClasses} data-testid={testId} id={id} onClick={handleClick}>
|
||||
{children}
|
||||
{action &&
|
||||
<td className={`px-6 py-3 text-center ${hideActions ? 'invisible group-hover:visible' : ''}`}>
|
||||
{action}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
);
|
||||
};
|
||||
|
||||
export default TableRow;
|
|
@ -1,14 +1,64 @@
|
|||
import Button from '../../../../admin-x-ds/global/Button';
|
||||
import List from '../../../../admin-x-ds/global/List';
|
||||
import ListItem from '../../../../admin-x-ds/global/ListItem';
|
||||
// import List from '../../../../admin-x-ds/global/List';
|
||||
// import ListItem from '../../../../admin-x-ds/global/ListItem';
|
||||
import NewsletterDetailModal from './NewsletterDetailModal';
|
||||
import NiceModal from '@ebay/nice-modal-react';
|
||||
import React from 'react';
|
||||
import Table from '../../../../admin-x-ds/global/Table';
|
||||
import TableCell from '../../../../admin-x-ds/global/TableCell';
|
||||
import TableRow from '../../../../admin-x-ds/global/TableRow';
|
||||
|
||||
interface NewslettersListProps {
|
||||
tab?: string;
|
||||
}
|
||||
|
||||
// We should create a NewsletterItem component based on TableRow and then loop through newsletters
|
||||
//
|
||||
// interface NewsletterItemProps {
|
||||
// name: string;
|
||||
// description: string;
|
||||
// subscribers: number;
|
||||
// emailsSent: number;
|
||||
// }
|
||||
|
||||
// const NewsletterItem: React.FC<NewsletterItemProps> = ({name, description, subscribers, emailsSent}) => {
|
||||
// const action = tab === 'active-newsletters' ? (
|
||||
// <Button color='green' label='Archive' link />
|
||||
// ) : (
|
||||
// <Button color='green' label='Activate' link />
|
||||
// );
|
||||
|
||||
// return (
|
||||
// <TableRow
|
||||
// action={action}
|
||||
// onClick={() => {
|
||||
// NiceModal.show(NewsletterDetailModal);
|
||||
// }}>
|
||||
// hideActions
|
||||
// separator
|
||||
// >
|
||||
// <TableCell>
|
||||
// <div className={`flex grow flex-col`}>
|
||||
// <span className='font-medium'>{name}</span>
|
||||
// <span className='whitespace-nowrap text-xs text-grey-700'>{description}</span>
|
||||
// </div>
|
||||
// </TableCell>
|
||||
// <TableCell>
|
||||
// <div className={`flex grow flex-col`}>
|
||||
// <span>{subscribers}</span>
|
||||
// <span className='whitespace-nowrap text-xs text-grey-700'>Subscribers</span>
|
||||
// </div>
|
||||
// </TableCell>
|
||||
// <TableCell>
|
||||
// <div className={`flex grow flex-col`}>
|
||||
// <span>{emailsSent}</span>
|
||||
// <span className='whitespace-nowrap text-xs text-grey-700'>Emails sent</span>
|
||||
// </div>
|
||||
// </TableCell>
|
||||
// </TableRow>
|
||||
// );
|
||||
// };
|
||||
|
||||
const NewslettersList: React.FC<NewslettersListProps> = ({
|
||||
tab
|
||||
}) => {
|
||||
|
@ -19,26 +69,81 @@ const NewslettersList: React.FC<NewslettersListProps> = ({
|
|||
);
|
||||
|
||||
return (
|
||||
<List>
|
||||
<ListItem
|
||||
<Table>
|
||||
<TableRow
|
||||
action={action}
|
||||
detail='This one is pretty good'
|
||||
title='Amazing newsletter'
|
||||
hideActions
|
||||
onClick={() => {
|
||||
NiceModal.show(NewsletterDetailModal);
|
||||
}}
|
||||
/>
|
||||
<ListItem
|
||||
}}>
|
||||
<TableCell>
|
||||
<div className={`flex grow flex-col`}>
|
||||
<span className='font-medium'>Amazing newsletter</span>
|
||||
<span className='whitespace-nowrap text-xs text-grey-700'>This one is pretty good</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className={`flex grow flex-col`}>
|
||||
<span>259</span>
|
||||
<span className='whitespace-nowrap text-xs text-grey-700'>Subscribers</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className={`flex grow flex-col`}>
|
||||
<span>14</span>
|
||||
<span className='whitespace-nowrap text-xs text-grey-700'>Emails sent</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow
|
||||
action={action}
|
||||
detail='This one is just spam'
|
||||
title='Awful newsletter'
|
||||
hideActions
|
||||
onClick={() => {
|
||||
NiceModal.show(NewsletterDetailModal);
|
||||
}}
|
||||
/>
|
||||
</List>
|
||||
}}>
|
||||
<TableCell>
|
||||
<div className={`flex grow flex-col`}>
|
||||
<span className='line-clamp-1 font-medium'>Crappy newsletter</span>
|
||||
<span className='whitespace-nowrap text-xs text-grey-700'>This one is just spam</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className={`flex grow flex-col`}>
|
||||
<span>145</span>
|
||||
<span className='whitespace-nowrap text-xs text-grey-700'>Subscribers</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className={`flex grow flex-col`}>
|
||||
<span>754</span>
|
||||
<span className='whitespace-nowrap text-xs text-grey-700'>Emails sent</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</Table>
|
||||
|
||||
// Newsletter list previously used the List component, can be removed
|
||||
//
|
||||
// <List>
|
||||
// <ListItem
|
||||
// action={action}
|
||||
// detail='This one is pretty good'
|
||||
// title='Amazing newsletter'
|
||||
// hideActions
|
||||
// onClick={() => {
|
||||
// NiceModal.show(NewsletterDetailModal);
|
||||
// }}
|
||||
// />
|
||||
// <ListItem
|
||||
// action={action}
|
||||
// detail='This one is just spam'
|
||||
// title='Awful newsletter'
|
||||
// hideActions
|
||||
// onClick={() => {
|
||||
// NiceModal.show(NewsletterDetailModal);
|
||||
// }}
|
||||
// />
|
||||
// </List>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue