Skip to content

Commit

Permalink
feat: pin actions column
Browse files Browse the repository at this point in the history
  • Loading branch information
sadmann7 committed Jul 28, 2024
1 parent dd349d4 commit 23681b2
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 42 deletions.
1 change: 1 addition & 0 deletions src/app/_components/tasks-table-columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ export function getColumns(): ColumnDef<Task>[] {
</>
)
},
size: 40,
},
]
}
4 changes: 2 additions & 2 deletions src/app/_components/tasks-table-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function TasksTableProvider({ children }: React.PropsWithChildren) {
setFeatureFlags,
}}
>
{/* <div className="w-full overflow-x-auto">
<div className="w-full overflow-x-auto">
<ToggleGroup
type="multiple"
variant="outline"
Expand Down Expand Up @@ -78,7 +78,7 @@ export function TasksTableProvider({ children }: React.PropsWithChildren) {
</Tooltip>
))}
</ToggleGroup>
</div> */}
</div>
{children}
</TasksTableContext.Provider>
)
Expand Down
10 changes: 7 additions & 3 deletions src/app/_components/tasks-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,15 @@ export function TasksTable({ tasksPromise }: TasksTableProps) {
data,
columns,
pageCount,
// optional props
/* optional props */
filterFields,
enableAdvancedFilter: featureFlags.includes("advancedFilter"),
defaultPerPage: 10,
defaultSort: "createdAt.desc",
state: {
sorting: [{ id: "createdAt", desc: true }],
pagination: { pageIndex: 0, pageSize: 10 },
columnPinning: { right: ["actions"] },
},
/* */
})

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ import {
SelectValue,
} from "@/components/ui/select"
import { Separator } from "@/components/ui/separator"

import { DataTableFacetedFilter } from "../data-table-faceted-filter"
import { DataTableFacetedFilter } from "@/components/data-table/data-table-faceted-filter"

interface DataTableMultiFilterProps<TData> {
table: Table<TData>
Expand Down
16 changes: 14 additions & 2 deletions src/components/data-table/data-table.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from "react"
import { flexRender, type Table as TanstackTable } from "@tanstack/react-table"

import { getCommonPinningStyles } from "@/lib/data-table"
import { cn } from "@/lib/utils"
import {
Table,
Expand Down Expand Up @@ -48,7 +49,13 @@ export function DataTable<TData>({
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
<TableHead
key={header.id}
colSpan={header.colSpan}
style={{
...getCommonPinningStyles({ column: header.column }),
}}
>
{header.isPlaceholder
? null
: flexRender(
Expand All @@ -69,7 +76,12 @@ export function DataTable<TData>({
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
<TableCell
key={cell.id}
style={{
...getCommonPinningStyles({ column: cell.column }),
}}
>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
Expand Down
66 changes: 33 additions & 33 deletions src/hooks/use-data-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
type ColumnFiltersState,
type PaginationState,
type SortingState,
type TableState,
type VisibilityState,
} from "@tanstack/react-table"
import { z } from "zod"
Expand Down Expand Up @@ -42,22 +43,6 @@ interface UseDataTableProps<TData, TValue> {
*/
pageCount: number

/**
* The default number of rows per page.
* @default 10
* @type number | undefined
* @example 20
*/
defaultPerPage?: number

/**
* The default sort order.
* @default undefined
* @type `${Extract<keyof TData, string | number>}.${"asc" | "desc"}` | undefined
* @example "createdAt.desc"
*/
defaultSort?: `${Extract<keyof TData, string | number>}.${"asc" | "desc"}`

/**
* Defines filter fields for the table. Supports both dynamic faceted filters and search filters.
* - Faceted filters are rendered when `options` are provided for a filter field.
Expand Down Expand Up @@ -96,9 +81,21 @@ interface UseDataTableProps<TData, TValue> {
* @type boolean
*/
enableAdvancedFilter?: boolean

/**
* The initial state of the table.
* Can be used to set the initial pagination, sorting, column visibility, row selection, column grouping, column pinning, and column filters.
* @default {}
*/
state?: Omit<Partial<TableState>, "sorting"> & {
sorting?: {
id: Extract<keyof TData, string>
desc: boolean
}[]
}
}

const schema = z.object({
const searchParamsSchema = z.object({
page: z.coerce.number().default(1),
per_page: z.coerce.number().optional(),
sort: z.string().optional(),
Expand All @@ -108,20 +105,18 @@ export function useDataTable<TData, TValue>({
data,
columns,
pageCount,
defaultPerPage = 10,
defaultSort,
filterFields = [],
enableAdvancedFilter = false,
state,
}: UseDataTableProps<TData, TValue>) {
const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()

// Search params
const search = schema.parse(Object.fromEntries(searchParams))
const page = search.page
const perPage = search.per_page ?? defaultPerPage
const sort = search.sort ?? defaultSort
const { page, per_page, sort } = searchParamsSchema.parse(
Object.fromEntries(searchParams)
)
const [column, order] = sort?.split(".") ?? []

// Memoize computation of searchableColumns and filterableColumns
Expand Down Expand Up @@ -188,10 +183,12 @@ export function useDataTable<TData, TValue>({

// Handle server-side pagination
const [{ pageIndex, pageSize }, setPagination] =
React.useState<PaginationState>({
pageIndex: page - 1,
pageSize: perPage,
})
React.useState<PaginationState>(
state?.pagination ?? {
pageIndex: page - 1,
pageSize: per_page ?? 10,
}
)

const pagination = React.useMemo(
() => ({
Expand All @@ -202,12 +199,14 @@ export function useDataTable<TData, TValue>({
)

// Handle server-side sorting
const [sorting, setSorting] = React.useState<SortingState>([
{
id: column ?? "",
desc: order === "desc",
},
])
const [sorting, setSorting] = React.useState<SortingState>(
state?.sorting ?? [
{
id: column ?? "",
desc: order === "desc",
},
]
)

React.useEffect(() => {
router.push(
Expand Down Expand Up @@ -307,6 +306,7 @@ export function useDataTable<TData, TValue>({
columns,
pageCount: pageCount ?? -1,
state: {
...state,
pagination,
sorting,
columnVisibility,
Expand Down
28 changes: 28 additions & 0 deletions src/lib/data-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { type Column } from "@tanstack/react-table"

export function getCommonPinningStyles<TData>({
column,
}: {
column: Column<TData>
}): React.CSSProperties {
const isPinned = column.getIsPinned()
const isLastLeftPinnedColumn =
isPinned === "left" && column.getIsLastColumn("left")
const isFirstRightPinnedColumn =
isPinned === "right" && column.getIsFirstColumn("right")

return {
boxShadow: isLastLeftPinnedColumn
? "-5px 0 5px -5px hsl(var(--border)) inset"
: isFirstRightPinnedColumn
? "5px 0 5px -5px hsl(var(--border)) inset"
: undefined,
left: isPinned === "left" ? `${column.getStart("left")}px` : undefined,
right: isPinned === "right" ? `${column.getAfter("right")}px` : undefined,
opacity: isPinned ? 0.95 : 1,
position: isPinned ? "sticky" : "relative",
background: isPinned ? "hsl(var(--background))" : undefined,
width: column.getSize(),
zIndex: isPinned ? 1 : 0,
}
}

0 comments on commit 23681b2

Please sign in to comment.