DataTableToolbar.tsx85 lines · main
1import { PanelLeftClose, PanelLeftOpen } from 'lucide-react'
2import { ReactNode, useMemo } from 'react'
3import { Button, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
4
5import { formatCompactNumber } from './DataTable.utils'
6import { DataTableFilterControlsDrawer } from './DataTableFilters/DataTableFilterControlsDrawer'
7import { DataTableResetButton } from './DataTableResetButton'
8import { DataTableViewOptions } from './DataTableViewOptions'
9import { Kbd } from './primitives/Kbd'
10import { useDataTable } from './providers/DataTableProvider'
11import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
12import { useShortcut } from '@/state/shortcuts/useShortcut'
13
14interface DataTableToolbarProps {
15 renderActions?: () => ReactNode
16 isFilterBarOpen: boolean
17 setIsFilterBarOpen: React.Dispatch<React.SetStateAction<boolean>>
18}
19
20export function DataTableToolbar({
21 renderActions,
22 isFilterBarOpen,
23 setIsFilterBarOpen,
24}: DataTableToolbarProps) {
25 const { table, isLoading, columnFilters } = useDataTable()
26 const filters = table.getState().columnFilters
27
28 useShortcut(SHORTCUT_IDS.DATA_TABLE_TOGGLE_FILTERS, () => setIsFilterBarOpen((prev) => !prev))
29
30 const rows = useMemo(
31 () => ({
32 total: table.getCoreRowModel().rows.length,
33 filtered: table.getFilteredRowModel().rows.length,
34 }),
35 [isLoading, columnFilters]
36 )
37
38 return (
39 <div className="flex flex-wrap items-center justify-between gap-4">
40 <div className="flex flex-wrap items-center gap-2">
41 <Tooltip>
42 <TooltipTrigger asChild>
43 <Button
44 size="tiny"
45 type="default"
46 icon={isFilterBarOpen ? <PanelLeftClose /> : <PanelLeftOpen />}
47 onClick={() => setIsFilterBarOpen((prev) => !prev)}
48 className="hidden sm:flex"
49 >
50 <span className="hidden md:block">{isFilterBarOpen ? 'Hide' : 'Show'} Controls</span>
51 </Button>
52 </TooltipTrigger>
53 <TooltipContent side="right">
54 <p>
55 Toggle controls with{' '}
56 <Kbd className="ml-1 text-muted-foreground group-hover:text-accent-foreground">
57 <span className="mr-1">⌘</span>
58 <span>B</span>
59 </Kbd>
60 </p>
61 </TooltipContent>
62 </Tooltip>
63 <div className="block sm:hidden">
64 <DataTableFilterControlsDrawer />
65 </div>
66 <div>
67 <p className="hidden text-sm text-muted-foreground sm:block">
68 <span className="font-mono font-medium">{formatCompactNumber(rows.filtered)}</span> of{' '}
69 <span className="font-mono font-medium">{formatCompactNumber(rows.total)}</span> row(s){' '}
70 <span className="sr-only sm:not-sr-only">filtered</span>
71 </p>
72 <p className="block text-sm text-muted-foreground sm:hidden">
73 <span className="font-mono font-medium">{formatCompactNumber(rows.filtered)}</span>{' '}
74 row(s)
75 </p>
76 </div>
77 </div>
78 <div className="ml-auto flex items-center gap-2">
79 {filters.length ? <DataTableResetButton /> : null}
80 {renderActions?.()}
81 <DataTableViewOptions />
82 </div>
83 </div>
84 )
85}