Skip to content

Commit 28776fe

Browse files
feat: add isFirstRow prop to TableCell and update styling for first row (#472)
1 parent 92a3ecb commit 28776fe

File tree

6 files changed

+270
-3
lines changed

6 files changed

+270
-3
lines changed

apps/site/src/demos/dataTableDemo.tsx

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,6 +1289,234 @@ const SimpleDataTableExample = () => {
12891289
)
12901290
}
12911291

1292+
// Simple Empty DataTable Examples
1293+
const EmptyDataTableExamples = () => {
1294+
// First empty table - Simple User Table
1295+
const simpleUserColumns: ColumnDefinition<Record<string, unknown>>[] = [
1296+
{
1297+
field: 'name',
1298+
header: 'User Name',
1299+
type: ColumnType.TEXT,
1300+
isSortable: true,
1301+
isEditable: true,
1302+
minWidth: '150px',
1303+
maxWidth: '200px',
1304+
},
1305+
{
1306+
field: 'email',
1307+
header: 'Email Address',
1308+
type: ColumnType.TEXT,
1309+
isSortable: true,
1310+
isEditable: true,
1311+
minWidth: '180px',
1312+
maxWidth: '250px',
1313+
},
1314+
{
1315+
field: 'role',
1316+
header: 'Role',
1317+
type: ColumnType.SELECT,
1318+
isSortable: true,
1319+
isEditable: true,
1320+
minWidth: '120px',
1321+
maxWidth: '160px',
1322+
},
1323+
{
1324+
field: 'status',
1325+
header: 'Status',
1326+
type: ColumnType.TAG,
1327+
isSortable: true,
1328+
isEditable: false,
1329+
minWidth: '100px',
1330+
maxWidth: '140px',
1331+
},
1332+
]
1333+
1334+
// Second empty table - Simple Product Table
1335+
const simpleProductColumns: ColumnDefinition<Record<string, unknown>>[] = [
1336+
{
1337+
field: 'productName',
1338+
header: 'Product Name',
1339+
type: ColumnType.TEXT,
1340+
isSortable: true,
1341+
isEditable: true,
1342+
minWidth: '150px',
1343+
maxWidth: '200px',
1344+
},
1345+
{
1346+
field: 'category',
1347+
header: 'Category',
1348+
type: ColumnType.DROPDOWN,
1349+
isSortable: true,
1350+
isEditable: true,
1351+
minWidth: '120px',
1352+
maxWidth: '160px',
1353+
},
1354+
{
1355+
field: 'price',
1356+
header: 'Price',
1357+
type: ColumnType.NUMBER,
1358+
isSortable: true,
1359+
isEditable: true,
1360+
minWidth: '100px',
1361+
maxWidth: '150px',
1362+
},
1363+
{
1364+
field: 'inStock',
1365+
header: 'In Stock',
1366+
type: ColumnType.TEXT,
1367+
isSortable: true,
1368+
isEditable: true,
1369+
minWidth: '80px',
1370+
maxWidth: '120px',
1371+
},
1372+
]
1373+
1374+
return (
1375+
<div style={{ marginTop: '40px' }}>
1376+
{/* First Empty Table */}
1377+
<div
1378+
style={{
1379+
marginBottom: '20px',
1380+
padding: '16px',
1381+
backgroundColor: '#fef7f0',
1382+
borderRadius: '8px',
1383+
border: '1px solid #fed7aa',
1384+
}}
1385+
>
1386+
<h3
1387+
style={{
1388+
margin: '0 0 8px 0',
1389+
fontSize: '18px',
1390+
fontWeight: 600,
1391+
color: '#c2410c',
1392+
}}
1393+
>
1394+
📋 Empty User Management Table
1395+
</h3>
1396+
<p style={{ margin: 0, fontSize: '14px', color: '#9a3412' }}>
1397+
🎯 <strong>EMPTY STATE DEMO:</strong> This table shows how
1398+
the DataTable component looks when there's no data to
1399+
display. Notice the "No data available" message and how the
1400+
table structure is maintained with proper headers and
1401+
borders.
1402+
</p>
1403+
</div>
1404+
1405+
<DataTable
1406+
data={[]} // Empty data array
1407+
columns={simpleUserColumns}
1408+
idField="id"
1409+
title="User Management"
1410+
description="This table has no data to demonstrate the empty state"
1411+
enableSearch={true}
1412+
enableFiltering={true}
1413+
enableAdvancedFilter={false}
1414+
enableInlineEdit={false}
1415+
enableRowExpansion={false}
1416+
enableRowSelection={true}
1417+
enableColumnManager={true}
1418+
showSettings={true}
1419+
columnFreeze={0}
1420+
pagination={{
1421+
currentPage: 1,
1422+
pageSize: 10,
1423+
totalRows: 0,
1424+
pageSizeOptions: [5, 10, 20],
1425+
}}
1426+
headerSlot1={
1427+
<Button
1428+
buttonType={ButtonType.SECONDARY}
1429+
leadingIcon={<RefreshCw size={16} />}
1430+
size={ButtonSize.SMALL}
1431+
onClick={() => console.log('Refresh clicked')}
1432+
>
1433+
Refresh
1434+
</Button>
1435+
}
1436+
headerSlot2={
1437+
<Button
1438+
buttonType={ButtonType.PRIMARY}
1439+
leadingIcon={<Package size={16} />}
1440+
size={ButtonSize.SMALL}
1441+
onClick={() => console.log('Add User clicked')}
1442+
>
1443+
Add User
1444+
</Button>
1445+
}
1446+
/>
1447+
1448+
{/* Second Empty Table */}
1449+
<div style={{ marginTop: '40px' }}>
1450+
<div
1451+
style={{
1452+
marginBottom: '20px',
1453+
padding: '16px',
1454+
backgroundColor: '#f0f4ff',
1455+
borderRadius: '8px',
1456+
border: '1px solid #c7d2fe',
1457+
}}
1458+
>
1459+
<h3
1460+
style={{
1461+
margin: '0 0 8px 0',
1462+
fontSize: '18px',
1463+
fontWeight: 600,
1464+
color: '#3730a3',
1465+
}}
1466+
>
1467+
🛍️ Empty Product Catalog Table
1468+
</h3>
1469+
<p
1470+
style={{
1471+
margin: 0,
1472+
fontSize: '14px',
1473+
color: '#312e81',
1474+
}}
1475+
>
1476+
🎯 <strong>MINIMAL CONFIGURATION DEMO:</strong> This is
1477+
a simpler empty table with fewer features enabled. Shows
1478+
how the table adapts to different configurations while
1479+
maintaining the empty state properly.
1480+
</p>
1481+
</div>
1482+
1483+
<DataTable
1484+
data={[]} // Empty data array
1485+
columns={simpleProductColumns}
1486+
idField="productId"
1487+
title="Product Catalog"
1488+
description="Browse and manage your product inventory"
1489+
enableSearch={true}
1490+
enableFiltering={false}
1491+
enableAdvancedFilter={false}
1492+
enableInlineEdit={false}
1493+
enableRowExpansion={false}
1494+
enableRowSelection={false}
1495+
enableColumnManager={false}
1496+
showSettings={false}
1497+
columnFreeze={1}
1498+
pagination={{
1499+
currentPage: 1,
1500+
pageSize: 5,
1501+
totalRows: 0,
1502+
pageSizeOptions: [5, 10, 15],
1503+
}}
1504+
headerSlot1={
1505+
<Button
1506+
buttonType={ButtonType.PRIMARY}
1507+
leadingIcon={<Package size={16} />}
1508+
size={ButtonSize.SMALL}
1509+
onClick={() => console.log('Add Product clicked')}
1510+
>
1511+
Add Product
1512+
</Button>
1513+
}
1514+
/>
1515+
</div>
1516+
</div>
1517+
)
1518+
}
1519+
12921520
const DataTableDemo = () => {
12931521
// Demo mode toggle
12941522
const [isServerSideMode, setIsServerSideMode] = useState(false)
@@ -2776,6 +3004,7 @@ const DataTableDemo = () => {
27763004
/>
27773005

27783006
<SimpleDataTableExample />
3007+
<EmptyDataTableExamples />
27793008
</div>
27803009
)
27813010
}

