Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/app/components/tasks-table-columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export function getTasksTableColumns({
header: ({ column }) => (
<DataTableColumnHeader column={column} label="Task" />
),
cell: ({ row }) => <div className="w-20">{row.getValue("code")}</div>,
cell: ({ row }) => <div>{row.getValue("code")}</div>,
enableSorting: false,
enableHiding: false,
},
Expand All @@ -80,7 +80,7 @@ export function getTasksTableColumns({
return (
<div className="flex items-center gap-2">
{label && <Badge variant="outline">{label}</Badge>}
<span className="max-w-125 truncate font-medium">
<span className="min-w-0 truncate font-medium">
{row.getValue("title")}
</span>
</div>
Expand All @@ -93,6 +93,7 @@ export function getTasksTableColumns({
icon: Text,
},
enableColumnFilter: true,
size: 500,
},
{
id: "status",
Expand Down Expand Up @@ -263,7 +264,7 @@ export function getTasksTableColumns({
</DropdownMenu>
);
},
size: 40,
size: 48,
},
];
}
2 changes: 1 addition & 1 deletion src/app/components/tasks-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export function TasksTable({
columns,
initialState: {
sorting: [{ id: "createdAt", desc: true }],
columnPinning: { start: [], end: ["actions"] },
columnPinning: { start: ["select"], end: ["actions"] },
},
queryKeys,
getRowId: (originalRow) => originalRow.id,
Expand Down
52 changes: 48 additions & 4 deletions src/lib/data-table-utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import type { Column, ColumnFilter, RowData } from "@tanstack/react-table";
import type {
Column,
ColumnFilter,
RowData,
Table,
} from "@tanstack/react-table";

import type { DataTableFeatures } from "@/lib/data-table-features";
import type {
Expand Down Expand Up @@ -140,16 +145,55 @@ export function getColumnPinningStyle<TData extends RowData>({
? "4px 0 4px -4px var(--border) inset"
: undefined
: undefined,
left: isPinned === "start" ? `${column.getStart("start")}px` : undefined,
right: isPinned === "end" ? `${column.getAfter("end")}px` : undefined,
insetInlineStart:
isPinned === "start"
? `var(${getColumnVar(column.id, "offset")})`
: undefined,
insetInlineEnd:
isPinned === "end"
? `var(${getColumnVar(column.id, "offset")})`
: undefined,
opacity: isPinned ? 0.97 : 1,
position: isPinned ? "sticky" : "relative",
background: isPinned ? "var(--background)" : "var(--background)",
width: column.getSize(),
width: `var(${getColumnVar(column.id, "size")})`,
zIndex: isPinned ? 1 : undefined,
};
}

/**
* Column sizes and pinned offsets as CSS variables on the `<table>`, so cells
* read them through `getColumnPinningStyle` without depending on sizing state.
* Columns only stretch past their sizes when the table fits its container, and
* pinned offsets only apply when it overflows, so the offsets always match.
*/
export function getColumnSizingStyle<TData extends RowData>(
table: Table<DataTableFeatures, TData>,
): React.CSSProperties {
const style: Record<string, string> = {
minWidth: `${table.getTotalSize()}px`,
};

for (const header of table.getFlatHeaders()) {
style[getColumnVar(header.column.id, "size")] = `${header.getSize()}px`;
}

for (const { column } of table.getLeafHeaders()) {
const isPinned = column.getIsPinned();
if (!isPinned) continue;

const offset =
isPinned === "start" ? column.getStart("start") : column.getAfter("end");
style[getColumnVar(column.id, "offset")] = `${offset}px`;
}

return style;
}

function getColumnVar(columnId: string, property: "size" | "offset") {
return `--column-${columnId.replace(/[^\w-]/g, "_")}-${property}`;
Comment thread
sadmann7 marked this conversation as resolved.
Outdated
}

export function getFilterOperators(filterVariant: FilterVariant) {
return FILTER_OPERATORS_BY_VARIANT[filterVariant] ?? [];
}
Expand Down
46 changes: 40 additions & 6 deletions src/registry/bases/base/components/data-table/data-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import * as React from "react";

import type { DataTableFeatures } from "@/lib/data-table-features";

import { getColumnPinningStyle } from "@/lib/data-table-utils";
import {
getColumnPinningStyle,
getColumnSizingStyle,
} from "@/lib/data-table-utils";
import { DataTablePagination } from "@/registry/bases/base/components/data-table/data-table-pagination";
import {
Table,
Expand Down Expand Up @@ -44,10 +47,10 @@ export function DataTable<TData extends RowData>({
>
{children}
<div className="overflow-hidden rounded-md border">
<Table>
<DataTableLayout table={table}>
<DataTableHeader table={table} />
<DataTableBody table={table} />
</Table>
</DataTableLayout>
</div>
<div className="flex flex-col gap-2.5">
<DataTablePagination table={table} />
Expand All @@ -59,6 +62,34 @@ export function DataTable<TData extends RowData>({
);
}

interface DataTableLayoutProps<TData extends RowData> {
table: TanstackTable<DataTableFeatures, TData>;
children: React.ReactNode;
}

function DataTableLayout<TData extends RowData>({
table,
children,
}: DataTableLayoutProps<TData>) {
return (
<Subscribe
source={table.store}
selector={(state) => ({
columnOrder: state.columnOrder,
columnPinning: state.columnPinning,
columnSizing: state.columnSizing,
columnVisibility: state.columnVisibility,
})}
>
{() => (
<Table className="table-fixed" style={getColumnSizingStyle(table)}>
{children}
</Table>
)}
</Subscribe>
);
}

function DataTableHeader<TData extends RowData>({
table,
}: {
Expand All @@ -70,7 +101,6 @@ function DataTableHeader<TData extends RowData>({
selector={(state) => ({
columnOrder: state.columnOrder,
columnPinning: state.columnPinning,
columnSizing: state.columnSizing,
columnVisibility: state.columnVisibility,
rowSelection: state.rowSelection,
sorting: state.sorting,
Expand All @@ -84,6 +114,7 @@ function DataTableHeader<TData extends RowData>({
<TableHead
key={header.id}
colSpan={header.colSpan}
className="overflow-hidden"
style={getColumnPinningStyle({ column: header.column })}
>
{header.isPlaceholder ? null : <FlexRender header={header} />}
Expand Down Expand Up @@ -147,7 +178,6 @@ function DataTableRow<TData extends RowData>({
selector={(state) => ({
columnOrder: state.columnOrder,
columnPinning: state.columnPinning,
columnSizing: state.columnSizing,
columnVisibility: state.columnVisibility,
})}
>
Expand All @@ -165,7 +195,11 @@ function DataTableRow<TData extends RowData>({
{(isSelected) => (
<TableRow data-state={isSelected ? "selected" : undefined}>
{cells.map(({ cell, style }) => (
<TableCell key={cell.id} style={style}>
<TableCell
key={cell.id}
className="overflow-hidden"
style={style}
>
<FlexRender cell={cell} />
</TableCell>
))}
Expand Down
46 changes: 40 additions & 6 deletions src/registry/bases/radix/components/data-table/data-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import * as React from "react";

import type { DataTableFeatures } from "@/lib/data-table-features";

import { getColumnPinningStyle } from "@/lib/data-table-utils";
import {
getColumnPinningStyle,
getColumnSizingStyle,
} from "@/lib/data-table-utils";
import { DataTablePagination } from "@/registry/bases/radix/components/data-table/data-table-pagination";
import {
Table,
Expand Down Expand Up @@ -44,10 +47,10 @@ export function DataTable<TData extends RowData>({
>
{children}
<div className="overflow-hidden rounded-md border">
<Table>
<DataTableLayout table={table}>
<DataTableHeader table={table} />
<DataTableBody table={table} />
</Table>
</DataTableLayout>
</div>
<div className="flex flex-col gap-2.5">
<DataTablePagination table={table} />
Expand All @@ -59,6 +62,34 @@ export function DataTable<TData extends RowData>({
);
}

interface DataTableLayoutProps<TData extends RowData> {
table: TanstackTable<DataTableFeatures, TData>;
children: React.ReactNode;
}

function DataTableLayout<TData extends RowData>({
table,
children,
}: DataTableLayoutProps<TData>) {
return (
<Subscribe
source={table.store}
selector={(state) => ({
columnOrder: state.columnOrder,
columnPinning: state.columnPinning,
columnSizing: state.columnSizing,
columnVisibility: state.columnVisibility,
})}
>
{() => (
<Table className="table-fixed" style={getColumnSizingStyle(table)}>
{children}
</Table>
)}
</Subscribe>
);
}

interface DataTableHeaderProps<TData extends RowData> {
table: TanstackTable<DataTableFeatures, TData>;
}
Expand All @@ -72,7 +103,6 @@ function DataTableHeader<TData extends RowData>({
selector={(state) => ({
columnOrder: state.columnOrder,
columnPinning: state.columnPinning,
columnSizing: state.columnSizing,
columnVisibility: state.columnVisibility,
rowSelection: state.rowSelection,
sorting: state.sorting,
Expand All @@ -86,6 +116,7 @@ function DataTableHeader<TData extends RowData>({
<TableHead
key={header.id}
colSpan={header.colSpan}
className="overflow-hidden"
style={getColumnPinningStyle({ column: header.column })}
>
{header.isPlaceholder ? null : <FlexRender header={header} />}
Expand Down Expand Up @@ -149,7 +180,6 @@ function DataTableRow<TData extends RowData>({
selector={(state) => ({
columnOrder: state.columnOrder,
columnPinning: state.columnPinning,
columnSizing: state.columnSizing,
columnVisibility: state.columnVisibility,
})}
>
Expand All @@ -167,7 +197,11 @@ function DataTableRow<TData extends RowData>({
{(isSelected) => (
<TableRow data-state={isSelected ? "selected" : undefined}>
{cells.map(({ cell, style }) => (
<TableCell key={cell.id} style={style}>
<TableCell
key={cell.id}
className="overflow-hidden"
style={style}
>
<FlexRender cell={cell} />
</TableCell>
))}
Expand Down
Loading