Skip to content

feat(toolbar): flat single-surface styling, scoped preflight reset, and parity fixes#790

Closed
jacobjove wants to merge 16 commits into
eigenpal:mainfrom
jacobjove:feat/toolbar-refresh
Closed

feat(toolbar): flat single-surface styling, scoped preflight reset, and parity fixes#790
jacobjove wants to merge 16 commits into
eigenpal:mainfrom
jacobjove:feat/toolbar-refresh

Conversation

@jacobjove

@jacobjove jacobjove commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Aligns the editor toolbar's visual styling with the flat, single-surface look of the Word/Google-Docs bar (borderless icon buttons, blue-tint active state, consistent dividers, compact height), and folds in the fixes surfaced along the way.

Bug fix — scoped button preflight (.ep-root). The library ships @tailwind utilities only, no preflight, by design (so it never resets a host app's styles). But nothing reproduced the button-relevant subset for the editor's own controls, so in a host without its own reset: toolbar buttons inherited user-agent chrome, width-only border utilities rendered nothing (border-style defaults to none), buttons had no pointer cursor, and content-box inputs resized on focus. Now reproduced, scoped to .ep-root.

Vue parity regressions restored. documentStylesuseParagraphStyleOptions (real document styles in the style picker, not just static presets); the editable font-size <input> (arbitrary sizes by direct entry, replacing a display-only button); aria-expanded / aria-haspopup on the dropdown triggers.

Dark mode + i18n. Toolbar and agent-chip colors moved off bare hex onto the existing --doc-* chrome tokens so they re-theme under .ep-root.dark; the AgentActivityIndicator labels go through useTranslation.

Additive — AgentActivityIndicator. A small, opt-in component for AI-collaborator presence in the title-bar slot. Minor bump; nothing renders it unless a host opts in.

React and Vue both updated; changeset included.

@vercel

vercel Bot commented Jun 13, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the EigenPal Team on Vercel.

A member of the Team first needs to authorize it.

@eigenpal-release-pal

eigenpal-release-pal Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅

Posted by the CLA bot.

@jacobjove jacobjove force-pushed the feat/toolbar-refresh branch 3 times, most recently from a6571c2 to 20d89c5 Compare June 15, 2026 13:47
Refresh the editor toolbar to a flat, single-surface design — borderless
icon buttons, a blue-tint active state, a segmented font-size control, and
consistent dividers/spacing — and add an AgentActivityIndicator component
for AI-collaborator presence in the title-bar slot. React + Vue.

Also reproduce the button-relevant subset of Tailwind preflight, scoped to
.ep-root. The library ships without preflight (so it never resets a host
app's styles); without it, host apps lacking their own reset get leftover
user-agent button chrome, width-only border utilities that render nothing,
no pointer cursor on buttons, and content-box inputs that resize on focus.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jacobjove jacobjove force-pushed the feat/toolbar-refresh branch from 20d89c5 to 0414e17 Compare June 15, 2026 13:53
Jacob Jove and others added 5 commits June 15, 2026 13:38
- Replace bare hex/rgba/named colors in the toolbar + agent-presence components
  with the existing --doc-* chrome tokens (surface, shadow, primary, text,
  border, bg-hover, text-subtle/-muted) so they re-theme under .ep-root.dark.
  Adds a constant --doc-on-agent token for the white foreground on the indigo
  agent badge (badge stays indigo in dark, so it must not invert). React + Vue.
- Regenerate docs/api/docx-editor-react/ui.api.md for the ZoomControl props this
  PR added — api:check was missing them (would fail CI on merge).
… reset

The library ships `@tailwind utilities` only (no preflight) so it never resets a
host app's styles. Document the silent breakages in a host without its own reset
(UA button chrome, no-op width-only borders, content-box inputs, var-dependent
transform utilities) and the .ep-root scoped subset that mitigates them. Pairs
with the editor.css preflight reset in eigenpal#790.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The api-extractor golden for @eigenpal/docx-editor-react drifted once main's
toolchain bump changed how the AgentActivityIndicator return type resolves
(react_jsx_runtime.JSX.Element -> React_2.JSX.Element). Regenerated on the
merged state so api:check is green.
@vercel

vercel Bot commented Jun 17, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
docx-editor Ready Ready Preview, Comment Jun 23, 2026 4:53pm

Request Review

@greptile-apps

greptile-apps Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR delivers a flat toolbar redesign (white surface, leading-divider ToolbarGroup pattern, blue-tint active state, segmented font-size control) across React and Vue, adds an AgentActivityIndicator presence chip and an activity dot on AgentPanelToggle, and fixes a latent host-app rendering bug by adding a scoped preflight subset to editor.css.

  • Flat toolbar (React + Vue): pill layout replaced with a borderless white surface; ToolbarGroup now owns a leading 1px divider; font-family and font-size split into separate groups; icon baseline nudges added for underline/super/subscript.
  • Agent presence: AgentActivityIndicator component (React + Vue) renders a pulsing indigo chip in renderTitleBarRight; AgentPanelToggle gains an activity dot; DocxEditorToolbar threads agentPanel.activity through. Previously flagged issues (unforwarded activity prop, unused ZoomControl props, Vue editable font-size regression, documentStyles in Vue style picker, ARIA dropdown attributes) are all addressed at the current HEAD.
  • Scoped preflight fix: .ep-root * border reset and .ep-root button chrome/cursor reset added to editor.css; documented in CLAUDE.md pitfalls.

Confidence Score: 4/5

Safe to merge once the AgentActivityIndicator label strings are run through the i18n system.

Both the React and Vue AgentActivityIndicator components render user-visible text ("is editing…" / "connected") as hardcoded English strings rather than using useTranslation. CLAUDE.md explicitly forbids this, and en.json has no keys for these phrases. Every other UI string added in this PR correctly uses t(), so the fix is straightforward — add two keys to en.json and wire useTranslation in both components. All previously flagged regressions (unforwarded activity prop, unused ZoomControl props, Vue font-size input, documentStyles, ARIA attributes) are resolved at HEAD.

packages/react/src/components/DocxEditor/AgentActivityIndicator.tsx and packages/vue/src/components/DocxEditor/AgentActivityIndicator.vue — both need i18n wiring for the chip labels.

Important Files Changed

Filename Overview
packages/react/src/components/DocxEditor/AgentActivityIndicator.tsx New component for AI-collaborator presence chip; hardcodes user-facing English labels instead of using t() — violates CLAUDE.md i18n rule
packages/vue/src/components/DocxEditor/AgentActivityIndicator.vue Vue port of the React presence chip; same hardcoded English label strings as the React version, missing useTranslation
packages/core/src/styles/editor.css Adds scoped preflight subset, toolbar divider CSS, and agent-presence pulse animation; new --doc-agent-bg token has no dark-mode override (will be bright in dark mode)
packages/react/src/components/DocxEditor/DocxEditorToolbar.tsx Switches trailing cluster from bare ToolbarSeparators to ToolbarGroups and forwards agentPanel.activity to AgentPanelToggle — previously flagged issues addressed
packages/react/src/components/Toolbar.tsx Flat redesign: pill→borderless layout, ToolbarGroup leading-divider pattern, font-family and font-size split into separate groups, icon baseline nudges for underline/super/subscript
packages/vue/src/components/Toolbar.vue Mirrors React flat redesign; restores editable font-size input via useToolbarFontSize, documentStyles forwarded to useParagraphStyleOptions, ARIA attributes preserved on all dropdown triggers
packages/react/src/components/ui/ZoomControl.tsx Simplified to a pure Radix Select dropdown — removes unused minZoom/maxZoom/showButtons/persistZoom/storageKey props and stepper buttons as flagged in prior review
packages/core/tailwind-preset.cjs Adds doc-separator, doc-agent, doc-agent-bg Tailwind colour utilities mapped to the new CSS tokens
packages/react/src/components/DocxEditor/AgentPanelToggle.tsx Adds activity prop with awareness dot (steady or pulsing) — previously flagged forwarding gap resolved in DocxEditorToolbar
packages/vue/src/composables/useToolbarFontSize.ts Font-size editing composable refactored to add snap-back for invalid input and applied-flag to avoid double-commit; well-tested

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Host as Host App
    participant DocxEditorToolbar as DocxEditorToolbar
    participant AgentPanelToggle as AgentPanelToggle
    participant TitleBar as TitleBar (renderTitleBarRight)
    participant AgentActivityIndicator as AgentActivityIndicator

    Host->>DocxEditorToolbar: "agentPanel={activity:'editing', ...}"
    DocxEditorToolbar->>AgentPanelToggle: "activity='editing'"
    Note over AgentPanelToggle: pulsing dot on toggle button

    Host->>TitleBar: renderTitleBarRight()
    TitleBar->>AgentActivityIndicator: "activity='editing', agentName='Claude'"
    Note over AgentActivityIndicator: chip: "Claude is editing" + pulse dot
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Host as Host App
    participant DocxEditorToolbar as DocxEditorToolbar
    participant AgentPanelToggle as AgentPanelToggle
    participant TitleBar as TitleBar (renderTitleBarRight)
    participant AgentActivityIndicator as AgentActivityIndicator

    Host->>DocxEditorToolbar: "agentPanel={activity:'editing', ...}"
    DocxEditorToolbar->>AgentPanelToggle: "activity='editing'"
    Note over AgentPanelToggle: pulsing dot on toggle button

    Host->>TitleBar: renderTitleBarRight()
    TitleBar->>AgentActivityIndicator: "activity='editing', agentName='Claude'"
    Note over AgentActivityIndicator: chip: "Claude is editing" + pulse dot
Loading

Reviews (2): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

Comment thread packages/react/src/components/ui/ZoomControl.tsx Outdated
Comment thread packages/react/src/components/DocxEditor/DocxEditorToolbar.tsx
Comment thread packages/vue/src/components/Toolbar.vue Outdated
Comment thread packages/vue/src/components/Toolbar.vue
Comment thread packages/vue/src/components/Toolbar.vue
Comment thread packages/react/src/components/ui/Select.tsx Outdated
Jacob Jove and others added 2 commits June 18, 2026 09:18
# Conflicts:
#	packages/core/src/styles/editor.css
#	packages/react/src/components/Toolbar.tsx
Resolves the Greptile review on eigenpal#790 plus the merge conflict with main.

React:
- ZoomControl: remove 5 dead props (minZoom, maxZoom, showButtons,
  persistZoom, storageKey) that were declared but never consumed; drop
  the no-op values the Toolbar caller passed. Document `levels` as the
  single source of range (smallest/largest preset = bounds).
- DocxEditorToolbar: forward agentPanel.activity to AgentPanelToggle so
  the awareness dot is reachable from the public <DocxEditor agentPanel>
  surface; add `activity` to AgentPanelOptions.
- Select: SelectLabel uses text-doc-text-subtle (doc token) instead of
  hardcoded text-slate-500 so it survives dark mode.

Vue (parity regressions vs main, restored):
- Restore documentStyles prop + useParagraphStyleOptions so real
  document styles show in the style picker (not just static presets).
- Restore the editable font-size <input> (direct text entry of arbitrary
  sizes) via useToolbarFontSize, replacing the display-only button.
- Restore aria-expanded / aria-haspopup on the zoom, style, font, size,
  align, and spacing dropdown triggers.

Merge: resolve conflicts in editor.css (keep both agent + scrollbar
tokens; re-point light-theme --doc-toggle-active-* to the flat blue-tint
so the redesign's active state lands through main's .ep-toolbar-toggle
mechanism) and Toolbar.tsx (adopt main's CSS-class toggle states).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review follow-up on eigenpal#790. The restored size box is a persistent <input>
with a one-way :value bind. On blur/Enter with empty or non-numeric
input, commitFontSize applies nothing, so currentFontSize never changes
and Vue's VDOM diff never re-patches the input — the typed garbage (e.g.
"abc") lingers in the box while the document keeps its real size. Reset
the DOM value to currentFontSize when nothing was applied; skip the reset
on a valid commit so reactivity re-patches without a flash of the old
value. Adds composable unit tests (commit half-points, clamp, snap-back,
sizeTyped guard, preset pick).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
# Conflicts:
#	packages/react/src/components/Toolbar.tsx
#	packages/vue/src/components/Toolbar.vue
@jacobjove

Copy link
Copy Markdown
Contributor Author

Merged main to resolve the conflicts in Toolbar.tsx / Toolbar.vue — the flat redesign collided with the new documentFonts font-group that landed on main. Resolution keeps the redesign's split font-family / font-size groups and threads documentFonts through the picker (React + Vue). documentFonts was already declared and destructured on both sides, so only the JSX/template structure needed reconciling.

For re-review: the earlier review (against 95eabe11) flagged the Vue parity regressions (document-style picker, editable font-size input, dropdown ARIA), the unforwarded agent-presence activity prop, and the unused ZoomControl props. All of those were already addressed in commits after the reviewed SHA — the current HEAD carries the fixes.

@greptile review

…t token

The presence chip rendered hardcoded English ('{name} is editing…' / '{name}
connected') as both visible text and aria-label, violating the i18n rule. Add
agentPanel.activityEditing/activityConnected keys and wire useTranslation in
both the React and Vue components. Also give --doc-agent / --doc-agent-bg a
dark-mode override so the chip isn't bright indigo on dark surfaces.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jacobjove pushed a commit to jacobjove/docx-editor that referenced this pull request Jun 22, 2026
…al#790 review)

Addresses the Greptile review on eigenpal#790:
- Vue Toolbar: restore document-style picker (documentStyles prop +
  useParagraphStyleOptions), editable font-size entry (useToolbarFontSize),
  and aria-expanded/aria-haspopup on the dropdown triggers — all dropped by
  the flat redesign. Re-wires the two orphaned composables; the host already
  passed :document-styles.
- DocxEditorToolbar: forward agentPanel.activity to AgentPanelToggle so the
  presence dot is reachable; add activity to AgentPanelOptions.
- ZoomControl: drop the five never-read props (minZoom/maxZoom/showButtons/
  persistZoom/storageKey) and the call-site that passed them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jacobjove pushed a commit to jacobjove/docx-editor that referenced this pull request Jun 22, 2026
…ze input, aria)

Real-browser regression coverage for the restored Vue toolbar behaviors:
style dropdown opens/lists/aria, and the font-size readout is an editable
<input> that opens its preset list on focus. Green via the vue Playwright
project against the live demo + demo.docx.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jacobjove pushed a commit to jacobjove/docx-editor that referenced this pull request Jun 22, 2026
… font-size input, aria)"

This reverts commit 4acb2db.
jacobjove pushed a commit to jacobjove/docx-editor that referenced this pull request Jun 22, 2026
The main merge brought origin/main's documentFonts font-group in alongside the
redesign's split font/size groups, pushing the file to 1001 lines and tripping
the max-lines lint rule. Collapse a two-line comment back to one.
origin/main keeps the Font Family and Font Size pickers in a single
ToolbarGroup; the flat-redesign branch had split them into two groups,
which inserts a vertical divider between the family and size boxes and
diverges from origin for no visual gain. Word places no divider there,
and the Vue toolbar already puts the group divider before the font
family box with none between family and size — so the single group also
restores React/Vue parity.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Jacob Jove and others added 2 commits June 22, 2026 16:46
Drop the always-on input border boxes the flat redesign had put on the
font-family / style / zoom dropdowns and the font-size stepper. Selectors
now read borderless at rest with a hover wash (Select bordered defaults to
false); the font-size stepper loses its segmented outer box, keeping a thin
box on the editable value only. The active toggle is already the blue tint.
Mirrored in the Vue toolbar for parity.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the flat toolbar from min-height 40px / py-1 to 34px / py-0.5 around the 28px buttons (2px slack), matching the compact Google Docs bar. Mirrored in Vue.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jacobjove jacobjove changed the title feat(toolbar): flat toolbar redesign + agent presence indicator feat(toolbar): flat single-surface styling, scoped preflight reset, and parity fixes Jun 23, 2026
@jacobjove

Copy link
Copy Markdown
Contributor Author

Superseded — this PR has been split into three cohesive, independently reviewable PRs and is being closed:

Together these cover the full diff that was here. Please review the three above instead.

@jacobjove jacobjove closed this Jun 24, 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