@indico-data/design-system 2.47.3 → 2.49.0

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.
Files changed (54) hide show
  1. package/lib/components/index.d.ts +1 -0
  2. package/lib/components/pagination/Pagination.d.ts +2 -0
  3. package/lib/components/pagination/Pagination.stories.d.ts +6 -0
  4. package/lib/components/pagination/__tests__/Pagination.test.d.ts +1 -0
  5. package/lib/components/pagination/index.d.ts +1 -0
  6. package/lib/components/pagination/types.d.ts +6 -0
  7. package/lib/components/table/Table.stories.d.ts +1 -0
  8. package/lib/components/table/__tests__/Table.test.d.ts +1 -0
  9. package/lib/components/table/components/HorizontalStickyHeader.d.ts +10 -0
  10. package/lib/components/table/components/TablePagination.d.ts +9 -0
  11. package/lib/components/table/components/__tests__/HorizontalStickyHeader.test.d.ts +1 -0
  12. package/lib/components/table/components/__tests__/TablePagination.test.d.ts +1 -0
  13. package/lib/components/table/components/helpers.d.ts +6 -0
  14. package/lib/components/table/hooks/usePinnedColumnsManager.d.ts +8 -0
  15. package/lib/components/table/sampleData.d.ts +6 -0
  16. package/lib/components/table/types.d.ts +16 -5
  17. package/lib/components/table/utils/processColumns.d.ts +2 -0
  18. package/lib/index.css +78 -17
  19. package/lib/index.d.ts +16 -5
  20. package/lib/index.esm.css +78 -17
  21. package/lib/index.esm.js +305 -14
  22. package/lib/index.esm.js.map +1 -1
  23. package/lib/index.js +304 -13
  24. package/lib/index.js.map +1 -1
  25. package/lib/utils/getPreviousHeadersWidth.d.ts +1 -0
  26. package/package.json +1 -1
  27. package/src/components/index.ts +1 -0
  28. package/src/components/pagination/Pagination.mdx +31 -0
  29. package/src/components/pagination/Pagination.stories.tsx +80 -0
  30. package/src/components/pagination/Pagination.tsx +117 -0
  31. package/src/components/pagination/__tests__/Pagination.test.tsx +91 -0
  32. package/src/components/pagination/index.ts +1 -0
  33. package/src/components/pagination/styles/Pagination.scss +22 -0
  34. package/src/components/pagination/types.ts +6 -0
  35. package/src/components/table/Table.mdx +136 -0
  36. package/src/components/table/Table.stories.tsx +91 -30
  37. package/src/components/table/Table.tsx +25 -2
  38. package/src/components/table/__tests__/Table.test.tsx +10 -0
  39. package/src/components/table/components/HorizontalStickyHeader.tsx +57 -0
  40. package/src/components/table/components/TablePagination.tsx +44 -0
  41. package/src/components/table/components/__tests__/HorizontalStickyHeader.test.tsx +104 -0
  42. package/src/components/table/components/__tests__/TablePagination.test.tsx +17 -0
  43. package/src/components/table/components/helpers.ts +90 -0
  44. package/src/components/table/hooks/usePinnedColumnsManager.ts +146 -0
  45. package/src/components/table/sampleData.tsx +436 -0
  46. package/src/components/table/styles/Table.scss +72 -24
  47. package/src/components/table/styles/_variables.scss +3 -0
  48. package/src/components/table/types.ts +19 -7
  49. package/src/components/table/utils/processColumns.tsx +35 -0
  50. package/src/setup/setupIcons.ts +4 -0
  51. package/src/setup/setupTests.ts +8 -0
  52. package/src/styles/index.scss +1 -0
  53. package/src/utils/getPreviousHeadersWidth.ts +12 -0
  54. package/src/components/table/sampleData.ts +0 -171
