@praxisui/table 9.0.0-beta.27 → 9.0.0-beta.29

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.
@@ -7,7 +7,7 @@ Allow users to resize and move columns in `praxis-table` without conflicting wit
7
7
  ## Guiding Principles
8
8
 
9
9
  - `sort` belongs to a dedicated sortable label/container, not to the entire `th`
10
- - `reorder` belongs to a dedicated drag handle
10
+ - `reorder` belongs to the draggable header cell, without a permanent move icon
11
11
  - `resize` belongs to a dedicated handle on the right edge of the header cell
12
12
  - runtime mutations should reuse the existing persistence pipeline through a shared column-mutation coordinator
13
13
  - width persistence should normalize to `px`
@@ -33,15 +33,17 @@ This is the main reason resize must not be introduced as another gesture on the
33
33
 
34
34
  Additional constraints from the current implementation:
35
35
 
36
- - reorder keyboard parity is attached to the `th`, not to a standalone handle
37
- - reorder aria-label and tooltip are currently attached to the `th`
36
+ - reorder keyboard parity is attached to the dedicated header sort trigger through Ctrl/Alt + arrows
37
+ - runtime reorder does not render a visible move icon/handle, matching SAP Fiori and MUI Data Grid patterns
38
38
  - persistence currently saves the full `config` snapshot for each runtime mutation
39
39
  - width styling may already come from `column.width`, `headerStyle`, or `style`
40
40
 
41
41
  Current reorder affordance note:
42
42
 
43
- - the drag handle is rendered before the header text in draggable headers so the grip appears first visually without changing the current `cdkDrag` root on the `th`
44
- - this is a visual/layout choice only in the current implementation slice; the handle is still non-interactive and the full draggable header remains the active drag target
43
+ - reorder is implicit on the draggable header cell, matching enterprise grids such as SAP Fiori and MUI Data Grid
44
+ - the current `cdkDrag` root remains on the `th` so preview, placeholder sizing, and index semantics stay stable
45
+ - `mat-sort-header` is mounted on `.praxis-header-sort-trigger`, not on the full `th`, so sort remains a focused label interaction while header drag remains available
46
+ - keyboard reorder belongs to the focused header sort trigger via Ctrl/Alt + arrow keys
45
47
 
46
48
  The plan must explicitly unwind those couplings instead of treating them as incidental details.
47
49
 
@@ -52,37 +54,32 @@ The plan must explicitly unwind those couplings instead of treating them as inci
52
54
  Refactor the header so each interaction has an explicit zone:
53
55
 
54
56
  - sortable label container: sort
55
- - drag icon/handle: reorder
57
+ - draggable header cell: reorder, with no permanent move icon
56
58
  - right-edge handle: resize
57
59
 
58
60
  Changes in `praxis-table.html`:
59
61
 
60
62
  - keep `.praxis-header-label-text`
61
- - keep the drag handle rendered before the label text while the current reorder UX still relies on the full `th` as drag root
62
- - add a sortable wrapper such as `.praxis-header-sort-trigger`
63
- - keep `.praxis-column-drag-handle`
64
- - add `.praxis-column-resize-handle`
63
+ - add a sortable wrapper `.praxis-header-sort-trigger`
65
64
  - keep `cdkDrag` on the `th`
66
- - add `cdkDragHandle` to the reorder handle so the existing drag root, preview, placeholder sizing, and index semantics stay intact
67
- - move reorder `aria-label`, tooltip, and keyboard listeners from the `th` to the reorder handle
68
- - ensure the resize handle and reorder handle both stop `click`, `pointerdown`, and keyboard bubbling into the sort trigger
65
+ - do not render a visible reorder icon/handle in the runtime header
66
+ - add `.praxis-column-resize-handle`
67
+ - keep keyboard reorder on the header sort trigger without blocking sort Enter/Space behavior
68
+ - ensure the resize handle stops `click`, `pointerdown`, and keyboard bubbling into the sort trigger
69
69
 
