Skip to content

Commit

Permalink
fix(Table): add focused prop
Browse files Browse the repository at this point in the history
  • Loading branch information
LamaEats committed Aug 1, 2023
1 parent dea32ba commit 2be3fc8
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 32 deletions.
85 changes: 59 additions & 26 deletions src/components/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { gray4, gray6 } from '@taskany/colors';
import styled, { css } from 'styled-components';

const maxCols = 12;
Expand All @@ -17,36 +18,53 @@ interface JustifyProps {
justify: 'start' | 'center' | 'end' | 'between' | 'around' | 'baseline';
}

export type TableCellProps =
| {
/** Size of column width in range from `1` to `12` */
col: number;
/** Minimum size column, use instead of `col` prop */
min?: never;
/** Absolute or relative width, ex. `10ch` or `100` */
width?: never;
}
| {
col?: never;
min: boolean;
width?: never;
}
| {
col?: never;
min?: never;
width: number | string;
}
| {
col?: never;
min?: never;
width?: never;
};
export type TableCellProps = Partial<JustifyProps & AlignProps> &
(
| {
/** Size of column width in range from `1` to `12` */
col: number;
min?: never;
width?: never;
}
| {
col?: never;
/** Minimum size column, use instead of `col` prop */
min: true;
width?: never;
}
| {
col?: never;
min?: never;
/** Absolute or relative width, ex. `10ch` or `100` */
width: number | string;
}
| {
col?: never;
min?: never;
width?: never;
}
);

export interface TableProps extends GapProps {
/** Container width */
width?: number;
}

export type TableRowProps = GapProps &
Partial<AlignProps & JustifyProps> &
(
| {
interactive?: false | never;
focused?: never;
}
| {
/** Apply interactive styles: hover */
interactive: true;
/** Prop that mark current row as focused, ex. for keyboard navigation */
focused: boolean;
}
);

const mapRuleSet: { [key in AlignProps['align'] | JustifyProps['justify']]: string } = {
baseline: 'baseline',
start: 'flex-start',
Expand All @@ -73,7 +91,7 @@ export const Table = styled.div<TableProps>`
`}
`;

export const TableRow = styled.div<Partial<AlignProps & JustifyProps> & GapProps>`
export const TableRow = styled.div<TableRowProps>`
display: flex;
flex-basis: 100%;
align-items: flex-start;
Expand All @@ -96,9 +114,24 @@ export const TableRow = styled.div<Partial<AlignProps & JustifyProps> & GapProps
css`
gap: ${gap}px;
`}
${({ interactive }) =>
interactive &&
css`
&:hover {
background-color: ${gray6};
}
`}
${({ focused, interactive }) =>
interactive &&
focused &&
css`
background-color: ${gray4};
`}
`;

export const TableCell = styled.div<TableCellProps & Partial<JustifyProps & AlignProps>>`
export const TableCell = styled.div<TableCellProps>`
display: inline-flex;
align-items: baseline;
flex-wrap: wrap;
Expand Down
85 changes: 79 additions & 6 deletions src/stories/Table.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import type { Meta, StoryFn } from '@storybook/react';
import { gray5, gray3 } from '@taskany/colors';
import styled from 'styled-components';
import { gray5, gray3, gapS, radiusM } from '@taskany/colors';
import styled, { css } from 'styled-components';

import { Table, TableRow, TableCell } from '../components/Table';
import { GoalIcon } from '../components/Icon/GoalIcon';
Expand All @@ -11,6 +11,7 @@ import { Dot } from '../components/Dot';
import { Tag } from '../components/Tag';
import { CircleProgressBar } from '../components/CircleProgressBar';
import { Button } from '../components/Button';
import { useKeyPress } from '../hooks/useKeyPress';

const meta: Meta<typeof Table> = {
title: 'Table',
Expand Down Expand Up @@ -41,9 +42,20 @@ const data = Array.from({ length: 10 }, (_, i) => ({
}));

const StyledTableRow = styled(TableRow)<{ depth?: number }>`
padding: 5px 0;
border-bottom: 1px solid ${gray5};
border-top: 1px solid ${gray3};
padding: ${gapS};
${({ interactive }) =>
interactive &&
css`
border-radius: ${radiusM};
`}
${({ interactive }) =>
!interactive &&
css`
border-bottom: 1px solid ${gray5};
border-top: 1px solid ${gray3};
`}
&:first-child {
border-top: 0;
Expand Down Expand Up @@ -137,3 +149,64 @@ export const RecursiveTable = () => {
</Table>
);
};

export const FocusAndHover: Story = () => {
const [activeIndex, setActiveIndex] = useState(0);

const downPress = useKeyPress('ArrowDown');
const upPress = useKeyPress('ArrowUp');

useEffect(() => {
setActiveIndex((prev) => {
if (upPress) {
return prev > 0 ? prev - 1 : prev;
}

return prev;
});
}, [upPress]);

useEffect(() => {
setActiveIndex((prev) => {
if (downPress) {
return prev < data.length - 1 ? prev + 1 : prev;
}

return prev;
});
}, [downPress]);

return (
<Table width={600}>
{data.map(({ title, projectId, tags, progress }, index) => (
<StyledTableRow key={title} align="center" gap={10} interactive focused={activeIndex === index}>
<TableCell min>
<GoalIcon size="xxs" noWrap />
</TableCell>
<TableCell col={5}>
<Text size="s" weight="bold">
<Dot size="m" view="primary" />
{title}
</Text>
</TableCell>
<TableCell min>
<CircleProgressBar value={progress} size="s" />
</TableCell>
<TableCell width="6ch">
<Text size="s" weight="thin">
{projectId}
</Text>
</TableCell>
<TableCell justify="end">
{tags.map((t) => (
<Tag size="s" title={t} />
))}
</TableCell>
<TableCell min justify="center">
<UserPic size={14} email="admin@taskany.org" />
</TableCell>
</StyledTableRow>
))}
</Table>
);
};

0 comments on commit 2be3fc8

Please sign in to comment.