Skip to content

Commit dc3eb9e

Browse files
authored
feat(ui): added emptyState prop to table for handling no data and keeping formatting (#74)
1 parent 26a2b9d commit dc3eb9e

5 files changed

Lines changed: 97 additions & 17 deletions

File tree

packages/demo/src/components/demo/table.tsx

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1-
import { Button, SortButton, Table, Badge } from "@eqtylab/equality";
21
import type { Elevation } from "@eqtylab/equality";
2+
import {
3+
Badge,
4+
Button,
5+
EmptyTableState,
6+
SortButton,
7+
Table,
8+
} from "@eqtylab/equality";
39

410
interface TableDemoProps {
511
variant?:
612
| "unclickable"
713
| "clickable"
814
| "with-actions"
915
| "with-border"
10-
| "with-sorter";
16+
| "with-sorter"
17+
| "empty-state"
18+
| "empty-state-custom";
1119
elevation: Elevation;
1220
}
1321

@@ -187,6 +195,38 @@ export const TableDemo = ({
187195
);
188196
}
189197

198+
if (variant === "empty-state") {
199+
return (
200+
<Table
201+
columns={columns}
202+
rows={[]}
203+
border
204+
elevation={elevation}
205+
emptyState="No data available"
206+
/>
207+
);
208+
}
209+
210+
if (variant === "empty-state-custom") {
211+
return (
212+
<Table
213+
columns={columns}
214+
rows={[]}
215+
border
216+
elevation={elevation}
217+
emptyState={
218+
<EmptyTableState
219+
icon="SearchX"
220+
title="No Members Found"
221+
description="Try refining your search terms or clearing filters."
222+
showClearButton
223+
onClear={() => {}}
224+
/>
225+
}
226+
/>
227+
);
228+
}
229+
190230
if (variant === "with-sorter") {
191231
const columns_with_sorter = [
192232
{

packages/demo/src/content/components/table.mdx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ import { ELEVATION } from "@eqtylab/equality";
2525

2626
<TableDemo client:only="react" variant="with-sorter" />
2727

28+
### Empty State
29+
30+
When `rows` is empty and `emptyState` is provided, the table keeps column headers visible and renders the empty state content spanning all columns.
31+
32+
<TableDemo client:only="react" variant="empty-state" />
33+
34+
### Empty State with Custom Component
35+
36+
The `emptyState` prop accepts any `ReactNode`, so you can pass a custom component like `EmptyTableState`.
37+
38+
<TableDemo client:only="react" variant="empty-state-custom" />
39+
2840
## Style Options
2941

3042
### With Border
@@ -94,3 +106,13 @@ import { ELEVATION } from "@eqtylab/equality";
94106
variant="with-border"
95107
elevation={ELEVATION.FLOATING}
96108
/>
109+
110+
## Props
111+
112+
| Name | Description | Type | Default | Required |
113+
| ------------ | ------------------------------------------------------------ | ------------------------------------------------- | ------- | -------- |
114+
| `columns` | Column definitions with key, content, and optional className | `TableColumn[]` | ||
115+
| `rows` | Row data with key, cells, and optional onClick/className | `TableRowData[]` | ||
116+
| `border` | Adds a border and rounded corners around the table | `boolean` | `false` ||
117+
| `elevation` | Controls the shadow and border elevation level | `sunken`, `base`, `raised`, `overlay`, `floating` | `base` ||
118+
| `emptyState` | Content rendered when rows is empty, spanning all columns | `ReactNode` | ||

packages/ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@eqtylab/equality",
33
"description": "EQTYLab's component and token-based design system",
44
"homepage": "https://equality.eqtylab.io/",
5-
"version": "1.2.0",
5+
"version": "1.2.1",
66
"license": "Apache-2.0",
77
"keywords": [
88
"component library",

packages/ui/src/components/table/table.module.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
@apply overflow-hidden rounded-md;
1818
}
1919

20+
.table-empty-state {
21+
@apply text-text-secondary py-8 text-center;
22+
}
23+
2024
/* ELEVATION */
2125

2226
.table--sunken {

packages/ui/src/components/table/table.tsx

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ interface TableProps extends VariantProps<typeof tableElevationVariants> {
3838
rows: TableRowData[];
3939
className?: string;
4040
border?: boolean;
41+
emptyState?: React.ReactNode;
4142
}
4243

4344
const tableElevationVariants = generateElevationVariants(styles, 'table', ELEVATION.BASE);
@@ -48,7 +49,10 @@ const Table = ({
4849
className,
4950
border = false,
5051
elevation = ELEVATION.BASE,
52+
emptyState,
5153
}: TableProps) => {
54+
const isEmpty = rows.length === 0;
55+
5256
return (
5357
<div
5458
className={cn(
@@ -68,21 +72,31 @@ const Table = ({
6872
))}
6973
</TableRow>
7074
</TableHeader>
71-
<TableBody>
72-
{rows.map((row) => (
73-
<TableRow
74-
key={row.key}
75-
className={cn(row.className, row.onClick && styles['table-row-clickable'])}
76-
onClick={row.onClick}
77-
>
78-
{row.cells.map((cell) => (
79-
<TableCell key={cell.key} className={cell.className}>
80-
{cell.content}
81-
</TableCell>
82-
))}
75+
{isEmpty && emptyState ? (
76+
<TableBody>
77+
<TableRow>
78+
<TableCell colSpan={columns.length} className={styles['table-empty-state']}>
79+
{emptyState}
80+
</TableCell>
8381
</TableRow>
84-
))}
85-
</TableBody>
82+
</TableBody>
83+
) : (
84+
<TableBody>
85+
{rows.map((row) => (
86+
<TableRow
87+
key={row.key}
88+
className={cn(row.className, row.onClick && styles['table-row-clickable'])}
89+
onClick={row.onClick}
90+
>
91+
{row.cells.map((cell) => (
92+
<TableCell key={cell.key} className={cell.className}>
93+
{cell.content}
94+
</TableCell>
95+
))}
96+
</TableRow>
97+
))}
98+
</TableBody>
99+
)}
86100
</TableContainer>
87101
</div>
88102
);

0 commit comments

Comments
 (0)