From 562053827abaa28cedcaaf3cc8218eed74a59e3f Mon Sep 17 00:00:00 2001 From: pondc Date: Tue, 11 Nov 2025 15:04:56 +0700 Subject: [PATCH 1/2] feat: add style to pin column --- .../components/primitives/tanstack-table.tsx | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/packages/react/src/react/components/primitives/tanstack-table.tsx b/packages/react/src/react/components/primitives/tanstack-table.tsx index 2df3760e..7ddc8649 100644 --- a/packages/react/src/react/components/primitives/tanstack-table.tsx +++ b/packages/react/src/react/components/primitives/tanstack-table.tsx @@ -1,10 +1,11 @@ 'use client' -import React, { useRef } from 'react' +import React, { type CSSProperties, useRef } from 'react' import { CircleNotchIcon, WarningCircleIcon, WarningIcon } from '@phosphor-icons/react' import { CaretDownIcon, CaretUpDownIcon, CaretUpIcon } from '@phosphor-icons/react/dist/ssr' import { + type Column, flexRender, type Row, type SortDirection, @@ -41,6 +42,28 @@ export interface TanstackTableProps { } } +const getCommonPinningClassesAndStyle = (column: Column) => { + const isPinned = column.getIsPinned() + const isLastLeftPinnedColumn = isPinned === 'left' && column.getIsLastColumn('left') + const isFirstRightPinnedColumn = isPinned === 'right' && column.getIsFirstColumn('right') + + const className = clsx( + isPinned ? 'sticky z-[1]' : 'relative', + isLastLeftPinnedColumn && 'shadow-[inset_-4px_0_4px_-4px_gray]', + isFirstRightPinnedColumn && 'shadow-[inset_4px_0_4px_-4px_gray]' + ) + + const style: CSSProperties = { + left: isPinned === 'left' ? `${column.getStart('left')}px` : undefined, + right: isPinned === 'right' ? `${column.getAfter('right')}px` : undefined, + width: column.getSize(), + minWidth: column.getSize(), + maxWidth: column.getSize(), + } + + return { className, style } +} + export const getSortIcon = (isSorted: false | SortDirection) => { switch (isSorted) { case false: @@ -92,6 +115,8 @@ export function TanstackTable({ const canSort = configuration?.sortBy?.some( ([columnPath]) => columnPath === normalizeColumnId(header.column.id) ) + const { className: pinnedHeaderClassName, style: pinnedHeaderStyle } = + getCommonPinningClassesAndStyle(header.column) return ( ({ 'focus-visible:ring-focus ring-inset', header.colSpan > 1 && 'border-bluegray-300 border-b', classNames?.tableHead, - header.column.columnDef.meta?.thClassName + header.column.columnDef.meta?.thClassName, + pinnedHeaderClassName )} + style={pinnedHeaderStyle} onClick={ canSort && children ? header.column.getToggleSortingHandler() : undefined } @@ -138,10 +165,13 @@ export function TanstackTable({ className={clsx('border-b border-border last:border-b-0', classNames?.tableBodyRow)} > {row.getVisibleCells().map((cell) => { + const { className: pinnedCellClassName, style: pinnedCellStyle } = + getCommonPinningClassesAndStyle(cell.column) return ( onRowClick?.(row, e)} > {flexRender(cell.column.columnDef.cell, cell.getContext())} From 873044a1efbe2f0c3f093a1304887a147e8fef67 Mon Sep 17 00:00:00 2001 From: pondc Date: Wed, 12 Nov 2025 15:28:23 +0700 Subject: [PATCH 2/2] fix: as per cr and changeset --- .changeset/deep-paths-rest.md | 5 ++++ .../components/primitives/tanstack-table.tsx | 26 ++++++++++--------- packages/react/src/types/tanstack.d.ts | 1 + 3 files changed, 20 insertions(+), 12 deletions(-) create mode 100644 .changeset/deep-paths-rest.md diff --git a/.changeset/deep-paths-rest.md b/.changeset/deep-paths-rest.md new file mode 100644 index 00000000..fb5f4fb5 --- /dev/null +++ b/.changeset/deep-paths-rest.md @@ -0,0 +1,5 @@ +--- +'@genseki/react': patch +--- + +Add sticky column pinning style diff --git a/packages/react/src/react/components/primitives/tanstack-table.tsx b/packages/react/src/react/components/primitives/tanstack-table.tsx index 7ddc8649..a7ca1e7f 100644 --- a/packages/react/src/react/components/primitives/tanstack-table.tsx +++ b/packages/react/src/react/components/primitives/tanstack-table.tsx @@ -11,10 +11,11 @@ import { type SortDirection, type Table as TanstackTableCore, } from '@tanstack/react-table' -import clsx from 'clsx' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from './table' +import { cn } from '../../utils/cn' + type RowClickHandler = (row: Row, e: React.MouseEvent) => void export interface TanstackTableProps { @@ -47,7 +48,7 @@ const getCommonPinningClassesAndStyle = (column: Column) => { const isLastLeftPinnedColumn = isPinned === 'left' && column.getIsLastColumn('left') const isFirstRightPinnedColumn = isPinned === 'right' && column.getIsFirstColumn('right') - const className = clsx( + const className = cn( isPinned ? 'sticky z-[1]' : 'relative', isLastLeftPinnedColumn && 'shadow-[inset_-4px_0_4px_-4px_gray]', isFirstRightPinnedColumn && 'shadow-[inset_4px_0_4px_-4px_gray]' @@ -56,9 +57,6 @@ const getCommonPinningClassesAndStyle = (column: Column) => { const style: CSSProperties = { left: isPinned === 'left' ? `${column.getStart('left')}px` : undefined, right: isPinned === 'right' ? `${column.getAfter('right')}px` : undefined, - width: column.getSize(), - minWidth: column.getSize(), - maxWidth: column.getSize(), } return { className, style } @@ -120,12 +118,12 @@ export function TanstackTable({ return ( 1 && 'border-bluegray-300 border-b', classNames?.tableHead, - header.column.columnDef.meta?.thClassName, - pinnedHeaderClassName + pinnedHeaderClassName, + header.column.columnDef.meta?.thClassName )} style={pinnedHeaderStyle} onClick={ @@ -136,7 +134,7 @@ export function TanstackTable({ tabIndex={canSort ? 0 : -1} > 1 && 'justify-center' )} @@ -150,7 +148,7 @@ export function TanstackTable({ ))} - + {isLoading ? ( ) : isError ? ( @@ -162,7 +160,7 @@ export function TanstackTable({ {row.getVisibleCells().map((cell) => { const { className: pinnedCellClassName, style: pinnedCellStyle } = @@ -170,7 +168,11 @@ export function TanstackTable({ return ( onRowClick?.(row, e)} > diff --git a/packages/react/src/types/tanstack.d.ts b/packages/react/src/types/tanstack.d.ts index c0553d76..29a5f63d 100644 --- a/packages/react/src/types/tanstack.d.ts +++ b/packages/react/src/types/tanstack.d.ts @@ -4,5 +4,6 @@ import '@tanstack/react-table' declare module '@tanstack/react-table' { interface ColumnMeta { thClassName?: string + tdClassName?: string } }