@@ -0,0 +1,436 @@
1
+ import { TableColumn } from './types';
2
+ import { useState } from 'react';
3
+ import { Table } from './Table';
4
+
5
+ export interface SampleDataRow {
6
+ name: string;
7
+ class: string;
8
+ age: number;
9
+ weapon: string;
10
+ backstory: string;
11
+ favoriteMeal: string;
12
+ homeland: string;
13
+ alignment: string;
14
+ specialAbility: string;
15
+ test: string;
16
+ }
17
+
18
+ export const sampleData: SampleDataRow[] = [
19
+ {
20
+ name: 'Thalion',
21
+ class: 'Ranger',
22
+ age: 120,
23
+ weapon: 'Longbow',
24
+ backstory: 'Raised by wolves in the deep forests.',
25
+ favoriteMeal: 'Venison stew',
26
+ homeland: 'Silverleaf Forest',
27
+ alignment: 'Neutral Good',
28
+ specialAbility: 'Beast Speech',
29
+ test: 'test',
30
+ },
31
+ {
32
+ name: 'Brom',
33
+ class: 'Fighter',
34
+ age: 35,
35
+ weapon: 'Greatsword',
36
+ backstory: 'A former soldier seeking redemption.',
37
+ favoriteMeal: 'Roasted boar',
38
+ homeland: 'Kingdom of Valorhaven',
39
+ alignment: 'Lawful Good',
40
+ specialAbility: 'Battle Master',
41
+ test: 'test',
42
+ },
43
+ {
44
+ name: 'Elysia',
45
+ class: 'Cleric',
46
+ age: 60,
47
+ weapon: 'Mace',
48
+ backstory: 'A devoted follower of the goddess of life.',
49
+ favoriteMeal: 'Vegetable soup',
50
+ homeland: 'Temple of Dawn',
51
+ alignment: 'Lawful Good',
52
+ specialAbility: 'Divine Healing',
53
+ test: 'test',
54
+ },
55
+ {
56
+ name: 'Faelar',
57
+ class: 'Rogue',
58
+ age: 80,
59
+ weapon: 'Dagger',
60
+ backstory: 'Grew up on the streets of a bustling city.',
61
+ favoriteMeal: 'Bread and cheese',
62
+ homeland: 'Shadowport City',
63
+ alignment: 'Chaotic Neutral',
64
+ specialAbility: 'Shadow Step',
65
+ test: 'test',
66
+ },
67
+ {
68
+ name: 'Maelis',
69
+ class: 'Wizard',
70
+ age: 200,
71
+ weapon: 'Staff',
72
+ backstory: 'A scholar obsessed with ancient magic.',
73
+ favoriteMeal: 'Mushroom stew',
74
+ homeland: 'Crystal Spire Academy',
75
+ alignment: 'Neutral',
76
+ specialAbility: 'Time Manipulation',
77
+ test: 'test',
78
+ },
79
+ {
80
+ name: 'Grimm',
81
+ class: 'Barbarian',
82
+ age: 40,
83
+ weapon: 'Battleaxe',
84
+ backstory: 'Hails from a tribe in the frozen north.',
85
+ favoriteMeal: 'Grilled salmon',
86
+ homeland: 'Frostpeak Mountains',
87
+ alignment: 'Chaotic Good',
88
+ specialAbility: 'Berserker Rage',
89
+ test: 'test',
90
+ },
91
+ {
92
+ name: 'Seraphina',
93
+ class: 'Bard',
94
+ age: 25,
95
+ weapon: 'Rapier',
96
+ backstory: 'A wandering minstrel with a mysterious past.',
97
+ favoriteMeal: 'Apple pie',
98
+ homeland: 'Wandering Roads',
99
+ alignment: 'Chaotic Good',
100
+ specialAbility: 'Enchanting Voice',
101
+ test: 'test',
102
+ },
103
+ {
104
+ name: 'Kael',
105
+ class: 'Druid',
106
+ age: 75,
107
+ weapon: 'Scimitar',
108
+ backstory: 'A guardian of the natural world.',
109
+ favoriteMeal: 'Berry tart',
110
+ homeland: 'Emerald Grove',
111
+ alignment: 'True Neutral',
112
+ specialAbility: 'Wild Shape',
113
+ test: 'test',
114
+ },
115
+ {
116
+ name: 'Aria',
117
+ class: 'Paladin',
118
+ age: 30,
119
+ weapon: 'Longsword',
120
+ backstory: 'A knight on a divine mission.',
121
+ favoriteMeal: 'Roasted chicken',
122
+ homeland: 'Radiant Citadel',
123
+ alignment: 'Lawful Good',
124
+ specialAbility: 'Holy Smite',
125
+ test: 'test',
126
+ },
127
+ {
128
+ name: 'Xan',
129
+ class: 'Warlock',
130
+ age: 45,
131
+ weapon: 'Pact Blade',
132
+ backstory: 'Made a pact with a powerful entity for magic.',
133
+ favoriteMeal: 'Stuffed peppers',
134
+ homeland: 'Shadowfell Gate',
135
+ alignment: 'Lawful Evil',
136
+ specialAbility: 'Eldritch Blast',
137
+ test: 'test',
138
+ },
139
+ {
140
+ name: 'Lyra',
141
+ class: 'Sorcerer',
142
+ age: 28,
143
+ weapon: 'Dagger',
144
+ backstory: 'Born with innate magical abilities.',
145
+ favoriteMeal: 'Pancakes with syrup',
146
+ homeland: 'Storm Peaks',
147
+ alignment: 'Chaotic Neutral',
148
+ specialAbility: 'Wild Magic',
149
+ test: 'test',
150
+ },
151
+ {
152
+ name: 'Thorn',
153
+ class: 'Monk',
154
+ age: 50,
155
+ weapon: 'Quarterstaff',
156
+ backstory: 'A hermit who seeks enlightenment.',
157
+ favoriteMeal: 'Rice and vegetables',
158
+ homeland: 'Mountain Sanctuary',
159
+ alignment: 'Lawful Neutral',
160
+ specialAbility: 'Ki Mastery',
161
+ test: 'test',
162
+ },
163
+ {
164
+ name: 'Cassia',
165
+ class: 'Ranger',
166
+ age: 32,
167
+ weapon: 'Shortbow',
168
+ backstory: 'A hunter with a keen eye.',
169
+ favoriteMeal: 'Roasted pheasant',
170
+ homeland: 'Misty Vale',
171
+ alignment: 'Neutral Good',
172
+ specialAbility: 'Eagle Eye',
173
+ test: 'test',
174
+ },
175
+ {
176
+ name: 'Darius',
177
+ class: 'Fighter',
178
+ age: 36,
179
+ weapon: 'Longsword',
180
+ backstory: 'A mercenary with a heart of gold.',
181
+ favoriteMeal: 'Beef stew',
182
+ homeland: 'Free Cities',
183
+ alignment: 'Neutral Good',
184
+ specialAbility: 'Second Wind',
185
+ test: 'test',
186
+ },
187
+ {
188
+ name: 'Iris',
189
+ class: 'Cleric',
190
+ age: 60,
191
+ weapon: 'Warhammer',
192
+ backstory: 'A healer devoted to the god of light.',
193
+ favoriteMeal: 'Fresh bread and soup',
194
+ homeland: 'Sun Temple',
195
+ alignment: 'Lawful Good',
196
+ specialAbility: 'Turn Undead',
197
+ test: 'test',
198
+ },
199
+ {
200
+ name: 'Fenrir',
201
+ class: 'Barbarian',
202
+ age: 42,
203
+ weapon: 'Greataxe',
204
+ backstory: 'A warrior from a distant land.',
205
+ favoriteMeal: 'Grilled steak',
206
+ homeland: 'Northern Wastes',
207
+ alignment: 'Chaotic Neutral',
208
+ specialAbility: 'Primal Strike',
209
+ test: 'test',
210
+ },
211
+ {
212
+ name: 'Luna',
213
+ class: 'Druid',
214
+ age: 70,
215
+ weapon: 'Sickle',
216
+ backstory: 'A protector of the natural world.',
217
+ favoriteMeal: 'Fruit salad',
218
+ homeland: 'Moongrove Forest',
219
+ alignment: 'Neutral Good',
220
+ specialAbility: 'Natures Blessing',
221
+ test: 'test',
222
+ },
223
+ {
224
+ name: 'Orion',
225
+ class: 'Paladin',
226
+ age: 33,
227
+ weapon: 'Halberd',
228
+ backstory: 'A knight on a holy quest.',
229
+ favoriteMeal: 'Roasted lamb',
230
+ homeland: 'Golden Spires',
231
+ alignment: 'Lawful Good',
232
+ specialAbility: 'Divine Shield',
233
+ test: 'test',
234
+ },
235
+ {
236
+ name: 'Astra',
237
+ class: 'Bard',
238
+ age: 26,
239
+ weapon: 'Lute',
240
+ backstory: 'A musician with a magical voice.',
241
+ favoriteMeal: 'Honey cake',
242
+ homeland: 'Singing Valleys',
243
+ alignment: 'Chaotic Good',
244
+ specialAbility: 'Sonic Wave',
245
+ test: 'test',
246
+ },
247
+ {
248
+ name: 'Zephyr',
249
+ class: 'Rogue',
250
+ age: 29,
251
+ weapon: 'Shortsword',
252
+ backstory: 'A thief with a quick hand.',
253
+ favoriteMeal: 'Fish and chips',
254
+ homeland: 'Port Haven',
255
+ alignment: 'Chaotic Neutral',
256
+ specialAbility: 'Quick Strike',
257
+ test: 'test',
258
+ },
259
+ {
260
+ name: 'Thalia',
261
+ class: 'Wizard',
262
+ age: 150,
263
+ weapon: 'Crystal Staff',
264
+ backstory: 'An archivist of forbidden knowledge.',
265
+ favoriteMeal: 'Spiced wine and cheese',
266
+ homeland: 'Arcane Archives',
267
+ alignment: 'Neutral',
268
+ specialAbility: 'Spell Mastery',
269
+ test: 'test',
270
+ },
271
+ {
272
+ name: 'Ragnar',
273
+ class: 'Fighter',
274
+ age: 45,
275
+ weapon: 'War Hammer',
276
+ backstory: 'A dwarven smith turned adventurer.',
277
+ favoriteMeal: 'Mead and roasted mutton',
278
+ homeland: 'Iron Mountains',
279
+ alignment: 'Lawful Neutral',
280
+ specialAbility: 'Master Smith',
281
+ test: 'test',
282
+ },
283
+ {
284
+ name: 'Sylvana',
285
+ class: 'Ranger',
286
+ age: 95,
287
+ weapon: 'Elven Bow',
288
+ backstory: 'Guardian of the enchanted forest.',
289
+ favoriteMeal: 'Elvish waybread',
290
+ homeland: 'Eternal Woods',
291
+ alignment: 'Neutral Good',
292
+ specialAbility: 'Forest Walker',
293
+ test: 'test',
294
+ },
295
+ {
296
+ name: 'Magnus',
297
+ class: 'Warlock',
298
+ age: 38,
299
+ weapon: 'Cursed Dagger',
300
+ backstory: 'Made a deal with a demon for revenge.',
301
+ favoriteMeal: 'Blood oranges',
302
+ homeland: 'Cursed Lands',
303
+ alignment: 'Neutral Evil',
304
+ specialAbility: 'Dark Pact',
305
+ test: 'test',
306
+ },
307
+ {
308
+ name: 'Echo',
309
+ class: 'Bard',
310
+ age: 23,
311
+ weapon: 'Enchanted Violin',
312
+ backstory: 'Can mimic any sound perfectly.',
313
+ favoriteMeal: 'Sweet rolls',
314
+ homeland: 'Harmony Hall',
315
+ alignment: 'Chaotic Good',
316
+ specialAbility: 'Perfect Pitch',
317
+ test: 'test',
318
+ },
319
+ {
320
+ name: 'Korg',
321
+ class: 'Barbarian',
322
+ age: 32,
323
+ weapon: 'Stone Maul',
324
+ backstory: 'Last survivor of a petrified tribe.',
325
+ favoriteMeal: 'Raw meat',
326
+ homeland: 'Stone Peaks',
327
+ alignment: 'Neutral',
328
+ specialAbility: 'Stone Skin',
329
+ test: 'test',
330
+ },
331
+ {
332
+ name: 'Celeste',
333
+ class: 'Sorcerer',
334
+ age: 19,
335
+ weapon: 'Starlight Wand',
336
+ backstory: 'Born during a celestial convergence.',
337
+ favoriteMeal: 'Moon cakes',
338
+ homeland: 'Star Tower',
339
+ alignment: 'Chaotic Good',
340
+ specialAbility: 'Celestial Power',
341
+ test: 'test',
342
+ },
343
+ {
344
+ name: 'Raven',
345
+ class: 'Rogue',
346
+ age: 27,
347
+ weapon: 'Shadow Blade',
348
+ backstory: 'Professional assassin seeking redemption.',
349
+ favoriteMeal: 'Whatever their mark is having',
350
+ homeland: 'Night City',
351
+ alignment: 'True Neutral',
352
+ specialAbility: 'Death Strike',
353
+ test: 'test',
354
+ },
355
+ {
356
+ name: 'Terra',
357
+ class: 'Druid',
358
+ age: 156,
359
+ weapon: 'Living Wood Staff',
360
+ backstory: 'Speaks with ancient trees.',
361
+ favoriteMeal: 'Wild mushrooms',
362
+ homeland: 'Ancient Grove',
363
+ alignment: 'Neutral Good',
364
+ specialAbility: 'Tree Speech',
365
+ test: 'test',
366
+ },
367
+ {
368
+ name: 'Ash',
369
+ class: 'Monk',
370
+ age: 29,
371
+ weapon: 'Flame Fists',
372
+ backstory: 'Raised by phoenix monks in a volcano.',
373
+ favoriteMeal: 'Spicy noodles',
374
+ homeland: 'Phoenix Monastery',
375
+ alignment: 'Lawful Neutral',
376
+ specialAbility: 'Fire Fist',
377
+ test: 'test',
378
+ },
379
+ ];
380
+
381
+ export const columns: TableColumn<SampleDataRow>[] = [
382
+ {
383
+ name: 'Name',
384
+ selector: (row: SampleDataRow) => row.name,
385
+ id: 'name',
386
+ width: '150px',
387
+ },
388
+ {
389
+ name: 'Class',
390
+ selector: (row) => row.class,
391
+ id: 'class',
392
+ width: '150px',
393
+ },
394
+ {
395
+ name: 'Age',
396
+ selector: (row) => row.age,
397
+ id: 'age',
398
+ width: '150px',
399
+ },
400
+ {
401
+ name: 'Weapon',
402
+ selector: (row) => row.weapon,
403
+ id: 'weapon',
404
+ width: '150px',
405
+ },
406
+ {
407
+ name: 'Backstory',
408
+ selector: (row) => row.backstory,
409
+ id: 'backstory',
410
+ width: '150px',
411
+ },
412
+ {
413
+ name: 'Favorite Meal',
414
+ selector: (row) => row.favoriteMeal,
415
+ id: 'favoriteMeal',
416
+ width: '200px',
417
+ },
418
+ {
419
+ name: 'Homeland',
420
+ selector: (row) => row.homeland,
421
+ id: 'homeland',
422
+ width: '200px',
423
+ },
424
+ {
425
+ name: 'Alignment',
426
+ selector: (row) => row.alignment,
427
+ id: 'alignment',
428
+ width: '200px',
429
+ },
430
+ {
431
+ name: 'Special Ability',
432
+ selector: (row) => row.specialAbility,
433
+ id: 'specialAbility',
434
+ width: '200px',
435
+ },
436
+ ];
@@ -12,7 +12,7 @@
12
12
 
13
13
  .table {
14
14
  border-radius: var(--pf-rounded);
15
- border: var(--pf-border-sm) solid var(--pf-table-border-color);
15
+ background-color: var(--pf-table-background-color);
16
16
 
17
17
  &--full-height {
18
18
  height: 100%;
@@ -26,17 +26,59 @@
26
26
  color: var(--pf-table-font-color);
27
27
  border-radius: var(--pf-rounded) !important;
28
28
  border: var(--pf-border-sm) solid var(--pf-table-border-color);
29
+ height: 100%;
30
+
31
+ // Webkit scrollbar styles
32
+ &::-webkit-scrollbar {
33
+ width: var(--pf-size-2);
34
+ height: var(--pf-size-2);
35
+ cursor: pointer;
36
+ }
37
+
38
+ &::-webkit-scrollbar-track {
39
+ background: var(--pf-table-background-color);
40
+ border-radius: var(--pf-rounded);
41
+ cursor: pointer;
42
+ }
43
+
44
+ &::-webkit-scrollbar-thumb {
45
+ background: var(--pf-table-border-color);
46
+ border-radius: var(--pf-rounded);
47
+ cursor: pointer;
48
+ &:hover {
49
+ background: var(--pf-primary-color);
50
+ }
51
+ }
52
+
53
+ // Firefox scrollbar styles
54
+ scrollbar-width: thin;
55
+ scrollbar-color: var(--pf-table-border-color) var(--pf-table-background-color);
56
+ } // body
57
+
58
+ // Pinned Columns
59
+ .table__column__pin-action {
60
+ padding: 0;
61
+ padding-right: var(--pf-padding-1);
62
+ }
63
+ .table__column--is-pinned {
64
+ opacity: 1;
29
65
  }
30
66
 
67
+ .table__column--is-not-pinned {
68
+ opacity: 0.3;
69
+ }
70
+
71
+ .table__header-cell {
72
+ display: flex;
73
+ align-items: center;
74
+ }
75
+
76
+ // End Pinned Columns
77
+
31
78
  & > *:nth-child(3) {
32
79
  margin-top: auto;
33
80
  background-color: transparent;
34
81
  border: none;
35
-
36
- .rdt_Pagination {
37
- background-color: transparent;
38
- border: none;
39
- }
40
82
  }
41
83
  .rdt_Table,
42
84
  .rdt_TableRow,
@@ -48,8 +90,7 @@
48
90
  .rdt_TableHead,
49
91
  .rdt_TableHeadRow,
50
92
  .rdt_TableBody,
51
- .rdt_ExpanderRow,
52
- .rdt_Pagination {
93
+ .rdt_ExpanderRow {
53
94
  background-color: var(--pf-table-background-color);
54
95
  color: var(--pf-table-font-color);
55
96
  }
@@ -66,32 +107,26 @@
66
107
  }
67
108
  }
