Refactor Table component

This commit is contained in:
Arnaud 2024-08-28 10:02:39 +02:00
parent e1a20e96ab
commit 3c314b455d
No known key found for this signature in database
GPG Key ID: 69D6CE281FCAE663
15 changed files with 81 additions and 94 deletions

View File

@ -0,0 +1,14 @@
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,20 +0,0 @@
import { SimpleText } from "../SimpleText/SimpleText";
export const ActionCellRender =
(action: string, onClick: (row: string[]) => void) =>
(_: string, row: string[]) => {
return (
<a
href="#"
onClick={(e) => {
e.preventDefault();
onClick(row);
}}
className="cell--action"
>
<SimpleText variant="primary" bold={true}>
{action}
</SimpleText>
</a>
);
};

View File

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

View File

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

View File

@ -1,3 +0,0 @@
export const BreakCellRender = (val: string) => (
<span className="cell--break">{val || " "}</span>
);

View File

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

View File

@ -0,0 +1,7 @@
import "./Cell.css";
type Props = {
value: string;
};
export const Cell = ({ value }: Props) => <span>{value}</span>;

View File

@ -1,22 +0,0 @@
.cell--break {
word-break: break-all;
}
.cell--action {
text-decoration: none;
transition: text-shadow 0.35s;
}
.cell--action:hover {
text-shadow: var(--codex-color-primary) 0px 0 20px;
}
.cell-state {
border-radius: var(--codex-border-radius);
padding: 0.5rem 0.75rem;
}
.cell-state--error {
background-color: var(--codex-color-error);
mix-blend-mode: difference;
}

View File

@ -1,10 +0,0 @@
import { ReactNode } from "react";
import "./CellRender.css";
export type CellRender = (
value: string,
row: string[],
index: number
) => ReactNode;
export const DefaultCellRender = (val: string) => val;

View File

@ -1,3 +0,0 @@
import "./CellRender.css";
export const DefaultCellRender = (val: string) => val;

View File

@ -1,10 +0,0 @@
import prettyMilliseconds from "pretty-ms";
export function DurationCellRender(value: string) {
const ms = parseInt(value, 10);
if (isNaN(ms)) {
return "Nan";
}
return prettyMilliseconds(ms, { compact: true });
}

View File

@ -0,0 +1,24 @@
.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-blue), 0.2);
color: rgb(var(--codex-color-blue));
}

View File

@ -0,0 +1,10 @@
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,11 +0,0 @@
type Mapping = { [k: string]: "success" | "warning" | "error" | "default" };
export const StateCellRender = (mapping: Mapping) => (value: string) => {
return (
<p>
<span className={"cell-state cell-state--" + mapping[value]}>
{value}
</span>
</p>
);
};

View File

@ -1,5 +1,5 @@
import "./Table.css"; import "./Table.css";
import { CellRender } from "./CellRender"; import { ReactNode } from "react";
type Props = { type Props = {
/** /**
@ -7,21 +7,12 @@ type Props = {
*/ */
headers: string[]; headers: string[];
/** cells: ReactNode[][];
* The data are represented by a 2 dimensions array.
* Each row contains a dataset whose data structure is a string array.
*/
data: string[][];
/**
* The cell render is an array of function that returns the cell data.
*/
cells: CellRender[];
className?: string; className?: string;
}; };
export function Table({ data, headers, cells, className }: Props) { export function Table({ headers, cells, className }: Props) {
return ( return (
<div className={`table-container ${className}`}> <div className={`table-container ${className}`}>
<table className={"table"}> <table className={"table"}>
@ -35,14 +26,14 @@ export function Table({ data, headers, cells, className }: Props) {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{data.map((row, index) => ( {cells.map((row, index) => (
<tr key={index} className="table-tbodyTr"> <tr key={index} className="table-tbodyTr">
{headers.map((header, idx) => { {headers.map((header, idx) => {
const render = cells[idx]; const cell = row[idx];
return ( return (
<td key={header} className="table-tbodyTd"> <td key={header} className="table-tbodyTd">
{render(row[idx], row, index)} {cell}
</td> </td>
); );
})} })}