Visual settings and theme configuration.
Settings control the visual appearance and behavior of the grid. Configure heights, colors, borders, empty states, and conditional styling.
interface GridSettings<TData = any> {
rowHeight?: number;
headerHeight?: number;
groupHeaderHeight?: number;
filterBarHeight?: number;
paginationHeight?: number;
stripedRows?: boolean;
stripeClassName?: string;
showColumnBorders?: boolean;
disableHoverEffect?: boolean;
noDataMessage?: string;
noDataOverlay?: ReactNode;
footer?: {
className?: string;
cellClassName?: string;
};
rowClassRules?: Record<string, (data: TData) => boolean>;
}<ActiveGrid
columns={columns}
data={data}
settings={{
rowHeight: 48,
stripedRows: true,
showColumnBorders: true,
}}
{...}
/>number44settings={{
rowHeight: 56, // Taller rows
}}number48settings={{
headerHeight: 60,
}}number32settings={{
groupHeaderHeight: 40,
}}number36settings={{
filterBarHeight: 44,
}}numberbooleanfalsestring'bg-muted/20'booleanfalsebooleanfalsestring'No results.'ReactNodeNew in v5.1
stringstringRecord<string, (data: TData) => boolean>Settings work automatically with dark mode:
Settings use CSS variables that can be customized:
Override via settings:
rowClassRules functions simple and fastEnsure settings maintain accessibility:
settings={{
paginationHeight: 56,
}}settings={{
stripedRows: true,
}}settings={{
stripedRows: true,
stripeClassName: 'bg-blue-50',
}}settings={{
showColumnBorders: true,
}}settings={{
disableHoverEffect: true,
}}settings={{
noDataMessage: 'No users found',
}}settings={{
noDataOverlay: (
<div className="flex flex-col items-center justify-center p-8">
<EmptyIcon className="h-12 w-12 text-muted-foreground mb-4" />
<h3 className="text-lg font-semibold">No data available</h3>
<p className="text-muted-foreground">Try adjusting your filters</p>
<Button className="mt-4" onClick={clearFilters}>
Clear Filters
</Button>
</div>
),
}}settings={{
footer: {
className: 'bg-muted font-bold border-t-2',
},
}}settings={{
footer: {
cellClassName: 'font-semibold text-primary',
},
}}settings={{
rowClassRules: {
'bg-red-50': (row) => row.status === 'error',
'bg-green-50': (row) => row.status === 'success',
'opacity-50': (row) => !row.isActive,
'font-bold': (row) => row.priority === 'high',
},
}}settings={{
rowHeight: 36,
headerHeight: 40,
filterBarHeight: 32,
stripedRows: false,
showColumnBorders: false,
}}settings={{
rowHeight: 56,
headerHeight: 64,
stripedRows: true,
showColumnBorders: true,
}}settings={{
rowHeight: 48,
headerHeight: 52,
stripedRows: true,
stripeClassName: 'bg-muted/10',
showColumnBorders: true,
footer: {
className: 'bg-muted/20 font-semibold border-t-2 border-primary',
cellClassName: 'text-primary',
},
}}type Order = {
id: string;
status: 'pending' | 'completed' | 'cancelled';
priority: 'high' | 'normal' | 'low';
};
settings={{
stripedRows: true,
rowClassRules: {
'bg-yellow-50 dark:bg-yellow-950/20': (row) => row.status === 'pending',
'bg-green-50 dark:bg-green-950/20': (row) => row.status === 'completed',
'bg-red-50 dark:bg-red-950/20': (row) => row.status === 'cancelled',
'border-l-4 border-l-red-500': (row) => row.priority === 'high',
},
}}settings={{
noDataOverlay: (
<div className="text-center p-12">
<div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-muted mb-4">
<Search className="h-8 w-8 text-muted-foreground" />
</div>
<h3 className="text-xl font-semibold mb-2">No results found</h3>
<p className="text-muted-foreground mb-4">
We couldn't find any data matching your criteria
</p>
<div className="flex gap-2 justify-center">
<Button onClick={clearFilters}>Clear Filters</Button>
<Button variant="outline" onClick={resetView}>Reset View</Button>
</div>
</div>
),
}}function ResponsiveGrid() {
const isMobile = useMediaQuery('(max-width: 768px)');
return (
<ActiveGrid
columns={columns}
data={data}
settings={{
rowHeight: isMobile ? 48 : 44,
headerHeight: isMobile ? 56 : 48,
stripedRows: !isMobile,
showColumnBorders: false,
}}
/>
);
}settings={{
stripedRows: true,
stripeClassName: 'bg-muted/20', // Adapts to dark mode
rowClassRules: {
'bg-red-50 dark:bg-red-950/20': (row) => row.hasError,
},
}}.grid-container {
--grid-row-height: 44px;
--grid-header-height: 48px;
--grid-group-header-height: 32px;
--grid-filter-bar-height: 36px;
}settings={{
rowHeight: 52, // Sets --grid-row-height: 52px
}}settings={{
rowHeight: 44, // Minimum 44px for touch targets
noDataMessage: 'No results found', // Clear message for screen readers
disableHoverEffect: false, // Keep hover for visual feedback
}}<ActiveGrid
columns={columns}
data={data}
settings={{
// Heights
rowHeight: 48,
headerHeight: 52,
groupHeaderHeight: 36,
filterBarHeight: 40,
// Visual
stripedRows: true,
stripeClassName: 'bg-muted/10',
showColumnBorders: true,
disableHoverEffect: false,
// Empty state
noDataMessage: 'No users found',
noDataOverlay: <CustomEmptyState />,
// Footer
footer: {
className: 'bg-muted font-semibold border-t-2',
cellClassName: 'text-primary',
},
// Conditional styling
rowClassRules: {
'bg-red-50': (row) => row.status === 'error',
'bg-green-50': (row) => row.status === 'success',
'font-bold': (row) => row.isImportant,
'opacity-50': (row) => !row.isActive,
},
}}
/>import { GridSettings } from '@workspace/active-grid';
type User = {
id: string;
status: 'active' | 'inactive';
};
const settings: GridSettings<User> = {
rowHeight: 48,
stripedRows: true,
rowClassRules: {
'opacity-50': (row: User) => row.status === 'inactive',
},
};
<ActiveGrid<User>
settings={settings}
{...}
/>