Skip to content

feat(playground): wire pagination into the editor behind a toolbar toggle - #425

Open
arthrod wants to merge 2 commits into
codex/pagination-enabled-optionfrom
codex/playground-pagination-toggle
Open

feat(playground): wire pagination into the editor behind a toolbar toggle#425
arthrod wants to merge 2 commits into
codex/pagination-enabled-optionfrom
codex/playground-pagination-toggle

Conversation

@arthrod

@arthrod arthrod commented May 24, 2026

Copy link
Copy Markdown
Collaborator

Stacked on codex/pagination-enabled-option. Wires @platejs/pagination into the playground editor, toggled from the toolbar.

Live deploy (OpenNext → Cloudflare): https://plate-playground.cicero-im.workers.dev/editor

Change

  • PaginationKit adds PaginationPlugin (configured enabled: false initially) to EditorKit in a new "Layout" group.
  • PaginationToolbarButton — "Page breaks" (SeparatorHorizontal icon), in the lists/toggle toolbar group. Toggles via editor.setOption(PaginationPlugin, 'enabled', next); pressed reflects state.
  • biome cleanup: drop unused React import in pagination2-view.tsx.
  • Vendored dist (vendor/platejs-pagination) is gitignored and regenerated via vendor:pagination; the package change (base PR) + this branch reproduce it.

Verification

  • bun run typecheck ✓, OpenNext build ✓ (deployed), biome clean on changed files.
  • Live: /editor → 200, /dev/pagination2 → 200; "Page breaks" button + pagination overlay confirmed present in the deployed client bundle.
  • Not done: interactive click of the toggle in a live browser (Playwright headless-shell download blocked in this env). Toggle logic is unit-tested in the base PR.
  • eslint . over the whole template OOM'd (env heap limit); biome (primary linter) passed.

