Skip to content

Commit

Permalink
feat(Table): fix styles; add mock example; add zebra stripes
Browse files Browse the repository at this point in the history
  • Loading branch information
inomdzhon committed Mar 15, 2024
1 parent 83487a7 commit 7c52f05
Show file tree
Hide file tree
Showing 8 changed files with 272 additions and 61 deletions.
141 changes: 136 additions & 5 deletions packages/vkui/src/components/Table/Table.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import * as React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { getRandomInt, getRandomString } from '@vkontakte/vkjs';
import { Placeholder } from '../../storybook/Placeholder';
import { DisableCartesianParam } from '../../storybook/constants';
import { getAvatarUrl } from '../../testing/mock';
import { getAvatarUrl, getRandomUser } from '../../testing/mock';
import { Badge } from '../Badge/Badge';
import { Checkbox } from '../Checkbox/Checkbox';
import { Image } from '../Image/Image';
import { TableBody } from '../TableBody/TableBody';
import { TableCell } from '../TableCell/TableCell';
import { TableFooter } from '../TableFooter/TableFooter';
import { TableHeader } from '../TableHeader/TableHeader';
import { TableRow } from '../TableRow/TableRow';
import { Caption } from '../Typography/Caption/Caption';
import { Footnote } from '../Typography/Footnote/Footnote';
import { Headline } from '../Typography/Headline/Headline';
import { Subhead } from '../Typography/Subhead/Subhead';
import { Text } from '../Typography/Text/Text';
import { UsersStack } from '../UsersStack/UsersStack';
import { Table, type TableProps } from './Table';

