Refactor table to give more customization when building rows
This commit is contained in:
parent
9e5d284fb8
commit
2bec229ab7
|
@ -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>
|
||||
);
|
|
@ -1,3 +0,0 @@
|
|||
.cell--break {
|
||||
word-break: break-all;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
import "./BreakCell.css";
|
||||
|
||||
type Props = {
|
||||
value: string;
|
||||
};
|
||||
|
||||
export const BreakCell = ({ value }: Props) => (
|
||||
<span className="cell--break">{value || " "}</span>
|
||||
);
|
|
@ -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;
|
||||
}
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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>;
|
||||
};
|
|
@ -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>
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
.cell {
|
||||
text-align: left;
|
||||
padding: 1rem;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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"],
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue