Repository navigation
feat(studio): show Style panel edits on the canvas before the save lands - #77
Conversation
A Style panel edit reached the canvas only after the save, the dev server's re-render and the morph. Measured with Playwright on an Astro site, 12 edits from Enter in the Size field until the canvas's stylesheets held the value: a median of 592 ms. The save itself is done in about 60 ms; the rest is the render and the morph. The panel now also sends the edited rule (selector, at-rule context, property, value, `!important`) through `host.previewRule`. Studio forwards it to the canvas as a `studio:live-rule` message, and the canvas sets the property on the matching rules of its loaded stylesheets (`features/preview/liveRules.ts`): - Selectors compare without Astro's scoping (`[data-astro-cid-*]`, `:where(.astro-*)`) and with uniform spacing around combinators. - `@media`, `@supports` and `@container` must match the panel's context; `@layer` is ignored, since it orders the cascade but doesn't change what a rule matches. - The rule classes come from the document's own window, so the frame's globals are used and a window without one (jsdom, older browsers) works. Nothing is persisted by the patch. The real update arrives as before with the same value and replaces the sheets, so a rule the patch could not match (a new rule, a nested one) still shows, at the old speed. Desktop does not set `previewRule`, so it is unchanged. Result: an edit to a rule in another file (a component's `<style>`) shows in a median of 25 ms instead of 592 ms. A rule in the open page's `<style>` takes about 90 ms, because the save's synchronous work holds the canvas's paint back; a follow-up change addresses that.
A follow-up change (mhmdjaouhari@45cb38f) addresses that and reduces it to 58 ms instead of 91 ms, but it's worth deciding if it's worth it before opening a PR, since it changes timing and delays the write to one frame later (at most 50 ms), so the canvas can paint the preview before the save's synchronous work blocks the shared main thread. That moves the save relative to whatever happens right after a commit, such as quick consecutive edits or undo, so you may want to check it against edge cases I haven't covered. |
|
Thanks so much for these suggestions! I've merged it over and am going to make some smaller tweaks to make this work with Astro's scoped styles and reuse some functionality we already have, but overall this is in a great place. |
Assets: Cloudflare R2, Bunny Storage and S3-compatible hosts sit beside
the project's own files. The panel heading switches source, the trail
starts at Assets, and hosts can be browsed, uploaded to, renamed,
reordered and deleted, with image, video, audio and font ("Aa") tiles.
Replace and Copy link are on every tile; Replace refuses code under
src/. Connect with Cloudflare or Bunny is the default, manual keys sit
under Advanced, and keys stay in the main process or on the Studio
server. Every file type can be selected; Compress skips what it cannot
compress.
Style panel: edits show on the canvas before the save lands, on one
shared protocol for Desktop and Studio that keeps Astro scoping, skips
grouped rules and restores the original on a failed save (rewrites
#77). Other properties rows are code fields, colour variables appear in
gradient fields, arrows step a number with the caret after its unit,
typed nested selectors keep their text, a new property fills a blank
line, and the selector field no longer swallows the first click.
Search: the Components tab is a grid of live previews that render each
component with its .stacki defaults or its first use on a page, and
open hidden dialogs and details (rewrites #76). Folder pills filter it,
tabs slide, the popup resizes smoothly, and the last tab and folder are
remembered. The other tabs use the classic list again.
Elsewhere: optional commit types in the git panel, "Version history"
with app dropdowns, reset menus on loop section labels, stylesheet and
folder locks against selector cleanup, dotted class labels in the
Navigator and on the canvas, inserted HTML lining up with its
siblings, dropdowns that preview on hover only for live canvas
previews, and colour swatches that resolve on a textarea.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream merged our live Style preview (flowtricks#77) and rewrote it for 1.0.23 (shared/properties/liveRules.ts, electron/preload/frameLiveRules.ts, src/features/style/model/liveRuleEdits.ts): source-scoped matching that keeps Astro's scoping, removals, undo on a failed save, and Desktop support. Our version (e7eef07) is dropped in favour of it, including its paint-first wait. Conflicts: files upstream changed that the fork deletes stay deleted; root package.json keeps ours at upstream's version; featureRoutes keeps the new media hosting routes without the chat route the fork removed.
I noticed style edits on Studio were a bit slow so I tried improving the speed. Noticeable difference after the change, both on my local machine as well as self-hosted on a cheap VPS. More details below.
A Style panel edit reached the canvas only after the save, the dev server's re-render and the morph. Measured with Playwright on an Astro site, 12 edits from Enter in the Size field until the canvas's stylesheets held the value: a median of 592 ms. The save itself is done in about 60 ms; the rest is the render and the morph.
The panel now also sends the edited rule (selector, at-rule context, property, value, !important) through host.previewRule. Studio forwards it to the canvas as a studio:live-rule message, and the canvas sets the property on the matching rules of its loaded stylesheets (features/preview/liveRules.ts):
[data-astro-cid-*], :where(.astro-*)) and with uniform spacing around combinators.@media,@supportsand@containermust match the panel's context;@layeris ignored, since it orders the cascade but doesn't change what a rule matches.Nothing is persisted by the patch. The real update arrives as before with the same value and replaces the sheets, so a rule the patch could not match (a new rule, a nested one) still shows, at the old speed. Desktop does not set previewRule, so it is unchanged.
Result: an edit to a rule in another file (a component's <style>) shows in a median of 25 ms instead of 592 ms. A rule in the open page's <style> takes about 90 ms, because the save's synchronous work holds the canvas's paint back.