test: add story for table header (#204)
* test: add story for table header * feature: wrap chips in a container and set shrink to 0 so they don't grow vertically * feature: cancel button is darker * feature: set gap between chip to 4px instead of 8 * lint: remove unused code * bugfix: ChipContainer has a starting margin
This commit is contained in:
@ -26,6 +26,17 @@ const StyledBar = styled.div`
|
|||||||
height: 40px;
|
height: 40px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledChipcontainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 40px;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-left: ${(props) => props.theme.spacing(2)};
|
||||||
|
gap: ${(props) => props.theme.spacing(1)};
|
||||||
|
`;
|
||||||
|
|
||||||
const StyledCancelButton = styled.button`
|
const StyledCancelButton = styled.button`
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
border: none;
|
border: none;
|
||||||
@ -35,7 +46,7 @@ const StyledCancelButton = styled.button`
|
|||||||
const vert = props.theme.spacing(1);
|
const vert = props.theme.spacing(1);
|
||||||
return `${vert} ${horiz} ${vert} ${horiz}`;
|
return `${vert} ${horiz} ${vert} ${horiz}`;
|
||||||
}};
|
}};
|
||||||
color: ${(props) => props.theme.text40};
|
color: ${(props) => props.theme.text60};
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-right: ${(props) => props.theme.spacing(2)};
|
margin-right: ${(props) => props.theme.spacing(2)};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -56,29 +67,31 @@ function SortAndFilterBar<SortField, TData extends FilterableFieldsType>({
|
|||||||
}: OwnProps<SortField, TData>) {
|
}: OwnProps<SortField, TData>) {
|
||||||
return (
|
return (
|
||||||
<StyledBar>
|
<StyledBar>
|
||||||
{sorts.map((sort) => {
|
<StyledChipcontainer>
|
||||||
return (
|
{sorts.map((sort) => {
|
||||||
<SortOrFilterChip
|
return (
|
||||||
key={sort.key}
|
<SortOrFilterChip
|
||||||
labelValue={sort.label}
|
key={sort.key}
|
||||||
id={sort.key}
|
labelValue={sort.label}
|
||||||
icon={sort.order === 'desc' ? <FaArrowDown /> : <FaArrowUp />}
|
id={sort.key}
|
||||||
onRemove={() => onRemoveSort(sort.key)}
|
icon={sort.order === 'desc' ? <FaArrowDown /> : <FaArrowUp />}
|
||||||
/>
|
onRemove={() => onRemoveSort(sort.key)}
|
||||||
);
|
/>
|
||||||
})}
|
);
|
||||||
{filters.map((filter) => {
|
})}
|
||||||
return (
|
{filters.map((filter) => {
|
||||||
<SortOrFilterChip
|
return (
|
||||||
key={filter.key}
|
<SortOrFilterChip
|
||||||
labelKey={filter.label}
|
key={filter.key}
|
||||||
labelValue={`${filter.operand.label} ${filter.displayValue}`}
|
labelKey={filter.label}
|
||||||
id={filter.key}
|
labelValue={`${filter.operand.label} ${filter.displayValue}`}
|
||||||
icon={filter.icon}
|
id={filter.key}
|
||||||
onRemove={() => onRemoveFilter(filter.key)}
|
icon={filter.icon}
|
||||||
/>
|
onRemove={() => onRemoveFilter(filter.key)}
|
||||||
);
|
/>
|
||||||
})}
|
);
|
||||||
|
})}
|
||||||
|
</StyledChipcontainer>
|
||||||
{filters.length + sorts.length > 0 && (
|
{filters.length + sorts.length > 0 && (
|
||||||
<StyledCancelButton
|
<StyledCancelButton
|
||||||
data-testid={'cancel-button'}
|
data-testid={'cancel-button'}
|
||||||
|
|||||||
@ -18,9 +18,9 @@ const StyledChip = styled.div`
|
|||||||
border: 1px solid ${(props) => props.theme.blueLowTransparency};
|
border: 1px solid ${(props) => props.theme.blueLowTransparency};
|
||||||
color: ${(props) => props.theme.blue};
|
color: ${(props) => props.theme.blue};
|
||||||
padding: ${(props) => props.theme.spacing(1) + ' ' + props.theme.spacing(2)};
|
padding: ${(props) => props.theme.spacing(1) + ' ' + props.theme.spacing(2)};
|
||||||
margin-left: ${(props) => props.theme.spacing(2)};
|
|
||||||
font-size: ${(props) => props.theme.fontSizeSmall};
|
font-size: ${(props) => props.theme.fontSizeSmall};
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
flex-shrink: 0;
|
||||||
`;
|
`;
|
||||||
const StyledIcon = styled.div`
|
const StyledIcon = styled.div`
|
||||||
margin-right: ${(props) => props.theme.spacing(1)};
|
margin-right: ${(props) => props.theme.spacing(1)};
|
||||||
|
|||||||
@ -0,0 +1,82 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { FaList } from 'react-icons/fa';
|
||||||
|
import { ApolloProvider } from '@apollo/client';
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
import { userEvent, within } from '@storybook/testing-library';
|
||||||
|
|
||||||
|
import { FullHeightStorybookLayout } from '~/testing/FullHeightStorybookLayout';
|
||||||
|
import { mockedClient } from '~/testing/mockedClient';
|
||||||
|
|
||||||
|
import { availableFilters } from '../../../../../../pages/companies/companies-filters';
|
||||||
|
import { availableSorts } from '../../../../../../pages/companies/companies-sorts';
|
||||||
|
import { TableHeader } from '../TableHeader';
|
||||||
|
|
||||||
|
const meta: Meta<typeof TableHeader> = {
|
||||||
|
title: 'Components/Table/TableHeader',
|
||||||
|
component: TableHeader,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof TableHeader>;
|
||||||
|
|
||||||
|
export const Empty: Story = {
|
||||||
|
render: () => (
|
||||||
|
<ApolloProvider client={mockedClient}>
|
||||||
|
<FullHeightStorybookLayout>
|
||||||
|
<TableHeader
|
||||||
|
viewName="ViewName"
|
||||||
|
viewIcon={<FaList />}
|
||||||
|
availableSorts={availableSorts}
|
||||||
|
availableFilters={availableFilters}
|
||||||
|
/>
|
||||||
|
</FullHeightStorybookLayout>
|
||||||
|
</ApolloProvider>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WithSortsAndFilters: Story = {
|
||||||
|
render: () => (
|
||||||
|
<ApolloProvider client={mockedClient}>
|
||||||
|
<FullHeightStorybookLayout>
|
||||||
|
<TableHeader
|
||||||
|
viewName="ViewName"
|
||||||
|
viewIcon={<FaList />}
|
||||||
|
availableSorts={availableSorts}
|
||||||
|
availableFilters={availableFilters}
|
||||||
|
/>
|
||||||
|
</FullHeightStorybookLayout>
|
||||||
|
</ApolloProvider>
|
||||||
|
),
|
||||||
|
play: async ({ canvasElement }) => {
|
||||||
|
const canvas = within(canvasElement);
|
||||||
|
const outsideClick = await canvas.findByText('ViewName');
|
||||||
|
|
||||||
|
userEvent.click(await canvas.findByText('Filter'));
|
||||||
|
userEvent.click(await canvas.findByText('Name'));
|
||||||
|
const nameInput = await canvas.findByPlaceholderText('Name');
|
||||||
|
userEvent.type(nameInput, 'My name');
|
||||||
|
userEvent.click(outsideClick);
|
||||||
|
|
||||||
|
userEvent.click(await canvas.findByText('Sort'));
|
||||||
|
userEvent.click(await canvas.findByText('Name'));
|
||||||
|
|
||||||
|
userEvent.click(await canvas.findByText('Sort'));
|
||||||
|
userEvent.click(await canvas.findByText('Creation'));
|
||||||
|
|
||||||
|
userEvent.click(await canvas.findByText('Sort'));
|
||||||
|
userEvent.click(await canvas.findByText('Address'));
|
||||||
|
|
||||||
|
userEvent.click(await canvas.findByText('Filter'));
|
||||||
|
userEvent.click(await canvas.findByText('Employees'));
|
||||||
|
const employeesInput = await canvas.findByPlaceholderText('Employees');
|
||||||
|
userEvent.type(employeesInput, '12');
|
||||||
|
|
||||||
|
userEvent.click(await canvas.findByText('Sort'));
|
||||||
|
userEvent.click(await canvas.findByText('Url'));
|
||||||
|
|
||||||
|
userEvent.click(await canvas.findByText('Filter'));
|
||||||
|
userEvent.click(await canvas.findByText('Created At'));
|
||||||
|
userEvent.click(await canvas.findByText('6'));
|
||||||
|
userEvent.click(outsideClick);
|
||||||
|
},
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user