data-table-column-header.tsx 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import {
  2. ArrowDownIcon,
  3. ArrowUpIcon,
  4. CaretSortIcon,
  5. EyeNoneIcon,
  6. } from '@radix-ui/react-icons'
  7. import { type Column } from '@tanstack/react-table'
  8. import { cn } from '@/lib/utils'
  9. import { Button } from '@/components/ui/button'
  10. import {
  11. DropdownMenu,
  12. DropdownMenuContent,
  13. DropdownMenuItem,
  14. DropdownMenuSeparator,
  15. DropdownMenuTrigger,
  16. } from '@/components/ui/dropdown-menu'
  17. interface DataTableColumnHeaderProps<TData, TValue>
  18. extends React.HTMLAttributes<HTMLDivElement> {
  19. column: Column<TData, TValue>
  20. title: string
  21. }
  22. export function DataTableColumnHeader<TData, TValue>({
  23. column,
  24. title,
  25. className,
  26. }: DataTableColumnHeaderProps<TData, TValue>) {
  27. if (!column.getCanSort()) {
  28. return <div className={cn(className)}>{title}</div>
  29. }
  30. return (
  31. <div className={cn('flex items-center space-x-2', className)}>
  32. <DropdownMenu>
  33. <DropdownMenuTrigger asChild>
  34. <Button
  35. variant='ghost'
  36. size='sm'
  37. className='data-[state=open]:bg-accent -ms-3 h-8'
  38. >
  39. <span>{title}</span>
  40. {column.getIsSorted() === 'desc' ? (
  41. <ArrowDownIcon className='ms-2 h-4 w-4' />
  42. ) : column.getIsSorted() === 'asc' ? (
  43. <ArrowUpIcon className='ms-2 h-4 w-4' />
  44. ) : (
  45. <CaretSortIcon className='ms-2 h-4 w-4' />
  46. )}
  47. </Button>
  48. </DropdownMenuTrigger>
  49. <DropdownMenuContent align='start'>
  50. <DropdownMenuItem onClick={() => column.toggleSorting(false)}>
  51. <ArrowUpIcon className='text-muted-foreground/70 me-2 h-3.5 w-3.5' />
  52. Asc
  53. </DropdownMenuItem>
  54. <DropdownMenuItem onClick={() => column.toggleSorting(true)}>
  55. <ArrowDownIcon className='text-muted-foreground/70 me-2 h-3.5 w-3.5' />
  56. Desc
  57. </DropdownMenuItem>
  58. {column.getCanHide() && (
  59. <>
  60. <DropdownMenuSeparator />
  61. <DropdownMenuItem onClick={() => column.toggleVisibility(false)}>
  62. <EyeNoneIcon className='text-muted-foreground/70 me-2 h-3.5 w-3.5' />
  63. Hide
  64. </DropdownMenuItem>
  65. </>
  66. )}
  67. </DropdownMenuContent>
  68. </DropdownMenu>
  69. </div>
  70. )
  71. }