fix(notes): use SVG filters for soft shadow in SVG export#7934
fix(notes): use SVG filters for soft shadow in SVG export#7934steveruizok merged 8 commits intomainfrom
Conversation
Replace the hard offset rectangle shadow with a proper SVG filter using feGaussianBlur and feOffset to create a soft drop shadow that closely matches the in-app CSS box-shadow appearance. The shadow filter is skipped in dark mode, matching the in-app behavior.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
5 Skipped Deployments
|
Co-Authored-By: Claude Opus 4.6 <[email protected]>
| </feMerge> | ||
| </filter> | ||
| ), | ||
| }) |
There was a problem hiding this comment.
Dark-mode exports include unused shadow filters
Low Severity
toSvg always calls ctx.addExportDef for the note shadow filter, even when ctx.isDarkMode prevents any filtered shadow rect from rendering. This leaves large unused filter definitions in dark-mode SVG exports, increasing output size and parse cost without affecting visuals.
Additional Locations (1)
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| </feMerge> | ||
| </filter> | ||
| ), | ||
| }) |
There was a problem hiding this comment.
Filter IDs can collide across SVGs
Medium Severity
The new SVG filter id uses shape.id (cast to SafeId) without any per-export scoping, so exporting multiple SVGs that contain the same note shape.id and embedding them in the same document can cause url(#...) to reference the wrong <filter>, producing incorrect shadows.
| fill={getColorValue(theme, shape.props.color, 'noteFill')} | ||
| filter={`url(#${filterId})`} | ||
| /> | ||
| )} |
There was a problem hiding this comment.
Note fill rendered twice in light mode
Low Severity
In light mode, a filled <rect> with filter is rendered and then an identical filled <rect> is rendered again on top, so the note’s fill is drawn twice. If noteFill ever includes transparency or non-normal blending, this changes exported colors/opacity compared to rendering a single fill.
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| 🕒 Queued | multiplayer-template | b3231a5 | Feb 25 2026, 10:01 AM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| 🔵 In progress View logs |
image-pipeline-template | b3231a5 | Feb 25 2026, 10:01 AM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
multiplayer-template | c8277fd | Feb 25 2026, 06:18 PM |
The update-snapshots workflow was missing the build step that the regular e2e workflow has, which is needed for `vite preview` to serve the app. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Add 12 new entries from PRs merged since v4.4.0: - Featured: click-through on transparent image pixels (#7942) - API: enum-to-const-object refactor (#8084) - Improvements: SVG sanitizer (#7896), save-on-blur (#8037) - Bug fixes: cross-origin download (#8090), zero-size draw (#8067), rich text toolbar cleanup (#8050), zoom threshold (#8040), selection foreground fallback (#8011), sticky note SVG shadow (#7934), arrow frame clamping (#7932), zero pressure draw (#5693)


Closes #5110
When exporting sticky notes as SVG, the shadow was rendered as a simple semi-transparent offset rectangle, producing a hard shadow that looked different from the soft CSS
box-shadowseen in-app. This PR replaces that with a proper SVG filter usingfeGaussianBlurandfeOffsetto create a two-layer soft drop shadow that closely matches the in-app appearance. The shadow is skipped in dark mode, matching the in-app behavior.Change type
bugfixTest plan
Release notes
Note
Medium Risk
Touches SVG export rendering and introduces per-shape SVG defs/filters, which can affect exported output and snapshot stability across viewers. CI workflow change is low risk but may lengthen runs or fail if build prerequisites change.
Overview
Sticky note SVG export now uses a per-note
filterdefinition (registered viactx.addExportDef) to render a soft, multi-pass drop shadow instead of the previous hard shadow rectangle, and the shadow is omitted in dark mode.The Playwright snapshot update workflow now builds
apps/examples(including asset refresh + prebuild) before runningyarn e2e --update-snapshots, reducing snapshot churn from stale builds.Written by Cursor Bugbot for commit c8277fd. This will update automatically on new commits. Configure here.