Skip to content

Fix page editor alignment: checkboxes, bullets, drag handles + heading rhythm - #285

Merged
crs48 merged 7 commits into
mainfrom
claude/competent-hawking-c025dc
Jun 26, 2026
Merged

Fix page editor alignment: checkboxes, bullets, drag handles + heading rhythm#285
crs48 merged 7 commits into
mainfrom
claude/competent-hawking-c025dc

Conversation

@crs48

@crs48 crs48 commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Implements exploration 0231 — dials in the page/document editor's typography and fixes the alignment of bullets, checkboxes, and drag handles. Every fix was measured live in the running app (getBoundingClientRect, computed styles, screenshots).

What was broken (measured)

Issue Before After
Drag handle overlapped list bullets / checkboxes handle on top of the checkbox (−17.6px overlap) handle in the gutter, +4px gap, X identical (422) for every block
Drag handle vertical +3.3px low on paragraphs/lists within ±0.7px of the first-line centre for H1/H2/H3/p/bullet/numbered/task/blockquote
Unchecked to-dos rendered checked (blue ✓) input.checked desynced from node state unchecked = empty box, checked = blue + strikethrough
Heading vertical rhythm bypassed the rhythm system space-before uneven (H2=24, H3=20, code=16px) uniform 27.2px before / 6.4px after, body 12px flow

How

  • Drag handle (DragHandle.ts): anchor X to the editor content-left (constant gutter) not the matched block's edge; centre the button on the block's first rendered line via a Range (robust to inner list-item <p> margins); resolve the top-level block (depth 1) so a list drags as a whole.
  • Checkbox state: key the fill/checkmark off the authoritative li[data-checked] instead of the input's :checked DOM property; coerce a string checked attr ("false" is truthy!) to a real boolean in the task pipeline; fix the seed that wrote String(false).
  • Heading rhythm (globals.css): pierce the React node-view .react-renderer wrappers with :has() so "space precedes headings" fires uniformly; neutralise the node view's legacy margins.
  • Heading scale: one source of truth in editor.css (.ProseMirror h1..h6); HeadingView drops its duplicate/conflicting classes.
  • Checkbox shape/centre + measure: rounded-square radius, corrected optical nudge (~±0.3px), reading measure narrowed toward ~70ch.

Scope / notes

  • @xnetjs/editor and @xnetjs/devtools are private → no changeset needed (coverage passes). Page-specific fixes are scoped to .page-prose; the base editor.css changes (checkbox state, drag-handle centring, heading leading) intentionally apply to every editor surface.
  • Verified: editor (3247 tests) + devtools seed suites green; dark mode unaffected; bullet/numbered/to-do text still share one left edge (regression guard).

🤖 Generated with Claude Code

xNet Test and others added 7 commits June 26, 2026 09:29
…rag-handle alignment

Empirically measured the seeded "Sample Page – All Block Types" in the running
web app (getBoundingClientRect, computed styles, annotated screenshots) and
documented four alignment issues with root causes and a surgical fix set:

- Drag handle overlaps list bullets/checkboxes (~18px) — anchors to the inner
  list-item <p>, not the outer block; recommend a fixed-gutter anchor.
- Drag handle ~3px low vertically — fixed padding-top; recommend first-line
  (lh) centering.
- Unchecked tasks render checked — blue fill keys off input:checked (desynced
  DOM property) instead of li[data-checked]; recommend styling from data-checked.
- Heading vertical rhythm bypassed — React node views wrapped in
  .react-renderer escape the 0198 rhythm direct-child selectors; recommend
  piercing wrappers with :has() and one consolidated heading scale.

Horizontal list alignment (bullet/number/to-do share one edge) is already good.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ng scale

- Drag handle: anchor X to the editor content-left (constant gutter) instead
  of the matched block's left edge, so it no longer lands on list bullets /
  to-do checkboxes; centre the button on the block's first *rendered* line
  (via a Range, robust to inner list-item paragraph margins) at any size; and
  resolve the top-level block (depth 1) so a list drags as a whole.
- Checkbox: key the fill + checkmark off the authoritative li[data-checked]
  rather than the input's :checked DOM property, which can desync from the
  node and render unchecked tasks as filled.
- Task pipeline: coerce a string `checked` attr (e.g. "false", which is
  truthy) to a real boolean and self-heal the node, fixing both the checkbox
  and the completion mirror.
- Headings: editor.css `.ProseMirror h1..h6` is now the single source of the
  heading scale (size/weight/line-height/margins, leading on all 6 levels);
  HeadingView drops its duplicate/conflicting classes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Heading rhythm now pierces the React node-view `.react-renderer` wrappers
  via :has(), so the "space precedes headings" rule fires uniformly across
  levels, and the node view's legacy heading margins are neutralised.
- To-do checkbox: rounded-square radius (reads as a checkbox, not a dot) and
  a corrected optical nudge that centres the box on the first line within ~1px.
- Narrow the reading measure (max-w-[44rem]) toward ~70ch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…lse"

Yjs attributes are strings and the editor reads any non-empty string as
truthy, so `setAttribute('checked', String(false))` rendered seeded unchecked
to-dos as checked. Only set the attribute when checked is true; absent means
the schema's boolean false default.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ox drag handle alignment

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@crs48
crs48 temporarily deployed to pr-285 June 26, 2026 17:29 — with GitHub Actions Inactive
@github-actions

Copy link
Copy Markdown
Contributor

🖼️ UI changes in this PR

Interactions

🎬 Create a page and use the editor

Create a page and use the editor

▶ Watch MP4

Auto-captured by CI · run. Informational — not a blocking check.

github-actions Bot added a commit that referenced this pull request Jun 26, 2026
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Preview removed for PR #285.

github-actions Bot added a commit that referenced this pull request Jun 26, 2026
@crs48
crs48 merged commit 4cbd0e2 into main Jun 26, 2026
13 of 14 checks passed
@crs48
crs48 deleted the claude/competent-hawking-c025dc branch June 26, 2026 17:35
github-actions Bot added a commit that referenced this pull request Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant