Refactor table to give more customization when building rows

This commit is contained in:
Arnaud 2024-10-04 18:41:08 +02:00
parent 9e5d284fb8
commit 2bec229ab7
No known key found for this signature in database
GPG Key ID: 69D6CE281FCAE663
14 changed files with 78 additions and 173 deletions

View File

@ -1,15 +0,0 @@
import { SimpleText } from "../SimpleText/SimpleText";
type Props = {
action: string;
onClick: (data: unknown) => unknown | Promise<unknown>;
};
export const ActionCell = ({ action, onClick }: Props) => (
<a onClick={onClick} className="cell--action">
<SimpleText variant="primary" bold={true}>
{action}
</SimpleText>
</a>
);

View File

@ -1,3 +0,0 @@
.cell--break {
word-break: break-all;
}

View File

@ -1,9 +0,0 @@
import "./BreakCell.css";
type Props = {
value: string;
};
export const BreakCell = ({ value }: Props) => (
<span className="cell--break">{value || " "}</span>
);

View File

@ -1,8 +0,0 @@
.cell--action {
text-decoration: none;
transition: text-shadow 0.35s;
}
.cell--action:hover {
text-shadow: var(--codex-color-primary) 0px 0 20px;
}

View File

@ -1,7 +1,15 @@
import "./Cell.css";
import { ReactNode } from "react";
import "./cell.css";
type Props = {
value: string;
};
export type CellProps = {
children: ReactNode | string;
} & React.DetailedHTMLProps<
React.TdHTMLAttributes<HTMLTableCellElement>,
HTMLTableCellElement
>;
export const Cell = ({ value }: Props) => <span>{value}</span>;
export const Cell = ({ children, className = "", ...rest }: CellProps) => (
<td className={"cell" + className} {...rest}>
{children}
</td>
);

View File

@ -0,0 +1,18 @@
import { Fragment, ReactElement } from "react";
import { Cell, CellProps } from "./Cell";
import "./row.css";
export type RowProps = {
cells: ReactElement<CellProps, typeof Cell>[];
className?: string;
};
export function Row({ cells, className = "" }: RowProps) {
return (
<tr className={"row " + className}>
{cells.map((Cell, index) => (
<Fragment key={index}>{Cell}</Fragment>
))}
</tr>
);
}

View File

@ -1,24 +0,0 @@
.cell-state {
border-radius: var(--codex-border-radius);
padding: 0.5rem;
}
.cell-state--error {
background-color: rgba(var(--codex-color-error), 0.2);
color: rgb(var(--codex-color-error));
}
.cell-state--success {
background-color: rgba(var(--codex-color-success), 0.2);
color: rgb(var(--codex-color-success));
}
.cell-state--warning {
background-color: rgba(var(--codex-color-warning), 0.2);
color: rgb(var(--codex-color-warning));
}
.cell-state--loading {
background-color: rgba(var(--codex-color-grey), 0.2);
color: rgb(var(--codex-color-grey));
}

View File

@ -1,10 +0,0 @@
import "./StateCell.css";
type Props = {
type: "success" | "warning" | "error" | "default";
value: string;
};
export const StateCell = ({ type, value }: Props) => {
return <span className={"cell-state cell-state--" + type}>{value}</span>;
};

View File

