feat(editor-state): add align blocks in row context-menu action by mouse-far · Pull Request #1203 · 8f4e/8f4e · GitHub
Skip to content

feat(editor-state): add align blocks in row context-menu action - #1203

Merged
andorthehood merged 6 commits into
8f4e:mainfrom
mouse-far:feat/411-align-blocks-in-row
Oct 22, 2026
Merged

andorthehood merged 6 commits into
8f4e:mainfrom
mouse-far:feat/411-align-blocks-in-row

Conversation

@mouse-far

Copy link
Copy Markdown
Contributor

Hi, thank you for asking me to do another task. This one was medium, but a little difficult. The hardest part was understanding what was required — the problem itself, and also pinpointing where the problem is. As usual, I used Muse AI (disclaimer: I used it to examine the code and understand the problem).

As far as I can see, the problem is clear in practice. It is about positions — x and y, under the name "grid". Imagine you have 3 boxes on the ground, scattered, with uneven distances between them, and you want to arrange them in one row. Arranging them was manual, and that is really annoying and impractical. So the goal is to turn it into one button that does this, with a gap of exactly 4.

12 small automatic checks were made, and we tested, and there was a bug: one block had the wrong distance — its gridX was 55 instead of the correct 50. The reason is the thing that confused me the most, so let me explain it in detail: every block keeps its own position written inside its own code, in a line like ; @pos x y. And a block's width is measured from its code — from its longest line. My first version moved the blocks one by one: it moved the first block, which rewrote its code with the new @pos line, and only then measured that block's width to place the next one. But it measured the already-changed code, and the new @pos line made the measured width bigger than the real one. Everything placed after it shifted by that difference, and the third block landed at 55 instead of 50. The fix: measure everything and decide all the positions first, from the original code, and only then move anything.

The expected numbers were accurate, as far as I know.

A few more things that need explaining: the button only appears for blocks that belong to a group, and only while editing; if the group has fewer than 2 blocks it does nothing. Blocks that are already in the right place are not touched at all — their code is not even rewritten. The whole rearrangement is a single step for undo, because the editor's history keeps a snapshot of the whole project. If two blocks start at the same gridX, their current order is kept. Viewport-anchored blocks are treated the same way as in the other group actions — no special case. And I did not update the docs page, because the internal TODO for this task left the docs out on purpose; I am happy to add it if you want.

Below, I am giving you the text prepared by the AI about what we did, so you can understand what I did. But once again, I assure you: I am not 100% sure of my work. Please review it well. And thank you.


Technical write-up (prepared by Muse AI, as mentioned above):

Closes #411

What was added

  • groupRowAligner effect (packages/editor/packages/editor-core/packages/editor-state/src/features/code-blocks/features/group/rowAligner/effect.ts): handles the alignGroupBlocksInRow event. Resolves the group with getGroupBlocks, stable-sorts targets by gridX, computes the complete layout before mutating anything, then applies the block dragger's mutation sequence (gridX/gridY, pixel position, lastUpdated, upsertPos, programmatic-edit notification) to each block that actually moves. The anchor block (leftmost) is never mutated and lends its gridY to the row. Widths come from getCodeBlockGridWidth(code, minGridWidth) — the same source the renderer uses — and the row gap is a named constant, ROW_GAP_GRID_COLUMNS = 4.
  • Menu item "Align blocks in row" in the hasGroup block of moduleMenu.ts, plus effect registration in index.ts.

Tests — 12 new

  • Effect (10): order preservation, y alignment to the first block, width-aware 4-column spacing, no-op with fewer than 2 targets, no-op without a group, no-op while editing is disabled, group isolation, gridX ties, @pos/pixel synchronisation, already-aligned rows left untouched.
  • Menu (2): item present for a grouped block, absent otherwise.

Verification (actually run, results as observed)

  • npx nx run @8f4e/editor-state:test — 154 test files, 1,174 tests passed, no type errors (baseline before this change: 153 files, 1,162 tests).
  • npx nx run @8f4e/editor-state:typecheck — passed.
  • Biome check on all changed files — clean.
  • Blast radius: @8f4e/editor-core tests 86/86 passed; @8f4e/editor-default tests 50/50 passed.

AI use: this change was prepared with an AI coding agent (Muse, Meta) directed by @mouse-far.

@andorthehood

Copy link
Copy Markdown
Member

@andorthehood andorthehood added editor Editor, web UI, VS Code integration, and interactive experience work contributor labels Oct 21, 2026
@andorthehood

Copy link
Copy Markdown
Member

@mouse-far I just tested this in the Hymn to Aurora example, which has several grouped code blocks. I held Alt (Option) to move them individually and scatter them around, then used “Align blocks in row” from the context menu to line them up again. It worked perfectly! Thanks a lot for the contribution!

@andorthehood andorthehood left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good too

@andorthehood

Copy link
Copy Markdown
Member

@andorthehood
andorthehood merged commit ecb8a69 into 8f4e:main Oct 22, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor editor Editor, web UI, VS Code integration, and interactive experience work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add row-align context-menu action with fixed spacing

2 participants