@alaarab/ogrid-react-fluent 2.0.9 → 2.0.12

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 (30) hide show
  1. package/README.md +1 -1
  2. package/dist/esm/ColumnChooser/ColumnChooser.js +10 -128
  3. package/dist/esm/ColumnChooser/ColumnChooser.module.css +45 -10
  4. package/dist/esm/ColumnHeaderFilter/ColumnHeaderFilter.js +16 -36
  5. package/dist/esm/ColumnHeaderFilter/ColumnHeaderFilter.module.css +3 -0
  6. package/dist/esm/ColumnHeaderMenu/ColumnHeaderMenu.js +56 -55
  7. package/dist/esm/ColumnHeaderMenu/ColumnHeaderMenu.module.css +46 -0
  8. package/dist/esm/DataGridTable/DataGridTable.js +121 -292
  9. package/dist/esm/DataGridTable/DataGridTable.module.css +555 -426
  10. package/dist/esm/DataGridTable/DropIndicator.js +5 -0
  11. package/dist/esm/DataGridTable/EmptyState.js +5 -0
  12. package/dist/esm/DataGridTable/GridContextMenu.js +10 -32
  13. package/dist/esm/DataGridTable/LoadingOverlay.js +6 -0
  14. package/dist/esm/{FluentDataTable/FluentDataTable.js → OGrid/OGrid.js} +0 -2
  15. package/dist/esm/OGrid/index.js +1 -0
  16. package/dist/esm/PaginationControls/PaginationControls.js +14 -8
  17. package/dist/esm/index.js +1 -1
  18. package/dist/types/ColumnChooser/ColumnChooser.d.ts +2 -8
  19. package/dist/types/ColumnHeaderFilter/ColumnHeaderFilter.d.ts +2 -20
  20. package/dist/types/ColumnHeaderMenu/ColumnHeaderMenu.d.ts +14 -2
  21. package/dist/types/DataGridTable/DropIndicator.d.ts +7 -0
  22. package/dist/types/DataGridTable/EmptyState.d.ts +11 -0
  23. package/dist/types/DataGridTable/LoadingOverlay.d.ts +6 -0
  24. package/dist/types/{FluentDataTable/FluentDataTable.d.ts → OGrid/OGrid.d.ts} +0 -2
  25. package/dist/types/OGrid/index.d.ts +1 -0
  26. package/dist/types/PaginationControls/PaginationControls.d.ts +2 -10
  27. package/dist/types/index.d.ts +1 -1
  28. package/package.json +5 -5
  29. package/dist/esm/FluentDataTable/index.js +0 -1
  30. package/dist/types/FluentDataTable/index.d.ts +0 -1
@@ -4,313 +4,163 @@
4
4
  flex-direction: column;
5
5
  width: 100%;
6
6
  min-width: 0;
