- Custom domain checkboxes are disabled+unchecked on free plan
- Staging domain checkbox remains enabled (user can check/uncheck)
- handlePublish reads formData directly; disabled checkboxes are never
submitted so custom domains are naturally excluded
- Removed force-set of hasSelectedDomains on free plan so publish button
correctly reflects actual checkbox state
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
- Add new story variants across ~100 files covering previously untested props
- Fix all story titles to use sentence case per UI label guidelines
- Consolidate duplicate card, thumbnail, and value-text stories into parent files
- Add interactive/controlled variants for checkbox, radio, switch, select, etc.
- Add style source, disabled, icon, placeholder, unit options variants to CssValueInput
- Add sub-menu, radio group, destructive, and disabled variants to dropdown/context menus
- Add dialog resize, maximize, actions, and non-draggable variants
- Add popover title, actions, and side placement variants
- Add tooltip side placements and content variant stories
- Fix shouldHideDot axis mapping: x always maps to justify-content
(main-axis), y always maps to align-items (cross-axis). The visual
transposition for column direction is handled by the CSS grid swap
in the render code, not in the dot-hiding logic.
- Export shouldHideDot and cover with 21 unit tests.
- Refactor stories into Flex_ and Grid_ combination grids showing
all alignItems x justifyContent combinations.
- Delete old flex-alignment.stories.tsx (used hooks, could not work).
- Rewrite shouldHideDot as cross-axis × main-axis intersection check
- Use visibility:hidden instead of conditional rendering to preserve layout
- Consolidate stories into FlexRow/FlexColumn combination grids
- Include normal/default values in story combinations
- Use real style panel dimensions (64×62)
- Skip loader/optimization for data: src in getImageAttributes
- Replace external picsum.photos URL with inline SVG data URI in social-preview story
- Remove unnecessary ThumbnailWrapper from thumbnail stories
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
- Show "Don't forget to publish" banner when a domain is connected but
not yet published
- Default-check newly added domains so they're included on publish
- Move domain instructions into a tooltip with help icon and docs link
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
- Add brush-cleaning icon and regenerate icons package
- Add delete unused assets command to command panel
- Add DeleteUnusedAssetsDialog with scrollable asset list
- Add icon button to assets panel header for quick access
- Export calculateUsagesByAssetId from asset-info
- Add autoFocus to Delete button in all delete-unused dialogs"
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
Previously only purchases with a subscriptionId (recurring
subscriptions) were displayed. Lifetime deals were counted as paid (no
"Free" badge) but not shown in the dropdown. Now LTDs appear as
non-clickable labels while subscriptions remain clickable and navigate
to the billing portal.
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
filter requires a callback (arrow function) which is blocked by the
linter's blanket "Functions are not supported" rule, making it
effectively dead code. Remove it and update all related tests.
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
Show a warning banner when a redirect path matches the current page
path, indicating the redirect will override access to the page.
Changes:
- Add PanelBanner component with warning variant to page settings
- Implement findMatchingRedirect utility to detect redirect conflicts
- Show contextual warning with link to Redirects settings section
- Add comprehensive tests for redirect conflict detection
Code quality:
- Replace 'return undefined' with 'return' per style guide
- Use 'return null' for React components returning nothing
## Summary
Upgrades colorjs.io from v0.5.x to v0.6.x and adopts the new functional
API to fix TypeScript compatibility issues and reduce bundle size.
## Breaking Changes in v0.6
This release includes two major changes from colorjs.io that required
code updates:
1. `null` instead of `NaN` for "none" values — Coordinates now use
`number | null` instead of the custom `Number` instance that previously
used `"none"` strings. This eliminates runtime casting and improves
TypeScript DX.
2. Plain numbers instead of `Number` objects — Coordinates are now plain
number primitives rather than `Number` objects with parsing metadata,
improving performance and bundle size.
## Changes Made
- Upgraded colorjs.io to v0.6.x
- Adopted functional API (`/fn` entry point) for tree-shakeable imports
and reduced bundle size
- Updated coordinate handling to use `number | null` directly instead of
custom `Number` instances with `"none"` values
- Removed runtime casting previously required for TypeScript
compatibility
- Aligned with engramma and hdr-color-input — both already use the
functional style, enabling code deduplication
## Migration Notes
See [colorjs.io v0.6.0 release
notes](https://github.com/color-js/color.js/releases/tag/v0.6.0) for
full details on the breaking changes.
- Remove fixed widths in topbar to allow flexible space distribution
- Add flexShrink: 0 to prevent button shrinking
- Adjust breakpoint container hide threshold from 640px to 800px
- Ensure ViewMode and SyncStatus icons don't shrink
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
- Changed safe mode detection from .has() to strict === 'true' check
- Made safemode a required boolean parameter in builderPath/builderUrl
- Added 'Open in safe mode' option to dashboard project menu
- Added safe mode indicator button with shield icon in topbar
- Safe mode now prevents all script execution in HTML embeds
- Added isSafeMode to React SDK context
- Added test coverage for safe mode in HTML embed component
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
The scrub (drag to change value) feature was not working on CSS value
inputs when the initial value was a keyword like 'auto'.
This was a regression from b18315e570 which changed the early-return
checks to use valueRef.current.type but forgot to add value.type to the
useEffect dependency array, so the scrub control was never re-attached
when the value type changed.
fixes https://github.com/webstudio-is/webstudio/issues/5597
When adding a new breakpoint, editing its name and settings, then
closing and reopening the menu, the breakpoint appeared with empty
values instead of the saved data.
Reset breakpoints editor state when closing to correctly display
breakpoints
- Add Token class and token() helper in template package for JSX token
support
- Refactor insertFragmentWithConflictResolution to
detectFragmentTokenConflicts
- Refactor insertPageWithConflictResolution to detectPageTokenConflicts
- Move dialog display to callers for better testability
- Add conflictResolution parameter to page-utils
- Add comprehensive tests for token functionality and conflict detection
- Fix bug: remove .values() call on arrays in breakpoint handling
## Problem
When defining CSS variables with different values for condition-based
breakpoints (e.g., `prefers-color-scheme:dark` vs
`prefers-color-scheme:light`), designers had no way to preview these
variations without manually changing system preferences.
Example:
```css
:root {
--primary-color: #000;
--background: #fff;
}
@media (prefers-color-scheme: dark) {
:root {
--primary-color: #fff;
--background: #000;
}
}
```
Previously, testing dark mode required switching OS settings back and
forth.
## Solution
Implements runtime CSS media rule manipulation to simulate
condition-based breakpoints without changing system settings. When a
designer selects a condition-based breakpoint, the simulator dynamically
modifies CSS media rules:
- Matching rules (e.g., `prefers-color-scheme:dark` when dark is
selected) → replaced with `(min-width: 0px)` (always true)
- Non-matching rules → appended with `(max-width: 0px)` (always false)
- Original media queries are stored and restored when switching away
## Features
**Core Functionality:**
- Simulates media query conditions by replacing them with
always-true/false queries
- Supports all condition-based media features (`prefers-color-scheme`,
`prefers-reduced-motion`, etc.)
- Handles both spaced and non-spaced formats
**Performance:**
- Caches media rules by feature to avoid repeated DOM traversal
- Debounces rapid breakpoint changes (50ms)
- Uses WeakMap for automatic memory management
**Robustness:**
- Validates restoration success with warning logs
- Handles CORS-restricted stylesheets gracefully
- Proper cleanup on abort signal with cache clearing
## Technical Implementation
**Key Functions:**
- `parseCondition()` - Parses condition strings
- `getMediaRulesForFeature()` - Caches and retrieves relevant media
rules
- `applySimulation()` - Debounced application of media rule
modifications
- `restoreAllRules()` - Restores original media queries
- `subscribeBreakpointSimulator()` - Integrates with nano-states and
lifecycle
**Integration:**
- Subscribes to `$selectedBreakpoint` nano-state
- Runs in design mode only
- Cleanup via AbortSignal
## Testing Instructions
**Setup:**
1. Create CSS variables with condition-based values
2. Configure breakpoints with conditions (e.g.,
`prefers-color-scheme:light`, `prefers-color-scheme:dark`)
**Test Cases:**
- Select condition-based breakpoint → verify canvas reflects correct
theme without changing OS settings
- Rapidly switch between breakpoints → verify smooth transitions
- Switch to width-based breakpoint → verify original media queries are
restored
- Check console for errors (should only see warnings for legitimate
issues)
## Impact
Designers can now preview dark/light themes and other condition-based
styles instantly without changing system settings, significantly
improving the workflow for building modern, accessible interfaces.
---------
Co-authored-by: zehjotkah <111518041+zehjotkah@users.noreply.github.com>
## Description
When pasting HTML containing external image URLs (e.g. from Tailwind UI
components), the server fetches those images with an `Accept` header
that includes `image/avif`. Services like Unsplash that support
`auto=format` perform content negotiation based on this header and serve
AVIF data. Cloudflare Image Resizing cannot process AVIF as input,
resulting in **ERROR 9520: Original image has unsupported format**.
This PR adds a `RESIZABLE_IMAGE_MIME_TYPES` whitelist in the SDK
containing only formats that Cloudflare Image Resizing supports as input
(JPEG, PNG, GIF, WebP, SVG), and uses it in the `Accept` header when
fetching external images during paste.
Direct file uploads are unaffected — users can still upload AVIF files,
which are stored as-is.
Reference:
https://developers.cloudflare.com/images/transform-images/#supported-input-formats
## Steps for reproduction
1. Open the builder and create or open a project
2. Copy this HTML to your clipboard:
```html
<img
src="https://images.unsplash.com/photo-1521737604893-d14cc237f11d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&crop=focalpoint&fp-y=.8&w=2830&h=1500&q=80&blend=111827&sat=-100&exp=15&blend-mode=screen"
alt="" class="absolute inset-0 -z-10 size-full object-cover object-right
opacity-10 md:object-center" />
```
3. Paste it into the canvas
4. **Before fix:** Image fails to load with `ERROR 9520: Original image
has unsupported format`
5. **After fix:** Image loads correctly — the server requests
JPEG/PNG/GIF/WebP/SVG from Unsplash instead of AVIF
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [x] made a self-review
- [x] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- Note: full verification requires the hosted environment with
Cloudflare Image Resizing (`RESIZE_ORIGIN`)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
Co-authored-by: Oleg Isonen <oleg008@gmail.com>
Here's the list of available user plan flags with their defaults
- allowAdditionalPermissions: true,
- allowDynamicData: true,
- allowContentMode: true,
- allowStagingPublish: true,
- maxContactEmails: 5,
- maxDomainsAllowedPerUser: Number.MAX_SAFE_INTEGER,
- maxPublishesAllowedPerUser: Number.MAX_SAFE_INTEGER,
---------
Co-authored-by: Oleg Isonen <oleg008@gmail.com>
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
When pressing arrow up/down to adjust values in the spacing UI popover,
the popover would close immediately after applying the value. Now it
stays open by passing close: false for delta (arrow key) changes.
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
## Description
In places like tag control we started focusing autocomplete container
instead of first item highighting, and we lost focus on the input, so
user started typing numbers and switching breakpoints
- Replace custom capitalizeFirstLetter with capitalCase from change-case
- Fix title case labels: Box shadows, Text shadows, Backdrop filters,
Data variables, CSS preview
## Description
1. What is this PR about (link the issue and add a short description)
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
0000)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
Custom selectors like ::before were persisting in the style source menu
after clearing styles because the code iterated over ALL project styles
instead of filtering to the current instance's style sources.
- Extract getComponentStates as pure function
- Filter styles by instanceStyleSourceIds from styleSourceSelections
- Add regression tests for the bug fix