70
70
  Changes in `praxis-table.scss`:
71
71
 
72
72
  - make the sortable label container the only area that shows sort cursor/hover treatment
73
- - keep drag handle aligned next to the label text
74
73
  - add resize handle positioned at the far right edge
75
- - use `cursor: grab` for reorder
76
74
  - use `cursor: col-resize` for resize
77
75
  - use a hit area around `8px` to `12px` for resize
78
- - remove `pointer-events: none` from the drag handle and make it a real interactive control
79
76
 
80
77
  Sorting strategy:
81
78
 
82
79
  - do not keep the full `th` as the primary sort interaction target
83
80
  - move the sort trigger to the label/container inside the header cell
84
81
  - preserve keyboard sort semantics on that dedicated sort target
85
- - treat suppression of `click` on reorder/resize handles as a hard requirement, not a best-effort safeguard
82
+ - treat suppression of `click` on resize handles as a hard requirement, not a best-effort safeguard
86
83
 
87
84
  ### Phase 2: Add Runtime Resize State
88
85
 
@@ -125,7 +122,7 @@ On resize start:
125
122
 
126
123
  Behavioral rule:
127
124
 
128
- - dragging only starts from the reorder handle
125
+ - dragging starts from the header cell, except the resize handle and sortable label interactions
129
126
  - sorting only starts from the dedicated sortable label/container
130
127
  - resizing only starts from the right-edge resize handle
131
128
 
@@ -151,6 +148,12 @@ Width rules:
151
148
  - if `column.width` is already in `px`, use it directly
152
149
  - if width is `%`, `auto`, or empty, measure the current header width at first resize and convert to `px`
153
150
  - persist resized widths as `px`
151
+ - resizing changes the internal table content width, not the host/card/viewport width
152
+ - when the summed column widths exceed the viewport, the scroll container owns horizontal overflow
153
+ - when the summed column widths are smaller than the viewport, empty space may remain after the last column instead of redistributing widths implicitly
154
+ - do not resize neighboring columns in `px` mode; the resized column changes and following columns move accordingly
155
+ - when resize is enabled, persisted `px` widths below the effective readable minimum are normalized back into `config.columns[]`, not only corrected during rendering
156
+ - the effective readable minimum includes the column header text, the resize separator gutter, and the sort gutter only when that concrete column is sortable
154
157
  - explicitly define precedence when `headerStyle` or `style` also carry width declarations
155
158
  - document that first user resize converts responsive width intent into fixed runtime width intent
156
159
  - validate width behavior under sticky start/end columns and horizontal scroll mode
@@ -186,9 +189,10 @@ Resize persistence policy:
186
189
 
187
190
  - persist on commit only, not continuously during pointer move
188
191
  - commit point is `pointerup` for pointer interactions
189
- - keyboard resize is not part of the first delivery slice
190
- - when keyboard resize is added later, commit semantics must be explicit (`Enter`, `blur`, or stepwise save), not implied
192
+ - keyboard resize commits stepwise on each handled key event
193
+ - keyboard resize uses `ArrowLeft`, `ArrowRight`, `Shift + Arrow`, `Home`, and `End`
191
194
  - define stale-callback protection for resize and reorder through the same shared coordinator
195
+ - derived table width used during/after resize must be cleared when the visible column contract changes externally
192
196
  - do not add undo in the first slice unless a concrete UX requirement appears, but keep the runtime contract compatible with future undo support
193
197
 
194
198
  Emit a resize event after persistence:
@@ -240,16 +244,18 @@ Resize handle:
240
244
 
241
245
  Keyboard behavior for resize handle:
242
246
 