7
- min-height: 100%;
8
- /* Match wrapper so any gap to the right is not transparent (no purple stripe showing through) */
9
- background-color: var(--colorNeutralBackground1, #ffffff);
7
+ background: var(--ogrid-bg, #fff);
10
8
  }
11
9
 
12
10
  .tableWidthAnchor {
13
11
  position: relative;
14
- /* When table fits (data-auto-fit): fill 100% so last column gets space. When overflow: size to content for scroll. */
15
12
  width: max-content;
16
- background-color: var(--colorNeutralBackground1, #ffffff);
17
- }
18
-
19
- /* When table fits in container: fill full width so columns (including Tags) use the space, no dead zone on the right */
20
- .tableWrapper[data-auto-fit=true] .tableWidthAnchor {
21
- width: 100%;
13
+ min-width: var(--data-table-min-width, max-content);
14
+ background: var(--ogrid-bg, #fff);
22
15
  }
23
16
 
24
- /* Always use full container width (matches pagination); columns fill the space */
25
17
  .tableWrapper {
26
18
  position: relative;
27
19
  flex: 1;
28
20
  min-height: 0;
29
- /* Default: no horizontal scroll unless we explicitly allow overflow (wide tables). */
30
21
  overflow-x: hidden;
31
22
  overflow-y: auto;
32
23
  width: 100%;
33
24
  min-width: 0;
34
25
  max-width: 100%;
35
26
  box-sizing: border-box;
36
- /* Border is applied to the grid itself so we don't draw an empty bordered area
37
- when the grid content is narrower than the container. */
38
- border: none;
39
- background-color: var(--colorNeutralBackground1, #ffffff);
40
- -webkit-overflow-scrolling: touch;
27
+ background: var(--ogrid-bg, #fff);
41
28
  will-change: scroll-position;
42
- /* Wide tables: allow horizontal scroll */
43
29
  }
44
30
  .tableWrapper[data-overflow-x=true] {
45
31
  overflow-x: auto;
46
32
  }
47
- .tableWrapper {
48
- /* Empty state: no horizontal scroll – can't scroll right into white space */
49
- }
50
33
  .tableWrapper[data-empty=true] {
51
34
  overflow-x: hidden;
52
35
  }
53
- .tableWrapper {
54
- /* Scoped by data-column-count so our overrides apply; variable is set on this wrapper */
55
- }
56
- .tableWrapper[data-column-count] :global {
57
- /* Let the grid/table size to its content.
58
- This avoids "last column becomes a giant spacer" when the container is wider than the columns,
59
- and keeps header actions (sort/filter) from drifting all the way to the far right.
60
- The wrapper still stays width:100% so pagination aligns. */
61
- }
62
- .tableWrapper[data-column-count] :global .fui-DataGrid {
63
- /* Width behavior is controlled by a CSS var from the React wrapper. */
64
- width: var(--data-table-width, fit-content) !important;
65
- max-width: 100% !important;
66
- min-width: var(--data-table-min-width, max-content) !important;
67
- box-sizing: border-box !important;
68
- overflow: hidden;
69
- }
70
- .tableWrapper[data-column-count] :global {
71
- /* Use auto layout so Fluent sizing/resize works naturally. */
72
- }
73
- .tableWrapper[data-column-count] :global .fui-DataGrid .fui-Table {
74
- width: var(--data-table-width, fit-content) !important;
75
- max-width: 100% !important;
76
- min-width: var(--data-table-min-width, max-content) !important;
77
- table-layout: auto !important;
78
- box-sizing: border-box !important;
79
- border: none !important;
80
- outline: none !important;
81
- }
82
- .tableWrapper[data-column-count] :global {
83
- /* Rows span full table width */
84
- }
85
- .tableWrapper[data-column-count] :global .fui-DataGrid .fui-TableRow,
86
- .tableWrapper[data-column-count] :global .fui-DataGrid .fui-DataGridRow {
87
- width: 100% !important;
88
- min-width: 100% !important;
89
- }
90
- .tableWrapper[data-column-count] :global .fui-DataGridHeader {
91
- background-color: var(--colorSubtleBackgroundSelected, #f3f2f1);
92
- }
93
- .tableWrapper[data-column-count] :global {
94
- /* Let Fluent's column sizing system own widths (resizableColumns + columnSizingOptions).
95
- We only enforce a min-width + sane box sizing. */
96
- }
97
- .tableWrapper[data-column-count] :global .fui-DataGridHeaderCell,
98
- .tableWrapper[data-column-count] :global .fui-DataGridCell {
99
- /* Do NOT use !important here: Fluent sets inline width/min/max during resize. */
100
- min-width: 80px;
101
- box-sizing: border-box !important;
102
- }
103
- .tableWrapper[data-column-count] :global .fui-DataGridHeaderCell {
104
- min-width: var(--data-table-cell-min-width, 80px);
105
- white-space: nowrap !important;
106
- position: relative;
107
- background-color: var(--colorSubtleBackgroundSelected, #f3f2f1);
108
- font-size: 14px;
109
- border-right: 1px solid var(--colorNeutralStroke1, #c4c4c4);
110
- }
111
- .tableWrapper[data-column-count] :global {
112
- /* No extra right border on last column – wrapper provides right edge (row may have trailing <i> so use last-of-type) */
113
- }
114
- .tableWrapper[data-column-count] :global .fui-DataGridHeader .fui-DataGridRow .fui-DataGridHeaderCell:last-of-type,
115
- .tableWrapper[data-column-count] :global .fui-DataGridBody .fui-DataGridRow .fui-DataGridCell:last-of-type {
116
- border-right: none !important;
117
- }
118
- .tableWrapper[data-column-count] :global .fui-DataGridCell {
119
- min-width: var(--data-table-cell-min-width, 80px);
120
- overflow: hidden !important;
121
- text-overflow: ellipsis !important;
122
- white-space: nowrap !important;
123
- font-size: 12px;
124
- padding: 0 !important;
125
- height: 1px;
126
- border-right: 1px solid var(--colorNeutralStroke1, #c4c4c4);
127
- /* Prevent long unbroken content from forcing intrinsic widths / overlap */
128
- }
129
- .tableWrapper[data-column-count] :global .fui-DataGridCell > * {
130
- min-width: 0;
131
- }
132
- .tableWrapper[data-column-count] :global .fui-DataGridCell .fui-TableCellLayout {
133
- font-size: 12px;
134
- }
135
- .tableWrapper[data-column-count] :global {
136
- /* Resize handle: contained so focus ring doesn't create a purple stripe to the right */
137
- }
138
- .tableWrapper[data-column-count] :global .fui-DataGridHeaderCell__aside {
139
- display: flex !important;
140
- cursor: col-resize !important;
141
- position: absolute !important;
142
- right: 0 !important;
143
- top: 0 !important;
144
- bottom: 0 !important;
145
- width: 16px !important;
146
- z-index: 1 !important;
147
- outline: none !important;
148
- border-radius: 0 !important;
149
- }
150
- .tableWrapper[data-column-count] :global {
151
- /* Fix: Fluent renders a resize handle on the last header cell.
152
- The handle has negative horizontal margins (hit target), which bleeds past the table edge
153
- and makes the last header look like it has extra space vs the body cells.
154
- Hide the resize affordance on the last column header. */
155
- }
156
- .tableWrapper[data-column-count] :global .fui-DataGridHeader .fui-DataGridRow .fui-DataGridHeaderCell:last-of-type .fui-DataGridHeaderCell__aside,
157
- .tableWrapper[data-column-count] :global .fui-DataGridHeader .fui-DataGridRow .fui-DataGridHeaderCell:last-of-type .fui-TableResizeHandle {
158
- display: none !important;
159
- }
160
- .tableWrapper[data-column-count] :global {
161
- /* No extra bottom border: last row (row + cells) – wrapper provides bottom edge so no double line */
162
- }
163
- .tableWrapper[data-column-count] :global .fui-DataGridBody .fui-DataGridRow:last-child {
164
- border-bottom: none !important;
165
- }
166
- .tableWrapper[data-column-count] :global .fui-DataGridBody .fui-DataGridRow:last-child .fui-DataGridCell {
167
- border-bottom: none !important;
168
- }
169
- .tableWrapper[data-column-count] :global .fui-Link {
170
- color: var(--colorBrandForeground1, #0f6cbd) !important;
171
- font-weight: 600 !important;
172
- text-decoration: none !important;
173
- }
174
- .tableWrapper[data-column-count] :global .fui-Link:hover {
175
- text-decoration: underline !important;
176
- color: var(--colorBrandForeground1Hover, #115ea3) !important;
177
- }
178
- .tableWrapper[data-column-count] :global .fui-Link:active {
179
- color: var(--colorBrandForeground1Pressed, #0c3b5e) !important;
180
- }
181
- .tableWrapper {
182
- /* When table fits: fill 100% and distribute column width evenly so last column (e.g. Tags) isn't tiny */
183
- }
184
- .tableWrapper[data-auto-fit=true][data-column-count] :global .fui-DataGrid {
185
- width: 100% !important;
186
- }
187
- .tableWrapper[data-auto-fit=true][data-column-count] :global .fui-DataGrid .fui-Table {
188
- width: 100% !important;
189
- }
190
- .tableWrapper[data-auto-fit=true][data-column-count] :global {
191
- /* Equal base width for all columns — override Fluent's inline width/min-width/max-width */
192
- }
193
- .tableWrapper[data-auto-fit=true][data-column-count] :global .fui-DataGridHeaderCell,
194
- .tableWrapper[data-auto-fit=true][data-column-count] :global .fui-DataGridCell {
195
- width: calc(100% / var(--data-table-column-count, 1)) !important;
196
- min-width: 0 !important;
197
- max-width: none !important;
198
- }
199
- .tableWrapper {
200
- /* Selection column must stay 48px even in auto-fit mode (needs same specificity depth to win) */
201
- }
202
- .tableWrapper[data-auto-fit=true][data-column-count] .selectionHeaderCellWrapper, .tableWrapper[data-auto-fit=true][data-column-count] .selectionCellWrapper {
203
- width: 48px !important;
204
- min-width: 48px !important;
205
- max-width: 48px !important;
206
- }
207
- .tableWrapper {
208
- /* Row numbers column must stay 50px even in auto-fit mode */
209
- }
210
- .tableWrapper[data-auto-fit=true][data-column-count] .rowNumberHeaderCellWrapper, .tableWrapper[data-auto-fit=true][data-column-count] .rowNumberCellWrapper {
211
- width: 50px !important;
212
- min-width: 50px !important;
213
- max-width: 50px !important;
214
- }
215
- .tableWrapper {
216
- /* Hide resize handle on last column only when table fits (autoFitColumns); when overflow/scroll, last column can resize (Fluent docs) */
217
- }
218
- .tableWrapper[data-column-count][data-auto-fit=true] :global(.fui-DataGridHeader .fui-DataGridRow .fui-DataGridHeaderCell:last-of-type .fui-DataGridHeaderCell__aside) {
219
- display: none !important;
220
- }
221
-
222
- .dataGrid {
223
- min-width: 0;
224
- }
225
36
 
226
- .groupHeaderRow th {
227
- background: var(--ogrid-header-bg, #f5f5f5);
37
+ .dataTable {
38
+ width: var(--data-table-width, fit-content);
39
+ max-width: 100%;
40
+ min-width: var(--data-table-min-width, max-content);
41
+ border-collapse: separate;
42
+ border-spacing: 0;
43
+ box-sizing: border-box;
44
+ table-layout: auto;
45
+ background-color: var(--ogrid-bg, #fff);
46
+ color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
228
47
  }
229
48
 
230
49
  .groupHeaderCell {
231
50
  text-align: center;
232
51
  font-weight: 600;
233
- border-bottom: 2px solid var(--ogrid-border, #e0e0e0);
234
- padding: 6px 10px;
235
- }
236
-
237
- .leafHeaderCellSpan {
238
- font-weight: 600;
52
+ border-bottom: 2px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
239
53
  padding: 6px 10px;
240
54
  background: var(--ogrid-header-bg, #f5f5f5);
241
55
  }
242
56
 
243
- .selectionHeaderCellWrapper {
244
- width: 48px !important;
245
- min-width: 48px !important;
246
- max-width: 48px !important;
247
- padding: 0 !important;
248
- }
249
-
250
- .selectionCellWrapper {
251
- width: 48px !important;
252
- min-width: 48px !important;
253
- max-width: 48px !important;
254
- padding: 0 !important;
255
- }
256
-
257
- .rowNumberHeaderCellWrapper {
258
- width: 50px !important;
259
- min-width: 50px !important;
260
- max-width: 50px !important;
261
- padding: 0 !important;
262
- }
263
-
264
- .rowNumberCellWrapper {
265
- width: 50px !important;
266
- min-width: 50px !important;
267
- max-width: 50px !important;
268
- padding: 0 !important;
269
- }
270
-
271
- .selectionHeaderCell {
57
+ .headerCellContent {
272
58
  display: flex;
273
59
  align-items: center;
274
- justify-content: center;
275
- width: 100%;
276
- height: 100%;
60
+ gap: 4px;
277
61
  }
278
62
 
279
- .selectionCell {
63
+ .headerMenuTrigger {
64
+ background: transparent;
65
+ border: none;
66
+ cursor: pointer;
67
+ padding: 2px 4px;
68
+ font-size: 16px;
69
+ line-height: 1;
70
+ color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.6));
71
+ opacity: 1;
72
+ transition: background-color 0.15s;
73
+ border-radius: 3px;
280
74
  display: flex;
281
75
  align-items: center;
282
76
  justify-content: center;
283
- width: 100%;
284
- height: 100%;
77
+ min-width: 20px;
78
+ height: 20px;
79
+ }
80
+ .headerMenuTrigger:hover {
81
+ background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04));
82
+ }
83
+ .headerMenuTrigger:active {
84
+ background: var(--ogrid-active-bg, rgba(0, 0, 0, 0.08));
85
+ }
86
+ .headerMenuTrigger:focus-visible {
87
+ outline: 2px solid var(--ogrid-accent, #0078d4);
88
+ outline-offset: 2px;
285
89
  }
286
90
 
287
- .rowNumberHeaderCell,
288
- .rowNumberCell {
289
- display: flex;
290
- align-items: center;
291
- justify-content: center;
292
- width: 100%;
293
- height: 100%;
294
- font-weight: 600;
295
- font-variant-numeric: tabular-nums;
296
- color: var(--colorNeutralForeground3, #666);
297
- background: var(--colorNeutralBackground3, #f5f5f5);
91
+ .dropIndicator {
92
+ position: absolute;
93
+ top: 0;
94
+ bottom: 0;
95
+ width: 3px;
96
+ background: var(--ogrid-selection-color, #217346);
97
+ pointer-events: none;
98
+ z-index: 100;
99
+ transition: left 0.05s;
298
100
  }
299
101
 
300
- .selectedRow :global .fui-DataGridCell {
301
- background-color: var(--colorNeutralBackground1Selected, #e6f0fb) !important;
102
+ .resizeHandle {
103
+ position: absolute;
104
+ top: 0;
105
+ right: -3px;
106
+ bottom: 0;
107
+ width: 8px;
108
+ cursor: col-resize;
109
+ user-select: none;
110
+ z-index: 1;
111
+ }
112
+ .resizeHandle::after {
113
+ content: "";
114
+ position: absolute;
115
+ top: 0;
116
+ right: 3px;
117
+ bottom: 0;
118
+ width: 2px;
119
+ }
120
+ .resizeHandle:hover::after {
121
+ background-color: var(--ogrid-accent, #0078d4);
122
+ }
123
+ .resizeHandle:active::after {
124
+ background-color: var(--ogrid-accent-dark, #005a9e);
302
125
  }
303
126
 
304
- .selectableGrid :global .fui-DataGridBody .fui-DataGridRow:hover .fui-DataGridCell {
305
- background-color: var(--colorSubtleBackgroundHover, #f5f5f5);
306
- cursor: pointer;
127
+ .pinnedColLeft {
128
+ position: sticky;
129
+ z-index: 6;
130
+ background: var(--ogrid-bg, #ffffff);
307
131
  }
308
- .selectableGrid :global .fui-DataGridBody .fui-DataGridRow:hover.selectedRow .fui-DataGridCell {
309
- background-color: var(--colorNeutralBackground1Hover, #dae8f8) !important;
132
+ .pinnedColLeft::after {
133
+ content: "";
134
+ position: absolute;
135
+ top: -1px;
136
+ right: -4px;
137
+ bottom: -1px;
138
+ width: 4px;
139
+ background: linear-gradient(to right, var(--ogrid-pinned-shadow, rgba(0, 0, 0, 0.12)), transparent);
140
+ pointer-events: none;
310
141
  }
311
142
 
312
- .selectableGrid :global(.fui-DataGridBody .fui-DataGridRow) {
313
- cursor: pointer;
143
+ .pinnedColRight {
144
+ position: sticky;
145
+ z-index: 6;
146
+ background: var(--ogrid-bg, #ffffff);
147
+ }
148
+ .pinnedColRight::before {
149
+ content: "";
150
+ position: absolute;
151
+ top: -1px;
152
+ left: -4px;
153
+ bottom: -1px;
154
+ width: 4px;
155
+ background: linear-gradient(to left, var(--ogrid-pinned-shadow, rgba(0, 0, 0, 0.12)), transparent);
156
+ pointer-events: none;
157
+ }
158
+
159
+ .freezeColFirst {
160
+ position: sticky;
161
+ left: 0;
162
+ z-index: 6;
163
+ background: var(--ogrid-bg, #ffffff);
314
164
  }
315
165
 
316
166
  .cellContent {
@@ -318,7 +168,7 @@
318
168
  height: 100%;
319
169
  display: flex;
320
170
  align-items: center;
321
- padding: 4px 8px;
171
+ min-width: 0;
322
172
  box-sizing: border-box;
323
173
  overflow: hidden;
324
174
  text-overflow: ellipsis;
@@ -326,29 +176,33 @@
326
176
  user-select: none;
327
177
  outline: none;
328
178
  }
179
+ .cellContent:focus-visible {
180
+ outline: none;
181
+ }
329
182
 
330
183
  .activeCellContent {
331
- outline: 2px solid var(--ogrid-selection, #217346) !important;
184
+ outline: 2px solid var(--ogrid-selection-color, #217346);
332
185
  outline-offset: -1px;
333
186
  z-index: 2;
334
187
  position: relative;
335
188
  overflow: visible;
189
+ background: var(--ogrid-active-cell-bg, rgba(0, 0, 0, 0.02));
336
190
  }
337
191
 
338
192
  .cellInRange {
339
- background-color: var(--ogrid-bg-range, rgba(33, 115, 70, 0.12)) !important;
193
+ background: var(--ogrid-range-bg, rgba(33, 115, 70, 0.12)) !important;
340
194
  }
341
195
 
342
196
  :global([data-drag-range]) {
343
- background-color: var(--ogrid-bg-range, rgba(33, 115, 70, 0.12)) !important;
197
+ background: var(--ogrid-range-bg, rgba(33, 115, 70, 0.12)) !important;
344
198
  }
345
199
 
346
200
  :global([data-drag-anchor]) {
347
- background-color: var(--colorNeutralBackground1, #fff) !important;
201
+ background: var(--ogrid-bg, #fff) !important;
348
202
  }
349
203
 
350
204
  .cellCut {
351
- background-color: var(--colorNeutralBackground1Hover, rgba(0, 0, 0, 0.04)) !important;
205
+ background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)) !important;
352
206
  opacity: 0.7;
353
207
  }
354
208
 
@@ -358,7 +212,7 @@
358
212
  bottom: -3px;
359
213
  width: 7px;
360
214
  height: 7px;
361
- background: var(--ogrid-selection, #217346);
215
+ background: var(--ogrid-selection-color, #217346);
362
216
  border: 1px solid var(--ogrid-bg, #fff);
363
217
  border-radius: 1px;
364
218
  cursor: crosshair;
@@ -366,74 +220,21 @@
366
220
  z-index: 3;
367
221
  }
368
222
 
369
- /* Freeze panes: sticky header when freezeRows >= 1 */
370
- .stickyHeader {
371
- position: sticky;
372
- top: 0;
373
- z-index: 8;
374
- background-color: var(--colorSubtleBackgroundSelected, #f3f2f1);
375
- }
376
-
377
- /* Freeze panes: sticky first column(s) when freezeCols >= 1; only first column gets left: 0 (multi-column needs width measurement) */
378
- .freezeColFirst {
379
- position: sticky;
380
- left: 0;
381
- z-index: 6;
382
- background-color: var(--colorNeutralBackground1, #ffffff);
383
- will-change: transform;
384
- }
385
-
386
- :global(.fui-DataGridHeader) .freezeColFirst {
387
- background-color: var(--colorSubtleBackgroundSelected, #f3f2f1);
388
- }
389
-
390
- /* Freeze/pinned header cells need top: 0 + highest z-index so they stick in BOTH
391
- directions — left/right (from .freezeCol/.pinnedCell) AND top (from .stickyHeader).
392
- Without explicit top, the child's own position: sticky overrides the parent's. */
393
- .stickyHeader .freezeColFirst,
394
- .stickyHeader .pinnedLeft,
395
- .stickyHeader .pinnedRight {
396
- top: 0;
397
- z-index: 9;
398
- }
399
-
400
- .activeRow :global .fui-DataGridCell:not(:has(.activeCellContent)) {
401
- background-color: var(--colorSubtleBackgroundSelected, #f3f2f1);
402
- }
403
-
404
- .pinnedCell {
405
- position: sticky;
406
- z-index: 6;
407
- background-color: inherit;
408
- will-change: transform;
409
- }
410
-
411
- .pinnedLeft {
412
- left: 0;
413
- }
414
- .pinnedLeft::after {
415
- content: "";
416
- position: absolute;
417
- top: 0;
418
- right: -4px;
419
- bottom: 0;
420
- width: 4px;
421
- background: linear-gradient(to right, var(--ogrid-pinned-shadow, rgba(0, 0, 0, 0.12)), transparent);
422
- pointer-events: none;
223
+ .selectionHeaderCellInner,
224
+ .selectionCellInner {
225
+ display: flex;
226
+ align-items: center;
227
+ justify-content: center;
228
+ width: 100%;
423
229
  }
424
230
 
425
- .pinnedRight {
426
- right: 0;
427
- }
428
- .pinnedRight::before {
429
- content: "";
430
- position: absolute;
431
- top: 0;
432
- left: -4px;
433
- bottom: 0;
434
- width: 4px;
435
- background: linear-gradient(to left, var(--ogrid-pinned-shadow, rgba(0, 0, 0, 0.12)), transparent);
436
- pointer-events: none;
231
+ .rowNumberHeaderCellInner,
232
+ .rowNumberCellInner {
233
+ display: flex;
234
+ align-items: center;
235
+ justify-content: center;
236
+ width: 100%;
237
+ font-variant-numeric: tabular-nums;
437
238
  }
438
239
 
439
240
  .statusBar {
@@ -441,15 +242,13 @@
441
242
  align-items: center;
442
243
  gap: 16px;
443
244
  width: 100%;
444
- min-width: 0;
445
- box-sizing: border-box;
446
245
  padding: 6px 12px;
246
+ box-sizing: border-box;
447
247
  font-size: 12px;
448
- color: var(--colorNeutralForeground2, #616161);
449
- background-color: var(--colorSubtleBackgroundSelected, #f3f2f1);
450
- border-top: 1px solid var(--colorNeutralStroke2, #e0e0e0);
248
+ color: var(--ogrid-fg-muted, rgba(0, 0, 0, 0.5));
249
+ background: var(--ogrid-header-bg, #f5f5f5);
250
+ border-top: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
451
251
  min-height: 28px;
452
- user-select: none;
453
252
  }
454
253
 
455
254
  .statusBarItem {
@@ -459,20 +258,18 @@
459
258
  }
460
259
  .statusBarItem:not(:last-child)::after {
461
260
  content: "";
462
- display: inline-block;
463
261
  width: 1px;
464
262
  height: 14px;
465
- background-color: var(--colorNeutralStroke1, #c4c4c4);
263
+ background: var(--ogrid-border, rgba(0, 0, 0, 0.12));
466
264
  margin-left: 12px;
467
265
  }
468
266
 
469
267
  .statusBarLabel {
470
- color: var(--colorNeutralForeground3, #707070);
471
- font-weight: 400;
268
+ color: var(--ogrid-fg-muted, rgba(0, 0, 0, 0.5));
472
269
  }
473
270
 
474
271
  .statusBarValue {
475
- color: var(--colorNeutralForeground1, #242424);
272
+ color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
476
273
  font-weight: 600;
477
274
  }
478
275
 
@@ -481,11 +278,10 @@
481
278
  z-index: 10000;
482
279
  min-width: 160px;
483
280
  padding: 4px 0;
484
- background: var(--colorNeutralBackground1, #fff);
485
- border: 1px solid var(--colorNeutralStroke1, #e0e0e0);
486
- border-radius: var(--borderRadiusMedium, 4px);
487
- box-shadow: var(--shadow16, 0 4px 16px rgba(0, 0, 0, 0.12));
488
- outline: none;
281
+ background: var(--ogrid-bg, #fff);
282
+ border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
283
+ border-radius: 6px;
284
+ box-shadow: var(--ogrid-shadow, 0 4px 16px rgba(0, 0, 0, 0.12));
489
285
  }
490
286
 
491
287
  .contextMenuItem {
@@ -500,10 +296,10 @@
500
296
  font-size: 13px;
501
297
  text-align: left;
502
298
  cursor: pointer;
503
- color: var(--colorNeutralForeground1, #242424);
299
+ color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
504
300
  }
505
301
  .contextMenuItem:hover:not(:disabled) {
506
- background-color: var(--colorSubtleBackgroundHover, #f5f5f5);
302
+ background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04));
507
303
  }
508
304
  .contextMenuItem:disabled {
509
305
  opacity: 0.5;
@@ -515,14 +311,14 @@
515
311
  }
516
312
 
517
313
  .contextMenuItemShortcut {
518
- color: var(--colorNeutralForeground3, rgba(0, 0, 0, 0.4));
314
+ color: var(--ogrid-fg-muted, rgba(0, 0, 0, 0.5));
519
315
  font-size: 0.85em;
520
316
  }
521
317
 
522
318
  .contextMenuDivider {
523
319
  height: 1px;
524
320
  margin: 4px 0;
525
- background-color: var(--colorNeutralStroke2, #e0e0e0);
321
+ background: var(--ogrid-border, rgba(0, 0, 0, 0.12));
526
322
  }
527
323
 
528
324
  .loadingOverlay {
@@ -532,7 +328,7 @@
532
328
  display: flex;
533
329
  align-items: center;
534
330
  justify-content: center;
535
- background: var(--ogrid-loading-bg, rgba(255, 255, 255, 0.7));
331
+ background: var(--ogrid-loading-overlay, rgba(255, 255, 255, 0.7));
536
332
  backdrop-filter: blur(1px);
537
333
  pointer-events: all;
538
334
  }
@@ -543,22 +339,21 @@
543
339
  align-items: center;
544
340
  gap: 8px;
545
341
  padding: 16px 24px;
546
- background: var(--colorNeutralBackground1, #ffffff);
547
- border: 1px solid var(--colorNeutralStroke1, #c4c4c4);
548
- border-radius: var(--borderRadiusMedium, 4px);
549
- box-shadow: var(--shadow4, 0 2px 4px rgba(0, 0, 0, 0.14));
342
+ background: var(--ogrid-bg, #fff);
343
+ border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
344
+ border-radius: 6px;
345
+ box-shadow: var(--ogrid-shadow-sm, 0 2px 4px rgba(0, 0, 0, 0.08));
550
346
  }
551
347
 
552
348
  .loadingOverlayText {
553
349
  font-size: 13px;
554
350
  font-weight: 500;
555
- color: var(--colorNeutralForeground2, #616161);
351
+ color: var(--ogrid-fg-muted, rgba(0, 0, 0, 0.5));
556
352
  }
557
353
 
558
354
  .loadingDimmed {
559
355
  opacity: 0.6;
560
356
  pointer-events: none;
561
- transition: opacity 0.15s ease;
562
357
  }
563
358
 
564
359
  .emptyStateInGrid {
@@ -569,47 +364,29 @@
569
364
  text-align: center;
570
365
  padding: 20px 16px;
571
366
  min-height: 88px;
572
- min-width: 0;
573
367
  width: 100%;
574
368
  box-sizing: border-box;
575
- border-top: 1px solid var(--colorNeutralStroke2, #e0e0e0);
576
- background-color: var(--colorNeutralBackground2, #fafafa);
577
- }
578
-
579
- .emptyStateInGridMessageSticky {
580
- position: sticky;
581
- left: 50%;
582
- transform: translateX(-50%);
583
- display: inline-flex;
584
- flex-direction: column;
585
- align-items: center;
586
- text-align: center;
587
- }
588
-
589
- .emptyStateInGridIcon {
590
- font-size: 24px;
591
- margin-bottom: 8px;
592
- opacity: 0.6;
369
+ border-top: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
370
+ background: var(--ogrid-header-bg, #f5f5f5);
593
371
  }
594
372
 
595
373
  .emptyStateInGridTitle {
596
374
  font-size: 14px;
597
375
  font-weight: 600;
598
- color: var(--colorNeutralForeground1, #242424);
376
+ color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
599
377
  margin-bottom: 4px;
600
378
  }
601
379
 
602
380
  .emptyStateInGridMessage {
603
381
  font-size: 13px;
604
- color: var(--colorNeutralForeground2, #616161);
605
- max-width: 100%;
382
+ color: var(--ogrid-fg-muted, rgba(0, 0, 0, 0.5));
606
383
  line-height: 1.5;
607
384
  }
608
385
 
609
386
  .emptyStateInGridLink {
610
387
  background: none;
611
388
  border: none;
612
- color: var(--colorBrandForeground1, #0f6cbd);
389
+ color: var(--ogrid-accent, #0078d4);
613
390
  text-decoration: underline;
614
391
  cursor: pointer;
615
392
  padding: 0;
@@ -617,88 +394,440 @@
617
394
  font-family: inherit;
618
395
  }
619
396
  .emptyStateInGridLink:hover {
620
- color: var(--colorBrandForeground1Hover, #115ea3);
397
+ color: var(--ogrid-accent-dark, #005a9e);
398
+ }
399
+
400
+ .spinner {
401
+ width: 24px;
402
+ height: 24px;
403
+ border: 2px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
404
+ border-top-color: var(--ogrid-accent, #0078d4);
405
+ border-radius: 50%;
406
+ animation: ogrid-spin 0.8s linear infinite;
407
+ }
408
+
409
+ @keyframes ogrid-spin {
410
+ to {
411
+ transform: rotate(360deg);
412
+ }
413
+ }
414
+ /* ─── OGrid Theme Variables ─── */
415
+ /* Bridge Fluent UI tokens -> ogrid CSS variables so headless components (SideBar, etc.)
416
+ automatically follow the active FluentProvider theme (light or dark). */
417
+ :global(:root) {
418
+ --ogrid-bg: #ffffff;
419
+ --ogrid-fg: rgba(0, 0, 0, 0.87);
420
+ --ogrid-fg-secondary: rgba(0, 0, 0, 0.6);
421
+ --ogrid-fg-muted: rgba(0, 0, 0, 0.5);
422
+ --ogrid-border: rgba(0, 0, 0, 0.12);
423
+ --ogrid-header-bg: #f3f2f1;
424
+ --ogrid-hover-bg: rgba(0, 0, 0, 0.04);
425
+ --ogrid-selected-row-bg: #e6f0fb;
426
+ --ogrid-active-cell-bg: rgba(0, 0, 0, 0.02);
427
+ --ogrid-range-bg: rgba(33, 115, 70, 0.12);
428
+ --ogrid-accent: #0078d4;
429
+ --ogrid-selection-color: #217346;
430
+ --ogrid-loading-overlay: rgba(255, 255, 255, 0.7);
431
+ }
432
+
433
+ /* Page-level dark mode (for body background, non-FluentProvider elements) */
434
+ :global([data-theme="dark"]) {
435
+ --ogrid-bg: #1b1b1f;
436
+ --ogrid-fg: rgba(255, 255, 255, 0.87);
437
+ --ogrid-fg-secondary: rgba(255, 255, 255, 0.6);
438
+ --ogrid-fg-muted: rgba(255, 255, 255, 0.5);
439
+ --ogrid-border: rgba(255, 255, 255, 0.12);
440
+ --ogrid-header-bg: #2c2c2c;
441
+ --ogrid-hover-bg: rgba(255, 255, 255, 0.06);
442
+ --ogrid-selected-row-bg: #1a3a5c;
443
+ --ogrid-active-cell-bg: rgba(255, 255, 255, 0.04);
444
+ --ogrid-range-bg: rgba(33, 115, 70, 0.2);
445
+ --ogrid-accent: #4da6ff;
446
+ --ogrid-selection-color: #217346;
447
+ --ogrid-loading-overlay: rgba(0, 0, 0, 0.5);
448
+ }
449
+
450
+ /* Inside FluentProvider: derive --ogrid-* from Fluent tokens so light/dark follows automatically */
451
+ :global(.fui-FluentProvider) {
452
+ --ogrid-bg: var(--colorNeutralBackground1, #ffffff);
453
+ --ogrid-fg: var(--colorNeutralForeground1, rgba(0, 0, 0, 0.87));
454
+ --ogrid-fg-secondary: var(--colorNeutralForeground2, rgba(0, 0, 0, 0.6));
455
+ --ogrid-fg-muted: var(--colorNeutralForeground3, rgba(0, 0, 0, 0.5));
456
+ --ogrid-border: var(--colorNeutralStroke2, rgba(0, 0, 0, 0.12));
457
+ --ogrid-header-bg: var(--colorSubtleBackgroundSelected, #f3f2f1);
458
+ --ogrid-hover-bg: var(--colorSubtleBackgroundHover, rgba(0, 0, 0, 0.04));
459
+ --ogrid-selected-row-bg: var(--colorNeutralBackground1Selected, #e6f0fb);
460
+ --ogrid-active-cell-bg: rgba(0, 0, 0, 0.02);
461
+ --ogrid-range-bg: rgba(33, 115, 70, 0.12);
462
+ --ogrid-accent: var(--colorBrandForeground1, #0078d4);
463
+ --ogrid-selection-color: #217346;
464
+ --ogrid-loading-overlay: rgba(255, 255, 255, 0.7);
621
465
  }
622
466
 
623
- /* Column reorder drop indicator */
624
- .dropIndicator {
625
- position: absolute;
467
+ .tableScrollContent {
468
+ min-height: 100%;
469
+ background-color: var(--colorNeutralBackground1, var(--ogrid-bg, #ffffff));
470
+ }
471
+
472
+ .tableWidthAnchor {
473
+ background-color: var(--colorNeutralBackground1, var(--ogrid-bg, #ffffff));
474
+ }
475
+
476
+ .tableWrapper {
477
+ border: none;
478
+ background-color: var(--colorNeutralBackground1, var(--ogrid-bg, #ffffff));
479
+ -webkit-overflow-scrolling: touch;
480
+ outline: none;
481
+ }
482
+
483
+ .dataTable {
484
+ table-layout: auto !important;
485
+ background-color: var(--colorNeutralBackground1, var(--ogrid-bg, #ffffff));
486
+ }
487
+
488
+ .dataTable :global(.fui-TableHeaderCell),
489
+ .dataTable :global(.fui-TableCell) {
490
+ min-width: 80px;
491
+ box-sizing: border-box;
492
+ border-right: 1px solid var(--colorNeutralStroke1, #c4c4c4);
493
+ font-size: 13px;
494
+ vertical-align: middle;
495
+ }
496
+
497
+ .dataTable :global(.fui-TableHeaderCell) {
498
+ padding: 6px 10px;
499
+ font-weight: 600;
500
+ font-size: 14px;
501
+ color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
502
+ white-space: nowrap;
503
+ position: sticky;
626
504
  top: 0;
627
- bottom: 0;
628
- width: 3px;
629
- background: var(--ogrid-primary, #217346);
630
- pointer-events: none;
631
- z-index: 100;
632
- transition: left 0.05s;
505
+ background-color: var(--colorSubtleBackgroundSelected, var(--ogrid-header-bg, #f3f2f1));
506
+ z-index: 8;
507
+ border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
508
+ }
509
+ .dataTable :global(.fui-TableHeaderCell) > :global(.fui-TableHeaderCell__button) {
510
+ position: static !important;
511
+ }
512
+ .dataTable :global(.fui-TableHeaderCell):focus-visible {
513
+ outline: 2px solid var(--colorBrandStroke1, var(--ogrid-accent, #0078d4));
514
+ outline-offset: -2px;
515
+ z-index: 11;
516
+ }
517
+
518
+ .dataTable :global(.fui-TableCell) {
519
+ padding: 0;
520
+ overflow: hidden;
521
+ text-overflow: ellipsis;
522
+ white-space: nowrap;
523
+ font-size: 12px;
524
+ height: 1px;
525
+ border-right: 1px solid var(--colorNeutralStroke1, #c4c4c4);
526
+ position: relative;
527
+ border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
528
+ /* Prevent long unbroken content from forcing intrinsic widths / overlap */
529
+ }
530
+ .dataTable :global(.fui-TableCell) > * {
531
+ min-width: 0;
532
+ }
533
+ .dataTable :global(.fui-TableCell):focus-visible {
534
+ outline: none;
633
535
  }
634
536
 
635
- /* Empty state: hide body, keep header and empty message */
636
- .tableWrapper[data-empty=true] :global(.fui-DataGrid) tbody {
637
- display: none;
537
+ /* No extra right border on last column */
538
+ .dataTable :global(.fui-TableHeaderCell:last-of-type),
539
+ .dataTable :global(.fui-TableCell:last-of-type) {
540
+ border-right: none;
638
541
  }
639
542
 
640
- /* Empty state: no extra bottom border (header row is last row, remove its border-bottom) */
641
- .tableWrapper[data-empty=true] :global(.fui-DataGridHeader .fui-DataGridRow) {
642
- border-bottom: none !important;
543
+ /* No extra bottom border on last row */
544
+ .dataTable :global(.fui-TableBody .fui-TableRow:last-child .fui-TableCell) {
545
+ border-bottom: none;
643
546
  }
644
547
 
645
- .headerCellContent {
646
- display: flex;
647
- align-items: center;
648
- gap: 4px;
548
+ /* Row hover */
549
+ .dataTable :global(.fui-TableBody .fui-TableRow:hover .fui-TableCell) {
550
+ background-color: var(--colorSubtleBackgroundHover, var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)));
649
551
  }
650
552
 
651
- .headerMenuTrigger {
652
- background: transparent;
653
- border: none;
553
+ .leafHeaderCellSpan {
554
+ font-weight: 600;
555
+ padding: 6px 10px;
556
+ background: var(--ogrid-header-bg, #f3f2f1);
557
+ }
558
+
559
+ .selectionHeaderCellWrapper {
560
+ width: 48px;
561
+ min-width: 48px;
562
+ max-width: 48px;
563
+ padding: 4px !important;
564
+ text-align: center;
565
+ }
566
+
567
+ .selectionCellWrapper {
568
+ width: 48px;
569
+ min-width: 48px;
570
+ max-width: 48px;
571
+ padding: 4px !important;
572
+ text-align: center;
573
+ }
574
+
575
+ .rowNumberHeaderCellWrapper {
576
+ width: 50px;
577
+ min-width: 50px;
578
+ max-width: 50px;
579
+ padding: 4px 8px !important;
580
+ text-align: center;
581
+ background: var(--ogrid-header-bg, #f5f5f5);
582
+ font-weight: 600;
583
+ color: var(--colorNeutralForeground3, #666);
584
+ border-right: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
585
+ }
586
+
587
+ .rowNumberCellWrapper {
588
+ width: 50px;
589
+ min-width: 50px;
590
+ max-width: 50px;
591
+ padding: 4px 8px !important;
592
+ text-align: center;
593
+ background: var(--colorNeutralBackground3, #f5f5f5);
594
+ font-weight: 600;
595
+ color: var(--colorNeutralForeground3, #666);
596
+ border-right: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
597
+ }
598
+
599
+ .dataTable :global(.fui-TableBody) .selectedRow :global(.fui-TableCell) {
600
+ background-color: var(--colorNeutralBackground1Selected, var(--ogrid-selected-row-bg, #e6f0fb));
601
+ }
602
+
603
+ .selectableGrid .dataTable :global(.fui-TableBody .fui-TableRow:hover .fui-TableCell) {
604
+ background-color: var(--colorSubtleBackgroundHover, #f5f5f5);
654
605
  cursor: pointer;
655
- padding: 2px 4px;
656
- font-size: 16px;
657
- line-height: 1;
606
+ }
607
+
608
+ .selectableGrid .dataTable :global(.fui-TableBody) .selectedRow:hover :global(.fui-TableCell) {
609
+ background-color: var(--colorNeutralBackground1Hover, #dae8f8);
610
+ }
611
+
612
+ .selectableGrid .dataTable :global(.fui-TableBody .fui-TableRow) {
613
+ cursor: pointer;
614
+ }
615
+
616
+ .cellContent {
617
+ padding: 4px 8px;
618
+ }
619
+
620
+ .activeCellContent {
621
+ outline: 2px solid var(--ogrid-selection-color, #217346) !important;
622
+ background-color: var(--ogrid-active-cell-bg, rgba(0, 0, 0, 0.02)) !important;
623
+ }
624
+
625
+ .cellInRange {
626
+ background-color: var(--ogrid-range-bg, rgba(33, 115, 70, 0.12)) !important;
627
+ }
628
+
629
+ :global([data-drag-range]) {
630
+ background-color: var(--ogrid-range-bg, rgba(33, 115, 70, 0.12)) !important;
631
+ }
632
+
633
+ :global([data-drag-anchor]) {
634
+ background-color: var(--ogrid-bg, #ffffff) !important;
635
+ }
636
+
637
+ .cellCut {
638
+ background-color: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)) !important;
639
+ }
640
+
641
+ .stickyHeader {
642
+ z-index: 8;
643
+ background-color: var(--colorSubtleBackgroundSelected, var(--ogrid-header-bg, #f3f2f1));
644
+ }
645
+
646
+ .freezeColFirst {
647
+ background-color: var(--colorNeutralBackground1, #ffffff);
648
+ }
649
+
650
+ .dataTable :global(.fui-TableHeader) .freezeColFirst {
651
+ background-color: var(--colorSubtleBackgroundSelected, var(--ogrid-header-bg, #f3f2f1));
652
+ }
653
+
654
+ .stickyHeader .freezeColFirst,
655
+ .stickyHeader .pinnedColLeft,
656
+ .stickyHeader .pinnedColRight {
657
+ top: 0;
658
+ z-index: 10;
659
+ }
660
+
661
+ .dataTable .pinnedColLeft {
662
+ background-color: var(--colorNeutralBackground1, var(--ogrid-bg, #ffffff));
663
+ }
664
+
665
+ .dataTable :global(.fui-TableHeader) .pinnedColLeft {
666
+ background-color: var(--colorSubtleBackgroundSelected, var(--ogrid-header-bg, #f3f2f1));
667
+ }
668
+
669
+ .dataTable .pinnedColRight {
670
+ background-color: var(--colorNeutralBackground1, var(--ogrid-bg, #ffffff));
671
+ }
672
+
673
+ .dataTable :global(.fui-TableHeader) .pinnedColRight {
674
+ background-color: var(--colorSubtleBackgroundSelected, var(--ogrid-header-bg, #f3f2f1));
675
+ }
676
+
677
+ .headerMenuTrigger {
658
678
  color: var(--colorNeutralForeground3, #666);
659
- opacity: 0;
660
- transition: opacity 0.15s, background-color 0.15s;
661
- border-radius: 3px;
662
- display: flex;
663
- align-items: center;
664
- justify-content: center;
665
- min-width: 20px;
666
- height: 20px;
667
679
  }
668
680
  .headerMenuTrigger:hover {
669
681
  background: var(--colorNeutralBackground1Hover, #f3f2f1);
670
- opacity: 1;
671
682
  }
672
683
  .headerMenuTrigger:active {
673
684
  background: var(--colorNeutralBackground1Pressed, #e1dfdd);
674
685
  }
686
+ .headerMenuTrigger:focus-visible {
687
+ outline: 2px solid var(--colorBrandStroke1, var(--ogrid-accent, #0078d4));
688
+ }
675
689
 
676
- .tableWrapper :global(.fui-DataGridHeaderCell:hover) .headerMenuTrigger {
677
- opacity: 1;
690
+ /* Column resize handle -- Fluent token override */
691
+ .resizeHandle:hover::after {
692
+ background-color: var(--colorBrandForeground1, var(--ogrid-accent, #0078d4));
693
+ }
694
+ .resizeHandle:active::after {
695
+ background-color: var(--colorBrandForeground1Pressed, #005a9e);
696
+ }
697
+
698
+ .statusBar {
699
+ min-width: 0;
700
+ color: var(--colorNeutralForeground2, #616161);
701
+ background-color: var(--colorSubtleBackgroundSelected, #f3f2f1);
702
+ border-top: 1px solid var(--colorNeutralStroke2, #e0e0e0);
703
+ user-select: none;
704
+ }
705
+
706
+ .statusBarItem:not(:last-child)::after {
707
+ display: inline-block;
708
+ background-color: var(--colorNeutralStroke1, #c4c4c4);
678
709
  }
679
710
 
680
- .tableWrapper :global(.fui-DataGridHeaderCell.pinnedColLeft),
681
- .tableWrapper :global(.fui-DataGridCell.pinnedColLeft) {
682
- border-left: 2px solid var(--colorBrandForeground1, #0078d4) !important;
711
+ .statusBarLabel {
712
+ color: var(--colorNeutralForeground3, #707070);
713
+ font-weight: 400;
683
714
  }
684
715
 
685
- .tableWrapper :global(.fui-DataGridHeaderCell.pinnedColRight),
686
- .tableWrapper :global(.fui-DataGridCell.pinnedColRight) {
687
- border-right: 2px solid var(--colorBrandForeground1, #0078d4) !important;
716
+ .statusBarValue {
717
+ color: var(--colorNeutralForeground1, #242424);
688
718
  }
689
719
 
690
- .density-compact :global(.fui-DataGridHeaderCell),
691
- .density-compact :global(.fui-DataGridCell) {
720
+ .contextMenu {
721
+ background: var(--colorNeutralBackground1, #fff);
722
+ border: 1px solid var(--colorNeutralStroke1, #e0e0e0);
723
+ border-radius: var(--borderRadiusMedium, 4px);
724
+ box-shadow: var(--shadow16, 0 4px 16px rgba(0, 0, 0, 0.12));
725
+ outline: none;
726
+ }
727
+
728
+ .contextMenuItem {
729
+ color: var(--colorNeutralForeground1, #242424);
730
+ }
731
+ .contextMenuItem:hover:not(:disabled) {
732
+ background-color: var(--colorSubtleBackgroundHover, #f5f5f5);
733
+ }
734
+
735
+ .contextMenuItemShortcut {
736
+ color: var(--colorNeutralForeground3, rgba(0, 0, 0, 0.4));
737
+ }
738
+
739
+ .contextMenuDivider {
740
+ background-color: var(--colorNeutralStroke2, #e0e0e0);
741
+ }
742
+
743
+ .loadingOverlayContent {
744
+ background: var(--colorNeutralBackground1, #ffffff);
745
+ border: 1px solid var(--colorNeutralStroke1, #c4c4c4);
746
+ border-radius: var(--borderRadiusMedium, 4px);
747
+ box-shadow: var(--shadow4, 0 2px 4px rgba(0, 0, 0, 0.14));
748
+ }
749
+
750
+ .loadingOverlayText {
751
+ color: var(--colorNeutralForeground2, #616161);
752
+ }
753
+
754
+ .loadingDimmed {
755
+ transition: opacity 0.15s ease;
756
+ }
757
+
758
+ .emptyStateInGrid {
759
+ min-width: 0;
760
+ border-top: 1px solid var(--colorNeutralStroke2, #e0e0e0);
761
+ background-color: var(--colorNeutralBackground2, #fafafa);
762
+ }
763
+
764
+ .emptyStateInGridMessageSticky {
765
+ position: sticky;
766
+ left: 50%;
767
+ transform: translateX(-50%);
768
+ display: inline-flex;
769
+ flex-direction: column;
770
+ align-items: center;
771
+ text-align: center;
772
+ }
773
+
774
+ .emptyStateInGridIcon {
775
+ font-size: 24px;
776
+ margin-bottom: 8px;
777
+ opacity: 0.6;
778
+ }
779
+
780
+ .emptyStateInGridTitle {
781
+ color: var(--colorNeutralForeground1, #242424);
782
+ }
783
+
784
+ .emptyStateInGridMessage {
785
+ color: var(--colorNeutralForeground2, #616161);
786
+ max-width: 100%;
787
+ }
788
+
789
+ .emptyStateInGridLink {
790
+ color: var(--colorBrandForeground1, #0f6cbd);
791
+ }
792
+ .emptyStateInGridLink:hover {
793
+ color: var(--colorBrandForeground1Hover, #115ea3);
794
+ }
795
+
796
+ /* Fluent Link styling within grid */
797
+ .dataTable :global(.fui-Link) {
798
+ color: var(--colorBrandForeground1, #0f6cbd);
799
+ font-weight: 600;
800
+ text-decoration: none;
801
+ }
802
+ .dataTable :global(.fui-Link):hover {
803
+ text-decoration: underline;
804
+ color: var(--colorBrandForeground1Hover, #115ea3);
805
+ }
806
+ .dataTable :global(.fui-Link):active {
807
+ color: var(--colorBrandForeground1Pressed, #0c3b5e);
808
+ }
809
+
810
+ .density-compact .dataTable :global(.fui-TableHeaderCell) {
692
811
  padding: 4px 8px;
693
812
  }
694
813
  .density-compact .cellContent {
695
814
  padding: 4px 8px;
696
815
  }
697
816
 
698
- .density-comfortable :global(.fui-DataGridHeaderCell),
699
- .density-comfortable :global(.fui-DataGridCell) {
817
+ .density-comfortable .dataTable :global(.fui-TableHeaderCell) {
700
818
  padding: 12px 16px;
701
819
  }
702
820
  .density-comfortable .cellContent {
703
821
  padding: 12px 16px;
822
+ }
823
+
824
+ /* ─── Accessibility: Focus Visible Styles ─────────────────────── */
825
+ .tableWrapper :global .fui-Button:focus-visible,
826
+ .tableWrapper :global .fui-MenuButton:focus-visible {
827
+ outline: 2px solid var(--colorBrandStroke1, #0078d4);
828
+ outline-offset: 2px;
829
+ }
830
+ .tableWrapper :global .fui-Checkbox:focus-visible {
831
+ outline: 2px solid var(--colorBrandStroke1, #0078d4);
832
+ outline-offset: 2px;
704
833
  }