Add text alignment (left/center/right/justify)#1086
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds text-alignment support to the editor toolbar (left/center/right/justify), including sanitization support and end-to-end tests to ensure alignment is applied and preserved.
Changes:
- Add an “Alignment” dropdown to the toolbar and dispatch Lexical element-format commands for alignment.
- Track current block alignment in selection formatting and reflect it in toolbar pressed states.
- Add Playwright + Rails system tests covering alignment behavior and persistence.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/test_helpers/toolbar_helper.rb | Adds a test helper to apply alignment via the toolbar dropdown. |
| test/system/text_alignment_test.rb | Introduces Rails system tests to verify alignment persistence after save/edit. |
| test/browser/tests/formatting/toolbar.test.js | Tweaks viewport width used in the toolbar overflow test. |
| test/browser/tests/formatting/text_alignment.test.js | Adds Playwright coverage for alignment commands and UI state. |
| test/browser/helpers/toolbar.js | Extends toolbar helpers to open the alignment dropdown automatically. |
| src/elements/toolbar.js | Adds alignment dropdown UI and pressed-state syncing based on selection format. |
| src/editor/selection.js | Exposes blockAlignment from the current selection. |
| src/editor/command_dispatcher.js | Adds alignment commands using FORMAT_ELEMENT_COMMAND. |
| src/config/dom_purify.js | Allows text-align through DOMPurify style filtering. |
Files not reviewed (1)
- src/elements/toolbar_icons.js: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| click_on "Update Post" | ||
|
|
||
| assert_selector "p[style='text-align:right;']", text: "Hello everyone" |
There was a problem hiding this comment.
Mirroring the existing precedent in test/system/color_highlighter_test.rb — it uses the same strict mark[style='background-color:var(--highlight-bg-1);'] matcher. The serialized format is stable for server-rendered HTML (it's the CSSStyleDeclaration cssText form, not the editor JS output), and the test passes consistently. Happy to switch to style*= if you'd prefer, but the strict form matches the codebase convention.
| #getBlockAlignment(anchorNode) { | ||
| return $getNearestBlockElementAncestorOrThrow(anchorNode).getFormatType() ?? "" | ||
| } |
There was a problem hiding this comment.
Good catch — agreed that toolbar state updates shouldn't be able to crash the editor on edge-case selections. Wrapped the call in a try/catch with a "" fallback in 0ee9fa7. (The non-throwing $getNearestBlockElementAncestor variant isn't exported from @lexical/utils 0.44, so try/catch is the lightest fix.)
| <div data-dropdown-panel role="menu" class="lexxy-editor__toolbar-dropdown-list" hidden> | ||
| <button type="button" name="align-left" data-command="alignLeft" title="Align left" role="menuitem"> | ||
| ${ToolbarIcons.alignLeft} <span>Left</span> | ||
| </button> | ||
| <button type="button" name="align-center" data-command="alignCenter" title="Align center" role="menuitem"> | ||
| ${ToolbarIcons.alignCenter} <span>Center</span> | ||
| </button> | ||
| <button type="button" name="align-right" data-command="alignRight" title="Align right" role="menuitem"> | ||
| ${ToolbarIcons.alignRight} <span>Right</span> | ||
| </button> | ||
| <button type="button" name="align-justify" data-command="alignJustify" title="Justify" role="menuitem"> | ||
| ${ToolbarIcons.alignJustify} <span>Justify</span> | ||
| </button> | ||
| </div> |
There was a problem hiding this comment.
Fair point on the ARIA semantics, but the existing format dropdown (Normal / Large / Medium / Small Heading) right above this one is also a mutually exclusive set using role="menuitem" + aria-pressed. Matching that pattern here for consistency — happy to flip both dropdowns to menuitemradio + aria-checked in a follow-up PR if that's the direction you'd like.
Implements text alignment as a toolbar dropdown by dispatching Lexical's FORMAT_ELEMENT_COMMAND. Works on paragraphs, headings, list items, and table cells. Adds state-driven active-button highlighting in the dropdown. - Add "text-align" to DOMPurify's allowed style properties so the inline style survives sanitization. - Surface blockAlignment from Selection#getFormat for toolbar state reads. - Register the four align* commands in the command dispatcher. - Add the alignment dropdown to the default toolbar template, after the format dropdown and before highlight. - Add 4 alignment SVG icons. Bumps the viewport in the existing overflow-compaction test from 360px to 400px to accommodate one more non-overflowable toolbar item. Closes basecamp#1067
f07f7b7 to
0ee9fa7
Compare
Implements text alignment as a toolbar dropdown by dispatching Lexical's
FORMAT_ELEMENT_COMMAND. Works on paragraphs, headings, list items, and table cells. Adds state-driven active-button highlighting in the dropdown.Bumps the viewport in the existing overflow-compaction test from 360px to 400px to accommodate one more non-overflowable toolbar item.
Closes #1067