|
| 1 | +## Context |
| 2 | + |
| 3 | +The rich text editor uses TipTap, which already supports column widths via the `colwidth` attribute on table cells. TipTap's base `TableCell` extension includes this attribute, and the `TableBackgroundColor` extension reads it to generate `<colgroup>` elements for column sizing. |
| 4 | + |
| 5 | +Currently: |
| 6 | + |
| 7 | +- `colwidth` is an array of pixel values (e.g., `[150]` for single column, `[100, 150, 200]` for colspan) |
| 8 | +- TipTap has a `resizable: true` option that should enable drag-to-resize, but the custom `TableBackgroundColorNodeView` doesn't implement resize handles |
| 9 | +- Users can click column borders, which sets a width, but cannot drag to adjust |
| 10 | +- No UI control exists to set exact pixel widths |
| 11 | + |
| 12 | +The existing cell configuration dropdown already has sections for background color, border color/style/width using a `ConfigurationSection` pattern. |
| 13 | + |
| 14 | +## Goals / Non-Goals |
| 15 | + |
| 16 | +**Goals:** |
| 17 | + |
| 18 | +- Add a number input control to the cell configuration dropdown for setting column width |
| 19 | +- Support exact pixel values (25-1000px range) |
| 20 | +- Provide clear button to reset to auto width |
| 21 | +- Handle colspan cells by setting only the first column width |
| 22 | +- Follow existing configuration dropdown patterns and styling |
| 23 | +- Validate input and clamp to acceptable ranges |
| 24 | + |
| 25 | +**Non-Goals:** |
| 26 | + |
| 27 | +- Implementing drag-to-resize handles (would require significant NodeView work) |
| 28 | +- Supporting percentage or other CSS units (only pixels for now) |
| 29 | +- Setting widths for all columns in a colspan cell (only first column) |
| 30 | +- Syncing widths across all rows (only first row widths apply per TipTap's design) |
| 31 | +- Adding column width presets dropdown (keep it simple with number input only) |
| 32 | + |
| 33 | +## Decisions |
| 34 | + |
| 35 | +### Decision 1: Use number input type (not dropdown with presets) |
| 36 | + |
| 37 | +**Rationale:** User requested "exact pixel values" in requirements. A number input provides precision without limiting users to preset sizes. |
| 38 | + |
| 39 | +**Alternatives considered:** |
| 40 | + |
| 41 | +- Dropdown with presets (Small/Medium/Large): Too restrictive, doesn't meet "exact values" requirement |
| 42 | +- Hybrid (input + preset buttons): Over-engineered for initial implementation |
| 43 | +- Text input: Number input provides better UX with built-in increment/decrement and validation |
| 44 | + |
| 45 | +**Implementation:** Add new `"numberInput"` type to `ConfigurationSection` interface alongside existing `"colorPicker"` and `"dropdown"` types. |
| 46 | + |
| 47 | +--- |
| 48 | + |
| 49 | +### Decision 2: Set only first column width for colspan cells |
| 50 | + |
| 51 | +**Rationale:** |
| 52 | + |
| 53 | +- User explicitly requested "set only first column" in requirements |
| 54 | +- Simplifies implementation and UX (no need for multi-column width editor) |
| 55 | +- Matches TipTap's array-based `colwidth` structure where `colwidth[0]` is the first column |
| 56 | + |
| 57 | +**Alternatives considered:** |
| 58 | + |
| 59 | +- Set all spanned columns to same width: Could surprise users if they had different widths set |
| 60 | +- Show per-column width array editor: Complex UI for edge case (most cells don't have colspan) |
| 61 | +- Disable control for colspan cells: Too restrictive |
| 62 | + |
| 63 | +**Implementation:** `onChange` handler creates `colwidth` array with single value: `[width]` |
| 64 | + |
| 65 | +--- |
| 66 | + |
| 67 | +### Decision 3: Use setCellAttribute command (not custom command) |
| 68 | + |
| 69 | +**Rationale:** |
| 70 | + |
| 71 | +- `setCellAttribute("colwidth", value)` should work because `colwidth` is in TipTap's base TableCell |
| 72 | +- Other cell properties (backgroundColor, borderColor, etc.) use `setCellAttribute` successfully |
| 73 | +- No need to define custom commands in extensions |
| 74 | + |
| 75 | +**Alternatives considered:** |
| 76 | + |
| 77 | +- Custom `setCellWidth` command in `TableCellBackgroundColor`: Unnecessary abstraction |
| 78 | +- Modify `TableCellBackgroundColor.addAttributes()` to re-declare colwidth: Already inherits via `...this.parent?.()` |
| 79 | + |
| 80 | +**Implementation:** Direct call to `editor.chain().focus().setCellAttribute("colwidth", [width]).run()` |
| 81 | + |
| 82 | +--- |
| 83 | + |
| 84 | +### Decision 4: Render clear button conditionally (when value exists) |
| 85 | + |
| 86 | +**Rationale:** |
| 87 | + |
| 88 | +- Provides explicit way to reset to auto width (null) |
| 89 | +- Visual indicator that a custom width is set |
| 90 | +- Follows common UI pattern (seen in search inputs, etc.) |
| 91 | + |
| 92 | +**Alternatives considered:** |
| 93 | + |
| 94 | +- Always show clear button: Clutters UI when empty |
| 95 | +- Use empty string to mean auto: Less explicit, could be confusing |
| 96 | +- Add separate "Auto" button: Redundant with clear functionality |
| 97 | + |
| 98 | +**Implementation:** Render `×` button only when `currentValue !== null` |
| 99 | + |
| 100 | +--- |
| 101 | + |
| 102 | +### Decision 5: Store null for auto width (not empty array or zero) |
| 103 | + |
| 104 | +**Rationale:** |
| 105 | + |
| 106 | +- TipTap treats `colwidth: null` as auto-sizing behavior |
| 107 | +- Consistent with how TipTap's base extensions work |
| 108 | +- `colwidth: []` or `colwidth: [0]` could cause layout issues |
| 109 | + |
| 110 | +**Implementation:** When user clears input, call `setCellAttribute("colwidth", null)` |
| 111 | + |
| 112 | +## Risks / Trade-offs |
| 113 | + |
| 114 | +### Risk: Parent attribute inheritance might not work |
| 115 | + |
| 116 | +If `TableCellBackgroundColor` doesn't properly inherit `colwidth` from base `TableCell`, `setCellAttribute` calls will fail silently. |
| 117 | + |
| 118 | +**Mitigation:** The extension already uses `...this.parent?.()` in `addAttributes()`, which should preserve `colwidth`. If issues arise, explicitly re-declare `colwidth` in the extension's attributes. |
| 119 | + |
| 120 | +--- |
| 121 | + |
| 122 | +### Risk: First-row-only behavior might confuse users |
| 123 | + |
| 124 | +TipTap only uses `colwidth` from the first row of the table to generate `<colgroup>`. Setting widths on other rows has no effect. |
| 125 | + |
| 126 | +**Mitigation:** Could add tooltip or helper text: "Note: Only first row column widths apply." For initial implementation, leave as-is since it matches TipTap's inherent behavior. |
| 127 | + |
| 128 | +--- |
| 129 | + |
| 130 | +### Risk: Custom NodeView might interfere with colwidth updates |
| 131 | + |
| 132 | +The `TableBackgroundColorNodeView` manually generates `<colgroup>` in `updateColgroup()`. If it's not reactive to `colwidth` changes, widths might not update visually. |
| 133 | + |
| 134 | +**Mitigation:** The NodeView's `update()` method already calls `updateColgroup()` on node changes, so it should react to `colwidth` updates. Test thoroughly during implementation. |
| 135 | + |
| 136 | +--- |
| 137 | + |
| 138 | +### Trade-off: No drag-to-resize (only manual input) |
| 139 | + |
| 140 | +Users lose the convenience of dragging column borders to resize. |
| 141 | + |
| 142 | +**Mitigation:** The number input provides precision that drag handles lack. If drag-to-resize is needed later, it would require integrating ProseMirror's `columnResizing` plugin into the custom NodeView (~200 lines of code). For now, manual input meets the stated requirements. |
| 143 | + |
| 144 | +--- |
| 145 | + |
| 146 | +### Trade-off: Pixel-only units (no percentages) |
| 147 | + |
| 148 | +Users cannot set responsive column widths using percentages. |
| 149 | + |
| 150 | +**Mitigation:** Percentage support would require custom rendering logic (TipTap's `colwidth` is pixel-only). Tables in rich text editors typically use fixed layouts. Can be added later if users request it. |
| 151 | + |
| 152 | +## Migration Plan |
| 153 | + |
| 154 | +No migration needed. This is a purely additive feature: |
| 155 | + |
| 156 | +- Existing tables without `colwidth` continue to work (auto width) |
| 157 | +- Existing tables with `colwidth` set (via TipTap's base functionality) display correctly |
| 158 | +- No data model changes or breaking API changes |
| 159 | + |
| 160 | +Deployment: |
| 161 | + |
| 162 | +1. Merge code changes |
| 163 | +2. Run build |
| 164 | +3. Deploy widget to Mendix project |
| 165 | +4. Feature is immediately available in cell configuration dropdown |
| 166 | + |
| 167 | +Rollback: |
| 168 | + |
| 169 | +- If issues arise, remove the new configuration section from `createCellConfigurationSections()` |
| 170 | +- No data corruption risk (colwidth attribute is standard TipTap) |
| 171 | + |
| 172 | +## Open Questions |
| 173 | + |
| 174 | +1. **Should we show the actual rendered column width vs. the set value?** |
| 175 | + - The set `colwidth` might differ from actual rendered width due to table layout constraints |
| 176 | + - For initial implementation: Show the set value only (simpler) |
| 177 | + - Can add "measured width" tooltip later if needed |
| 178 | + |
| 179 | +2. **Should we prevent setting widths on non-first-row cells?** |
| 180 | + - Pro: Avoids confusion about why widths don't apply |
| 181 | + - Con: Restricts user control, might not match mental model |
| 182 | + - Decision: Allow setting on any cell (simpler), rely on TipTap's first-row behavior |
| 183 | + |
| 184 | +3. **Should we add keyboard shortcuts for common widths?** |
| 185 | + - Out of scope for initial implementation |
| 186 | + - Can be added later if users request it |
0 commit comments