Helper functions for column and row pinning.
The getPinningStyles utility calculates the necessary CSS styles for pinned columns. It handles positioning, offsets, and z-index to ensure pinned columns display correctly.
import { getPinningStyles } from '@workspace/active-grid';
const { style, isPinned, isLastLeftPinned, isFirstRightPinned } =
getPinningStyles(column);Calculate pinning styles for a column.
function getPinningStyles<TData>(
column: Column<TData>
): {
style: React.CSSProperties;
isPinned: boolean;
isLastLeftPinned: boolean;
isFirstRightPinned: boolean;
}{
style: {
position?: 'sticky';
left?: number;
right?: number;
zIndex?: number;
};
isPinned: boolean;
isLastLeftPinned: boolean;
isFirstRightPinned: boolean;
}import { Column } from '@tanstack/react-table';
import { getPinningStyles } from '@workspace/active-grid';
function CustomHeader<TData>({ column }: { column: Column<TData> }) {
const { style, isPinned } = getPinningStyles(column);
return (
<div style={style} className={isPinned ? 'pinned-header' : ''}>
{column.columnDef.header}
</div>
);
}import { Cell } from '@tanstack/react-table';
import { getPinningStyles } from '@workspace/active-grid';
function CustomCell<TData>({ cell }: { cell: Cell<TData, unknown> }) {
const { style, isPinned } = getPinningStyles(cell.column);
return (
<div style={style} className={isPinned ? 'pinned-cell' : ''}>
{cell.getValue()}
</div>
);
}Applied when column is pinned:
const { style } = getPinningStyles(column);
// style.position = 'sticky'Offset from left for left-pinned columns:
const { style } = getPinningStyles(column);
// For second left-pinned column:
// style.left = widthOfFirstColumnOffset from right for right-pinned columns:
const { style } = getPinningStyles(column);
// For first right-pinned column:
// style.right = 0Z-index for pinned columns:
const { style } = getPinningStyles(column);
// style.zIndex = 1Whether the column is pinned (left or right):
const { isPinned } = getPinningStyles(column);
if (isPinned) {
// Column is pinned
}Whether this is the last column pinned to the left:
const { isLastLeftPinned } = getPinningStyles(column);
if (isLastLeftPinned) {
// Add border to separate from unpinned columns
}Whether this is the first column pinned to the right:
const { isFirstRightPinned } = getPinningStyles(column);
if (isFirstRightPinned) {
// Add border to separate from unpinned columns
}import { Column } from '@tanstack/react-table';
import { getPinningStyles } from '@workspace/active-grid';
import { cn } from '@/lib/utils';
type CustomHeaderProps<TData> = {
column: Column<TData>;
children: React.ReactNode;
};
function CustomHeader<TData>({ column, children }: CustomHeaderProps<TData>) {
const {
style,
isPinned,
isLastLeftPinned,
isFirstRightPinned,
} = getPinningStyles(column);
return (
<div
style={style}
className={cn(
'grid-header-cell',
isPinned && 'bg-background',
isLastLeftPinned && 'border-r-2 border-primary',
isFirstRightPinned && 'border-l-2 border-primary'
)}
>
{children}
</div>
);
}import { Cell } from '@tanstack/react-table';
import { getPinningStyles } from '@workspace/active-grid';
type CustomCellProps<TData, TValue> = {
cell: Cell<TData, TValue>;
children: React.ReactNode;
};
function CustomCell<TData, TValue>({
cell,
children,
}: CustomCellProps<TData, TValue>) {
const {
style,
isPinned,
isLastLeftPinned,
isFirstRightPinned,
} = getPinningStyles(cell.column);
return (
<div
style={style}
className={cn(
'grid-cell',
isPinned && [
'bg-background',
'shadow-sm',
],
isLastLeftPinned && 'border-r',
isFirstRightPinned && 'border-l'
)}
>
{children}
</div>
);
}The utility is lightweight and calculates styles on-demand:
The ActiveGrid uses getPinningStyles internally for all pinned columns. You typically only need this utility when creating custom header or cell components.
The utility returns inline styles, but you can combine with CSS classes:
Check pinning styles in DevTools:
const { style, isPinned, isLastLeftPinned } = getPinningStyles(column);
const customStyle = {
...style,
...(isPinned && {
backgroundColor: 'white',
boxShadow: '2px 0 4px rgba(0,0,0,0.1)',
}),
...(isLastLeftPinned && {
borderRight: '2px solid #e5e7eb',
}),
};const { style, isPinned } = getPinningStyles(column);
const customStyle = {
...style,
zIndex: isPinned ? 10 : 1, // Higher z-index for pinned
};function CustomCell({ cell }) {
const { style, isPinned } = getPinningStyles(cell.column);
const [isHovered, setIsHovered] = useState(false);
return (
<div
style={{
...style,
backgroundColor: isPinned && isHovered ? '#f3f4f6' : undefined,
}}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
{cell.getValue()}
</div>
);
}const { style, isLastLeftPinned } = getPinningStyles(column);
const cellStyle = {
...style,
...(isLastLeftPinned && {
boxShadow: '2px 0 4px rgba(0, 0, 0, 0.1)',
}),
};const { style, isFirstRightPinned } = getPinningStyles(column);
const cellStyle = {
...style,
...(isFirstRightPinned && {
boxShadow: '-2px 0 4px rgba(0, 0, 0, 0.1)',
}),
};const { style, isLastLeftPinned, isFirstRightPinned } = getPinningStyles(column);
return (
<div
style={style}
className={cn(
isLastLeftPinned && 'border-r-2 border-blue-500',
isFirstRightPinned && 'border-l-2 border-blue-500'
)}
>
{children}
</div>
);// ✓ Good: Calculate once per render
const pinningStyles = getPinningStyles(column);
// ✗ Bad: Multiple calculations
const isPinned = getPinningStyles(column).isPinned;
const style = getPinningStyles(column).style;import { Column } from '@tanstack/react-table';
import { getPinningStyles } from '@workspace/active-grid';
type User = {
id: string;
name: string;
};
function MyComponent({ column }: { column: Column<User> }) {
const {
style, // React.CSSProperties
isPinned, // boolean
isLastLeftPinned, // boolean
isFirstRightPinned, // boolean
} = getPinningStyles(column);
return <div style={style}>{/* content */}</div>;
}const { style, isPinned } = getPinningStyles(column);
return (
<div
style={style}
className={cn(
'grid-cell',
isPinned && 'grid-cell--pinned'
)}
>
{children}
</div>
);.grid-cell--pinned {
background-color: white;
box-shadow: 2px 0 4px rgba(0, 0, 0, 0.1);
}const pinningInfo = getPinningStyles(column);
console.log('Pinning info:', pinningInfo);
// {
// style: { position: 'sticky', left: 150, zIndex: 1 },
// isPinned: true,
// isLastLeftPinned: false,
// isFirstRightPinned: false
// }