Skip to content

Commit e78a99c

Browse files
added more scenarios
1 parent babe87c commit e78a99c

5 files changed

Lines changed: 258 additions & 125 deletions

File tree

package-lock.json

Lines changed: 49 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,14 @@
1111
},
1212
"dependencies": {
1313
"@semcore/base-components": "^16.4.2",
14+
"@semcore/button": "^16.0.12",
1415
"@semcore/data-table": "^16.5.3",
16+
"@semcore/dropdown-menu": "^16.2.2",
1517
"@semcore/icon": "^16.7.4",
1618
"@semcore/pagination": "^16.1.12",
19+
"@semcore/tooltip": "^16.0.11",
1720
"@semcore/typography": "^16.3.2",
21+
"@semcore/widget-empty": "^16.0.11",
1822
"react": "^18.3.1",
1923
"react-dom": "^18.3.1"
2024
},

src/ActionBar.tsx

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { Flex, ScreenReaderOnly } from '@semcore/base-components';
2+
import { Text } from '@semcore/typography';
3+
import Button from '@semcore/button';
4+
import Settings from '@semcore/icon/Settings/m';
5+
import { columns as defaultColumns } from './data';
6+
import DropdownMenu from '@semcore/dropdown-menu';
7+
8+
interface ActionBarProps {
9+
ariaMessage: string;
10+
selectedRowsDisplay: number;
11+
columns: typeof defaultColumns;
12+
setColumns: (columns: typeof defaultColumns) => void;
13+
handleDelete: () => void;
14+
}
15+
16+
const ActionBar = ({ ariaMessage, selectedRowsDisplay, columns, setColumns, handleDelete }: ActionBarProps) => {
17+
const handleColumn = (value: string) => {
18+
console.log(value)
19+
const newColumns = columns.map(column => {
20+
if (column.name === value) {
21+
column.enabled = !column.enabled
22+
}
23+
return column;
24+
});
25+
setColumns(newColumns);
26+
}
27+
return (
28+
<Flex
29+
role='region'
30+
aria-label='Table action bar'
31+
alignItems='center'
32+
h={44}
33+
gap={6}
34+
px={3}
35+
>
36+
<ScreenReaderOnly role='status' aria-live='polite'>
37+
{ariaMessage}
38+
</ScreenReaderOnly>
39+
{selectedRowsDisplay !== 0 && (
40+
<>
41+
<Text size={200}>
42+
Selected rows:
43+
{' '}
44+
<Text bold>{selectedRowsDisplay}</Text>
45+
</Text>
46+
<Button use='tertiary' onClick={handleDelete}>
47+
Delete selected
48+
</Button>
49+
</>
50+
)}
51+
<DropdownMenu multiselect>
52+
<DropdownMenu.Trigger
53+
ml='auto'
54+
tag={Button}
55+
use='tertiary'
56+
addonLeft={Settings}
57+
id='menu-trigger'
58+
>
59+
Manage columns
60+
</DropdownMenu.Trigger>
61+
<DropdownMenu.Menu aria-labelledby='menu-trigger'>
62+
{columns.map(column => (
63+
<DropdownMenu.Item
64+
key={column.name}
65+
selected={column.enabled}
66+
onClick={() => handleColumn(column.name)}
67+
disabled={column.name === 'name'}
68+
>
69+
{column.children}
70+
</DropdownMenu.Item>
71+
))}
72+
</DropdownMenu.Menu>
73+
</DropdownMenu>
74+
</Flex>
75+
)
76+
}
77+
78+
export default ActionBar;

src/App.tsx

Lines changed: 54 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
import type { DataTableSort } from '@semcore/data-table';
22
import { DataTable } from '@semcore/data-table';
3-
import { Flex } from '@semcore/base-components';
4-
import { Text } from '@semcore/typography';
3+
import { Box } from '@semcore/base-components';
54
import Pagination from '@semcore/pagination';
5+
import ActionBar from './ActionBar';
6+
import './App.css';
7+
import { data as defaultData, columns as defaultColumns } from './data';
68
import React from 'react';
7-
8-
type SortableColumn = Exclude<keyof typeof data[0], 'name' | 'category' | 'season'>;
9+
import { NoData } from '@semcore/widget-empty';
910