243
- - defer keyboard resize to a follow-up slice after pointer behavior and persistence are stable
244
- - when implemented, define `ArrowLeft`, `ArrowRight`, `Shift + Arrow`, `Home`, `End`, and `Escape`
245
- - define exactly when the resize is committed and when it is cancelled
247
+ - `ArrowLeft` and `ArrowRight` resize by the default step
248
+ - `Shift + ArrowLeft` and `Shift + ArrowRight` resize by the larger step
249
+ - `Home` applies the configured minimum width
250
+ - `End` applies the configured maximum width when one is configured
251
+ - `Escape` cancels an active pointer resize before commit
252
+ - keyboard resize commits stepwise on each handled key event
246
253
 
247
- Reorder handle:
254
+ Reorder accessibility:
248
255
 
249
- - make the reorder handle a real focusable control
250
- - move existing Alt/Ctrl+Arrow reorder behavior onto the handle
251
- - move existing reorder aria-label and tooltip onto the handle
252
- - preserve visible focus styling and screen-reader parity after removing those affordances from the `th`
256
+ - keep keyboard reorder on the focused header sort trigger with Alt/Ctrl + arrow keys
257
+ - do not add a permanent focusable move icon unless a future accessibility review proves the header-trigger model insufficient
258
+ - preserve visible focus styling and screen-reader parity on the header label/sort trigger
253
259
 
254
260
  ### Phase 8: Testing
255
261
 
@@ -260,7 +266,7 @@ Add focused tests for interaction conflicts:
260
266
  - resize handle click does not bubble into sort click
261
267
  - reorder does not alter width
262
268
  - clicking the sortable label still sorts
263
- - reorder still works through the dedicated `cdkDragHandle`
269
+ - reorder still works through the draggable header cell
264
270
  - keyboard reorder still works after moving intent to the handle
265
271
  - sort keyboard interaction still works after sort leaves the `th`
266
272
 
@@ -300,18 +306,18 @@ Add visual/e2e coverage later:
300
306
  ## Recommended Delivery Sequence
301
307
 
302
308
  1. Refactor header structure so sort is isolated to a dedicated sortable label/container
303
- 2. Move reorder affordance, keyboard handling, aria-label, and tooltip to a real drag handle
304
- 3. Add resize handle with runtime-only pointer support and explicit cancel paths
305
- 4. Validate sticky and horizontal-scroll behavior in the same slice
309
+ 2. Keep reorder implicit on the header and remove stale move-icon guidance from docs/editor copy
310
+ 3. Add resize handle with pointer support, keyboard support, and explicit cancel paths
311
+ 4. Validate sticky and horizontal-scroll behavior in a follow-up hardening slice
306
312
  5. Introduce shared column runtime mutation coordination for reorder + resize persistence
307
313
  6. Persist column width on commit only
308
314
  7. Add focused conflict and persistence tests
309
- 8. Add keyboard resize and final resize a11y semantics in a follow-up slice
315
+ 8. Add broader sticky, horizontal-scroll, and non-data-column E2E coverage
310
316
  9. Enable only through config/feature flag
311
317
 
312
318
  ## Definition of Done
313
319
 
314
- - users can reorder only from the drag handle
320
+ - users can reorder from the header without a permanent move icon
315
321
  - users can resize only from the right-edge handle
316
322
  - clicking the sortable label still sorts
317
323
  - reorder, resize, and sort do not interfere with each other
@@ -326,6 +332,8 @@ Add visual/e2e coverage later:
326
332
  - first resize may intentionally convert responsive width behavior into fixed pixel width behavior
327
333
  - sticky start/end columns and horizontal scroll are immediate implementation concerns
328
334
  - resize and reorder mutations need a shared commit/stale-callback policy, not parallel ad hoc logic
335
+ - table-level width is runtime-derived state; it must not outlive the column contract that produced it
336
+ - the canonical enterprise default follows the SAP/MUI model for fixed-width columns: resize the column and the internal content width, keep the outer viewport stable, and use horizontal overflow when needed
329
337
 
330
338
  ## Suggested Follow-Up
331
339