68
109
 
69
- .rdt_TableHeader {
70
- border-radius: var(--pf-rounded) 0;
71
- border-bottom: var(--pf-border-sm) solid var(--pf-table-border-color);
110
+ .rdt_TableHead {
111
+ z-index: 3;
72
112
  }
73
113
 
74
- .rdt_TableHeadRow,
75
- .rdt_TableRow {
76
- & > :first-child {
77
- padding-left: var(--pf-padding-4);
78
- min-width: 60px;
79
- justify-content: left;
80
- }
114
+ .rdt_TableHeader {
115
+ border-radius: var(--pf-rounded) 0;
116
+ border: var(--pf-border-sm) solid var(--pf-table-border-color);
117
+ border-bottom: none;
81
118
  }
82
119
 
83
120
  .rdt_TableRow {
84
121
  border-top: var(--pf-border-sm) solid var(--pf-table-border-color);
85
122
  border-bottom: var(--pf-border-sm) solid var(--pf-table-border-color);
86
123
  &:hover {
87
- .rdt_TableCell {
88
- background-color: var(--pf-table-hover-color) !important;
89
- }
90
- }
124
+ border-top: var(--pf-border-sm) solid var(--pf-table-border-color);
125
+ border-bottom: var(--pf-border-sm) solid var(--pf-table-border-color);
126
+ outline-color: var(--pf-table-border-color);
91
127
 
92
- &:first-child {
93
128
  .rdt_TableCell {
94
- border-top: var(--pf-border-sm) solid var(--pf-table-border-color);
129
+ background-color: var(--pf-table-hover-color) !important;
95
130
  }
96
131
  }
97
132
  }
@@ -103,6 +138,10 @@
103
138
  &:not(:first-child) {
104
139
  border-left: var(--pf-border-sm) solid var(--pf-table-border-color);
105
140
  }
141
+
142
+ &:not(:last-of-type) {
143
+ border-bottom-width: 0;
144
+ }
106
145
  }
107
146
 
108
147
  /* Striped: alternating background */
@@ -127,3 +166,12 @@
127
166
  }
128
167
  }
129
168
  }
169
+
170
+ .table__pagination {
171
+ padding-bottom: var(--pf-padding-4);
172
+ padding-top: var(--pf-padding-4);
173
+ background-color: var(--pf-table-pagination-background-color);
174
+ padding-left: var(
175
+ --pf-padding-4
176
+ ); // buttons have a visual illusion of having a gap, so we add padding to adjust the left side when the total results exist
177
+ }
@@ -27,4 +27,7 @@
27
27
  --pf-table-highlighted-color: var(--pf-primary-color);
28
28
  --pf-table-highlighted-box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4), 0 8px 16px rgba(0, 0, 0, 0.3);
29
29
  --pf-table-font-size: var(--pf-font-size-body2);
30
+ --pf-table-pagination-background-color: var(--pf-primary-color-700);
31
+ --pf-table-pinned-column-border-color: var(--pf-primary-color-100);
32
+ --pf-table-pinned-column-background-color: var(--pf-table-background-color);
30
33
  }
@@ -3,19 +3,31 @@ import {
3
3
  Direction as RDTDirection,
4
4
  Alignment as RDTAlignment,
5
5
  TableColumn as RDTTableColumn,
6
+ IDataTableProps,
6
7
  } from 'react-data-table-component';
8
+ import { CSSObject } from 'styled-components';
7
9
 