const story: Meta<TableProps> = {
Expand All @@ -22,6 +28,128 @@ const story: Meta<TableProps> = {

export default story;

type Story = StoryObj<TableProps>;

export const Mock: Story = {
render: function Mock({ padding, enableZebraStripes, ...restProps }) {
const someUser = React.useMemo(() => getRandomUser(), []);
const [rows, setRows] = React.useState(() =>
new Array(30).fill(undefined).map((_, index) => {
return {
id: index,
checked: false,
};
}),
);

const handleClickToSelectAllCells = (event: React.ChangeEvent<HTMLInputElement>) => {
setRows((prevRows) =>
prevRows.map((row) => {
row.checked = event.target.checked;
return row;
}),
);
};

const handleCellSelected = (event: React.ChangeEvent<HTMLInputElement>) => {
const idRaw = event.target.dataset.id;
if (typeof idRaw === 'string') {
const id = Number(idRaw);
setRows((prevRows) =>
prevRows.map((row, index) => {
if (id === index) {
row.checked = event.target.checked;
}
return row;
}),
);
}
};

return (
<Table
style={{ minWidth: 650 }}
aria-label="simple table"
padding={padding}
enableZebraStripes={enableZebraStripes}
{...restProps}
>
<TableHeader isSticky>
<TableRow>
<TableCell align="right" noPadding width={48}>
<Checkbox onChange={handleClickToSelectAllCells} />
</TableCell>
<TableCell>
<Text>Text</Text>
</TableCell>
<TableCell>
<Text>Text</Text>
</TableCell>
<TableCell align="right">
<Text>Text</Text>
</TableCell>
<TableCell align="right">
<Text>Text</Text>
</TableCell>
<TableCell align="right">
<Text>Text</Text>
</TableCell>
</TableRow>
</TableHeader>
<TableBody>
{rows.map((row) => (
<TableRow key={row.id}>
<TableCell align="right" noPadding>
<Checkbox data-id={row.id} checked={row.checked} onChange={handleCellSelected} />
</TableCell>
<TableCell asHeader scope="row" width={200} align={row.id === 0 ? 'right' : 'left'}>
<div>
<Footnote>Text</Footnote>
<Caption>Subscription</Caption>
</div>
</TableCell>
<TableCell width={220}>
{row.id === 0 ? (
<UsersStack photos={[someUser.photo_100]}>
Следующим людям понравилось: {someUser.first_name} {someUser.last_name}
</UsersStack>
) : (
<Placeholder />
)}
</TableCell>
<TableCell align="right">
<Headline>Text</Headline>
</TableCell>
<TableCell align="right">
<Headline>Text</Headline>
</TableCell>
<TableCell align="right">
<Headline>Text</Headline>
</TableCell>
</TableRow>
))}
</TableBody>
<TableFooter isSticky>
<TableRow>
<TableCell />
<TableCell>
<Text>Всего</Text>
</TableCell>
<TableCell />
<TableCell />
<TableCell align="right">
<Text>Text</Text>
</TableCell>
<TableCell align="right">
<Text>Text</Text>
</TableCell>
</TableRow>
</TableFooter>
</Table>
);
},
};

const numberFormatter = new Intl.NumberFormat('ru-RU');

const currencyFormatter = new Intl.NumberFormat('ru-RU', {
Expand All @@ -43,7 +171,12 @@ const rows = new Array(30).fill(undefined).map(() => {

const getTotalSpent = () => rows.reduce((total, { spent }) => total + spent, 0);

const styleContainer = { display: 'flex', alignItems: 'center', gap: 8 };
const styleContainer: React.CSSProperties = {
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
gap: 8,
};

const Status = ({ status = 'active', ...restProps }) => {
switch (status) {
Expand All @@ -66,9 +199,7 @@ const Status = ({ status = 'active', ...restProps }) => {
}
};

type Story = StoryObj<TableProps>;

export const Playground: Story = {
export const Example: Story = {
render(props) {
return (
<div>
Expand Down
9 changes: 7 additions & 2 deletions packages/vkui/src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ export interface TableProps
React.TableHTMLAttributes<HTMLTableElement>,
HasRootRef<HTMLElement> {}

export const Table = ({ padding = DEFAULT_TABLE_PADDING, children, ...restProps }: TableProps) => {
export const Table = ({
padding = DEFAULT_TABLE_PADDING,
enableZebraStripes,
children,
...restProps
}: TableProps) => {
return (
<TableContext.Provider value={{ padding }}>
<TableContext.Provider value={{ padding, enableZebraStripes }}>
<RootComponent Component="table" baseClassName={styles.Table} {...restProps}>
{children}
</RootComponent>
Expand Down
1 change: 1 addition & 0 deletions packages/vkui/src/components/Table/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { LiteralUnion } from '../../types';

export type TableContextProps = {
padding?: LiteralUnion<'xs' | 's' | 'm' | 'l', number | string>;
enableZebraStripes?: boolean;
};

export type TableSectionType = 'header' | 'body' | 'footer';
Expand Down
25 changes: 20 additions & 5 deletions packages/vkui/src/components/TableCell/TableCell.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,16 @@

.TableCell--section-header,
.TableCell--section-footer {
color: var(--vkui--color_text_subhead);
background-color: var(--vkui--color_background_secondary);
}

/* stylelint-disable selector-max-type */
tr:nth-child(even) .TableCell--zebra-stripes {
background-color: var(--vkui--color_background_tertiary);
}
/* stylelint-enable selector-max-type */

.TableCell--padding-m {
padding-block-start: 8px;
padding-block-end: calc(8px - var(--vkui--size_border--regular));
Expand Down Expand Up @@ -61,34 +68,42 @@
table > tr:first-of-type > .TableCell:first-child, /* тут нужен именно :first-of-type, т.к. может быть <caption> до */
thead > tr:first-child > .TableCell:first-child,
tbody:first-child > :first-child > .TableCell:first-child {
border-start-start-radius: 8px;
border-start-start-radius: var(--vkui--size_border_radius--regular);
}

table > tr:first-of-type > .TableCell:last-child, /* тут нужен именно :first-of-type, т.к. может быть <caption> до */
thead > tr:first-child > .TableCell:last-child,
tbody:first-child > :first-child > .TableCell:last-child {
border-start-end-radius: 8px;
border-start-end-radius: var(--vkui--size_border_radius--regular);
}

table > tr:last-child > .TableCell:first-child, /* тут нужен именно :first-child, а не :first-of-type */
tbody:last-child > :last-child > .TableCell:first-child,
tfoot > tr:last-child > .TableCell:first-child {
border-end-start-radius: 8px;
border-end-start-radius: var(--vkui--size_border_radius--regular);
}

table > tr:last-child > .TableCell:last-child, /* тут нужен именно :first-child, а не :first-of-type */
tbody:last-child > :last-child > .TableCell:last-child,
tfoot > :last-child > .TableCell:last-child {
border-end-end-radius: 8px;
border-end-end-radius: var(--vkui--size_border_radius--regular);
}

/*
* Удаляем разделитель у ячейках в конце таблицы.
*
* Т.к. <thead> должен быть объявлен в конце, то тут не указываем его тут.
* Т.к. <thead> должен быть объявлен только в начале, то тут не указываем его тут.
*/
table > tr:last-child > .TableCell,
tbody > tr:last-child > .TableCell,
tfoot > tr:last-child > .TableCell {
border-block-end: unset;
}

/*
* Для <tfoot> нужно выставить разделить сверху, т.к. он может быть sticky.
*/
tfoot > tr:last-child > .TableCell {
border-block-start: var(--vkui--size_border--regular) solid
var(--vkui--color_separator_primary_alpha);
}
Loading

0 comments on commit 7c52f05

Please sign in to comment.