@ -1,6 +1,7 @@
import "./Table.css";
import { ReactNode } from "react";
import "./table.css";
import { Search } from "lucide-react";
import { Row, RowProps } from "./Row";
import { Fragment, ReactElement } from "react";
type Props = {
/**
@ -8,17 +9,12 @@ type Props = {
*/
headers: string[];
/**
* The ReactNode cells in two dimensions array,
* one for the lines
* one for the data representation
*/
cells: ReactNode[][];
className?: string;
rows: ReactElement<RowProps, typeof Row>[];
};
export function Table({ headers, cells, className = "" }: Props) {
export function Table({ headers, rows, className = "" }: Props) {
return (
<div className={`table-container ${className}`}>
<table className={"table"}>
@ -32,22 +28,16 @@ export function Table({ headers, cells, className = "" }: Props) {
</tr>
</thead>
<tbody>
{cells.map((row, index) => (
<tr key={index} className="table-tbodyTr">
{headers.map((header, idx) => (
<td key={header} className="table-tbodyTd">
{row[idx]}
</td>
))}
</tr>
{rows.map((Row, index) => (
<Fragment key={index}>{Row}</Fragment>
))}
</tbody>
</table>
{!cells.length && (
{!rows.length && (
<div className="table-placeholder">
<Search />
<p className="table-placeholderText">No search results.</p>
<p className="table-placeholderText">No data.</p>
</div>
)}
</div>

View File

@ -0,0 +1,4 @@
.cell {
text-align: left;
padding: 1rem;
}

View File

@ -0,0 +1,8 @@
.row {
border-bottom: 1px solid var(--codex-border-color);
transition: background-color 0.35s;
}
.row:hover {
background-color: var(--codex-background-light);
}

View File

@ -36,17 +36,3 @@
text-align: left;
padding: 1rem;
}
.table-tbodyTr {
border-bottom: 1px solid var(--codex-border-color);
transition: background-color 0.35s;
}
.table-tbodyTr:hover {
background-color: var(--codex-background-light);
}
.table-tbodyTd {
text-align: left;
padding: 1rem;
}

View File

@ -7,7 +7,7 @@ export { Upload } from "./components/Upload/Upload";
export { Card } from "./components/Card/Card";
export { Select } from "./components/Select/Select";
export { Toast } from "./components/Toast/Toast";
export { SpaceAllocation } from "./components/SpaceAllocation/SpaceAllocation";
export { SpaceAllocation, type SpaceAllocationItem } from "./components/SpaceAllocation/SpaceAllocation";
export { EmptyPlaceholder } from "./components/EmptyPlaceholder/EmptyPlaceholder";
export { Dropdown, type DropdownOption } from "./components/Dropdown/Dropdown";
export { Failure } from "./components/Failure/Failure";
@ -16,11 +16,9 @@ export { Spinner } from "./components/Spinner/Spinner";
export { WebFileIcon } from "./components/WebFileIcon/WebFileIcon";
export { Stepper } from "./components/Stepper/Stepper";
export { Backdrop } from "./components/Backdrop/Backdrop";
export { ActionCell } from "./components/Table/ActionCell";
export { BreakCell } from "./components/Table/BreakCell";
export { Cell } from "./components/Table/Cell";
export { StateCell } from "./components/Table/StateCell";
export { Cell, type CellProps } from "./components/Table/Cell";
export { Table } from "./components/Table/Table";
export { Row, type RowProps } from "./components/Table/Row";
export {
Menu,
type MenuItem,

View File

@ -1,9 +1,8 @@
import type { Meta, StoryObj } from "@storybook/react";
import { Table } from "../src/components/Table/Table";
import "./Table.stories.css";
import { StateCell } from "../src/components/Table/StateCell";
import { ActionCell } from "../src/components/Table/ActionCell";
import { BreakCell } from "../src/components/Table/BreakCell";
import { Row } from "../src/components/Table/Row";
import { Cell } from "../src";
const meta = {
title: "Components/Table",
@ -20,77 +19,40 @@ type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {
cells: [
[
<span>Ox45678FDGHJKLBSA21</span>,
<span>My file</span>,
<span>Some data</span>,
<ActionCell
action="Action"
onClick={() => console.info("Hello")}
></ActionCell>,
rows: [
<Row
cells={[
<Cell>Ox45678FDGHJKLBSA21</Cell>,
<Cell>My file</Cell>,
<Cell>Some data</Cell>,
<Cell>Some data</Cell>,
]}
></Row>,
],
],
headers: ["id", "title", "other", "actions"],
headers: ["id", "title", "other"],
},
};
export const Scroll: Story = {
args: {
className: "tableSmall",
cells: [
[
<span>Ox45678FDGHJKLBSA21</span>,
<span>My file</span>,
<span>Some data</span>,
<ActionCell
action="Action"
onClick={() => console.info("Hello")}
></ActionCell>,
],
rows: [
<Row
cells={[
<Cell>Ox45678FDGHJKLBSA21</Cell>,
<Cell>My file</Cell>,
<Cell>Some data</Cell>,
<Cell>Some data</Cell>,
]}
></Row>,
],
headers: ["id", "title", "other", "actions"],
},
};
export const BreakableCell: Story = {
args: {
cells: [
[
<BreakCell value="veryverylongvaluetobreak"></BreakCell>,
<span>My file</span>,
<span>Some data</span>,
<ActionCell
action="Action"
onClick={() => console.info("Hello")}
></ActionCell>,
],
],
headers: ["break", "title", "other", "actions"],
className: "tableSmall",
},
};
export const State: Story = {
args: {
cells: [
[
<BreakCell value="veryverylongvaluetobreak"></BreakCell>,
<span>My file</span>,
<StateCell type="error" value="cancelled"></StateCell>,
<ActionCell
action="Action"
onClick={() => console.info("Hello")}
></ActionCell>,
],
],
headers: ["id", "title", "state", "actions"],
},
};
export const Empty: Story = {
args: {
cells: [],
rows: [],
headers: ["id", "title", "state", "actions"],
},
};