✨(react) add DataList
Implement DataList that is a wrapper of DataGrid without header, sorting nor pagination.
This commit is contained in:
5
.changeset/red-pots-worry.md
Normal file
5
.changeset/red-pots-worry.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@openfun/cunningham-react": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add DataList component
|
||||||
36
packages/react/src/components/DataGrid/DataList.spec.tsx
Normal file
36
packages/react/src/components/DataGrid/DataList.spec.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { render, screen } from "@testing-library/react";
|
||||||
|
import React from "react";
|
||||||
|
import { faker } from "@faker-js/faker";
|
||||||
|
import { getAllByRole, queryAllByRole } from "@testing-library/dom";
|
||||||
|
import { expect } from "vitest";
|
||||||
|
import { CunninghamProvider } from ":/components/Provider";
|
||||||
|
import { DataList } from ":/components/DataGrid/DataList";
|
||||||
|
|
||||||
|
describe("<DataList/>", () => {
|
||||||
|
it("should render a DataList", async () => {
|
||||||
|
const rows = Array.from(Array(3)).map((_value, index) => ({
|
||||||
|
id: `list key for element ${index}`,
|
||||||
|
firstName: faker.name.firstName(),
|
||||||
|
lastName: faker.name.lastName(),
|
||||||
|
}));
|
||||||
|
render(
|
||||||
|
<CunninghamProvider>
|
||||||
|
<DataList
|
||||||
|
columns={[{ field: "firstName" }, { field: "lastName" }]}
|
||||||
|
rows={rows}
|
||||||
|
/>
|
||||||
|
</CunninghamProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
const table = screen.getByRole("table");
|
||||||
|
expect(queryAllByRole(table, "columnheader")).toEqual([]);
|
||||||
|
|
||||||
|
rows.forEach((row) => {
|
||||||
|
const element = screen.getByTestId(row.id);
|
||||||
|
const tds = getAllByRole(element, "cell");
|
||||||
|
expect(tds.length).toBe(2);
|
||||||
|
expect(tds[0].textContent).toEqual(row.firstName);
|
||||||
|
expect(tds[1].textContent).toEqual(row.lastName);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
6
packages/react/src/components/DataGrid/DataList.tsx
Normal file
6
packages/react/src/components/DataGrid/DataList.tsx
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { BaseProps, DataGrid } from ":/components/DataGrid/index";
|
||||||
|
|
||||||
|
export const DataList = ({ rows, ...props }: BaseProps) => {
|
||||||
|
return <DataGrid {...props} displayHeader={false} rows={rows} />;
|
||||||
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Canvas, Meta, Story, Source, ArgsTable } from '@storybook/addon-docs';
|
import { Canvas, Meta, Story, Source, ArgsTable } from '@storybook/addon-docs';
|
||||||
import { DataGrid } from './index';
|
import { DataGrid } from './index';
|
||||||
import { SimpleDataGrid } from './SimpleDataGrid';
|
import { SimpleDataGrid } from './SimpleDataGrid';
|
||||||
|
import { DataList } from './DataList';
|
||||||
|
|
||||||
<Meta title="Components/DataGrid/Doc" component={DataGrid}/>
|
<Meta title="Components/DataGrid/Doc" component={DataGrid}/>
|
||||||
|
|
||||||
@@ -26,6 +27,27 @@ The `rows` props is an array of objects that describe the rows of the table. Eac
|
|||||||
|
|
||||||
We will explore the possibilities that those props provide through the following examples.
|
We will explore the possibilities that those props provide through the following examples.
|
||||||
|
|
||||||
|
## DataList
|
||||||
|
|
||||||
|
<Source
|
||||||
|
language='ts'
|
||||||
|
dark
|
||||||
|
format={false}
|
||||||
|
code={`import { DataList } from "@openfun/cunningham-react";`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
This component is a wrapper around the more complicated DataGrid component. It is made to be used for simple lists of elements that don't need pagination nor sorting. Also, it doesn't display any header.
|
||||||
|
|
||||||
|
Here a quick usage example
|
||||||
|
|
||||||
|
<Canvas withSource="open">
|
||||||
|
<Story id="components-datagrid--data-list-only"/>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
<ArgsTable of={DataList} />
|
||||||
|
|
||||||
## SimpleDataGrid
|
## SimpleDataGrid
|
||||||
|
|
||||||
<Source
|
<Source
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { usePagination } from ":/components/Pagination";
|
|||||||
import { CunninghamProvider } from ":/components/Provider";
|
import { CunninghamProvider } from ":/components/Provider";
|
||||||
import { Button } from ":/components/Button";
|
import { Button } from ":/components/Button";
|
||||||
import { SimpleDataGrid } from ":/components/DataGrid/SimpleDataGrid";
|
import { SimpleDataGrid } from ":/components/DataGrid/SimpleDataGrid";
|
||||||
|
import { DataList } from ":/components/DataGrid/DataList";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "Components/DataGrid",
|
title: "Components/DataGrid",
|
||||||
@@ -249,3 +250,27 @@ export const FullServerSide = () => {
|
|||||||
</CunninghamProvider>
|
</CunninghamProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DataListOnly = () => {
|
||||||
|
const database = useMemo(
|
||||||
|
() =>
|
||||||
|
Array.from(Array(5)).map((_value, index) => ({
|
||||||
|
id: `list key for element ${index}`,
|
||||||
|
title: faker.random.word(),
|
||||||
|
date: faker.date.past(1).toISOString(),
|
||||||
|
action: (
|
||||||
|
<Button size="small" color="secondary">
|
||||||
|
Do it
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
})),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
const columns = [{ field: "title" }, { field: "date" }, { field: "action" }];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CunninghamProvider>
|
||||||
|
<DataList rows={database} columns={columns} />
|
||||||
|
</CunninghamProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// import { Button } from "components/Button";
|
|
||||||
import React, { useMemo } from "react";
|
import React, { useMemo } from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import {
|
import {
|
||||||
@@ -49,6 +48,7 @@ interface Props<T extends Row = Row> extends BaseProps<T> {
|
|||||||
onSortModelChange?: (newSortModel: SortModel) => void;
|
onSortModelChange?: (newSortModel: SortModel) => void;
|
||||||
/** Options for the underlying tanstack table. */
|
/** Options for the underlying tanstack table. */
|
||||||
tableOptions?: TableOptions<Row>;
|
tableOptions?: TableOptions<Row>;
|
||||||
|
displayHeader?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DataGrid = ({
|
export const DataGrid = ({
|
||||||
@@ -62,6 +62,7 @@ export const DataGrid = ({
|
|||||||
onRowSelectionChange,
|
onRowSelectionChange,
|
||||||
rowSelection,
|
rowSelection,
|
||||||
tableOptions,
|
tableOptions,
|
||||||
|
displayHeader = true,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const { t } = useCunningham();
|
const { t } = useCunningham();
|
||||||
const headlessColumns = useHeadlessColumns({ columns, enableRowSelection });
|
const headlessColumns = useHeadlessColumns({ columns, enableRowSelection });
|
||||||
@@ -147,50 +148,51 @@ export const DataGrid = ({
|
|||||||
<>
|
<>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
{displayHeader &&
|
||||||
<tr key={headerGroup.id}>
|
table.getHeaderGroups().map((headerGroup) => (
|
||||||
{headerGroup.headers.map((header) => {
|
<tr key={headerGroup.id}>
|
||||||
return (
|
{headerGroup.headers.map((header) => {
|
||||||
<th key={header.id} colSpan={header.colSpan}>
|
return (
|
||||||
{header.isPlaceholder ? null : (
|
<th key={header.id} colSpan={header.colSpan}>
|
||||||
<div
|
{header.isPlaceholder ? null : (
|
||||||
className={classNames("c__datagrid__header", {
|
<div
|
||||||
"c__datagrid__header--sortable":
|
className={classNames("c__datagrid__header", {
|
||||||
header.column.getCanSort(),
|
"c__datagrid__header--sortable":
|
||||||
})}
|
header.column.getCanSort(),
|
||||||
{...(header.column.getCanSort()
|
})}
|
||||||
? {
|
{...(header.column.getCanSort()
|
||||||
role: "button",
|
? {
|
||||||
tabIndex: 0,
|
role: "button",
|
||||||
onClick:
|
tabIndex: 0,
|
||||||
header.column.getToggleSortingHandler(),
|
onClick:
|
||||||
}
|
header.column.getToggleSortingHandler(),
|
||||||
: {})}
|
}
|
||||||
>
|
: {})}
|
||||||
{flexRender(
|
>
|
||||||
header.column.columnDef.header,
|
{flexRender(
|
||||||
header.getContext()
|
header.column.columnDef.header,
|
||||||
)}
|
header.getContext()
|
||||||
{header.column.getIsSorted() === "asc" && (
|
)}
|
||||||
<span className="material-icons">
|
{header.column.getIsSorted() === "asc" && (
|
||||||
arrow_drop_up
|
<span className="material-icons">
|
||||||
</span>
|
arrow_drop_up
|
||||||
)}
|
</span>
|
||||||
{header.column.getIsSorted() === "desc" && (
|
)}
|
||||||
<span className="material-icons">
|
{header.column.getIsSorted() === "desc" && (
|
||||||
arrow_drop_down
|
<span className="material-icons">
|
||||||
</span>
|
arrow_drop_down
|
||||||
)}
|
</span>
|
||||||
{!header.column.getIsSorted() && (
|
)}
|
||||||
<span className="c__datagrid__header__icon-placeholder" />
|
{!header.column.getIsSorted() && (
|
||||||
)}
|
<span className="c__datagrid__header__icon-placeholder" />
|
||||||
</div>
|
)}
|
||||||
)}
|
</div>
|
||||||
</th>
|
)}
|
||||||
);
|
</th>
|
||||||
})}
|
);
|
||||||
</tr>
|
})}
|
||||||
))}
|
</tr>
|
||||||
|
))}
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{table.getRowModel().rows.map((row) => (
|
{table.getRowModel().rows.map((row) => (
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import "./index.scss";
|
|||||||
export * from "./components/Button";
|
export * from "./components/Button";
|
||||||
export * from "./components/DataGrid";
|
export * from "./components/DataGrid";
|
||||||
export * from "./components/DataGrid/SimpleDataGrid";
|
export * from "./components/DataGrid/SimpleDataGrid";
|
||||||
|
export * from "./components/DataGrid/DataList";
|
||||||
export * from "./components/Forms/Field";
|
export * from "./components/Forms/Field";
|
||||||
export * from "./components/Forms/Input";
|
export * from "./components/Forms/Input";
|
||||||
export * from "./components/Loader";
|
export * from "./components/Loader";
|
||||||
|
|||||||
Reference in New Issue
Block a user