Skip to content

feat(studio): show Style panel edits on the canvas before the save lands - #77

Merged
flowtricks merged 1 commit into
flowtricks:mainfrom
mhmdjaouhari:feat/live-style-rules
Nov 10, 2026
Merged

flowtricks merged 1 commit into
flowtricks:mainfrom
mhmdjaouhari:feat/live-style-rules

Conversation

@mhmdjaouhari

@mhmdjaouhari mhmdjaouhari commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

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):

  • 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 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.
@mhmdjaouhari

Copy link
Copy Markdown
Contributor Author

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 (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.

@flowtricks
flowtricks merged commit 6e51270 into flowtricks:main Nov 10, 2026
4 checks passed
@flowtricks

Copy link
Copy Markdown
Owner

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.

flowtricks added a commit that referenced this pull request Nov 10, 2026
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>
mhmdjaouhari added a commit to mhmdjaouhari/stacki that referenced this pull request Nov 11, 2026
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.
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.

2 participants