Skip to content

Commit 9736d6a

Browse files
feat: export datatable controls (#553)
* feat: export datatable controls * feat: improve datatable.displaycontrols
1 parent 259a025 commit 9736d6a

File tree

6 files changed

+121
-25
lines changed

6 files changed

+121
-25
lines changed

apps/www/src/app/examples/table/page.tsx

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
'use client';
22
import {
3-
Button,
43
DataTable,
54
DataTableColumnDef,
65
DataTableQuery,
7-
Flex,
8-
IconButton
6+
Flex
97
} from '@raystack/apsara';
10-
import { FilterIcon } from '@raystack/apsara/icons';
118
import { useMemo, useState } from 'react';
129

1310
const data: Payment[] = [
@@ -76,13 +73,16 @@ export const columns: DataTableColumnDef<Payment, unknown>[] = [
7673
}
7774
],
7875
filterType: 'multiselect',
79-
enableColumnFilter: true
76+
enableColumnFilter: true,
77+
enableHiding: true
8078
},
8179
{
8280
accessorKey: 'email',
8381
header: 'Email',
8482
cell: ({ row }) => <div className='lowercase'>{row.getValue('email')}</div>,
85-
enableColumnFilter: true
83+
enableColumnFilter: true,
84+
enableGrouping: true,
85+
enableSorting: true
8686
},
8787
{
8888
accessorKey: 'amount',
@@ -98,7 +98,8 @@ export const columns: DataTableColumnDef<Payment, unknown>[] = [
9898
return <div className='text-right font-medium'>{formatted}</div>;
9999
},
100100
enableColumnFilter: true,
101-
filterType: 'number'
101+
filterType: 'number',
102+
enableSorting: true
102103
}
103104
];
104105

@@ -137,8 +138,10 @@ const Page = () => {
137138
backgroundColor: 'var(--rs-color-background-base-primary)',
138139
padding: '32px'
139140
}}
141+
direction='column'
142+
gap={8}
140143
>
141-
<Flex direction='column' gap={4}>
144+
{/* <Flex direction='column' gap={4}>
142145
<DataTable
143146
data={filteredData}
144147
mode='server'
@@ -171,6 +174,21 @@ const Page = () => {
171174
>{`${item.email} - ${item.amount} - ${item.status}`}</div>
172175
))}
173176
</DataTable>
177+
</Flex> */}
178+
<Flex direction='row' gap={4}>
179+
<DataTable
180+
data={filteredData}
181+
mode='server'
182+
columns={columns}
183+
query={tableQuery}
184+
onColumnVisibilityChange={value =>
185+
console.log('column visibility change>> ', value)
186+
}
187+
onTableQueryChange={setTableQuery}
188+
defaultSort={{ name: 'email', order: 'asc' }}
189+
>
190+
<DataTable.DisplayControls />
191+
</DataTable>
174192
</Flex>
175193
</Flex>
176194
);

