Skip to content

feat(toolbar): flat toolbar redesign + agent presence indicator#790

Open
jacobjove wants to merge 9 commits into
eigenpal:mainfrom
jacobjove:feat/toolbar-refresh
Open

feat(toolbar): flat toolbar redesign + agent presence indicator#790
jacobjove wants to merge 9 commits into
eigenpal:mainfrom
jacobjove:feat/toolbar-refresh

Conversation

@jacobjove

@jacobjove jacobjove commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Refreshes the editor toolbar to a flat, single-surface design (borderless icon buttons, blue-tint active state, segmented font-size control, consistent dividers) and adds an AgentActivityIndicator component for showing AI-collaborator presence in the title-bar slot.

Separately fixes a latent rendering bug: the library ships without Tailwind's 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. In host apps without their 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.

React and Vue both updated; changeset included (minor — additive AgentActivityIndicator).


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.

@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 18, 2026 1:47pm

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, top hairline divider, blue-tint active state, segmented font-size control) across React and Vue, fixes latent preflight-related rendering bugs in host apps without a CSS reset, and adds AgentActivityIndicator for showing AI-collaborator presence in the title-bar slot.

  • Toolbar redesign: ToolbarGroup gains a self-managed leading divider, ToolbarButton active state migrates from a dark slab to a blue-tint doc token, and the font family/size pickers are split into separate groups; editor.css picks up a scoped preflight subset (border-style reset, button chrome reset) and the ep-agent-pulse animation.
  • AgentActivityIndicator: New React + Vue components expose activity (absent | connected | editing) for driving an awareness chip from Yjs or any presence layer; exported from both package entry points with a minor-bump changeset.
  • Vue Toolbar regressions: The documentStyles prop is dropped (doc-specific styles no longer appear in the Vue style picker), the font-size <input> is replaced with a display-only <button> (no custom size entry in Vue), and aria-expanded/aria-haspopup are stripped from dropdown triggers; ZoomControl grows five props that its implementation never reads.

Confidence Score: 3/5

Not safe to merge without addressing the Vue Toolbar regressions and the unconnected agent presence dot.

The toolbar redesign and AgentActivityIndicator additions are solid, but the Vue adapter ships with three user-visible regressions: document-specific styles vanish from the style picker, font size can no longer be typed directly, and dropdown triggers lose their accessibility semantics. The new AgentPanelToggle presence dot is also impossible to activate through DocxEditorToolbar because the activity prop is never threaded through, and ZoomControl exposes five props that are silently ignored.

packages/vue/src/components/Toolbar.vue (three regressions), packages/react/src/components/DocxEditor/DocxEditorToolbar.tsx (activity not forwarded), packages/react/src/components/ui/ZoomControl.tsx (dead props)

Important Files Changed

Filename Overview
packages/vue/src/components/Toolbar.vue Large flat-toolbar redesign; has three regressions: documentStyles prop removed (doc-specific styles vanish from the style picker), font-size input replaced with button (no custom size entry), and aria-expanded/aria-haspopup removed from dropdown triggers.
packages/react/src/components/ui/ZoomControl.tsx Stripped to a pure Radix Select dropdown; five newly added props (minZoom, maxZoom, showButtons, persistZoom, storageKey) are declared in the interface but never consumed, silently swallowing values the caller already passes.
packages/react/src/components/DocxEditor/DocxEditorToolbar.tsx Migrates trailing toolbar controls from bare ToolbarSeparators to ToolbarGroups; the new AgentPanelToggle activity prop is never forwarded, leaving the agent-presence dot on the toggle unreachable from DocxEditorToolbar.
packages/react/src/components/DocxEditor/AgentPanelToggle.tsx Adds activity prop with awareness dot (steady or pulsing); the prop itself is correct but is never forwarded by DocxEditorToolbar, so it is unreachable from the public surface.
packages/react/src/components/DocxEditor/AgentActivityIndicator.tsx New component — presence chip with avatar, status label, and pulse dot; uses inline styles and CSS tokens throughout, well-scoped and accessible.
packages/vue/src/components/DocxEditor/AgentActivityIndicator.vue Vue port of the React AgentActivityIndicator; uses getCurrentInstance() to detect click-listener wiring (fragile but documented); otherwise a clean port with scoped styles.
packages/react/src/components/Toolbar.tsx Flat toolbar redesign — pill removed, ToolbarGroup gains leading divider, ToolbarButton active state migrated to blue-tint doc tokens, font family and size split into separate groups; changes are coherent and consistent.
packages/core/src/styles/editor.css Adds scoped preflight subset (border-style reset, button chrome reset), toolbar-group first-child divider rule, agent CSS tokens, and ep-agent-pulse keyframe with reduced-motion guard — all well-scoped under .ep-root.
packages/react/src/components/ui/Select.tsx Adds bordered prop to SelectTrigger and migrates shadcn tokens to doc tokens; SelectLabel hardcodes text-slate-500 instead of the doc-text-subtle token used elsewhere.
packages/react/src/components/ui/FontSizePicker.tsx Segmented control redesign — outer border on container, borderless inner buttons, box-sizing fixed, inline styles get CSS variable fallbacks; preserves both editable input and display-only button states.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph React
        DET[DocxEditorToolbar] -->|active, badge, onClick| APT[AgentPanelToggle]
        APT -. activity prop exists but NOT forwarded .-> dot[presence dot - unreachable]
        DET --> TB[Toolbar]
        TB --> TG[ToolbarGroup with leading divider]
        TG --> FSP[FontSizePicker - editable input kept]
        TG --> ZC[ZoomControl - Select only]
        ZC -. minZoom maxZoom showButtons silently ignored .-> ZC
    end
    subgraph Vue
        VTB[Toolbar.vue] --> VFG[font-size - button only no typing]
        VTB --> VSP[style picker - static presets only]
        VTB --> VAAT[AgentActivityIndicator.vue]
    end
    subgraph Shared
        CSS[editor.css - scoped preflight + ep-agent-pulse]
        TW[tailwind-preset.cjs - doc-separator + doc-agent tokens]
        AAI[AgentActivityIndicator.tsx - activity prop drives chip]
    end
    CSS --> React
    CSS --> Vue
    TW --> React
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"}}}%%
flowchart TD
    subgraph React
        DET[DocxEditorToolbar] -->|active, badge, onClick| APT[AgentPanelToggle]
        APT -. activity prop exists but NOT forwarded .-> dot[presence dot - unreachable]
        DET --> TB[Toolbar]
        TB --> TG[ToolbarGroup with leading divider]
        TG --> FSP[FontSizePicker - editable input kept]
        TG --> ZC[ZoomControl - Select only]
        ZC -. minZoom maxZoom showButtons silently ignored .-> ZC
    end
    subgraph Vue
        VTB[Toolbar.vue] --> VFG[font-size - button only no typing]
        VTB --> VSP[style picker - static presets only]
        VTB --> VAAT[AgentActivityIndicator.vue]
    end
    subgraph Shared
        CSS[editor.css - scoped preflight + ep-agent-pulse]
        TW[tailwind-preset.cjs - doc-separator + doc-agent tokens]
        AAI[AgentActivityIndicator.tsx - activity prop drives chip]
    end
    CSS --> React
    CSS --> Vue
    TW --> React
Loading

Reviews (1): Last reviewed commit: "Merge branch 'main' into feat/toolbar-re..." | 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>
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