8
10
  export type Direction = `${RDTDirection}`;
9
11
  export type Alignment = `${RDTAlignment}`;
10
- export type TableColumn<T> = RDTTableColumn<T>;
11
12
 
12
- export type TableProps<T> = Omit<
13
- RDTTableProps<T>,
14
- 'disabled' | 'progressPending' | 'direction' | 'subHeaderAlign'
15
- > & {
13
+ export interface PinnableColumn<T> extends RDTTableColumn<T> {
14
+ id: string;
15
+ isPinned?: boolean;
16
+ style?: CSSObject;
17
+ position?: number;
18
+ }
19
+
20
+ export type TableColumn<T> = PinnableColumn<T>;
21
+
22
+ export interface TableProps<T>
23
+ extends Omit<IDataTableProps<T>, 'paginationComponent' | 'direction' | 'subHeaderAlign'> {
24
+ columns: TableColumn<T>[];
16
25
  isDisabled?: boolean;
17
26
  isLoading?: boolean;
18
27
  direction?: Direction;
19
- subHeaderAlign?: Alignment;
28
+ subHeaderAlign?: 'left' | 'right' | 'center';
20
29
  isFullHeight?: boolean;
21
- };
30
+ totalEntriesText?: string;
31
+ canPinColumns?: boolean;
32
+ onPinnedColumnsChange?: (pinnedColumnIds: any[]) => void;
33
+ }
@@ -0,0 +1,35 @@
1
+ import { TableColumn } from '../types';
2
+ import HorizontalStickyHeader from '../components/HorizontalStickyHeader';
3
+ import { getPinnedColumnStyles } from '../components/helpers';
4
+
5
+ export const processColumns = <T,>(
6
+ columns: TableColumn<T>[],
7
+ pinnedColumnIds: string[],
8
+ togglePinnedColumn: (id: string) => void,
9
+ ): TableColumn<T>[] => {
10
+ return columns.map((column, index) => {
11
+ const dataColumnId = `sticky-column-${index}`;
12
+ const isPinned = pinnedColumnIds.includes(dataColumnId);
13
+
14
+ const headerContent =
15
+ column.isPinned !== undefined ? (
16
+ <HorizontalStickyHeader
17
+ position={index}
18
+ isPinned={isPinned}
19
+ onPinColumn={() => togglePinnedColumn(column.id)}
20
+ pinnedColumnIds={pinnedColumnIds}
21
+ >
22
+ {column.name}
23
+ </HorizontalStickyHeader>
24
+ ) : (
25
+ <>{column.name}</>
26
+ );
27
+
28
+ return {
29
+ ...column,
30
+ name: headerContent,
31
+ id: dataColumnId,
32
+ style: getPinnedColumnStyles(isPinned, index, pinnedColumnIds),
33
+ };
34
+ });
35
+ };
@@ -23,6 +23,8 @@ import {
23
23
  faQuestionCircle,
24
24
  faCopy,
25
25
  faXmark,
26
+ faChevronLeft,
27
+ faChevronRight,
26
28
  } from '@fortawesome/free-solid-svg-icons';
27
29
  import { indiconDefinitions } from '@/components/icons/indicons';
28
30
 
@@ -54,6 +56,8 @@ registerFontAwesomeIcons(
54
56
  faQuestionCircle,
55
57
  faCopy,
56
58
  faXmark,
59
+ faChevronLeft,
60
+ faChevronRight,
57
61
  // backwards compat, don't require registration of custom indicons
58
62
  // might want to consider doing so in the future
59
63
  ...indiconDefinitions,
@@ -3,3 +3,11 @@ import { configure } from '@testing-library/react';
3
3
  import './setupIcons';
4
4
 
5
5
  configure({ testIdAttribute: 'data-testid' });
6
+
7
+ class ResizeObserverMock {
8
+ observe() {}
9
+ unobserve() {}
10
+ disconnect() {}
11
+ }
12
+
13
+ global.ResizeObserver = ResizeObserverMock;
@@ -23,6 +23,7 @@
23
23
  @import '../components/forms/date/datePicker/styles/DatePicker.scss';
24
24
  @import '../components/badge/styles/Badge.scss';
25
25
  @import '../components/modal/styles/Modal.scss';
26
+ @import '../components/pagination/styles/Pagination.scss';
26
27
 
27
28
  @import '../components/pill/styles/Pill.scss';
28
29
  @import 'sheets'; // Port to an sheets component when we build it