packages/blend/lib/components/DataTable/DataTable.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ const DataTable = forwardRef(
696696
position: tableToken.position,
697697
padding: tableToken.padding,
698698
width: tableToken.width,
699-
height: tableToken.height,
699+
maxHeight: tableToken.height,
700700
display: tableToken.display,
701701
flexDirection: tableToken.flexDirection,
702702
}}
@@ -769,7 +769,10 @@ const DataTable = forwardRef(
769769
flex: 1,
770770
position: 'relative',
771771
minHeight: 0,
772-
maxHeight: 'calc(100vh - 280px)',
772+
maxHeight:
773+
currentData.length > 0
774+
? tableToken.dataTable.maxHeight
775+
: 'auto',
773776
overflow: 'hidden',
774777
}}
775778
>

packages/blend/lib/components/DataTable/TableBody/index.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,16 @@ const StyledTableCell = styled.td<{
6464
$width?: string
6565
$customBackgroundColor?: string
6666
$hasCustomBackground?: boolean
67+
$isFirstRow?: boolean
6768
}>`
6869
padding: ${FOUNDATION_THEME.unit[12]} ${FOUNDATION_THEME.unit[16]};
6970
text-align: left;
7071
vertical-align: top;
71-
border-top: 1px solid ${FOUNDATION_THEME.colors.gray[150]};
72+
${({ $isFirstRow }) =>
73+
!$isFirstRow &&
74+
css`
75+
border-top: 1px solid ${FOUNDATION_THEME.colors.gray[150]};
76+
`}
7277
7378
${({ $width, $customBackgroundColor, $hasCustomBackground }) => css`
7479
${$width && `width: ${$width};`}
@@ -586,6 +591,7 @@ const TableBody = forwardRef<
586591
$hasCustomBackground={
587592
hasCustomBackground
588593
}
594+
$isFirstRow={index === 0}
589595
style={{
590596
minWidth: `${FOUNDATION_THEME.unit[52]}`,
591597
maxWidth: `${FOUNDATION_THEME.unit[52]}`,
@@ -650,6 +656,7 @@ const TableBody = forwardRef<
650656
$hasCustomBackground={
651657
hasCustomBackground
652658
}
659+
$isFirstRow={index === 0}
653660
style={{
654661
...(columnFreeze > 0 && {
655662
position: 'sticky',
@@ -826,6 +833,7 @@ const TableBody = forwardRef<
826833
}
827834
width={columnStyles}
828835
frozenStyles={getFrozenBodyStyles()}
836+
isFirstRow={index === 0}
829837
onFieldChange={(value) =>
830838
onFieldChange(
831839
row[idField],
@@ -854,6 +862,7 @@ const TableBody = forwardRef<
854862
hasCustomBackground
855863
}
856864
$width="200px"
865+
$isFirstRow={index === 0}
857866
style={{
858867
maxWidth: '200px',
859868
overflow: 'hidden',
@@ -898,6 +907,7 @@ const TableBody = forwardRef<
898907
$hasCustomBackground={
899908
hasCustomBackground
900909
}
910+
$isFirstRow={index === 0}
901911
style={{
902912
minWidth: '40px',
903913
maxWidth: '40px',
@@ -949,6 +959,7 @@ const TableBody = forwardRef<
949959
$hasCustomBackground={
950960
hasCustomBackground
951961
}
962+
$isFirstRow={index === 0}
952963
style={{
953964
minWidth:
954965
FOUNDATION_THEME.unit[48],

packages/blend/lib/components/DataTable/TableCell/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ const StyledTableCell = styled.td<{
1717
width?: React.CSSProperties
1818
$hasCustomContent?: boolean
1919
$tableToken?: TableTokenType
20+
$isFirstRow?: boolean
2021
}>`
2122
${(props) =>
2223
props.$tableToken ? props.$tableToken.dataTable.table.body.cell : ''}
2324
box-sizing: border-box;
2425
max-width: 0;
26+
${({ $isFirstRow }) => $isFirstRow && 'border-top: none'}
2527
`
2628

2729
const TruncatedTextWithTooltip = ({
@@ -93,6 +95,7 @@ const TableCell = forwardRef<
9395
currentValue,
9496
width,
9597
frozenStyles,
98+
isFirstRow,
9699
onFieldChange,
97100
getDisplayValue,
98101
},
@@ -322,6 +325,7 @@ const TableCell = forwardRef<
322325
column.type === ColumnType.REACT_ELEMENT ||
323326
(isEditing && column.isEditable)
324327
}
328+
$isFirstRow={isFirstRow}
325329
style={{
326330
...width,
327331
...frozenStyles,

packages/blend/lib/components/DataTable/TableCell/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export type TableCellProps<T extends Record<string, unknown>> = {
88
currentValue: unknown
99
width: React.CSSProperties
1010
frozenStyles?: React.CSSProperties
11+
isFirstRow?: boolean
1112
onFieldChange: (value: unknown) => void
1213
getDisplayValue?: (value: unknown, column: ColumnDefinition<T>) => unknown
1314
}

0 commit comments

Comments
 (0)