fix(table): sticky header & content placement in virtualized table (#5184)

* fix(table): header sticky in virtualized table + topContent and bottom content placement fix

* fix(table): header sticky in virtualized table PR return

* chore(changeset): revise changeset msg

---------

Co-authored-by: աӄա <wingkwong.code@gmail.com>
This commit is contained in:
Hova25 2025-04-19 17:27:05 +02:00 committed by GitHub
parent 531518f2ef
commit 8bd878341e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 73 additions and 56 deletions

View File

@ -0,0 +1,5 @@
---
"@heroui/table": patch
---
fix(table): Header sticky in virtualized table + topContent and bottom content placement fix in virtualized table (#5149)

View File

@ -81,71 +81,75 @@ const VirtualizedTable = forwardRef<"table", TableProps>((props, ref) => {
overscan: 5,
});
const tableProps = getTableProps();
return (
<div {...getBaseProps()}>
{/* We need to add p-1 to make the shadow-sm visible */}
{topContentPlacement === "outside" && topContent}
<Wrapper>
<>
{topContentPlacement === "outside" && topContent}
<div style={{height: `calc(${rowVirtualizer.getTotalSize() + headerHeight}px)`}}>
<>
{topContentPlacement === "inside" && topContent}
<Component {...getTableProps()}>
<TableRowGroup ref={headerRef} classNames={values.classNames} slots={values.slots}>
{collection.headerRows.map((headerRow) => (
<TableHeaderRow
key={headerRow?.key}
classNames={values.classNames}
node={headerRow}
slots={values.slots}
state={values.state}
>
{[...headerRow.childNodes].map((column) =>
column?.props?.isSelectionCell ? (
<TableSelectAllCheckbox
key={column?.key}
checkboxesProps={values.checkboxesProps}
classNames={values.classNames}
color={values.color}
disableAnimation={values.disableAnimation}
node={column}
selectionMode={values.selectionMode}
slots={values.slots}
state={values.state}
/>
) : (
<TableColumnHeader
key={column?.key}
classNames={values.classNames}
node={column}
slots={values.slots}
state={values.state}
/>
),
)}
</TableHeaderRow>
))}
<Spacer as="tr" tabIndex={-1} y={1} />
</TableRowGroup>
<VirtualizedTableBody
checkboxesProps={values.checkboxesProps}
{topContentPlacement === "inside" && topContent}
<Component
{...tableProps}
style={{
height: `calc(${rowVirtualizer.getTotalSize() + headerHeight}px)`,
...tableProps.style,
}}
>
<TableRowGroup ref={headerRef} classNames={values.classNames} slots={values.slots}>
{collection.headerRows.map((headerRow) => (
<TableHeaderRow
key={headerRow?.key}
classNames={values.classNames}
collection={values.collection}
color={values.color}
disableAnimation={values.disableAnimation}
isSelectable={values.isSelectable}
rowVirtualizer={rowVirtualizer}
selectionMode={values.selectionMode}
node={headerRow}
slots={values.slots}
state={values.state}
/>
</Component>
{bottomContentPlacement === "inside" && bottomContent}
</>
</div>
{bottomContentPlacement === "outside" && bottomContent}
>
{[...headerRow.childNodes].map((column) =>
column?.props?.isSelectionCell ? (
<TableSelectAllCheckbox
key={column?.key}
checkboxesProps={values.checkboxesProps}
classNames={values.classNames}
color={values.color}
disableAnimation={values.disableAnimation}
node={column}
selectionMode={values.selectionMode}
slots={values.slots}
state={values.state}
/>
) : (
<TableColumnHeader
key={column?.key}
classNames={values.classNames}
node={column}
slots={values.slots}
state={values.state}
/>
),
)}
</TableHeaderRow>
))}
<Spacer as="tr" tabIndex={-1} y={1} />
</TableRowGroup>
<VirtualizedTableBody
checkboxesProps={values.checkboxesProps}
classNames={values.classNames}
collection={values.collection}
color={values.color}
disableAnimation={values.disableAnimation}
isSelectable={values.isSelectable}
rowVirtualizer={rowVirtualizer}
selectionMode={values.selectionMode}
slots={values.slots}
state={values.state}
/>
</Component>
{bottomContentPlacement === "inside" && bottomContent}
</>
</Wrapper>
{bottomContentPlacement === "outside" && bottomContent}
</div>
);
});

View File

@ -1160,6 +1160,14 @@ export const Virtualized = {
},
};
export const VirtualizedWithHeaderSticky = {
...Virtualized,
args: {
...Virtualized.args,
isHeaderSticky: true,
},
};
export const TenThousandRows = {
render: VirtualizedTemplate,
args: {

View File

@ -55,7 +55,7 @@ const table = tv({
],
table: "min-w-full h-auto",
thead: "[&>tr]:first:rounded-lg",
tbody: "",
tbody: "after:block",
tr: ["group/tr", "outline-none", ...dataFocusVisibleClasses],
th: [
"group/th",