Skip to content

Commit

Permalink
Merge branch 'main' into feature/external-images-remove
Browse files Browse the repository at this point in the history
  • Loading branch information
marcinsawicki authored Dec 10, 2024
2 parents f6a21b9 + e52e072 commit e238507
Show file tree
Hide file tree
Showing 22 changed files with 1,714 additions and 0 deletions.
111 changes: 111 additions & 0 deletions packages/react-components/src/components/Table/Table.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { Meta, Title, Canvas, ArgTypes } from '@storybook/blocks';

import * as Stories from './Table.stories';

<Title>Table</Title>

[Intro](#Intro) | [Component API](#ComponentAPI) | [Content Spec](#ContentSpec)

## Intro <a id="Intro" />

`Table` component is a flexible and interactive table designed for displaying structured data. It supports key features such as sorting, column resizing, row selection, and a customizable layout.


<Canvas of={Stories.Default} sourceState="none" />

#### Example implementation

```jsx

import React from 'react';
import { Button, Column, Table } from '@livechat/design-system-react-components';

type Data = {
id: number;
name: string;
age: number;
role: string;
action: React.ReactNode;
};

const columns: Column<Data>[] = [
{
key: 'id',
header: 'ID',
sortable: true,
sortValue: (item: Data) => item.id,
},
{
key: 'name',
header: 'Name',
sortable: true,
sortValue: (item: Data) => item.name.toLowerCase(),
},
{
key: 'age',
header: 'Age',
sortable: true,
sortValue: (item: Data) => item.age,
},
{
key: 'role',
header: 'Role',
sortable: true,
sortValue: (item: Data) => item.role,
},
{
key: 'action',
header: 'Action',
},
];

const data: Data[] = [
{
id: 1,
name: 'John Doe',
age: 28,
role: 'Developer',
action: <Button size="xcompact">Edit</Button>,
},
{
id: 2,
name: 'Jane Smith',
age: 34,
role: 'Designer',
action: <Button size="xcompact">Edit</Button>,
},
{
id: 3,
name: 'Alice Johnson',
age: 42,
role: 'Manager',
action: <Button size="xcompact">Edit</Button>,
},
{
id: 4,
name: 'Mike Williams',
age: 25,
role: 'Intern',
action: <Button size="xcompact">Edit</Button>,
},
];

const getRowId = (row: Data) => row.id;

<Table size="medium" data={data} columns={columns} getRowId={getRowId} />

```

## Component API <a id="ComponentAPI" />

<ArgTypes of={Stories.Default} />

## Content Spec <a id="ContentSpec" />

<a
className="sb-unstyled"
href="https://www.figma.com/design/9FDwjR8lYvincseDkKypC4/Component-Documentations?node-id=21446-18742&node-type=canvas&t=XufCAXr9dcNjfXDk-0"
target="_blank"
>
Go to Figma documentation
</a>
98 changes: 98 additions & 0 deletions packages/react-components/src/components/Table/Table.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
@use './styles/pin';
@use './styles/size';
@use './styles/strips';

$base-class: 'table';
$action-bar-class: 'action-bar';

.#{$base-class} {
width: 100%;
border-collapse: collapse;
contain: paint;

&--small {
@include size.table-size(48px, 8px, 16px);
}

&--medium {
@include size.table-size(56px, 12px, 16px);
}

&--large {
@include size.table-size(64px, 14px, 16px);
}

&--pinned_header {
@include pin.generatePin('header');
}

&--pinned_leftColumn {
@include pin.generatePin('leftColumn');
}

&__cell {
text-align: start;
line-height: 21px;
font-size: 14px;
}

&__selected {
display: flex;
gap: var(--spacing-1);
align-items: center;
padding: var(--spacing-2);
font-weight: 500;

> p {
margin: 0;
font-weight: 500;
}

> div:first-child {
display: flex;
align-items: center;
margin-right: var(--spacing-1);
}
}

&--stripped_rows {
@include strips.generateStrips('rows');
}

&--stripped_columns {
@include strips.generateStrips('columns');
}

tbody {
width: 100%;
}

td,
th {
text-align: left;
}

th > div {
display: flex;
}
}

.#{$action-bar-class} {
display: flex;
gap: var(--spacing-2);

&__divider {
position: relative;

&::before {
position: absolute;
top: 0;
bottom: 0;
margin-right: var(--spacing-2);
background-color: var(--border-basic-secondary);
width: 1px;
height: var(--spacing-6);
content: '';
}
}
}
49 changes: 49 additions & 0 deletions packages/react-components/src/components/Table/Table.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { render, fireEvent, vi } from 'test-utils';

import { Table } from './Table';
import { Column } from './types';

type Data = {
id: number;
name: string;
age: number;
role: string;
};

const columns: Column<Data>[] = [
{ key: 'id', header: 'ID' },
{ key: 'name', header: 'Name' },
{ key: 'age', header: 'Age' },
{ key: 'role', header: 'Role' },
];

const data: Data[] = [
{ id: 1, name: 'John Doe', age: 28, role: 'Developer' },
{ id: 2, name: 'Jane Smith', age: 34, role: 'Designer' },
{ id: 3, name: 'Alice Johnson', age: 42, role: 'Manager' },
];

describe('<Table> component', () => {
const getRowId = (row: Data) => row.id;

it('should allow row selection if selectable prop is enabled', () => {
const onSelectionChange = vi.fn();
const selectedRows = new Set<string>();
const { getAllByRole } = render(
<Table
data={data}
columns={columns}
getRowId={getRowId}
selectable={true}
selectedRows={selectedRows}
onSelectionChange={onSelectionChange}
/>
);

const checkboxes = getAllByRole('checkbox');
expect(checkboxes.length).toBe(data.length + 1);

fireEvent.click(checkboxes[1]);
expect(onSelectionChange).toHaveBeenCalledWith(new Set([1]));
});
});
Loading

0 comments on commit e238507

Please sign in to comment.