Table
Render table with theme styles
Source
Docs
Package
Usage
Table data for all examples:
const elements = [
{ position: 6, mass: 12.011, symbol: 'C', name: 'Carbon' },
{ position: 7, mass: 14.007, symbol: 'N', name: 'Nitrogen' },
{ position: 39, mass: 88.906, symbol: 'Y', name: 'Yttrium' },
{ position: 56, mass: 137.33, symbol: 'Ba', name: 'Barium' },
{ position: 58, mass: 140.12, symbol: 'Ce', name: 'Cerium' },
];
Element position | Element name | Symbol | Atomic mass |
---|---|---|---|
6 | Carbon | C | 12.011 |
7 | Nitrogen | N | 14.007 |
39 | Yttrium | Y | 88.906 |
56 | Barium | Ba | 137.33 |
58 | Cerium | Ce | 140.12 |
import { Table } from '@thinker-core/mantine-core';
function Demo() {
const rows = elements.map((element) => (
<Table.Tr key={element.name}>
<Table.Td>{element.position}</Table.Td>
<Table.Td>{element.name}</Table.Td>
<Table.Td>{element.symbol}</Table.Td>
<Table.Td>{element.mass}</Table.Td>
</Table.Tr>
));
return (
<Table>
<Table.Thead>
<Table.Tr>
<Table.Th>Element position</Table.Th>
<Table.Th>Element name</Table.Th>
<Table.Th>Symbol</Table.Th>
<Table.Th>Atomic mass</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
);
}
data prop
You can use data
prop to automatically generate table rows from array of React nodes.
data
prop accepts an object with the following properties:
head
– an array of React nodes (React.ReactNode[]
) to renderTable.Th
inTable.Thead
foot
– an array of React nodes (React.ReactNode[]
) to renderTable.Th
inTable.Tfoot
body
- an array of arrays of React nodes (React.ReactNode[][]
) to renderTable.Td
inTable.Tbody
caption
– a React node to renderTable.Caption
Element position | Atomic mass | Symbol | Element name |
---|---|---|---|
6 | 12.011 | C | Carbon |
7 | 14.007 | N | Nitrogen |
39 | 88.906 | Y | Yttrium |
56 | 137.33 | Ba | Barium |
58 | 140.12 | Ce | Cerium |
import { Table, TableData } from '@thinker-core/mantine-core';
const tableData: TableData = {
caption: 'Some elements from periodic table',
head: ['Element position', 'Atomic mass', 'Symbol', 'Element name'],
body: [
[6, 12.011, 'C', 'Carbon'],
[7, 14.007, 'N', 'Nitrogen'],
[39, 88.906, 'Y', 'Yttrium'],
[56, 137.33, 'Ba', 'Barium'],
[58, 140.12, 'Ce', 'Cerium'],
],
};
function Demo() {
return <Table data={tableData} />;
}
Sticky header
Set stickyHeader
to make table header sticky. To customize top position of the header use stickyHeaderOffset
prop:
it is useful when you have a fixed header in your application. For example, Mantine documentation website has a fixed
header with 60px height:
Element position | Element name | Symbol | Atomic mass |
---|---|---|---|
6 | Carbon | C | 12.011 |
7 | Nitrogen | N | 14.007 |
39 | Yttrium | Y | 88.906 |
56 | Barium | Ba | 137.33 |
58 | Cerium | Ce | 140.12 |
import { Table } from '@thinker-core/mantine-core';
const elements = [
{ position: 6, mass: 12.011, symbol: 'C', name: 'Carbon' },
{ position: 7, mass: 14.007, symbol: 'N', name: 'Nitrogen' },
{ position: 39, mass: 88.906, symbol: 'Y', name: 'Yttrium' },
{ position: 56, mass: 137.33, symbol: 'Ba', name: 'Barium' },
{ position: 58, mass: 140.12, symbol: 'Ce', name: 'Cerium' },
];
function Demo() {
const rows = elements.map((element) => (
<Table.Tr key={element.name}>
<Table.Td>{element.position}</Table.Td>
<Table.Td>{element.name}</Table.Td>
<Table.Td>{element.symbol}</Table.Td>
<Table.Td>{element.mass}</Table.Td>
</Table.Tr>
));
return (
<Table stickyHeader stickyHeaderOffset={60}>
<Table.Thead>
<Table.Tr>
<Table.Th>Element position</Table.Th>
<Table.Th>Element name</Table.Th>
<Table.Th>Symbol</Table.Th>
<Table.Th>Atomic mass</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
<Table.Caption>Scroll page to see sticky thead</Table.Caption>
</Table>
);
}
Spacing
To control spacing use horizontalSpacing
and verticalSpacing
props. Both props support spacing from theme.spacing
and any valid CSS value to set cell padding:
Position | Name | Symbol |
---|---|---|
6 | Carbon | C |
7 | Nitrogen | N |
39 | Yttrium | Y |
56 | Barium | Ba |
58 | Cerium | Ce |
import { Table } from '@thinker-core/mantine-core';
function Demo() {
return (
<Table>
{/* {...rows} */}
</Table>
);
}
Caption and tfoot
Table support tfoot and caption elements. Set captionSide
prop (top or bottom) to change caption position.
Element position | Element name | Symbol | Atomic mass |
---|---|---|---|
6 | Carbon | C | 12.011 |
7 | Nitrogen | N | 14.007 |
39 | Yttrium | Y | 88.906 |
56 | Barium | Ba | 137.33 |
58 | Cerium | Ce | 140.12 |
Element position | Element name | Symbol | Atomic mass |
import { Table } from '@thinker-core/mantine-core';
function Demo() {
const rows = elements.map((element) => (
<Table.Tr key={element.name}>
<Table.Td>{element.position}</Table.Td>
<Table.Td>{element.name}</Table.Td>
<Table.Td>{element.symbol}</Table.Td>
<Table.Td>{element.mass}</Table.Td>
</Table.Tr>
));
const ths = (
<Table.Tr>
<Table.Th>Element position</Table.Th>
<Table.Th>Element name</Table.Th>
<Table.Th>Symbol</Table.Th>
<Table.Th>Atomic mass</Table.Th>
</Table.Tr>
);
return (
<Table captionSide="bottom">
<Table.Caption>Some elements from periodic table</Table.Caption>
<Table.Thead>{ths}</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
<Table.Tfoot>{ths}</Table.Tfoot>
</Table>
);
}
Striped and rows hover
Element position | Element name | Symbol | Atomic mass |
---|---|---|---|
6 | Carbon | C | 12.011 |
7 | Nitrogen | N | 14.007 |
39 | Yttrium | Y | 88.906 |
56 | Barium | Ba | 137.33 |
58 | Cerium | Ce | 140.12 |
import { Table } from '@thinker-core/mantine-core';
function Demo() {
return (
<Table>
{/* {...rows} */}
</Table>
);
}
Scroll container
To prevent viewport overflow wrap Table
with Table.ScrollContainer
.
The component accepts minWidth
prop which sets minimum width below which table will be scrollable.
Element position | Element name | Symbol | Atomic mass |
---|---|---|---|
6 | Carbon | C | 12.011 |
7 | Nitrogen | N | 14.007 |
39 | Yttrium | Y | 88.906 |
56 | Barium | Ba | 137.33 |
58 | Cerium | Ce | 140.12 |
import { Table } from '@thinker-core/mantine-core';
function Demo() {
const rows = elements.map((element) => (
<Table.Tr key={element.name}>
<Table.Td>{element.position}</Table.Td>
<Table.Td>{element.name}</Table.Td>
<Table.Td>{element.symbol}</Table.Td>
<Table.Td>{element.mass}</Table.Td>
</Table.Tr>
));
return (
<Table.ScrollContainer minWidth={500}>
<Table>
<Table.Thead>
<Table.Tr>
<Table.Th>Element position</Table.Th>
<Table.Th>Element name</Table.Th>
<Table.Th>Symbol</Table.Th>
<Table.Th>Atomic mass</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
</Table.ScrollContainer>
);
}
By default, Table.ScrollContainer
uses ScrollArea, you can change it
to native scrollbars by setting type="native"
:
Element position | Element name | Symbol | Atomic mass |
---|---|---|---|
6 | Carbon | C | 12.011 |
7 | Nitrogen | N | 14.007 |
39 | Yttrium | Y | 88.906 |
56 | Barium | Ba | 137.33 |
58 | Cerium | Ce | 140.12 |
import { Table } from '@thinker-core/mantine-core';
function Demo() {
const rows = elements.map((element) => (
<Table.Tr key={element.name}>
<Table.Td>{element.position}</Table.Td>
<Table.Td>{element.name}</Table.Td>
<Table.Td>{element.symbol}</Table.Td>
<Table.Td>{element.mass}</Table.Td>
</Table.Tr>
));
return (
<Table.ScrollContainer minWidth={500} type="native">
<Table>
<Table.Thead>
<Table.Tr>
<Table.Th>Element position</Table.Th>
<Table.Th>Element name</Table.Th>
<Table.Th>Symbol</Table.Th>
<Table.Th>Atomic mass</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
</Table.ScrollContainer>
);
}
You can also set maxHeight
prop on Table.ScrollContainer
to limit table height:
Element position | Element name | Symbol | Atomic mass |
---|---|---|---|
1 | Hydrogen | H | 1.008 |
2 | Helium | He | 4.0026 |
3 | Lithium | Li | 6.94 |
4 | Beryllium | Be | 9.0122 |
5 | Boron | B | 10.81 |
6 | Carbon | C | 12.011 |
7 | Nitrogen | N | 14.007 |
8 | Oxygen | O | 15.999 |
9 | Fluorine | F | 18.998 |
10 | Neon | Ne | 20.18 |
11 | Sodium | Na | 22.99 |
12 | Magnesium | Mg | 24.305 |
13 | Aluminium | Al | 26.982 |
14 | Silicon | Si | 28.085 |
15 | Phosphorus | P | 30.974 |
16 | Sulfur | S | 32.06 |
17 | Chlorine | Cl | 35.45 |
18 | Argon | Ar | 39.948 |
19 | Potassium | K | 39.098 |
20 | Calcium | Ca | 39.098 |
21 | Scandium | Sc | 40.078 |
22 | Titanium | Ti | 47.867 |
23 | Vanadium | V | 50.941 |
24 | Chromium | Cr | 51.996 |
25 | Manganese | Mn | 54.938 |
26 | Iron | Fe | 55.845 |
27 | Cobalt | Co | 58.933 |
28 | Nickel | Ni | 58.933 |
29 | Copper | Cu | 63.546 |
30 | Zinc | Zn | 65.38 |
31 | Gallium | Ga | 69.723 |
32 | Germanium | Ge | 72.63 |
33 | Arsenic | As | 74.922 |
34 | Selenium | Se | 78.971 |
35 | Bromine | Br | 79.904 |
36 | Krypton | Kr | 83.798 |
37 | Rubidium | Rb | 83.798 |
38 | Strontium | Sr | 87.62 |
39 | Yttrium | Y | 88.906 |
40 | Zirconium | Zr | 91.224 |
41 | Niobium | Nb | 92.906 |
42 | Molybdenum | Mo | 95.95 |
43 | Technetium | Tc | 98 |
44 | Ruthenium | Ru | 101.07 |
45 | Rhodium | Rh | 102.905 |
46 | Palladium | Pd | 106.42 |
47 | Silver | Ag | 106.42 |
48 | Cadmium | Cd | 112.414 |
49 | Indium | In | 114.818 |
50 | Tin | Sn | 118.71 |
51 | Antimony | Sb | 121.76 |
52 | Tellurium | Te | 127.6 |
53 | Iodine | I | 126.904 |
54 | Xenon | Xe | 126.904 |
55 | Cesium | Cs | 126.904 |
56 | Barium | Ba | 137.33 |
57 | Lanthanum | La | 138.905 |
58 | Cerium | Ce | 140.12 |
59 | Praseodymium | Pr | 140.116 |
60 | Neodymium | Nd | 140.907 |
61 | Promethium | Pm | 144.242 |
62 | Samarium | Sm | 145 |
63 | Europium | Eu | 150.36 |
64 | Gadolinium | Gd | 151.964 |
65 | Terbium | Tb | 157.25 |
66 | Dysprosium | Dy | 158.925 |
67 | Holmium | Ho | 162.5 |
68 | Erbium | Er | 164.93 |
69 | Thulium | Tm | 167.259 |
import { Table } from '@thinker-core/mantine-core';
function Demo() {
const rows = elementsLong.map((element) => (
<Table.Tr key={element.name}>
<Table.Td>{element.position}</Table.Td>
<Table.Td>{element.name}</Table.Td>
<Table.Td>{element.symbol}</Table.Td>
<Table.Td>{element.mass}</Table.Td>
</Table.Tr>
));
return (
<Table.ScrollContainer minWidth={500} maxHeight={300}>
<Table>
<Table.Thead>
<Table.Tr>
<Table.Th>Element position</Table.Th>
<Table.Th>Element name</Table.Th>
<Table.Th>Symbol</Table.Th>
<Table.Th>Atomic mass</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
</Table.ScrollContainer>
);
}
Vertical variant
Set variant="vertical"
to render table with vertical layout:
Epic name | 7.x migration |
---|---|
Status | Open |
Total issues | 135 |
Total story points | 874 |
Last updated at | September 26, 2024 17:41:26 |
import { Table } from '@thinker-core/mantine-core';
export function Demo() {
return (
<Table variant="vertical" layout="fixed" withTableBorder>
<Table.Tbody>
<Table.Tr>
<Table.Th w={160}>Epic name</Table.Th>
<Table.Td>7.x migration</Table.Td>
</Table.Tr>
<Table.Tr>
<Table.Th>Status</Table.Th>
<Table.Td>Open</Table.Td>
</Table.Tr>
<Table.Tr>
<Table.Th>Total issues</Table.Th>
<Table.Td>135</Table.Td>
</Table.Tr>
<Table.Tr>
<Table.Th>Total story points</Table.Th>
<Table.Td>874</Table.Td>
</Table.Tr>
<Table.Tr>
<Table.Th>Last updated at</Table.Th>
<Table.Td>September 26, 2024 17:41:26</Table.Td>
</Table.Tr>
</Table.Tbody>
</Table>
);
}
Tabular numbers
Set tabularNums
prop to render numbers in tabular style. It sets
font-variant-numeric: tabular-nums
which makes numbers to have equal width.
This is useful when you have columns with numbers and you want them to be aligned:
Product | Units sold |
---|---|
Apples | 2,214,411,234 |
Oranges | 9,983,812,411 |
Bananas | 1,234,567,890 |
Pineapples | 9,948,810,000 |
Pears | 9,933,771,111 |
import { NumberFormatter, Table } from '@thinker-core/mantine-core';
const data = [
{ product: 'Apples', unitsSold: 2214411234 },
{ product: 'Oranges', unitsSold: 9983812411 },
{ product: 'Bananas', unitsSold: 1234567890 },
{ product: 'Pineapples', unitsSold: 9948810000 },
{ product: 'Pears', unitsSold: 9933771111 },
];
function Demo() {
const rows = data.map((item) => (
<Table.Tr key={item.product}>
<Table.Td>{item.product}</Table.Td>
<Table.Td>
<NumberFormatter value={item.unitsSold} thousandSeparator />
</Table.Td>
</Table.Tr>
));
return (
<Table tabularNums>
<Table.Thead>
<Table.Tr>
<Table.Th>Product</Table.Th>
<Table.Th>Units sold</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
);
}
Example: Table with row selection
Element position | Element name | Symbol | Atomic mass | |
---|---|---|---|---|
6 | Carbon | C | 12.011 | |
7 | Nitrogen | N | 14.007 | |
39 | Yttrium | Y | 88.906 | |
56 | Barium | Ba | 137.33 | |
58 | Cerium | Ce | 140.12 |
import { useState } from 'react';
import { Table, Checkbox } from '@thinker-core/mantine-core';
const elements = [
{ position: 6, mass: 12.011, symbol: 'C', name: 'Carbon' },
{ position: 7, mass: 14.007, symbol: 'N', name: 'Nitrogen' },
{ position: 39, mass: 88.906, symbol: 'Y', name: 'Yttrium' },
{ position: 56, mass: 137.33, symbol: 'Ba', name: 'Barium' },
{ position: 58, mass: 140.12, symbol: 'Ce', name: 'Cerium' },
];
function Demo() {
const [selectedRows, setSelectedRows] = useState<number[]>([]);
const rows = elements.map((element) => (
<Table.Tr
key={element.name}
bg={selectedRows.includes(element.position) ? 'var(--mantine-color-ocean-light)' : undefined}
>
<Table.Td>
<Checkbox
aria-label="Select row"
checked={selectedRows.includes(element.position)}
onChange={(event) =>
setSelectedRows(
event.currentTarget.checked
? [...selectedRows, element.position]
: selectedRows.filter((position) => position !== element.position)
)
}
/>
</Table.Td>
<Table.Td>{element.position}</Table.Td>
<Table.Td>{element.name}</Table.Td>
<Table.Td>{element.symbol}</Table.Td>
<Table.Td>{element.mass}</Table.Td>
</Table.Tr>
));
return (
<Table>
<Table.Thead>
<Table.Tr>
<Table.Th />
<Table.Th>Element position</Table.Th>
<Table.Th>Element name</Table.Th>
<Table.Th>Symbol</Table.Th>
<Table.Th>Atomic mass</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
);
}
Example: Table with input cell
Number Number is a unique identifier for each row. | Name | Car Type | Chassis No. |
---|---|---|---|
1 | Somsri | Honda | |
2 | Chokdee | Toyota | |
3 | Rumruay | Nissan | |
4 | Hengheng | BYD | |
5 | Charoen | Izuzu |
import { useState } from 'react';
import {
ActionIcon,
Center,
Flex,
Group,
ScrollArea,
Stack,
Table,
Text,
TextInput,
} from '@thinker-core/mantine-core';
import {
ArrowDownSolidIcon,
ArrowUpSolidIcon,
MoreSolidIcon,
SortSolidIcon,
} from '@thinker-core/mantine-icons';
interface RowData {
number: number;
name: string;
carType: string;
chassisNumber?: string;
}
interface ThProps {
sorted?: boolean;
sortable?: boolean;
children: React.ReactNode;
orderBy: 'ASC' | 'DESC' | null;
onSort: () => void;
}
function Th({ children, orderBy, onSort, sortable, sorted }: ThProps) {
const Icon =
sorted && orderBy ? (orderBy === 'ASC' ? ArrowUpSolidIcon : ArrowDownSolidIcon) : SortSolidIcon;
return (
<Table.Th>
<Group onClick={onSort} style={{ cursor: sortable ? 'pointer' : 'default' }}>
{children}
{sortable && (
<Center>
<Icon size={16} stroke="1.5" />
</Center>
)}
</Group>
</Table.Th>
);
}
const tableColumns = [
{
key: 'number',
label: 'Number',
renderLabel: () => (
<Flex align="center" gap="md">
<Stack>
<Text fw={500} fz="sm">
Number
</Text>
<Text fz="xs" c="dimmed">
Number is a unique identifier for each row.
</Text>
</Stack>
<ActionIcon
variant="default"
size="sm"
onClick={(e) => {
e.stopPropagation();
}}
ml="md"
>
<MoreSolidIcon />
</ActionIcon>
</Flex>
),
sortable: true,
},
{
key: 'name',
label: 'Name',
sortable: true,
},
{
key: 'carType',
label: 'Car Type',
},
{
key: 'chassisNumber',
label: 'Chassis No.',
render: (data: RowData) => (
<TextInput value={data.chassisNumber} placeholder="Input Chassis No." />
),
},
];
const data = [
{
number: 1,
name: 'Somsri',
carType: 'Honda',
},
{
number: 2,
name: 'Chokdee',
carType: 'Toyota',
},
{
number: 3,
name: 'Rumruay',
carType: 'Nissan',
},
{
number: 4,
name: 'Hengheng',
carType: 'BYD',
},
{
number: 5,
name: 'Charoen',
carType: 'Izuzu',
},
];
const sortData = (
data: RowData[],
sortBy: keyof RowData | null,
orderBy: 'ASC' | 'DESC' | null
) => {
if (!sortBy) {
return data;
}
return [...data].sort((a, b) => {
if (orderBy === 'ASC') {
if (typeof a[sortBy] === 'string' && typeof b[sortBy] === 'string') {
return a[sortBy].localeCompare(b[sortBy]);
}
if (typeof a[sortBy] === 'number' && typeof b[sortBy] === 'number') {
return a[sortBy] - b[sortBy];
}
}
if (orderBy === 'DESC') {
if (typeof a[sortBy] === 'number' && typeof b[sortBy] === 'number') {
return b[sortBy] - a[sortBy];
}
if (typeof a[sortBy] === 'string' && typeof b[sortBy] === 'string') {
return b[sortBy].localeCompare(a[sortBy]);
}
}
return 0;
});
};
function Demo() {
const [sortBy, setSortBy] = useState<keyof RowData | null>(null);
const [orderBy, setOrderBy] = useState<'ASC' | 'DESC' | null>(null);
const setSorting = (field: keyof RowData) => {
setSortBy(field);
if (field === sortBy) {
setOrderBy(orderBy === 'ASC' ? 'DESC' : orderBy === 'DESC' ? null : 'ASC');
} else {
setOrderBy('ASC');
}
};
const rows = sortData(data, sortBy, orderBy).map((item) => {
return (
<Table.Tr key={item.number}>
{tableColumns.map((column) => (
<Table.Td key={column.key}>
{column.render ? column.render(item) : item?.[column.key as keyof typeof item]}
</Table.Td>
))}
</Table.Tr>
);
});
return (
<ScrollArea>
<Table miw={800} verticalSpacing="sm">
<Table.Thead>
<Table.Tr>
{tableColumns.map((column) => (
<Th
key={column.key}
orderBy={orderBy}
onSort={() => column.sortable && setSorting(column.key as keyof RowData)}
sortable={column.sortable}
sorted={column.key === sortBy}
>
{column.renderLabel ? (
column.renderLabel()
) : (
<Text fw={500} fz="sm">
{column.label}
</Text>
)}
</Th>
))}
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
</ScrollArea>
);
}
Example: Table with row selection and hover
# | Text | Avatar | Badge | ||
---|---|---|---|---|---|
1 | Text | AB AB JD +10 | Badge | ||
2 | Text | AB AB JD +10 | Badge | ||
3 | Text | AB AB JD +10 | Badge | ||
4 | Text | AB AB JD +10 | Badge | ||
5 | Text | AB AB JD +10 | Badge |
import { useState } from 'react';
import cx from 'clsx';
import {
ActionIcon,
Avatar,
Badge,
Checkbox,
Group,
HomeIcon,
ScrollArea,
Table,
Text,
} from '@thinker-core/mantine-core';
import classes from './Demo.module.css';
import data from './data.ts';
function Demo() {
const [selection, setSelection] = useState(['1']);
const toggleRow = (id: string) =>
setSelection((current) =>
current.includes(id) ? current.filter((item) => item !== id) : [...current, id]
);
const toggleAll = () =>
setSelection((current) => (current.length === data.length ? [] : data.map((item) => item.id)));
const rows = data.map((item) => {
const selected = selection.includes(item.id);
return (
<Table.Tr key={item.id} className={cx({ [classes.rowSelected]: selected }, classes.rowHover)}>
<Table.Td>
<Checkbox checked={selection.includes(item.id)} onChange={() => toggleRow(item.id)} />
</Table.Td>
<Table.Td>
<Text size="sm" fw={500}>
{item.id}
</Text>
</Table.Td>
<Table.Td>
<Text size="sm">{item.text}</Text>
</Table.Td>
<Table.Td>
<Avatar.Group>
{item.avatar.slice(0, 3).map((avatar) => (
<Avatar
key={avatar.name}
name={avatar.name}
color="initials"
size="sm"
variant="outline"
/>
))}
{item.avatar.length > 3 && (
<Avatar size="sm" color="initials" variant="outline">
+{item.avatar.length - 3}
</Avatar>
)}
</Avatar.Group>
</Table.Td>
<Table.Td>
<Badge h={20} size="xs">
{item.badge}
</Badge>
</Table.Td>
<Table.Td>
<Group>
{item.actions.map((action) => (
<ActionIcon key={action.id} variant="subtle" size="sm" color={action.color}>
<HomeIcon />
</ActionIcon>
))}
</Group>
</Table.Td>
</Table.Tr>
);
});
return (
<ScrollArea>
<Table miw={800} verticalSpacing="sm">
<Table.Thead>
<Table.Tr>
<Table.Th w={40}>
<Checkbox
onChange={toggleAll}
checked={selection.length === data.length}
indeterminate={selection.length > 0 && selection.length !== data.length}
/>
</Table.Th>
<Table.Th>#</Table.Th>
<Table.Th w={400}>Text</Table.Th>
<Table.Th>Avatar</Table.Th>
<Table.Th>Badge</Table.Th>
<Table.Th>
<div />
</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
</ScrollArea>
);
}
Example: Table with radio row selection
# | Text | Avatar | Badge | ||
---|---|---|---|---|---|
1 | Text | AB AB JD +10 | Badge | ||
2 | Text | AB AB JD +10 | Badge | ||
3 | Text | AB AB JD +10 | Badge | ||
4 | Text | AB AB JD +10 | Badge | ||
5 | Text | AB AB JD +10 | Badge |
import { useState } from 'react';
import cx from 'clsx';
import {
ActionIcon,
Avatar,
Badge,
Checkbox,
Group,
HomeIcon,
ScrollArea,
Table,
Text,
} from '@thinker-core/mantine-core';
import classes from './Demo.module.css';
import data from './data.ts';
function Demo() {
const [selection, setSelection] = useState('1');
const rows = data.map((item) => {
return (
<Table.Tr key={item.id} className={cx(classes.rowHover)} onClick={() => setSelection(item.id)}>
<Table.Td>
<Radio checked={selection === item.id} />
</Table.Td>
<Table.Td>
<Text size="sm" fw={500}>
{item.id}
</Text>
</Table.Td>
<Table.Td>
<Text size="sm">{item.text}</Text>
</Table.Td>
<Table.Td>
<Avatar.Group>
{item.avatar.slice(0, 3).map((avatar) => (
<Avatar
key={avatar.name}
name={avatar.name}
color="initials"
size="sm"
variant="outline"
/>
))}
{item.avatar.length > 3 && (
<Avatar size="sm" color="initials" variant="outline">
+{item.avatar.length - 3}
</Avatar>
)}
</Avatar.Group>
</Table.Td>
<Table.Td>
<Badge h={20} size="xs">
{item.badge}
</Badge>
</Table.Td>
<Table.Td>
<Group>
{item.actions.map((action) => (
<ActionIcon key={action.id} variant="subtle" size="sm" color={action.color}>
<HomeIcon />
</ActionIcon>
))}
</Group>
</Table.Td>
</Table.Tr>
);
});
return (
<ScrollArea>
<Table miw={800} verticalSpacing="sm">
<Table.Thead>
<Table.Tr>
<Table.Th w={40} />
<Table.Th>#</Table.Th>
<Table.Th w={400}>Text</Table.Th>
<Table.Th>Avatar</Table.Th>
<Table.Th>Badge</Table.Th>
<Table.Th>
<div />
</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
</ScrollArea>
);
}