apps/www/src/content/docs/components/datatable/index.mdx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ import {
2424

2525
<auto-type-table path="./props.ts" name="DataTableProps" />
2626

27+
### DataTable.DisplayControls Props
28+
29+
<auto-type-table path="./props.ts" name="DisplayControlsProps" />
30+
31+
### DataTable.Filters Props
32+
33+
<auto-type-table path="./props.ts" name="FiltersProps" />
34+
2735
## DataTableQuery Interface
2836

2937
<auto-type-table path="./props.ts" name="DataTableQuery" />
@@ -209,6 +217,21 @@ onTableQueryChange={handleQueryChange}>
209217
</DataTable>
210218
```
211219

220+
### Using DataTable Display Controls
221+
222+
The `DataTable.DisplayControls` component can be used separately to display the display controls for custom views.
223+
224+
```tsx
225+
<DataTable
226+
data={data}
227+
query={query}
228+
columns={columns}
229+
mode="server"
230+
onTableQueryChange={handleQueryChange}
231+
onColumnVisibilityChange={handleColumnVisibilityChange}>
232+
<DataTable.DisplayControls />
233+
</DataTable>
234+
```
212235
### Using DataTable Search
213236

214237
The `DataTable.Search` component provides search functionality that automatically integrates with the table query. By default, it is disabled in zero state (when no data and no filters/search applied).

apps/www/src/content/docs/components/datatable/props.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { ReactNode } from 'react';
2+
13
export interface DataTableProps {
24
/** Column definitions (Required) */
35
columns: DataTableColumnDef[];
@@ -28,6 +30,11 @@ export interface DataTableProps {
2830

2931
/** Infinite scroll callback */
3032
onLoadMore?: () => Promise<void>;
33+
34+
/** Column visibility change callback */
35+
onColumnVisibilityChange?: (
36+
columnVisibility: Record<string, boolean>
37+
) => void;
3138
}
3239

3340
export interface DataTableQuery {
@@ -73,6 +80,22 @@ export interface DataTableColumnDef<TData, TValue> {
7380
defaultHidden?: boolean;
7481
}
7582

83+
export interface DisplayControlsProps {
84+
/** Trigger element */
85+
trigger?: ReactNode;
86+
}
87+
88+
export interface FiltersProps {
89+
/** Trigger element */
90+
trigger?:
91+
| ReactNode
92+
| (({
93+
availableFilters,
94+
appliedFilters
95+
}: {
96+
availableFilters: DataTableColumn<TData, TValue>[];
97+
appliedFilters: Set<string>;
98+
}) => ReactNode);
7699
export interface DataTableContentProps {
77100
/**
78101
* Custom empty state shown when initial data exists but no results match after filters/search.

packages/raystack/components/data-table/components/display-settings.tsx

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { MixerHorizontalIcon } from '@radix-ui/react-icons';
44

5+
import { ReactNode } from 'react';
56
import { Button } from '../../button';
67
import { Flex } from '../../flex';
78
import { Popover } from '../../popover';
@@ -16,7 +17,22 @@ import { DisplayProperties } from './display-properties';
1617
import { Grouping } from './grouping';
1718
import { Ordering } from './ordering';
1819

19-
export function DisplaySettings<TData, TValue>() {
20+
interface DisplaySettingsProps {
21+
trigger?: ReactNode;
22+
}
23+
24+
export function DisplaySettings<TData, TValue>({
25+
trigger = (
26+
<Button
27+
variant='outline'
28+
color='neutral'
29+
size='small'
30+
leadingIcon={<MixerHorizontalIcon />}
31+
>
32+
Display
33+
</Button>
34+
)
35+
}: DisplaySettingsProps) {
2036
const {
2137
table,
2238
updateTableQuery,
@@ -69,16 +85,7 @@ export function DisplaySettings<TData, TValue>() {
6985

7086
return (
7187
<Popover>
72-
<Popover.Trigger asChild>
73-
<Button
74-
variant='outline'
75-
color='neutral'
76-
size='small'
77-
leadingIcon={<MixerHorizontalIcon />}
78-
>
79-
Display
80-
</Button>
81-
</Popover.Trigger>
88+
<Popover.Trigger asChild>{trigger}</Popover.Trigger>
8289
<Popover.Content
8390
className={styles['display-popover-content']}
8491
align='end'

packages/raystack/components/data-table/data-table.tsx

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use client';
22

33
import {
4+
Updater,
45
VisibilityState,
56
getCoreRowModel,
67
getExpandedRowModel,
@@ -10,6 +11,7 @@ import {
1011
} from '@tanstack/react-table';
1112
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
1213
import { Content } from './components/content';
14+
import { DisplaySettings } from './components/display-settings';
1315
import { Filters } from './components/filters';
1416
import { TableSearch } from './components/search';
1517
import { Toolbar } from './components/toolbar';
@@ -43,14 +45,26 @@ function DataTableRoot<TData, TValue>({
4345
children,
4446
onTableQueryChange,
4547
onLoadMore,
46-
onRowClick
48+
onRowClick,
49+
onColumnVisibilityChange
4750
}: React.PropsWithChildren<DataTableProps<TData, TValue>>) {
4851
const defaultTableQuery = getDefaultTableQuery(defaultSort, query);
4952
const initialColumnVisibility = getInitialColumnVisibility(columns);
5053

5154
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>(
5255
initialColumnVisibility
5356
);
57+
const handleColumnVisibilityChange = useCallback(
58+
(value: Updater<VisibilityState>) => {
59+
setColumnVisibility(prev => {
60+
const newValue = typeof value === 'function' ? value(prev) : value;
61+
onColumnVisibilityChange?.(newValue);
62+
return newValue;
63+
});
64+
},
65+
[onColumnVisibilityChange]
66+
);
67+
5468
const [tableQuery, setTableQuery] =
5569
useState<InternalQuery>(defaultTableQuery);
5670

@@ -63,8 +77,12 @@ function DataTableRoot<TData, TValue>({
6377

6478
const onDisplaySettingsReset = useCallback(() => {
6579
setTableQuery(prev => ({ ...prev, ...defaultTableQuery }));
66-
setColumnVisibility(initialColumnVisibility);
67-
}, [defaultTableQuery, initialColumnVisibility]);
80+
handleColumnVisibilityChange(initialColumnVisibility);
81+
}, [
82+
defaultTableQuery,
83+
initialColumnVisibility,
84+
handleColumnVisibilityChange
85+
]);
6886

6987
const group_by = tableQuery.group_by?.[0];
7088

@@ -100,7 +118,7 @@ function DataTableRoot<TData, TValue>({
100118
getFilteredRowModel: mode === 'server' ? undefined : getFilteredRowModel(),
101119
manualSorting: mode === 'server',
102120
manualFiltering: mode === 'server',
103-
onColumnVisibilityChange: setColumnVisibility,
121+
onColumnVisibilityChange: handleColumnVisibilityChange,
104122
globalFilterFn: mode === 'server' ? undefined : 'auto',
105123
initialState: {
106124
columnVisibility: initialColumnVisibility
@@ -193,5 +211,6 @@ export const DataTable = Object.assign(DataTableRoot, {
193211
Content: Content,
194212
Toolbar: Toolbar,
195213
Search: TableSearch,
196-
Filters: Filters
214+
Filters: Filters,
215+
DisplayControls: DisplaySettings
197216
});

packages/raystack/components/data-table/data-table.types.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import type { Column, ColumnDef, Table } from '@tanstack/table-core';
1+
import type {
2+
Column,
3+
ColumnDef,
4+
Table,
5+
VisibilityState
6+
} from '@tanstack/table-core';
27
import type {
38
DataTableFilterOperatorTypes,
49
FilterOperatorTypes,
@@ -103,6 +108,7 @@ export interface DataTableProps<TData, TValue> {
103108
defaultSort: DataTableSort;
104109
onLoadMore?: () => Promise<void>;
105110
onRowClick?: (row: TData) => void;
111+
onColumnVisibilityChange?: (columnVisibility: VisibilityState) => void;
106112
}
107113

108114
export type DataTableContentProps = {

0 commit comments

Comments
 (0)