Skip to content

Core: Fix handling complex viewport sizes#33615

Merged
ghengeveld merged 6 commits intonextfrom
viewport-complex-values
Mar 11, 2026
Merged

Core: Fix handling complex viewport sizes#33615
ghengeveld merged 6 commits intonextfrom
viewport-complex-values

Conversation

@ghengeveld
Copy link
Copy Markdown
Member

@ghengeveld ghengeveld commented Jan 21, 2026

What I did

Fixed custom viewports with complex CSS values such as calc(100% - 100px). These values now properly apply to the viewport, even when zooming, but cannot be updated since they aren't URL serializable.

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

Caution

This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>

Summary by CodeRabbit

  • New Features

    • CSS calc()-based viewport sizing.
    • Dimension locking to enable/disable width and height independently; drag handles and inputs respond to locks.
  • Improvements

    • Clearer disabled styling and not-allowed cursor for numeric inputs.
    • Simplified, more predictable viewport sizing and resize behavior.
  • Testing

    • Added a story demonstrating calculated viewport dimensions; updated preview stories to skip visual snapshotting.

@nx-cloud
Copy link
Copy Markdown

nx-cloud bot commented Jan 21, 2026

View your CI Pipeline Execution ↗ for commit ebe0233

Command Status Duration Result
nx run-many -t compile -c production --parallel=1 ✅ Succeeded 5m 4s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-11 12:56:47 UTC

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 21, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 08f892e8-aaba-4e8e-bd58-4d6d05d851ed

📥 Commits

Reviewing files that changed from the base of the PR and between a399e61 and ebe0233.

📒 Files selected for processing (1)
  • code/core/src/manager/components/preview/Viewport.stories.tsx

📝 Walkthrough

Walkthrough

Inlines numeric/unit parsing and switches viewport/frame sizing to CSS calc(...); introduces per-axis locked state that disables width/height inputs and conditionally renders drag handles; updates numeric-input disabled styling; adds a "Calculated" custom viewport story; simplifies the viewport resize handler to always apply computed values.

Changes

Cohort / File(s) Summary
Numeric input styling
code/core/src/manager/components/preview/NumericInput.tsx
Make input:disabled background transparent; wrapper matching :has(input:disabled) gets theme-based background and cursor: not-allowed.
Viewport component & UI
code/core/src/manager/components/preview/Viewport.tsx
Remove parseNumber helper and inline numeric/unit extraction; compute display/frame sizes using calc(...); add per-axis dimensions.locked to disable width/height inputs and conditionally render right/bottom/both drag handles; adjust value update paths to respect locked state.
Viewport story
code/core/src/manager/components/preview/Viewport.stories.tsx
Add calc custom viewport ("Calculated") with height/width: calc(100% - 50px); add exported Calculated story that sets globals to use it; disable Chromatic snapshots for several stories.
Viewport hook
code/core/src/viewport/useViewport.ts
Simplify resize handler by removing URL-value parsing and minimum-clamp logic; always update with the computed value (respecting rotation).

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant NumericInput
  participant Viewport
  participant useViewport
  participant StateStore

  User->>NumericInput: edit numeric value or drag handle
  NumericInput->>Viewport: emit new dimension value
  Viewport->>useViewport: request apply/normalize (calc-based)
  useViewport->>StateStore: update viewport state/globals
  StateStore-->>Viewport: new dimensions & locked flags
  Viewport-->>NumericInput: disable inputs / update displayed sizes
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@code/core/src/manager/components/preview/Viewport.tsx`:
- Around line 275-292: The per-axis lock in the dimensions useMemo allows
resizing when one axis is complex; compute an isLocked flag (e.g., const
isLocked = !nx || !ny) inside the same useMemo and set locked: { width:
isLocked, height: isLocked } so both axes are locked if either dimension is
non-serializable; update any downstream checks that currently read locked.width
or locked.height to use the single isLocked value (or the updated locked object)
so resizing/resolution logic treats the pair as locked when either axis is
complex.
🧹 Nitpick comments (1)
code/core/src/manager/components/preview/NumericInput.tsx (1)

49-63: Consider a non-:has() fallback for disabled styling.

:has() support is still uneven in some environments. If Storybook manager must run in older browsers, the disabled styling won’t apply. A simple data-attribute fallback keeps visuals consistent.

🔧 Possible fallback
 const Wrapper = styled.div<{ after?: ReactNode; before?: ReactNode }>(
   ({ after, before, theme }) => ({
     ...
-    '&:has(input:disabled)': {
+    '&:has(input:disabled), &[data-disabled="true"]': {
       background: theme.base === 'light' ? theme.color.lighter : theme.input.background,
       cursor: 'not-allowed',
     },
     ...
   })
 );
-    <Wrapper after={after} before={before} className={className} style={style}>
+    <Wrapper
+      after={after}
+      before={before}
+      className={className}
+      style={style}
+      data-disabled={props.disabled ? 'true' : undefined}
+    >

Comment thread code/core/src/manager/components/preview/Viewport.tsx
@storybook-app-bot
Copy link
Copy Markdown

storybook-app-bot bot commented Jan 21, 2026

Package Benchmarks

Commit: ebe0233, ran on 11 March 2026 at 12:52:00 UTC

No significant changes detected, all good. 👏

@github-actions github-actions bot added the Stale label Feb 2, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@code/core/src/manager/components/preview/Viewport.stories.tsx`:
- Around line 133-142: The Calculated story currently disables Chromatic
snapshots and opts out of story tests, so the 'calc' viewport path isn't
covered; change the story configuration for Calculated (created via meta.story)
to keep it under automation by removing chromatic: { disableSnapshot: true } and
removing the tags: ['!test'] entry (or alternatively add a dedicated
unit/integration test that mounts the same Calculated scenario using the
customViewports and the viewport: { value: 'calc' } setting to exercise the
calc(...) code path). Ensure references to Calculated, meta.story,
customViewports and viewport: { value: 'calc' } are used so the same behavior is
covered by automated tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e6400238-3c84-4646-a2e9-35120b32ddc3

📥 Commits

Reviewing files that changed from the base of the PR and between 60dda80 and a399e61.

📒 Files selected for processing (1)
  • code/core/src/manager/components/preview/Viewport.stories.tsx

Comment thread code/core/src/manager/components/preview/Viewport.stories.tsx Outdated
@yannbf
Copy link
Copy Markdown
Member

yannbf commented Mar 11, 2026

I am not sure if these are considered blockers but there are a couple scenarios when interacting with the viewport inputs and trying to type "calc"

2026-03-11 14 40 20

2026-03-11 14 41 44

Copy link
Copy Markdown
Member

@yannbf yannbf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but there are some minor issues, see my comment above

@ghengeveld
Copy link
Copy Markdown
Member Author

@yannbf calc isn't really supposed to be used dynamically, only through code. Therefore I'm going to just going to consider this "working as intended" for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants