diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-03-26 00:37:41 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-03-26 00:37:41 +0000 |
| commit | e0dfb55c5457aec489fc084c4567e791b4c65eb1 (patch) | |
| tree | 68543a65d88f5afb3a0202925804103daa91bc6f /components/data-table/data-table-column-header.tsx | |
3/25 까지의 대표님 작업사항
Diffstat (limited to 'components/data-table/data-table-column-header.tsx')
| -rw-r--r-- | components/data-table/data-table-column-header.tsx | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/components/data-table/data-table-column-header.tsx b/components/data-table/data-table-column-header.tsx new file mode 100644 index 00000000..aa0c754b --- /dev/null +++ b/components/data-table/data-table-column-header.tsx @@ -0,0 +1,109 @@ +"use client" + +import { SelectIcon } from "@radix-ui/react-select" +import { type Column } from "@tanstack/react-table" +import { ArrowDown, ArrowUp, ChevronsUpDown, EyeOff } from "lucide-react" + +import { cn } from "@/lib/utils" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, +} from "@/components/ui/select" + +interface DataTableColumnHeaderProps<TData, TValue> + extends React.HTMLAttributes<HTMLDivElement> { + column: Column<TData, TValue> + title: string +} + +export function DataTableColumnHeader<TData, TValue>({ + column, + title, + className, +}: DataTableColumnHeaderProps<TData, TValue>) { + if (!column.getCanSort() && !column.getCanHide()) { + return <div className={cn(className)}>{title}</div> + } + + const ascValue = `${column.id}-asc` + const descValue = `${column.id}-desc` + const hideValue = `${column.id}-hide` + + return ( + <div className={cn("flex items-center gap-2", className)}> + <Select + value={ + column.getIsSorted() === "desc" + ? descValue + : column.getIsSorted() === "asc" + ? ascValue + : undefined + } + onValueChange={(value) => { + if (value === ascValue) column.toggleSorting(false) + else if (value === descValue) column.toggleSorting(true) + else if (value === hideValue) column.toggleVisibility(false) + }} + > + <SelectTrigger + aria-label={ + column.getIsSorted() === "desc" + ? "Sorted descending. Click to sort ascending." + : column.getIsSorted() === "asc" + ? "Sorted ascending. Click to sort descending." + : "Not sorted. Click to sort ascending." + } + className="-ml-3 h-8 w-fit border-none text-xs hover:bg-accent hover:text-accent-foreground data-[state=open]:bg-accent [&>svg:last-child]:hidden" + > + {title} + <SelectIcon asChild> + {column.getCanSort() && column.getIsSorted() === "desc" ? ( + <ArrowDown className="ml-2.5 size-4" aria-hidden="true" /> + ) : column.getIsSorted() === "asc" ? ( + <ArrowUp className="ml-2.5 size-4" aria-hidden="true" /> + ) : ( + <ChevronsUpDown className="ml-2.5 size-4" aria-hidden="true" /> + )} + </SelectIcon> + </SelectTrigger> + <SelectContent align="start"> + {column.getCanSort() && ( + <> + <SelectItem value={ascValue}> + <span className="flex items-center"> + <ArrowUp + className="mr-2 size-3.5 text-muted-foreground/70" + aria-hidden="true" + /> + Asc + </span> + </SelectItem> + <SelectItem value={descValue}> + <span className="flex items-center"> + <ArrowDown + className="mr-2 size-3.5 text-muted-foreground/70" + aria-hidden="true" + /> + Desc + </span> + </SelectItem> + </> + )} + {column.getCanHide() && ( + <SelectItem value={hideValue}> + <span className="flex items-center"> + <EyeOff + className="mr-2 size-3.5 text-muted-foreground/70" + aria-hidden="true" + /> + Hide + </span> + </SelectItem> + )} + </SelectContent> + </Select> + </div> + ) +} |