⚠️ Per explicit request, this edits templates/** directly, overriding the repo's CI-controlled-templates rule. CI template regeneration would overwrite it unless the source registry is also updated.

🤖 Generated with Claude Code

…ggle

- PaginationKit adds @platejs/pagination (enabled:false initially) to EditorKit.
- PaginationToolbarButton ("Page breaks", SeparatorHorizontal icon) toggles
  enabled via editor.setOption(PaginationPlugin,'enabled',next); pressed state
  reflects it. Added to the lists/toggle toolbar group.
- biome: drop unused React import in pagination2-view.

Overrides the CI-controlled-templates rule per explicit user request.
Deployed via OpenNext: https://plate-playground.cicero-im.workers.dev/editor

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@arthrod

arthrod commented May 24, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review very carefully and fix

@arthrod

arthrod commented May 24, 2026

Copy link
Copy Markdown
Collaborator Author

@gemini review very carefully and fix

@arthrod

arthrod commented May 24, 2026

Copy link
Copy Markdown
Collaborator Author

@Kilo review very carefully and fix

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request integrates the pagination feature into the Plate playground template. Key changes include the addition of a PaginationKit plugin configuration, the implementation of a PaginationToolbarButton to toggle page breaks, and the registration of these components within the EditorKit and the fixed toolbar. I have no feedback to provide as there were no review comments to evaluate.

@coderabbitai

coderabbitai Bot commented May 24, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

Let me gather the PR diff and all changed files first.


🏁 Script executed:

#!/bin/bash
# Fetch the PR diff and file list
gh pr view 425 --repo cicero-im/plate --json files,additions,deletions,body,title,baseRefName,headRefName 2>/dev/null || echo "PR fetch failed"

echo "=== PR DIFF ==="
gh pr diff 425 --repo cicero-im/plate 2>/dev/null | head -1000

Length of output: 7415


Good, I have the diff. Let me now examine the surrounding files for full context.


🏁 Script executed:

#!/bin/bash
echo "=== editor-kit.tsx ==="
cat templates/plate-playground-template/src/components/editor/editor-kit.tsx

echo ""
echo "=== fixed-toolbar-buttons.tsx (full) ==="
cat templates/plate-playground-template/src/components/ui/fixed-toolbar-buttons.tsx

echo ""
echo "=== Other kit files for pattern comparison ==="
cat templates/plate-playground-template/src/components/editor/plugins/line-height-kit.tsx 2>/dev/null || echo "not found"
cat templates/plate-playground-template/src/components/editor/plugins/align-kit.tsx 2>/dev/null || echo "not found"

echo ""
echo "=== Check lucide-react for SeparatorHorizontalIcon ==="
fd -e tsx -e ts -e js . templates/plate-playground-template/node_modules/lucide-react/dist 2>/dev/null | head -5 || echo "node_modules not available"
rg "SeparatorHorizontal" templates/plate-playground-template/src/ -n 2>/dev/null || echo "not found in src"

echo ""
echo "=== Check usePluginOption usage patterns in codebase ==="
rg "usePluginOption" templates/plate-playground-template/src/ -n -A2 -B1 | head -60

echo ""
echo "=== Check how other toolbar buttons use toggle/pressed pattern ==="
cat templates/plate-playground-template/src/components/ui/toggle-toolbar-button.tsx 2>/dev/null || echo "not found"

echo ""
echo "=== Check ToolbarButton component for pressed prop type ==="
cat templates/plate-playground-template/src/components/ui/toolbar.tsx 2>/dev/null | head -80

echo ""
echo "=== Check pagination2-view.tsx full content ==="
cat templates/plate-playground-template/src/app/dev/pagination2/pagination2-view.tsx

Length of output: 20827


Let me check the lucide-react version and icon availability.


🏁 Script executed:

#!/bin/bash
echo "=== Check package.json for `@platejs/pagination` ==="
cat templates/plate-playground-template/package.json | python3 -c "import json,sys; p=json.load(sys.stdin); deps={**p.get('dependencies',{}), **p.get('devDependencies',{})}; [print(k,v) for k,v in deps.items() if 'pagination' in k.lower() or 'platejs' in k.lower()]"

echo ""
echo "=== lucide-react version ==="
cat templates/plate-playground-template/package.json | python3 -c "import json,sys; p=json.load(sys.stdin); deps={**p.get('dependencies',{}), **p.get('devDependencies',{})}; print(deps.get('lucide-react','not found'))"

echo ""
echo "=== Check ToolbarButton pressed prop definition ==="
grep -n "pressed" templates/plate-playground-template/src/components/ui/toolbar.tsx | head -20

echo ""
echo "=== Check if PaginationPlugin typed options include 'enabled' as boolean ==="
rg "enabled" templates/plate-playground-template/src/components/editor/plugins/pagination-kit.tsx
rg "enabled" templates/plate-playground-template/vendor/ -n 2>/dev/null | head -20 || echo "vendor dir not present or empty"

echo ""
echo "=== Check gitignore for vendor ==="
cat templates/plate-playground-template/.gitignore 2>/dev/null | grep vendor || echo "no vendor in gitignore found"
cat .gitignore 2>/dev/null | grep vendor | head -5

echo ""
echo "=== Check if there's a README or docs for vendor:pagination script ==="
cat templates/plate-playground-template/package.json | python3 -c "import json,sys; p=json.load(sys.stdin); scripts=p.get('scripts',{}); [print(k,':',v) for k,v in scripts.items() if 'vendor' in k or 'pagination' in k]"

Length of output: 1896


I have a thorough picture now. Here are the findings and required fixes:


@arthrod Here is a careful review of the PR with concrete issues and proposed fixes.


🔴 Bug — pressed silently falls back to plain button when enabled is undefined

File: pagination-toolbar-button.tsx

ToolbarButton (Line 132 of toolbar.tsx) uses typeof pressed === 'boolean' to decide whether to render as a ToggleItem or a plain Button. If usePluginOption returns undefined during early render (before plugin state is hydrated), typeof undefined === 'boolean' is false, so the button renders as a non-toggle — the pressed visual state never shows up and the button looks identical whether pagination is on or off.

// before
pressed={enabled}

// after — ensure it always renders as a toggle
pressed={enabled ?? false}

🟡 Wrong Toolbar Group — Pagination is a view toggle, not a list/format control

File: fixed-toolbar-buttons.tsx

PaginationToolbarButton is currently appended to the alignment + lists group:

<AlignToolbarButton />
<NumberedListToolbarButton />
<BulletedListToolbarButton />
<TodoListToolbarButton />
<ToggleToolbarButton />
<PaginationToolbarButton />   // ← wrong group

Pagination is a view/layout mode toggle (like ModeToolbarButton), not a content-formatting control. It should live either in its own dedicated group or alongside the line-height/indent controls. The most consistent placement that matches the "Layout" group designation in editor-kit.tsx would be alongside LineHeightToolbarButton:

// Current LineHeight/Indent group — move PaginationToolbarButton here
<ToolbarGroup>
  <LineHeightToolbarButton />
  <OutdentToolbarButton />
  <IndentToolbarButton />
  <PaginationToolbarButton />  // ← fits: all layout/view controls
</ToolbarGroup>

🟡 Build — .gitignore doesn't cover vendor/platejs-pagination

File: templates/plate-playground-template/.gitignore (and root .gitignore)

The PR description says:

Vendored dist (vendor/platejs-pagination) is gitignored and regenerated via vendor:pagination

But neither .gitignore file mentions the vendor path. This means either:

  • The dist is committed to the repo (fine, intentional), but the PR description is incorrect, or
  • The dist is not committed and not gitignored, so a fresh clone would fail to resolve file:./vendor/platejs-pagination without first running vendor:pagination.

Either add the entry to .gitignore and document the required setup step, or commit the dist and fix the PR description. Currently package.json declares:

"`@platejs/pagination`": "file:./vendor/platejs-pagination"

This requires the directory to exist at install time.


🟡 Portability — vendor:pagination script is monorepo-only

File: templates/plate-playground-template/package.json

The path ../../packages/pagination is relative to the template directory inside the monorepo. A standalone consumer of the template template can never run this script. This should be documented prominently (e.g., in a README or inline comment) and the eventual goal should be publishing @platejs/pagination to npm so the file-dep can be dropped.


✅ All other changes look correct

File Status
pagination-kit.tsxPaginationPlugin.configure({ options: { enabled: false } }) ✓ Correct, consistent with AlignKit/LineHeightKit pattern
editor-kit.tsx// Layout group placement ✓ Clean grouping
pagination2-view.tsx — drop unused React, import type { Value } ✓ Valid biome cleanup
import type * as React in toolbar button ✓ Consistent with toggle-toolbar-button.tsx, floating-toolbar.tsx
SeparatorHorizontalIcon from lucide-react ^1.13.0 ✓ Valid (v1 uses Icon suffix)
'use client' in pagination-kit.tsx ✓ Consistent with all other kit files

Fixes to apply

  • Fix pressed={enabled ?? false} in pagination-toolbar-button.tsx
  • Move PaginationToolbarButton to the LineHeight/Indent group in fixed-toolbar-buttons.tsx
  • Add vendor/platejs-pagination/dist to templates/plate-playground-template/.gitignore (or document that it is intentionally committed)

🏁 Script executed:

rm -rf vendor/platejs-pagination/dist && cp -r ../../packages/pagination/dist vendor/platejs-pagination/dist

Length of output: 76


🏁 Script executed:

cat templates/plate-playground-template/.gitignore

Length of output: 603


The .gitignore confirms vendor/platejs-pagination is not gitignored — the dist is committed to the repo, contradicting the PR description. The vendor:pagination script also fails outside the monorepo (as confirmed above). Here is the complete fix plan:


@arthrod — three fixes are needed. Here they are as ready-to-apply diffs:


Fix 1 🔴 — pressed falls back to plain button on undefined (bug)

templates/plate-playground-template/src/components/ui/pagination-toolbar-button.tsx

ToolbarButton uses typeof pressed === 'boolean' internally — if enabled is undefined the button silently renders as a non-toggle plain button and never shows the active/pressed state.

     <ToolbarButton
       {...props}
       onClick={() => editor.setOption(PaginationPlugin, 'enabled', !enabled)}
-      pressed={enabled}
+      pressed={enabled ?? false}
       tooltip="Page breaks"
     >

Fix 2 🟡 — PaginationToolbarButton is in the wrong toolbar group (UX)

templates/plate-playground-template/src/components/ui/fixed-toolbar-buttons.tsx

Pagination is a layout/view toggle — not a list or content-format button. It should live in the LineHeight/Indent group, which already holds the other layout controls. The // Layout grouping in editor-kit.tsx reinforces this intent.

           <NumberedListToolbarButton />
           <BulletedListToolbarButton />
           <TodoListToolbarButton />
           <ToggleToolbarButton />
-          <PaginationToolbarButton />
         </ToolbarGroup>

         ...

         <ToolbarGroup>
           <LineHeightToolbarButton />
           <OutdentToolbarButton />
           <IndentToolbarButton />
+          <PaginationToolbarButton />
         </ToolbarGroup>

Fix 3 🟡 — vendor/platejs-pagination/dist should be gitignored (accuracy + intent)

templates/plate-playground-template/.gitignore

The dist is currently committed (not gitignored), which contradicts the PR description. More importantly, committing a build artifact that is regenerated via vendor:pagination means stale dist can silently get out of sync. The correct approach is to gitignore the dist, commit the package skeleton (package.json, README.md, etc.), and document the required setup step.

 # typescript
 *.tsbuildinfo
 next-env.d.ts
+
+# vendored local packages – dist is regenerated via `bun run vendor:pagination`
+# (monorepo only: copies ../../packages/pagination/dist)
+/vendor/platejs-pagination/dist

And add a note in vendor/platejs-pagination/README.md (new file) like:

# `@platejs/pagination` (vendored)

This package is a local file-dep resolved from the monorepo's packages/pagination.
Run `bun run vendor:pagination` from this template's directory (inside the monorepo)
to regenerate the dist after changing the source package.

Not for standalone use until `@platejs/pagination` is published to npm.

No action needed ✅

Item Verdict
SeparatorHorizontalIcon (lucide-react ^1.13.0) ✓ Valid
import type * as React pattern ✓ Consistent with other UI files
'use client' in pagination-kit.tsx ✓ Consistent with all kit files
editor-kit.tsx Layout group placement ✓ Clean
pagination2-view.tsx biome cleanup ✓ Correct
PaginationPlugin.configure({ options: { enabled: false } }) ✓ Correct API

The requested changes have been implemented and a pull request has been created: View PR

@coderabbitai

coderabbitai Bot commented May 24, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d2e2c866-7090-4bbc-9c3c-c9513ae0fd6e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/playground-pagination-toggle

Comment @coderabbitai help to get the list of available commands and usage tips.

@arthrod
arthrod force-pushed the codex/playground-pagination-toggle branch from f6f0e6a to 419cd46 Compare May 24, 2026 18:44
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