Row Styling
Dynamically assign custom CSS classes to rows that meet business conditions such as canceled payments, low inventory, or VIP membership.
import * as React from 'react';
import { BGrid, BGridColumn, BGridDataItem } from 'beautiful-grid';
import DataGridContainer from '../components/DataGridContainer';
import { useContainerSize } from '../hooks/useContainerSize';
interface InventoryRisk {
sku: string;
productName: string;
warehouse: string;
stock: number;
safetyStock: number;
inboundDate: string;
}
const productNames = ['고속 충전 어댑터 65W', '무선 블루투스 이어폰', '강화유리 필름', '태블릿 마그네틱 거치대', 'USB-C 케이블'];
const data: BGridDataItem<InventoryRisk>[] = Array.from({ length: 120 }, (_, index) => {
const safetyStock = 10 + (index % 4) * 5;
const stock = index % 13 === 0 ? 0 : (index * 7) % 65;
return {
values: {
sku: `INV-${String(index + 1).padStart(5, '0')}`,
productName: productNames[index % productNames.length],
warehouse: `센터 ${String.fromCharCode(65 + (index % 4))}`,
stock,
safetyStock,
inboundDate: stock < safetyStock ? `2026-08-${String((index % 7) + 24).padStart(2, '0')}` : '-',
},
};
});
export default function GetRowClassName() {
const [columns, setColumns] = React.useState<BGridColumn<InventoryRisk>[]>([
{ key: 'sku', label: '품목코드', width: 110, align: 'center' },
{ key: 'productName', label: '품목명', width: 240 },
{ key: 'warehouse', label: '보관센터', width: 100, align: 'center' },
{ key: 'stock', label: '현재 재고', width: 100, align: 'right', itemRender: ({ values }) => <strong>{values.stock}개</strong> },
{ key: 'safetyStock', label: '안전 재고', width: 100, align: 'right', itemRender: ({ values }) => <>{values.safetyStock}개</> },
{
key: 'inboundDate',
label: '입고 예정일',
width: 120,
align: 'center',
itemRender: ({ values }) => <>{values.stock === 0 ? '품절 · 긴급 발주' : values.inboundDate}</>,
},
]);
const containerRef = React.useRef<HTMLDivElement>(null);
const { width, height } = useContainerSize(containerRef);
return (
<DataGridContainer ref={containerRef} className='get-row-class-example'>
<BGrid<InventoryRisk>
showLineNumber
width={width}
height={height}
headerHeight={35}
data={data}
columns={columns}
rowKey='sku'
onChangeColumns={(_columnIndex, { columns }) => setColumns(columns)}
getRowClassName={(_rowIndex, item) => {
if (item.values.stock === 0) return 'row-out-of-stock';
if (item.values.stock < item.values.safetyStock) return 'row-low-stock';
return undefined;
}}
/>
</DataGridContainer>
);
}import * as React from 'react';
import './DataGridContainer.css';
interface DataGridContainerProps extends React.HTMLAttributes<HTMLDivElement> {
children?: React.ReactNode;
}
/**
* Keeps a DataGrid in a measured, fixed layout box.
*
* BGrid's rendered root is absolutely positioned within this relative
* container. This makes a ResizeObserver measurement authoritative when a
* surrounding flex or grid layout shrinks as well as when it expands.
*/
const DataGridContainer = React.forwardRef<HTMLDivElement, DataGridContainerProps>(
({ className, ...rest }, ref) => (
<div ref={ref} className={`data-grid-container ${className ?? ''}`.trim()} {...rest} />
),
);
DataGridContainer.displayName = 'DataGridContainer';
export default DataGridContainer;.data-grid-container {
position: relative;
width: 100%;
height: 400px;
overflow: hidden;
font-size: 13px;
}
.data-grid-container > .bgrid-root {
position: absolute;
inset: 0;
}import * as React from 'react';
export function useContainerSize(ref: React.MutableRefObject<HTMLElement | null>, additionalDeps: unknown[] = []) {
const [width, setWidth] = React.useState(0);
const [height, setHeight] = React.useState(0);
const resizeObserver = React.useRef(
new ResizeObserver(entries => {
if (entries.length !== 1) {
throw new Error('Invalid Container length');
}
const [entry] = entries;
const { width, height } = entry.contentRect;
setWidth(width);
setHeight(height);
}),
);
React.useEffect(() => {
if (!ref.current) return;
const observer = resizeObserver.current;
const element = ref.current;
setWidth(element.clientWidth);
setHeight(element.clientHeight);
observer.observe(element);
return () => {
observer.unobserve(element);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [...additionalDeps, ref]);
return {
width,
height,
};
}1. When and why should you use it?
Use getRowClassName to draw attention to rows in warning states, such as error logs or low-inventory alerts, or important states, such as VIP customers and completed tasks. You can apply red, yellow, or green background highlights to the entire row based on your business rules.
2. Complete example: highlighting low-stock items
import React, { useState } from 'react';
import { BGrid, type BGridColumn, type BGridDataItem } from 'beautiful-grid';
interface InventoryItem {
id: string;
name: string;
stock: number;
threshold: number;
}
export default function RowStylingGrid() {
const [data] = useState<BGridDataItem<InventoryItem>[]>([
{ values: { id: 'P1', name: '65W Fast-Charging Adapter', stock: 4, threshold: 10 } }, // Low stock
{ values: { id: 'P2', name: 'Wireless Bluetooth Earbuds', stock: 28, threshold: 10 } }, // In stock
{ values: { id: 'P3', name: 'Tempered Glass Screen Protector', stock: 0, threshold: 5 } }, // Out of stock
{ values: { id: 'P4', name: 'Magnetic Tablet Stand', stock: 15, threshold: 5 } }, // In stock
]);
const columns: BGridColumn<InventoryItem>[] = [
{ key: 'id', label: 'Code', width: 80, align: 'center' },
{ key: 'name', label: 'Item Name', width: 240 },
{
key: 'stock',
label: 'Current Stock',
width: 100,
align: 'right',
itemRender: ({ values }) => <strong>{values.stock} units</strong>,
},
{ key: 'threshold', label: 'Safety Stock', width: 100, align: 'right', itemRender: ({ values }) => `${values.threshold} units` },
];
return (
<div>
<style>{`
.row-out-of-stock {
background-color: #fee2e2 !important; /* Light red */
color: #991b1b;
}
.row-low-stock {
background-color: #fef3c7 !important; /* Light yellow */
color: #92400e;
}
`}</style>
<BGrid<InventoryItem>
width={560}
height={220}
columns={columns}
data={data}
rowKey="id"
// Return a row class based on inventory state
getRowClassName={(_, item) => {
if (item.values.stock === 0) return 'row-out-of-stock';
if (item.values.stock < item.values.threshold) return 'row-low-stock';
return '';
}}
/>
</div>
);
}