1011
const App = () => {
11-
const [sort, setSort] = React.useState<DataTableSort<keyof typeof data[0]>>(['temp', 'desc']);
12+
const [columns, setColumns] = React.useState(defaultColumns);
13+
const [data, setData] = React.useState(defaultData);
14+
15+
type SortableColumn = keyof typeof data[0];
16+
const [sort, setSort] = React.useState<DataTableSort<keyof typeof data[0]>>(['name', 'asc']);
1217
const sortedData = React.useMemo(
1318
() =>
1419
[...data].sort((aRow, bRow) => {
@@ -19,153 +24,77 @@ const App = () => {
1924
if (sortDirection === 'asc') return a > b ? 1 : -1;
2025
else return a > b ? -1 : 1;
2126
}),
22-
[sort],
27+
[sort, data],
2328
);
24-
const numberFormat = React.useMemo(() => new Intl.NumberFormat('en-US'), []);
2529

2630
const handleSortChange: (sort: DataTableSort<string>, e?: React.SyntheticEvent) => void = (
2731
newSort,
2832
) => {
2933
setSort(newSort as DataTableSort<SortableColumn>);
3034
};
3135
const [selectedRows, setSelectedRows] = React.useState<string[]>([]);
32-
const [selectedRowsDisplay, setSelectedRowsDisplay] = React.useState(0);
36+
// const [selectedRowsDisplay, setSelectedRowsDisplay] = React.useState(0);
3337
const [ariaMessage, setAriaMessage] = React.useState('');
3438
const [currentPage, setCurrentPage] = React.useState(0);
35-
// const tableRef = React.useRef<HTMLDivElement>(null);
3639

3740
const handleChangeSelectedRows = (value: string[]) => {
3841
setSelectedRows(value);
39-
if (!selectedRows.length) setAriaMessage('Action bar appeared before the table');
40-
if (value.length) setSelectedRowsDisplay(value.length);
42+
if (!selectedRows.length) setAriaMessage('Actions are available before the table');
43+
// if (value.length) setSelectedRowsDisplay(value.length);
44+
console.log(selectedRows)
4145
};
4246

43-
// const handleDeselectAll = () => {
44-
// setSelectedRows([]);
45-
// tableRef.current?.focus();
46-
// };
47-
4847
React.useEffect(() => {
4948
const timer = setTimeout(() => setAriaMessage(''), 300);
5049
return () => clearTimeout(timer);
5150
}, [ariaMessage]);
5251

52+
const handleDelete = () => {
53+
const newData = data.filter(row => !selectedRows.includes(row.name))
54+
setData(newData);
55+
handleChangeSelectedRows([]);
56+
tableRef.current?.focus();
57+
};
58+
5359
const limit = 10;
5460
const tableData = sortedData.slice(currentPage * limit, currentPage * limit + limit);
5561

62+
const tableRef = React.useRef<HTMLDivElement>(null);
63+
5664
return (
5765
<>
58-
<Flex
59-
role='region'
60-
aria-label='Table action bar'
61-
alignItems='center'
62-
gap={6}
63-
py={2}
64-
px={3}
65-
style={{
66-
backgroundColor: 'var(--intergalactic-bg-primary-neutral, #ffffff)',
67-
}}
68-
>
69-
<Text size={200}>
70-
Selected rows:
71-
{' '}
72-
<Text bold>{selectedRowsDisplay}</Text>
73-
</Text>
74-
{/* <Button use='tertiary' onClick={handleDeselectAll}>
75-
Deselect all
76-
</Button> */}
77-
</Flex>
78-
<DataTable
79-
data={tableData}
80-
sort={sort}
81-
onSortChange={handleSortChange}
82-
aria-label='Sorting'
83-
wMax={800}
84-
selectedRows={selectedRows}
85-
onSelectedRowsChange={handleChangeSelectedRows}
86-
columns={columns}
87-
renderCell={(props) => {
88-
if (['name', 'category', 'season'].includes(props.columnName.toString())) {
89-
return props.defaultRender();
90-
}
91-
92-
const rawValue = props.row[props.columnName as SortableColumn];
93-
94-
return typeof rawValue === 'number' && rawValue !== -1
95-
? numberFormat.format(rawValue)
96-
: 'n/a';
97-
}}
98-
/>
99-
<Pagination
100-
mt={4}
101-
totalPages={Math.ceil(data.length / limit)}
102-
currentPage={currentPage + 1}
103-
onCurrentPageChange={(page) => setCurrentPage(page - 1)}
104-
aria-label='Table with selectable rows pagination'
105-
/>
66+
<h1>Welcome to the Table testing page</h1>
67+
<Box wMax={800}>
68+
<ActionBar
69+
ariaMessage={ariaMessage}
70+
selectedRowsDisplay={selectedRows.length}
71+
columns={columns}
72+
setColumns={setColumns}
73+
handleDelete={handleDelete}
74+
/>
75+
<DataTable
76+
data={tableData}
77+
sort={sort}
78+
onSortChange={handleSortChange}
79+
defaultGridTemplateColumnWidth='1fr'
80+
aria-label='Fruits and vegetables'
81+
uniqueRowKey='name'
82+
ref={tableRef}
83+
selectedRows={selectedRows}
84+
onSelectedRowsChange={handleChangeSelectedRows}
85+
columns={columns.filter(column => column.enabled)}
86+
renderEmptyData={() => <NoData w='100%' my={10} description="There's no data to show!" />}
87+
/>
88+
<Pagination
89+
mt={4}
90+
totalPages={Math.ceil(data.length / limit)}
91+
currentPage={currentPage + 1}
92+
onCurrentPageChange={(page) => setCurrentPage(page - 1)}
93+
aria-label='Table pagination'
94+
/>
95+
</Box>
10696
</>
10797
);
10898
};
10999

110100
export default App;
111-
112-
const data = [
113-
{ name: 'Apple', category: 'Fruit', season: 'Fall', weight: 182, temp: 2 },
114-
{ name: 'Apricot', category: 'Fruit', season: 'Summer', weight: 35, temp: 0 },
115-
{ name: 'Artichoke', category: 'Vegetable', season: 'Spring', weight: 340, temp: 1 },
116-
{ name: 'Asparagus', category: 'Vegetable', season: 'Spring', weight: 20, temp: 2 },
117-
{ name: 'Banana', category: 'Fruit', season: 'Year - round', weight: 120, temp: 13 },
118-
{ name: 'Beetroot', category: 'Vegetable', season: 'Winter', weight: 150, temp: 0 },
119-
{ name: 'Blueberry', category: 'Fruit', season: 'Summer', weight: 1, temp: 1 },
120-
{ name: 'Broccoli', category: 'Vegetable', season: 'Fall', weight: 225, temp: 0 },
121-
{ name: 'Cabbage', category: 'Vegetable', season: 'Winter', weight: 900, temp: 1 },
122-
{ name: 'Carrot', category: 'Vegetable', season: 'Year - round', weight: 60, temp: 0 },
123-
{ name: 'Cauliflower', category: 'Vegetable', season: 'Fall', weight: 575, temp: 0 },
124-
{ name: 'Cherry', category: 'Fruit', season: 'Summer', weight: 8, temp: 0 },
125-
{ name: 'Cucumber', category: 'Vegetable', season: 'Summer', weight: 300, temp: 10 },
126-
{ name: 'Eggplant', category: 'Vegetable', season: 'Summer', weight: 450, temp: 12 },
127-
{ name: 'Fig', category: 'Fruit', season: 'Fall', weight: 50, temp: 0 },
128-
{ name: 'Garlic', category: 'Vegetable', season: 'Summer', weight: 50, temp: 15 },
129-
{ name: 'Grape', category: 'Fruit', season: 'Fall', weight: 5, temp: 1 },
130-
{ name: 'Kale', category: 'Vegetable', season: 'Winter', weight: 60, temp: 0 },
131-
{ name: 'Kiwi', category: 'Fruit', season: 'Winter', weight: 70, temp: 0 },
132-
{ name: 'Lemon', category: 'Fruit', season: 'Winter', weight: 100, temp: 10 },
133-
{ name: 'Lettuce', category: 'Vegetable', season: 'Spring', weight: 500, temp: 1 },
134-
{ name: 'Mango', category: 'Fruit', season: 'Summer', weight: 330, temp: 12 },
135-
{ name: 'Onion', category: 'Vegetable', season: 'Fall', weight: 110, temp: 15 },
136-
{ name: 'Orange', category: 'Fruit', season: 'Winter', weight: 130, temp: 4 },
137-
{ name: 'Peach', category: 'Fruit', season: 'Summer', weight: 150, temp: 0 },
138-
{ name: 'Pear', category: 'Fruit', season: 'Fall', weight: 180, temp: 0 },
139-
{ name: 'Radish', category: 'Vegetable', season: 'Spring', weight: 20, temp: 1 },
140-
{ name: 'Spinach', category: 'Vegetable', season: 'Spring', weight: 30, temp: 0 },
141-
{ name: 'Strawberry', category: 'Fruit', season: 'Spring', weight: 12, temp: 2 },
142-
{ name: 'Zucchini', category: 'Vegetable', season: 'Summer', weight: 200, temp: 7 },
143-
];
144-
145-
const columns = [
146-
{ name: 'name', children: 'Name', justifyContent: 'left', sortable: true },
147-
{
148-
name: 'category',
149-
children: 'Category',
150-
// sortable: true,
151-
},
152-
{
153-
name: 'season',
154-
children: 'Season',
155-
// sortable: 'asc'
156-
},
157-
{
158-
name: 'weight',
159-
children: 'Weight (g)',
160-
gtcWidth: 'max-content',
161-
justifyContent: 'right',
162-
sortable: true,
163-
},
164-
{
165-
name: 'temp',
166-
children: 'Storage temp. (℃)',
167-
gtcWidth: 'max-content',
168-
justifyContent: 'right',
169-
sortable: true,
170-
},
171-
]

0 commit comments

Comments
 (0)