@adobe-commerce/elsie 1.5.0-alpha3000 → 1.5.0-alpha3002
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/Incrementer/Incrementer.css +6 -0
- package/src/components/Incrementer/Incrementer.stories.tsx +18 -0
- package/src/components/Incrementer/Incrementer.tsx +66 -59
- package/src/components/Table/Table.stories.tsx +65 -40
- package/src/components/Table/Table.tsx +86 -53
- package/src/i18n/en_US.json +0 -2
package/package.json
CHANGED
|
@@ -19,6 +19,12 @@
|
|
|
19
19
|
opacity: 1;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
.dropin-incrementer__content--no-buttons {
|
|
23
|
+
grid-template-columns: max-content;
|
|
24
|
+
width: fit-content;
|
|
25
|
+
margin-inline: auto;
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
.dropin-incrementer__content--disabled {
|
|
23
29
|
background: var(--color-neutral-300);
|
|
24
30
|
border-radius: var(--shape-border-radius-1);
|
|
@@ -79,6 +79,10 @@ const meta: Meta<IncrementerProps> = {
|
|
|
79
79
|
description: 'Maximum length of the input field',
|
|
80
80
|
type: 'number',
|
|
81
81
|
},
|
|
82
|
+
showButtons: {
|
|
83
|
+
description: 'Show increase/decrease buttons',
|
|
84
|
+
control: 'boolean',
|
|
85
|
+
},
|
|
82
86
|
},
|
|
83
87
|
};
|
|
84
88
|
|
|
@@ -170,3 +174,17 @@ export const WithError = {
|
|
|
170
174
|
await expect(error).toHaveTextContent('Maximum quantity is 100');
|
|
171
175
|
},
|
|
172
176
|
};
|
|
177
|
+
|
|
178
|
+
export const WithoutButtons: Story = {
|
|
179
|
+
args: {
|
|
180
|
+
size: 'medium',
|
|
181
|
+
onValue: action('onValue'),
|
|
182
|
+
name: 'incrementerField',
|
|
183
|
+
value: '1',
|
|
184
|
+
min: 1,
|
|
185
|
+
max: 100,
|
|
186
|
+
disabled: false,
|
|
187
|
+
'aria-label': 'Quantity',
|
|
188
|
+
showButtons: false,
|
|
189
|
+
},
|
|
190
|
+
};
|
|
@@ -28,6 +28,7 @@ export interface IncrementerProps
|
|
|
28
28
|
max?: number;
|
|
29
29
|
disabled?: boolean;
|
|
30
30
|
maxLength?: number;
|
|
31
|
+
showButtons?: boolean;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export const Incrementer: FunctionComponent<IncrementerProps> = ({
|
|
@@ -42,6 +43,7 @@ export const Incrementer: FunctionComponent<IncrementerProps> = ({
|
|
|
42
43
|
onValue,
|
|
43
44
|
onUpdateError,
|
|
44
45
|
size = 'medium',
|
|
46
|
+
showButtons = true,
|
|
45
47
|
...props
|
|
46
48
|
}) => {
|
|
47
49
|
const [currentValue, setCurrentValue] = useState<number>(Number(value));
|
|
@@ -99,41 +101,44 @@ export const Incrementer: FunctionComponent<IncrementerProps> = ({
|
|
|
99
101
|
className={classes([
|
|
100
102
|
'dropin-incrementer__content',
|
|
101
103
|
`dropin-incrementer__content--${size}`,
|
|
104
|
+
['dropin-incrementer__content--no-buttons', !showButtons],
|
|
102
105
|
[`dropin-incrementer__content--error`, isInvalid],
|
|
103
106
|
[`dropin-incrementer__content--success`, success],
|
|
104
107
|
[`dropin-incrementer__content--disabled`, disabled],
|
|
105
108
|
])}
|
|
106
109
|
>
|
|
107
110
|
{/* Minus Button */}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
<
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
111
|
+
{showButtons && (
|
|
112
|
+
<div
|
|
113
|
+
className={classes([
|
|
114
|
+
'dropin-incrementer__button-container',
|
|
115
|
+
[`dropin-incrementer__button-container--disabled`, disabled],
|
|
116
|
+
])}
|
|
117
|
+
>
|
|
118
|
+
<Localizer>
|
|
119
|
+
<button
|
|
120
|
+
type="button"
|
|
121
|
+
className={classes([
|
|
122
|
+
'dropin-incrementer__decrease-button',
|
|
123
|
+
[`dropin-incrementer__decrease-button--disabled`, disabled],
|
|
124
|
+
])}
|
|
125
|
+
onClick={() => handleIncrementer(currentValue - 1)}
|
|
126
|
+
disabled={disabled || currentValue < minValue + 1}
|
|
127
|
+
aria-label={
|
|
128
|
+
(<Text id="Dropin.Incrementer.decreaseLabel" />) as any
|
|
129
|
+
}
|
|
130
|
+
>
|
|
131
|
+
<Icon
|
|
132
|
+
source={Minus}
|
|
133
|
+
size="16"
|
|
134
|
+
stroke="1"
|
|
135
|
+
viewBox="4 2 20 20"
|
|
136
|
+
className="dropin-incrementer__down"
|
|
137
|
+
/>
|
|
138
|
+
</button>
|
|
139
|
+
</Localizer>
|
|
140
|
+
</div>
|
|
141
|
+
)}
|
|
137
142
|
|
|
138
143
|
{/* Input Field */}
|
|
139
144
|
<input
|
|
@@ -157,36 +162,38 @@ export const Incrementer: FunctionComponent<IncrementerProps> = ({
|
|
|
157
162
|
{...props}
|
|
158
163
|
/>
|
|
159
164
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
<
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
165
|
+
{showButtons && (
|
|
166
|
+
<div
|
|
167
|
+
className={classes([
|
|
168
|
+
'dropin-incrementer__button-container',
|
|
169
|
+
[`dropin-incrementer__button-container--disabled`, disabled],
|
|
170
|
+
])}
|
|
171
|
+
>
|
|
172
|
+
{/* Plus/Add button */}
|
|
173
|
+
<Localizer>
|
|
174
|
+
<button
|
|
175
|
+
type="button"
|
|
176
|
+
className={classes([
|
|
177
|
+
'dropin-incrementer__increase-button',
|
|
178
|
+
[`dropin-incrementer__increase-button--disabled`, disabled],
|
|
179
|
+
])}
|
|
180
|
+
onClick={() => handleIncrementer(currentValue + 1)}
|
|
181
|
+
disabled={disabled || currentValue > maxValue - 1}
|
|
182
|
+
aria-label={
|
|
183
|
+
(<Text id="Dropin.Incrementer.increaseLabel" />) as any
|
|
184
|
+
}
|
|
185
|
+
>
|
|
186
|
+
<Icon
|
|
187
|
+
source={Add}
|
|
188
|
+
size="16"
|
|
189
|
+
stroke="1"
|
|
190
|
+
viewBox="4 2 20 20"
|
|
191
|
+
className="dropin-incrementer__add"
|
|
192
|
+
/>
|
|
193
|
+
</button>
|
|
194
|
+
</Localizer>
|
|
195
|
+
</div>
|
|
196
|
+
)}
|
|
190
197
|
</div>
|
|
191
198
|
{isInvalid && (
|
|
192
199
|
<p className="dropin-incrementer__content--error-message">
|
|
@@ -96,6 +96,20 @@ const meta: Meta<TableProps> = {
|
|
|
96
96
|
},
|
|
97
97
|
control: 'object',
|
|
98
98
|
},
|
|
99
|
+
loading: {
|
|
100
|
+
description: 'When true, renders skeleton rows instead of actual data. Useful for showing loading state while data is being fetched.',
|
|
101
|
+
table: {
|
|
102
|
+
type: { summary: 'boolean' },
|
|
103
|
+
},
|
|
104
|
+
control: 'boolean',
|
|
105
|
+
},
|
|
106
|
+
skeletonRowCount: {
|
|
107
|
+
description: 'Number of skeleton rows to render when loading is true. Defaults to 10 rows.',
|
|
108
|
+
table: {
|
|
109
|
+
type: { summary: 'number' },
|
|
110
|
+
},
|
|
111
|
+
control: 'number',
|
|
112
|
+
},
|
|
99
113
|
},
|
|
100
114
|
};
|
|
101
115
|
|
|
@@ -326,7 +340,7 @@ export const WideTable: Story = {
|
|
|
326
340
|
* {
|
|
327
341
|
* user: <div><strong>John Doe</strong><br/>john@example.com<br/>Senior Developer</div>,
|
|
328
342
|
* description: <div>Lead developer for the<br/>e-commerce platform<br/>with 5+ years experience</div>,
|
|
329
|
-
* status: <span
|
|
343
|
+
* status: <span>Active</span>,
|
|
330
344
|
* actions: <div><button>Edit</button><br/><button>Delete</button><br/><button>View</button></div>
|
|
331
345
|
* }
|
|
332
346
|
* ]}
|
|
@@ -358,22 +372,13 @@ export const ComplexCells: Story = {
|
|
|
358
372
|
</div>
|
|
359
373
|
),
|
|
360
374
|
status: (
|
|
361
|
-
<span
|
|
362
|
-
background: '#22c55e',
|
|
363
|
-
color: 'white',
|
|
364
|
-
padding: '2px 8px',
|
|
365
|
-
borderRadius: '4px',
|
|
366
|
-
fontSize: '12px',
|
|
367
|
-
fontWeight: 'bold'
|
|
368
|
-
}}>
|
|
369
|
-
Active
|
|
370
|
-
</span>
|
|
375
|
+
<span>Active</span>
|
|
371
376
|
),
|
|
372
377
|
actions: (
|
|
373
378
|
<div>
|
|
374
|
-
<button
|
|
375
|
-
<button
|
|
376
|
-
<button
|
|
379
|
+
<button>Edit</button>
|
|
380
|
+
<button>Delete</button>
|
|
381
|
+
<button>View</button>
|
|
377
382
|
</div>
|
|
378
383
|
),
|
|
379
384
|
},
|
|
@@ -393,22 +398,13 @@ export const ComplexCells: Story = {
|
|
|
393
398
|
</div>
|
|
394
399
|
),
|
|
395
400
|
status: (
|
|
396
|
-
<span
|
|
397
|
-
background: '#f59e0b',
|
|
398
|
-
color: 'white',
|
|
399
|
-
padding: '2px 8px',
|
|
400
|
-
borderRadius: '4px',
|
|
401
|
-
fontSize: '12px',
|
|
402
|
-
fontWeight: 'bold'
|
|
403
|
-
}}>
|
|
404
|
-
Pending
|
|
405
|
-
</span>
|
|
401
|
+
<span>Pending</span>
|
|
406
402
|
),
|
|
407
403
|
actions: (
|
|
408
404
|
<div>
|
|
409
|
-
<button
|
|
410
|
-
<button
|
|
411
|
-
<button
|
|
405
|
+
<button>Edit</button>
|
|
406
|
+
<button>Approve</button>
|
|
407
|
+
<button>Reject</button>
|
|
412
408
|
</div>
|
|
413
409
|
),
|
|
414
410
|
},
|
|
@@ -428,22 +424,13 @@ export const ComplexCells: Story = {
|
|
|
428
424
|
</div>
|
|
429
425
|
),
|
|
430
426
|
status: (
|
|
431
|
-
<span
|
|
432
|
-
background: '#ef4444',
|
|
433
|
-
color: 'white',
|
|
434
|
-
padding: '2px 8px',
|
|
435
|
-
borderRadius: '4px',
|
|
436
|
-
fontSize: '12px',
|
|
437
|
-
fontWeight: 'bold'
|
|
438
|
-
}}>
|
|
439
|
-
Inactive
|
|
440
|
-
</span>
|
|
427
|
+
<span>Inactive</span>
|
|
441
428
|
),
|
|
442
429
|
actions: (
|
|
443
430
|
<div>
|
|
444
|
-
<button
|
|
445
|
-
<button
|
|
446
|
-
<button
|
|
431
|
+
<button>Edit</button>
|
|
432
|
+
<button>Activate</button>
|
|
433
|
+
<button>Archive</button>
|
|
447
434
|
</div>
|
|
448
435
|
),
|
|
449
436
|
},
|
|
@@ -645,4 +632,42 @@ export const RowDetails: Story = {
|
|
|
645
632
|
},
|
|
646
633
|
};
|
|
647
634
|
|
|
635
|
+
/**
|
|
636
|
+
* Table in loading state with skeleton rows.
|
|
637
|
+
* Demonstrates how the table appears while data is being fetched.
|
|
638
|
+
* Each cell shows a skeleton placeholder that matches the table structure.
|
|
639
|
+
*
|
|
640
|
+
* **Features**:
|
|
641
|
+
* - Shows skeleton rows instead of actual data when `loading` is true
|
|
642
|
+
* - Configurable number of skeleton rows via `skeletonRowCount` prop
|
|
643
|
+
* - Maintains table structure and column headers during loading
|
|
644
|
+
* - Each cell contains a single-line skeleton component
|
|
645
|
+
*
|
|
646
|
+
* ```tsx
|
|
647
|
+
* <Table
|
|
648
|
+
* loading={true}
|
|
649
|
+
* skeletonRowCount={5}
|
|
650
|
+
* columns={[
|
|
651
|
+
* { key: 'name', label: 'Name' },
|
|
652
|
+
* { key: 'email', label: 'Email' },
|
|
653
|
+
* { key: 'status', label: 'Status' }
|
|
654
|
+
* ]}
|
|
655
|
+
* rowData={[]} // Empty array when loading
|
|
656
|
+
* />
|
|
657
|
+
* ```
|
|
658
|
+
*/
|
|
659
|
+
export const LoadingState: Story = {
|
|
660
|
+
args: {
|
|
661
|
+
loading: true,
|
|
662
|
+
skeletonRowCount: 5,
|
|
663
|
+
columns: [
|
|
664
|
+
{ key: 'name', label: 'Name' },
|
|
665
|
+
{ key: 'email', label: 'Email' },
|
|
666
|
+
{ key: 'status', label: 'Status' },
|
|
667
|
+
{ key: 'actions', label: 'Actions' },
|
|
668
|
+
],
|
|
669
|
+
rowData: [], // Empty when loading
|
|
670
|
+
},
|
|
671
|
+
};
|
|
672
|
+
|
|
648
673
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { FunctionComponent, VNode, Fragment } from 'preact';
|
|
11
11
|
import { HTMLAttributes } from 'preact/compat';
|
|
12
12
|
import { classes, VComponent } from '@adobe-commerce/elsie/lib';
|
|
13
|
-
import { Icon, Button } from '@adobe-commerce/elsie/components';
|
|
13
|
+
import { Icon, Button, Skeleton, SkeletonRow } from '@adobe-commerce/elsie/components';
|
|
14
14
|
import { useText } from '@adobe-commerce/elsie/i18n';
|
|
15
15
|
|
|
16
16
|
import '@adobe-commerce/elsie/components/Table/Table.css';
|
|
@@ -28,13 +28,15 @@ type RowData = {
|
|
|
28
28
|
_rowDetails?: VNode | string; // Special property for expandable row content
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
export interface TableProps extends HTMLAttributes<HTMLTableElement> {
|
|
31
|
+
export interface TableProps extends Omit<HTMLAttributes<HTMLTableElement>, 'loading'> {
|
|
32
32
|
columns: Column[];
|
|
33
33
|
rowData: RowData[];
|
|
34
34
|
mobileLayout?: 'stacked' | 'none';
|
|
35
35
|
caption?: string;
|
|
36
|
-
onSortChange?: (columnKey: string, direction: Sortable) => void;
|
|
37
36
|
expandedRows?: Set<number>;
|
|
37
|
+
loading?: boolean;
|
|
38
|
+
skeletonRowCount?: number;
|
|
39
|
+
onSortChange?: (columnKey: string, direction: Sortable) => void;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
export const Table: FunctionComponent<TableProps> = ({
|
|
@@ -44,13 +46,13 @@ export const Table: FunctionComponent<TableProps> = ({
|
|
|
44
46
|
rowData = [],
|
|
45
47
|
mobileLayout = 'none',
|
|
46
48
|
caption,
|
|
47
|
-
onSortChange,
|
|
48
49
|
expandedRows = new Set(),
|
|
50
|
+
loading = false,
|
|
51
|
+
skeletonRowCount = 10,
|
|
52
|
+
onSortChange,
|
|
49
53
|
...props
|
|
50
54
|
}) => {
|
|
51
55
|
const translations = useText({
|
|
52
|
-
ariaSortAscending: 'Dropin.Table.ariaSortAscending',
|
|
53
|
-
ariaSortDescending: 'Dropin.Table.ariaSortDescending',
|
|
54
56
|
sortedAscending: 'Dropin.Table.sortedAscending',
|
|
55
57
|
sortedDescending: 'Dropin.Table.sortedDescending',
|
|
56
58
|
sortBy: 'Dropin.Table.sortBy',
|
|
@@ -72,7 +74,7 @@ export const Table: FunctionComponent<TableProps> = ({
|
|
|
72
74
|
onSortChange(column.key, nextDirection);
|
|
73
75
|
};
|
|
74
76
|
|
|
75
|
-
const
|
|
77
|
+
const renderSortButton = (column: Column) => {
|
|
76
78
|
if (column.sortBy === undefined) return null;
|
|
77
79
|
|
|
78
80
|
let iconSource: string;
|
|
@@ -101,6 +103,74 @@ export const Table: FunctionComponent<TableProps> = ({
|
|
|
101
103
|
);
|
|
102
104
|
};
|
|
103
105
|
|
|
106
|
+
const renderSkeletonRows = () => {
|
|
107
|
+
return Array.from({ length: skeletonRowCount }, (_, rowIndex) => (
|
|
108
|
+
<tr key={`skeleton-${rowIndex}`} className="dropin-table__body__row">
|
|
109
|
+
{columns.map((column) => (
|
|
110
|
+
<td key={column.key} className="dropin-table__body__cell" data-label={column.label}>
|
|
111
|
+
<Skeleton>
|
|
112
|
+
<SkeletonRow variant="row" size="small" fullWidth />
|
|
113
|
+
</Skeleton>
|
|
114
|
+
</td>
|
|
115
|
+
))}
|
|
116
|
+
</tr>
|
|
117
|
+
));
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const renderDataRows = () => {
|
|
121
|
+
return rowData.map((row, rowIndex) => {
|
|
122
|
+
const hasDetails = row._rowDetails !== undefined;
|
|
123
|
+
const isExpanded = expandedRows.has(rowIndex);
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<Fragment key={rowIndex}>
|
|
127
|
+
<tr className="dropin-table__body__row">
|
|
128
|
+
{columns.map((column) => {
|
|
129
|
+
const cell = row[column.key];
|
|
130
|
+
|
|
131
|
+
if (typeof cell === 'string' || typeof cell === 'number') {
|
|
132
|
+
return (
|
|
133
|
+
<td key={column.key} className="dropin-table__body__cell" data-label={column.label}>
|
|
134
|
+
{cell}
|
|
135
|
+
</td>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<td key={column.key} className="dropin-table__body__cell" data-label={column.label}>
|
|
141
|
+
<VComponent node={cell!} />
|
|
142
|
+
</td>
|
|
143
|
+
);
|
|
144
|
+
})}
|
|
145
|
+
</tr>
|
|
146
|
+
{hasDetails && isExpanded && (
|
|
147
|
+
<tr
|
|
148
|
+
key={`${rowIndex}-details`}
|
|
149
|
+
className="dropin-table__row-details dropin-table__row-details--expanded"
|
|
150
|
+
id={`row-${rowIndex}-details`}
|
|
151
|
+
>
|
|
152
|
+
<td
|
|
153
|
+
className="dropin-table__row-details__cell"
|
|
154
|
+
colSpan={columns.length}
|
|
155
|
+
role="region"
|
|
156
|
+
aria-labelledby={`row-${rowIndex}-details`}
|
|
157
|
+
>
|
|
158
|
+
{typeof row._rowDetails === 'string' ? row._rowDetails : <VComponent node={row._rowDetails!} />}
|
|
159
|
+
</td>
|
|
160
|
+
</tr>
|
|
161
|
+
)}
|
|
162
|
+
</Fragment>
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const getAriaSort = (column: Column): 'none' | 'ascending' | 'descending' | 'other' | undefined => {
|
|
168
|
+
if (column.sortBy === true) return 'none';
|
|
169
|
+
if (column.sortBy === 'asc') return 'ascending';
|
|
170
|
+
if (column.sortBy === 'desc') return 'descending';
|
|
171
|
+
return undefined;
|
|
172
|
+
};
|
|
173
|
+
|
|
104
174
|
return (
|
|
105
175
|
<div className={classes(['dropin-table', `dropin-table--mobile-layout-${mobileLayout}`, className])}>
|
|
106
176
|
<table {...props} className="dropin-table__table">
|
|
@@ -115,59 +185,22 @@ export const Table: FunctionComponent<TableProps> = ({
|
|
|
115
185
|
['dropin-table__header__cell--sorted', column.sortBy === 'asc' || column.sortBy === 'desc'],
|
|
116
186
|
['dropin-table__header__cell--sortable', column.sortBy !== undefined]
|
|
117
187
|
])}
|
|
118
|
-
|
|
188
|
+
aria-sort={getAriaSort(column)}
|
|
119
189
|
>
|
|
120
190
|
{column.label}
|
|
121
|
-
{
|
|
191
|
+
{renderSortButton(column)}
|
|
122
192
|
</th>
|
|
123
193
|
))}
|
|
124
194
|
</tr>
|
|
125
195
|
</thead>
|
|
126
196
|
<tbody className="dropin-table__body">
|
|
127
|
-
{
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
{columns.map((column) => {
|
|
135
|
-
const cell = row[column.key];
|
|
136
|
-
|
|
137
|
-
if (typeof cell === 'string' || typeof cell === 'number') {
|
|
138
|
-
return (
|
|
139
|
-
<td key={column.key} className="dropin-table__body__cell" data-label={column.label}>
|
|
140
|
-
{cell}
|
|
141
|
-
</td>
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return (
|
|
146
|
-
<td key={column.key} className="dropin-table__body__cell" data-label={column.label}>
|
|
147
|
-
<VComponent node={cell!} />
|
|
148
|
-
</td>
|
|
149
|
-
);
|
|
150
|
-
})}
|
|
151
|
-
</tr>
|
|
152
|
-
{hasDetails && isExpanded && (
|
|
153
|
-
<tr
|
|
154
|
-
key={`${rowIndex}-details`}
|
|
155
|
-
className="dropin-table__row-details dropin-table__row-details--expanded"
|
|
156
|
-
id={`row-${rowIndex}-details`}
|
|
157
|
-
>
|
|
158
|
-
<td
|
|
159
|
-
className="dropin-table__row-details__cell"
|
|
160
|
-
colSpan={columns.length}
|
|
161
|
-
role="region"
|
|
162
|
-
aria-labelledby={`row-${rowIndex}-details`}
|
|
163
|
-
>
|
|
164
|
-
{typeof row._rowDetails === 'string' ? row._rowDetails : <VComponent node={row._rowDetails!} />}
|
|
165
|
-
</td>
|
|
166
|
-
</tr>
|
|
167
|
-
)}
|
|
168
|
-
</Fragment>
|
|
169
|
-
);
|
|
170
|
-
})}
|
|
197
|
+
{loading ? (
|
|
198
|
+
// Render skeleton rows when loading
|
|
199
|
+
renderSkeletonRows()
|
|
200
|
+
) : (
|
|
201
|
+
// Render actual data when not loading
|
|
202
|
+
renderDataRows()
|
|
203
|
+
)}
|
|
171
204
|
</tbody>
|
|
172
205
|
</table>
|
|
173
206
|
</div>
|
package/src/i18n/en_US.json
CHANGED
|
@@ -143,8 +143,6 @@
|
|
|
143
143
|
"picker": "Select a date"
|
|
144
144
|
},
|
|
145
145
|
"Table": {
|
|
146
|
-
"ariaSortAscending": "ascending",
|
|
147
|
-
"ariaSortDescending": "descending",
|
|
148
146
|
"sortedAscending": "Sort {label} ascending",
|
|
149
147
|
"sortedDescending": "Sort {label} descending",
|
|
150
148
|
"sortBy": "Sort by {label}"
|