Skip to content

fix(editor): render checklist checkboxes via CSS pseudo-elements (#95)#97

Merged
zacharias-ona merged 1 commit into
mainfrom
fix/95-checklist-checkboxes
Apr 16, 2026
Merged

fix(editor): render checklist checkboxes via CSS pseudo-elements (#95)#97
zacharias-ona merged 1 commit into
mainfrom
fix/95-checklist-checkboxes

Conversation

@zacharias-ona
Copy link
Copy Markdown
Collaborator

Closes #95

What

Checklist/todo items in the editor had no visible checkboxes. Lexical's CheckListPlugin applies theme classes to <li> elements and expects CSS ::before pseudo-elements on those classes to render the checkbox UI. The theme only had Tailwind utility classes for padding and strikethrough — no actual checkbox was rendered, so items appeared as plain text.

How

Added marker CSS class names (editor-checklist-checked, editor-checklist-unchecked) to the editor theme's listitemChecked and listitemUnchecked entries. Added corresponding ::before and ::after pseudo-element rules in globals.css that render a checkbox square (unchecked) or a filled checkbox with checkmark (checked). This is raw CSS because Tailwind cannot generate ::before content for Lexical's injected DOM — an acceptable exception noted in the issue. Colors use design tokens (--muted-foreground, --accent, --primary-foreground, --ring).

Testing

  • Added 6 regression tests in theme.test.ts verifying:
    • Theme classes include the marker CSS class names
    • Theme classes have relative positioning for pseudo-element placement
    • Checked items have line-through styling
    • globals.css contains the required ::before/::after rules
  • pnpm lint && pnpm typecheck && pnpm test — all 57 tests pass
  • pnpm test:e2e — all 27 tests pass

Lexical's CheckListPlugin expects ::before pseudo-elements on checklist
item classes to render visible checkboxes. The theme only had Tailwind
utility classes (padding, strikethrough) but no actual checkbox rendering.

Add marker CSS class names to the theme and corresponding ::before/::after
rules in globals.css to render checkbox squares (unchecked) and filled
checkboxes with checkmarks (checked). Uses design tokens for colors.

Co-authored-by: Ona <no-reply@ona.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
memo Ready Ready Preview, Comment Apr 16, 2026 2:57pm

Request Review

@zacharias-ona
Copy link
Copy Markdown
Collaborator Author

Reviewed against AGENTS.md, conventions.md, and design.md. No blocking issues.

Correctness: Lexical's CheckListPlugin requires CSS pseudo-elements on theme classes — adding marker classes and ::before/::after rules is the correct approach. Positioning logic (absolute on pseudo-elements, relative on parent <li>) is sound.

Design: All colors use valid design tokens (--muted-foreground, --accent, --primary-foreground, --ring). Focus ring pattern matches existing convention in globals.css.

Conventions: Raw CSS exception is justified — Tailwind cannot target Lexical's injected DOM pseudo-elements. Documented in both the issue and PR description.

Testing: 6 regression tests verify the theme↔CSS contract. Static analysis test for globals.css follows the established pattern.

Scope: 3 files changed, all directly related to the fix.

Merging.

@zacharias-ona zacharias-ona merged commit 9c727c5 into main Apr 16, 2026
6 checks passed
@zacharias-ona zacharias-ona deleted the fix/95-checklist-checkboxes branch April 16, 2026 14:59
@zacharias-ona
Copy link
Copy Markdown
Collaborator Author

✅ UI verification passed — design spec compliance confirmed.

Static analysis (code review against .agents/design.md):

Check Result
Color tokens ✅ All colors use CSS variables (--muted-foreground, --accent, --primary-foreground, --ring)
Typography ✅ No changes to typography scale
Spacing ✅ Tailwind scale values (mt-0.5, pl-6); em units in pseudo-elements for relative sizing
Transitions ✅ No decorative animations added
Accessibility ✅ Focus ring uses var(--ring), cursor set to pointer on interactive elements
Dark mode ✅ All colors resolve through CSS variable tokens
Borders 1px solid with token variables
Custom CSS ✅ Justified — Tailwind cannot generate ::before/::after pseudo-elements; comment explains the exception

Visual verification (Playwright screenshots of /{workspaceSlug}/{pageId}):

  • Desktop (1280×800, dark): sidebar layout, editor area, spacing, and typography all match spec
  • Mobile (375×812): sidebar collapsed with hamburger, editor full-width, no horizontal scroll

Note: The test page was empty (no checklist content), so checkbox rendering could not be visually verified. The CSS changes are structural and only activate when Lexical renders checklist nodes — static analysis confirms correct token usage.

@zacharias-ona
Copy link
Copy Markdown
Collaborator Author

✅ Post-merge verification passed.

E2E suite: 27/27 tests passed against https://memo.software-factory.dev

Ad-hoc smoke tests:

  • ✅ Landing page — loaded, has title
  • /sign-in — rendered with email input
  • /api/health — healthy
  • ✅ Authenticated login flow — redirected to workspace
  • ✅ Workspace page — fully loaded
  • ✅ Editor navigation — page button click navigated to editor route, editor element rendered
  • ✅ No console errors (unauthenticated or authenticated)

Skipped: /dashboard (not yet built)

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.

fix: todo checklist checkboxes not visible in editor

1 participant