auto-scroll-table-react
v0.0.1
Published
A high-performance React auto-scroll table component with fixed header, customizable row count, and hover-to-pause support.
Maintainers
Readme
auto-scroll-table-react
A high-performance React auto-scroll table component with fixed header, virtual scrolling, and hover-to-pause support. Capable of handling 10,000+ rows without DOM bloat.
Features
- Virtual Scrolling — Only renders
visibleRowCount + bufferSizerows in the DOM, regardless of data size - Fixed Header — Table header stays fixed while data scrolls
- Auto Scroll — Automatically scrolls when data exceeds visible row count
- Seamless Loop — Smooth infinite scrolling with no visual flash on reset
- Hover to Pause — Scroll pauses on mouse enter, resumes on mouse leave
- RAF Animation — Scroll animation driven by
requestAnimationFrame, decoupled from React render cycle - Zero Dependencies — No third-party UI library required
- TypeScript — Written in TypeScript with full type support
Installation
npm install auto-scroll-table-reactQuick Start
Basic Usage
import { AutoScrollTable } from 'auto-scroll-table-react';
const columns = [
{ key: 'name', title: 'Name', dataIndex: 'name' },
{ key: 'age', title: 'Age', dataIndex: 'age', width: 80 },
{
key: 'status',
title: 'Status',
render: (value: any, record: any) => <span>{record.status}</span>,
},
];
const dataSource = [
{ name: 'Alice', age: 25, status: 'Active' },
{ name: 'Bob', age: 30, status: 'Inactive' },
{ name: 'Carol', age: 28, status: 'Active' },
// ... more rows
];
function App() {
return (
<AutoScrollTable
columns={columns}
dataSource={dataSource}
visibleRowCount={5}
scrollInterval={3000}
rowHeight={48}
/>
);
}Styles are auto-injected — No manual CSS import needed. The component injects its stylesheet into the document
<head>automatically on first render.
Large Data — 10,000+ Rows
The component uses virtual scrolling internally. Even with massive datasets, only a handful of DOM nodes are ever rendered.
import { AutoScrollTable } from 'auto-scroll-table-react';
const columns = [
{ key: 'id', title: 'ID', dataIndex: 'id', width: 80 },
{ key: 'value', title: 'Value', dataIndex: 'value' },
];
// 10,000 rows from the server
const bigData = Array.from({ length: 10000 }, (_, i) => ({
id: i + 1,
value: `Item ${i + 1}`,
}));
function Dashboard() {
return (
<AutoScrollTable
columns={columns}
dataSource={bigData}
visibleRowCount={6}
scrollInterval={2000}
rowHeight={40}
bufferSize={2}
/>
);
}Custom Cell Render
Use the render function for full control over cell content.
const columns = [
{
key: 'user',
title: 'User',
render: (_: any, record: any) => (
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<img src={record.avatar} width={24} height={24} style={{ borderRadius: '50%' }} />
<span>{record.name}</span>
</div>
),
width: 150,
},
{ key: 'email', title: 'Email', dataIndex: 'email' },
{
key: 'role',
title: 'Role',
dataIndex: 'role',
align: 'center',
render: (_: any, record: any) => (
<span
style={{
padding: '2px 8px',
borderRadius: 4,
background: record.role === 'Admin' ? '#1890ff' : '#f0f0f0',
color: record.role === 'Admin' ? '#fff' : '#333',
fontSize: 12,
}}
>
{record.role}
</span>
),
},
];Row Click Handler
<AutoScrollTable
columns={columns}
dataSource={dataSource}
visibleRowCount={5}
rowHeight={48}
onRowClick={(record, index) => {
console.log('Clicked row', index, record);
}}
/>Custom Styling
You can pass class names and inline styles to every part of the table.
<AutoScrollTable
columns={columns}
dataSource={dataSource}
visibleRowCount={5}
rowHeight={48}
className="my-dashboard-table"
headerClassName="my-header"
rowClassName="my-row"
headerStyle={{ background: '#001529', color: '#fff' }}
rowStyle={{ fontSize: 13 }}
/>Override the default SCSS in your own stylesheet:
.my-dashboard-table {
border: none;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
.auto-scroll-table__header {
background: #001529;
color: #fff;
}
.auto-scroll-table__row:hover {
background: #e6f7ff;
}
}TypeScript
The component is fully generic. Pass your data type for strict type checking:
interface User {
id: number;
name: string;
age: number;
status: 'Active' | 'Inactive';
}
const columns = [
{ key: 'name', title: 'Name', dataIndex: 'name' as const },
{ key: 'age', title: 'Age', dataIndex: 'age' as const, width: 80 },
{
key: 'status',
title: 'Status',
render: (_: any, record: User) => (
<span style={{ color: record.status === 'Active' ? 'green' : 'red' }}>
{record.status}
</span>
),
},
];
<AutoScrollTable<User>
columns={columns}
dataSource={users}
visibleRowCount={5}
rowHeight={48}
/>Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| columns | Column<T>[] | required | Column definitions |
| dataSource | T[] | required | Table data |
| visibleRowCount | number | 5 | Number of visible rows |
| scrollInterval | number | 3000 | Scroll interval in milliseconds |
| rowHeight | number | 48 | Height of each row in pixels |
| bufferSize | number | 2 | Extra rows rendered above/below the visible area for smooth scrolling |
| className | string | - | Custom class for table wrapper |
| style | CSSProperties | - | Custom style for table wrapper |
| headerClassName | string | - | Custom class for header |
| headerStyle | CSSProperties | - | Custom style for header |
| rowClassName | string | - | Custom class for rows |
| rowStyle | CSSProperties | - | Custom style for rows |
| bodyClassName | string | - | Custom class for body |
| bodyStyle | CSSProperties | - | Custom style for body |
| onRowClick | (record: T, index: number) => void | - | Row click handler |
| emptyText | ReactNode | '暂无数据' | Empty state text |
Column
| Property | Type | Description |
|----------|------|-------------|
| key | string | Unique key |
| title | ReactNode | Header content |
| dataIndex | string | Data field key |
| width | string \| number | Column width |
| align | 'left' \| 'center' \| 'right' | Text alignment |
| render | (value, record, index) => ReactNode | Custom cell renderer |
How It Works
- Virtual Scrolling — Only
visibleRowCount + bufferSizerows exist in the DOM at any time, no matter how largedataSourceis. - RAF Animation — The scroll animation is driven by
requestAnimationFramedirectly updating the DOMtransform, completely outside React's render cycle. - React Render Frequency —
setStateonly fires once perscrollInterval(e.g., every 3 seconds) to shift the data window, keeping React diff work trivial. - Seamless Loop — When the animation completes, the data window advances by one row and the
transformresets in auseLayoutEffectbefore the browser paints, producing a visually perfect infinite loop.
Browser Support
Works in all modern browsers that support requestAnimationFrame and CSS transform.
License
MIT
