fix(core): scoped .ep-root preflight reset for hosts without their own#1024
fix(core): scoped .ep-root preflight reset for hosts without their own#1024jacobjove wants to merge 1 commit into
Conversation
The library ships @tailwind utilities only (no preflight) so it never resets a host app's styles. In a host that supplies no reset of its own (e.g. a bare VS Code webview), Tailwind width-only border utilities rendered nothing (border-style defaults to none, so picker borders + toolbar dividers vanished) and buttons inherited user-agent chrome with no pointer cursor. Reproduce just the button-relevant subset, scoped to .ep-root, so it fixes the editor's own controls without touching the host's styles. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
All contributors have signed the CLA ✍️ ✅ Posted by the CLA bot. |
Greptile SummaryThis PR adds a minimal scoped preflight subset to
Confidence Score: 3/5The border reset and button chrome fix are sound and well-scoped; the one concrete defect is that the disabled-button cursor override promised in both the CSS comment and CLAUDE.md will silently fail for any component that applies plain The fix itself (restoring The
|
| Filename | Overview |
|---|---|
| packages/core/src/styles/editor.css | Adds a scoped preflight subset (universal border reset + button chrome/cursor reset) under .ep-root. Border specificity claims are correct; however the cursor-not-allowed specificity claim in the comment is wrong — .ep-root button:disabled (0,2,1) beats .ep-root .cursor-not-allowed (0,2,0), so the documented developer escape hatch doesn't work as described. |
| CLAUDE.md | Adds detailed "No Tailwind preflight" pitfall entry covering borders, button chrome, box-sizing, and transform variables. The cursor-not-allowed note contains the same incorrect specificity claim as the CSS comment. |
| .changeset/scoped-preflight-reset.md | Valid patch-level changeset for @eigenpal/docx-editor-core with a consumer-facing summary. Package name matches the published name exactly. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Browser renders inside .ep-root] --> B{Host app provides\nCSS reset?}
B -- Yes --> C[Host preflight covers border-style,\nbutton chrome, etc.]
B -- No --> D[UA defaults apply:\nborder-style: none\nbutton UA chrome\ncursor: default on buttons]
D --> E[New scoped preflight subset\nin editor.css]
E --> F[.ep-root * universal rule\nborder-width:0 / border-style:solid\nborder-color:currentColor\nSpecificity: 0,1,0]
E --> G[.ep-root button rule\nappearance:none / background:transparent\ncursor:pointer\nSpecificity: 0,1,1]
E --> H[.ep-root button:disabled\ncursor:default\nSpecificity: 0,2,1]
F --> I{Later rule applies?}
I -- Tailwind utility .border-t = 0,2,0 --> J[Utility wins ✓]
I -- Inline style from painter --> K[Inline style wins ✓]
G --> L{cursor-not-allowed override?}
L -- .ep-root .cursor-not-allowed = 0,2,0 --> M[button:disabled WINS ✗\nComment claim is wrong]
L -- disabled:cursor-not-allowed variant = 0,3,0 --> N[Variant wins ✓]
%%{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
A[Browser renders inside .ep-root] --> B{Host app provides\nCSS reset?}
B -- Yes --> C[Host preflight covers border-style,\nbutton chrome, etc.]
B -- No --> D[UA defaults apply:\nborder-style: none\nbutton UA chrome\ncursor: default on buttons]
D --> E[New scoped preflight subset\nin editor.css]
E --> F[.ep-root * universal rule\nborder-width:0 / border-style:solid\nborder-color:currentColor\nSpecificity: 0,1,0]
E --> G[.ep-root button rule\nappearance:none / background:transparent\ncursor:pointer\nSpecificity: 0,1,1]
E --> H[.ep-root button:disabled\ncursor:default\nSpecificity: 0,2,1]
F --> I{Later rule applies?}
I -- Tailwind utility .border-t = 0,2,0 --> J[Utility wins ✓]
I -- Inline style from painter --> K[Inline style wins ✓]
G --> L{cursor-not-allowed override?}
L -- .ep-root .cursor-not-allowed = 0,2,0 --> M[button:disabled WINS ✗\nComment claim is wrong]
L -- disabled:cursor-not-allowed variant = 0,3,0 --> N[Variant wins ✓]
Reviews (1): Last reviewed commit: "fix(core): scoped .ep-root preflight res..." | Re-trigger Greptile
| /* 2. Button chrome + cursor. Without preflight the browser's user-agent button | ||
| * styling (beveled border + gray gradient background) leaks through every | ||
| * borderless/ghost button, and buttons don't get the interactive pointer | ||
| * cursor preflight normally applies. Neutralize the chrome and restore the | ||
| * pointer; variants that set a background via `.bg-*` utilities still win on | ||
| * specificity, and `cursor-not-allowed` utilities still win for disabled. */ | ||
| .ep-root button { | ||
| appearance: none; | ||
| -webkit-appearance: none; | ||
| background: transparent; | ||
| cursor: pointer; | ||
| } | ||
| .ep-root button:disabled { | ||
| cursor: default; | ||
| } |
There was a problem hiding this comment.
cursor-not-allowed utility cannot override .ep-root button:disabled
The comment says "cursor-not-allowed utilities still win for disabled," but the specificity math is reversed. .ep-root button:disabled resolves to (0,2,1) — class + type + pseudo-class — while the Tailwind-scoped utility .ep-root .cursor-not-allowed is only (0,2,0). Any developer who adds the plain cursor-not-allowed class to a disabled button expecting to override the default cursor will be silently surprised; the rule introduced here always wins. The disabled:cursor-not-allowed variant (which appends its own :disabled pseudo-class to yield (0,3,0)) does beat it, but that nuance is absent from the comment here and from the identical claim added to CLAUDE.md. Either drop the cursor from .ep-root button:disabled (UA already resets :disabled cursor to default on the author-side cursor: pointer via the UA stylesheet cascade — but since .ep-root button has author specificity, it would still win there), or correct the comment to say disabled:cursor-not-allowed is required and plain cursor-not-allowed is insufficient.
Split out of #790 as a standalone bug fix.
The library ships
@tailwind utilitiesonly (no preflight) by design, so it never resets a host app's styles. But in a host that supplies no reset of its own (e.g. a bare VS Code webview), nothing reproduced the button-relevant subset for the editor's own controls, so: Tailwind width-only border utilities rendered nothing (border-styledefaults tonone, so picker borders and toolbar dividers vanished), and<button>s inherited user-agent chrome with no pointer cursor.This reproduces just that subset, scoped to
.ep-root(universal border-style reset + button chrome/cursor neutralization), so it fixes the editor's controls without touching the host's styles. Documented in CLAUDE.md; changeset included.Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.