-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Core: Zoom tool reimplementation #33375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: viewport-viewer
Are you sure you want to change the base?
Conversation
…ions - Updated ZoomIFrame to correctly apply scaling transformations. - Enhanced ZoomProvider to manage zoom levels with predefined constants. - Refactored Zoom component to utilize ActionList for zoom controls and added keyboard shortcuts for zoom actions. - Improved ZoomWrapper to dynamically adjust zoom levels based on user interactions.
|
View your CI Pipeline Execution ↗ for commit 955f23b
☁️ Nx Cloud last updated this comment at |
📝 WalkthroughWalkthroughThis pull request refactors keyboard shortcut handling by extracting the Shortcut component from Menu.tsx into a dedicated module, replaces the SizeInput component with a new NumericInput implementation, introduces Zoom storybook stories, and reorganizes the Zoom tool with context-based state management and enhanced UI. Additionally, iframe scaling logic is adjusted in ZoomIFrame and Viewport, and various import paths are updated accordingly. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45–75 minutes
Possibly related PRs
✨ Finishing touches
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (5)
code/core/src/manager/components/preview/Viewport.tsx (1)
417-429: Minor:data-valueinitialization may show units for non-px dimensions.The
.replace('px', '')only stripspx. For other units like%orvh, the unit would still appear in the tooltip. Consider usingparseNumber(width)?.numberfor consistency.<DragHandle ref={dragRefX} isDefault={isDefault} data-side="right" - data-value={width.replace('px', '')} + data-value={parseNumber(width)?.number ?? width} /> <DragHandle ref={dragRefY} isDefault={isDefault} data-side="bottom" - data-value={height.replace('px', '')} + data-value={parseNumber(height)?.number ?? height} />code/core/src/manager/components/preview/tools/zoom.stories.tsx (1)
27-28: Consider usingZOOM_LEVELSfor consistent behavior.The story's
zoomIn/zoomOutuse a fixed0.5increment, while the actual implementation uses predefinedZOOM_LEVELS. This divergence may cause stories to behave differently than production. For more realistic testing, consider importing and using the same zoom level logic.+import { Zoom, ZOOM_LEVELS } from './zoom'; -import { Zoom } from './zoom'; ... - zoomIn: () => setValue(value + 0.5), - zoomOut: () => setValue(value - 0.5), + zoomIn: () => { + const higher = ZOOM_LEVELS.find((level) => level > value); + if (higher) setValue(higher); + }, + zoomOut: () => { + const lower = [...ZOOM_LEVELS].reverse().find((level) => level < value); + if (lower) setValue(lower); + },Note: This would require exporting
ZOOM_LEVELSfromzoom.tsx.code/core/src/manager/components/preview/NumericInput.tsx (2)
71-71: Escape special regex characters inbaseUnit.If
baseUnitcontains regex metacharacters (e.g.,%,.,+), the pattern may not match correctly. Consider escaping special characters.- const baseUnitRegex = useMemo(() => baseUnit && new RegExp(`${baseUnit}$`), [baseUnit]); + const baseUnitRegex = useMemo( + () => baseUnit && new RegExp(`${baseUnit.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`), + [baseUnit] + );
77-77: Type mismatch inuseImperativeHandle.The
forwardRefdeclares{ select: () => void }but exposes the fullHTMLInputElement. While this works becauseHTMLInputElementhas aselect()method, it's semantically incorrect and exposes more than intended.- useImperativeHandle(forwardedRef, () => inputRef.current!); + useImperativeHandle(forwardedRef, () => ({ + select: () => inputRef.current?.select(), + }));code/core/src/manager/components/preview/tools/zoom.tsx (1)
182-201: Shortcuts re-registered on every zoom level change.The
useEffectdependencies includezoomIn,zoomOut, andzoomTo, which are recreated on eachvaluechange. This causessetAddonShortcutto be called repeatedly. Consider stabilizing the callbacks using refs or extracting state access to avoid re-registration on every zoom level change.+ const valueRef = useRef(value); + valueRef.current = value; + + const stableZoomIn = useCallback(() => { + const higherZoomLevel = ZOOM_LEVELS.find((level) => level > valueRef.current); + if (higherZoomLevel) set(higherZoomLevel); + }, [set]); + + const stableZoomOut = useCallback(() => { + const lowerZoomLevel = ZOOM_LEVELS.findLast((level) => level < valueRef.current); + if (lowerZoomLevel) set(lowerZoomLevel); + }, [set]); + + const stableZoomTo = useCallback((v: number) => set(v), [set]); + useEffect(() => { api.setAddonShortcut('zoom', { label: 'Zoom to 100%', defaultShortcut: ['alt', '0'], actionName: 'zoomReset', - action: () => zoomTo(1), + action: () => stableZoomTo(1), }); // ... similar for other shortcuts - }, [api, zoomIn, zoomOut, zoomTo]); + }, [api, stableZoomIn, stableZoomOut, stableZoomTo]);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
code/.storybook/bench/bench.stories.tsx(1 hunks)code/core/src/components/components/ActionList/ActionList.stories.tsx(1 hunks)code/core/src/components/components/Zoom/ZoomIFrame.tsx(2 hunks)code/core/src/manager/components/Shortcut.tsx(1 hunks)code/core/src/manager/components/preview/NumericInput.stories.tsx(1 hunks)code/core/src/manager/components/preview/NumericInput.tsx(1 hunks)code/core/src/manager/components/preview/SizeInput.tsx(0 hunks)code/core/src/manager/components/preview/Viewport.tsx(9 hunks)code/core/src/manager/components/preview/tools/share.tsx(1 hunks)code/core/src/manager/components/preview/tools/zoom.stories.tsx(1 hunks)code/core/src/manager/components/preview/tools/zoom.tsx(2 hunks)code/core/src/manager/components/sidebar/ContextMenu.tsx(1 hunks)code/core/src/manager/container/Menu.stories.tsx(1 hunks)code/core/src/manager/container/Menu.tsx(1 hunks)code/core/src/manager/container/Preview.tsx(1 hunks)
💤 Files with no reviewable changes (1)
- code/core/src/manager/components/preview/SizeInput.tsx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,json,html,ts,tsx,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use ESLint and Prettier configurations that are enforced in the codebase
Files:
code/core/src/components/components/ActionList/ActionList.stories.tsxcode/core/src/components/components/Zoom/ZoomIFrame.tsxcode/core/src/manager/components/preview/NumericInput.tsxcode/core/src/manager/components/preview/NumericInput.stories.tsxcode/core/src/manager/components/preview/tools/share.tsxcode/core/src/manager/components/preview/tools/zoom.stories.tsxcode/core/src/manager/components/Shortcut.tsxcode/core/src/manager/container/Preview.tsxcode/core/src/manager/container/Menu.tsxcode/core/src/manager/components/sidebar/ContextMenu.tsxcode/core/src/manager/container/Menu.stories.tsxcode/core/src/manager/components/preview/tools/zoom.tsxcode/core/src/manager/components/preview/Viewport.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Enable TypeScript strict mode
Files:
code/core/src/components/components/ActionList/ActionList.stories.tsxcode/core/src/components/components/Zoom/ZoomIFrame.tsxcode/core/src/manager/components/preview/NumericInput.tsxcode/core/src/manager/components/preview/NumericInput.stories.tsxcode/core/src/manager/components/preview/tools/share.tsxcode/core/src/manager/components/preview/tools/zoom.stories.tsxcode/core/src/manager/components/Shortcut.tsxcode/core/src/manager/container/Preview.tsxcode/core/src/manager/container/Menu.tsxcode/core/src/manager/components/sidebar/ContextMenu.tsxcode/core/src/manager/container/Menu.stories.tsxcode/core/src/manager/components/preview/tools/zoom.tsxcode/core/src/manager/components/preview/Viewport.tsx
code/**/*.{ts,tsx,js,jsx,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
code/**/*.{ts,tsx,js,jsx,mjs}: Use server-side logger from 'storybook/internal/node-logger' for Node.js code
Use client-side logger from 'storybook/internal/client-logger' for browser code
Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size
Files:
code/core/src/components/components/ActionList/ActionList.stories.tsxcode/core/src/components/components/Zoom/ZoomIFrame.tsxcode/core/src/manager/components/preview/NumericInput.tsxcode/core/src/manager/components/preview/NumericInput.stories.tsxcode/core/src/manager/components/preview/tools/share.tsxcode/core/src/manager/components/preview/tools/zoom.stories.tsxcode/core/src/manager/components/Shortcut.tsxcode/core/src/manager/container/Preview.tsxcode/core/src/manager/container/Menu.tsxcode/core/src/manager/components/sidebar/ContextMenu.tsxcode/core/src/manager/container/Menu.stories.tsxcode/core/src/manager/components/preview/tools/zoom.tsxcode/core/src/manager/components/preview/Viewport.tsx
code/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Export functions that need to be tested from their modules
Files:
code/core/src/components/components/ActionList/ActionList.stories.tsxcode/core/src/components/components/Zoom/ZoomIFrame.tsxcode/core/src/manager/components/preview/NumericInput.tsxcode/core/src/manager/components/preview/NumericInput.stories.tsxcode/core/src/manager/components/preview/tools/share.tsxcode/core/src/manager/components/preview/tools/zoom.stories.tsxcode/core/src/manager/components/Shortcut.tsxcode/core/src/manager/container/Preview.tsxcode/core/src/manager/container/Menu.tsxcode/core/src/manager/components/sidebar/ContextMenu.tsxcode/core/src/manager/container/Menu.stories.tsxcode/core/src/manager/components/preview/tools/zoom.tsxcode/core/src/manager/components/preview/Viewport.tsx
code/**/*.{js,jsx,json,html,ts,tsx,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
code/**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier with --write flag to format code before committing
Run ESLint with yarn lint:js:cmd to check for linting issues and fix errors before committing
Files:
code/core/src/components/components/ActionList/ActionList.stories.tsxcode/core/src/components/components/Zoom/ZoomIFrame.tsxcode/core/src/manager/components/preview/NumericInput.tsxcode/core/src/manager/components/preview/NumericInput.stories.tsxcode/core/src/manager/components/preview/tools/share.tsxcode/core/src/manager/components/preview/tools/zoom.stories.tsxcode/core/src/manager/components/Shortcut.tsxcode/core/src/manager/container/Preview.tsxcode/core/src/manager/container/Menu.tsxcode/core/src/manager/components/sidebar/ContextMenu.tsxcode/core/src/manager/container/Menu.stories.tsxcode/core/src/manager/components/preview/tools/zoom.tsxcode/core/src/manager/components/preview/Viewport.tsx
🧠 Learnings (8)
📚 Learning: 2025-09-24T09:39:39.233Z
Learnt from: ndelangen
Repo: storybookjs/storybook PR: 32507
File: code/core/src/manager/globals/globals-module-info.ts:25-33
Timestamp: 2025-09-24T09:39:39.233Z
Learning: In Storybook, storybook/actions/decorator is a preview-only entrypoint and should not be included in manager globals configuration. The duplicatedKeys array in code/core/src/manager/globals/globals-module-info.ts is specifically for manager-side externalization, not preview entrypoints.
Applied to files:
code/core/src/components/components/ActionList/ActionList.stories.tsxcode/core/src/manager/components/preview/NumericInput.stories.tsxcode/core/src/manager/components/preview/tools/share.tsxcode/core/src/manager/components/preview/tools/zoom.stories.tsxcode/core/src/manager/container/Preview.tsxcode/core/src/manager/container/Menu.stories.tsx
📚 Learning: 2025-10-01T15:24:01.060Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.
Applied to files:
code/core/src/components/components/ActionList/ActionList.stories.tsx
📚 Learning: 2025-11-28T14:50:24.889Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T14:50:24.889Z
Learning: Follow existing patterns and conventions in the Storybook codebase
Applied to files:
code/core/src/manager/components/preview/NumericInput.stories.tsxcode/core/src/manager/components/preview/tools/zoom.stories.tsxcode/core/src/manager/components/Shortcut.tsx
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Document complex mock behaviors in Vitest tests
Applied to files:
code/core/src/manager/components/preview/NumericInput.stories.tsxcode/core/src/manager/components/preview/tools/zoom.stories.tsx
📚 Learning: 2025-11-05T09:37:25.920Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/tooltip/WithTooltip.tsx:54-96
Timestamp: 2025-11-05T09:37:25.920Z
Learning: Repo: storybookjs/storybook — In code/core/src/components/components/tooltip/WithTooltip.tsx, the legacy WithTooltip implementation is intentionally reintroduced for backward compatibility and is deprecated; maintainers (per Sidnioulz) do not want maintenance or improvements on it. Prefer WithTooltipNew/Popover; avoid suggesting changes to WithTooltip.* going forward.
Applied to files:
code/core/src/manager/components/preview/tools/share.tsxcode/core/src/manager/components/preview/tools/zoom.stories.tsxcode/core/src/manager/container/Menu.tsxcode/core/src/manager/components/sidebar/ContextMenu.tsxcode/core/src/manager/container/Menu.stories.tsxcode/core/src/manager/components/preview/tools/zoom.tsxcode/core/src/manager/components/preview/Viewport.tsx
📚 Learning: 2025-11-05T09:38:47.712Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.
Applied to files:
code/core/src/manager/components/preview/tools/zoom.stories.tsxcode/core/src/manager/container/Menu.tsxcode/core/src/manager/components/preview/tools/zoom.tsxcode/core/src/manager/components/preview/Viewport.tsx
📚 Learning: 2025-10-03T07:55:42.639Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/manager/components/preview/Toolbar.tsx:102-105
Timestamp: 2025-10-03T07:55:42.639Z
Learning: In code/core/src/manager/components/preview/Toolbar.tsx, we intentionally do not add aria-label/aria-labelledby to StyledToolbar (AbstractToolbar) because the enclosing section is already labeled via an sr-only heading and the toolbar is the only content. Revisit only if real user testing indicates a need.
Applied to files:
code/core/src/manager/container/Preview.tsx
📚 Learning: 2025-11-25T11:09:33.798Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 33140
File: code/core/src/manager/components/sidebar/TagsFilter.tsx:247-259
Timestamp: 2025-11-25T11:09:33.798Z
Learning: In the storybookjs/storybook repository, PopoverProvider creates popovers with a dialog role, so using aria-haspopup="dialog" on buttons that trigger PopoverProvider is semantically correct.
Applied to files:
code/core/src/manager/components/preview/Viewport.tsx
🧬 Code graph analysis (4)
code/core/src/manager/components/preview/NumericInput.stories.tsx (1)
code/core/src/manager/components/preview/NumericInput.tsx (1)
NumericInput(66-152)
code/core/src/manager/components/preview/tools/zoom.stories.tsx (1)
code/core/src/manager/components/preview/tools/zoom.tsx (1)
Zoom(54-153)
code/core/src/manager/container/Preview.tsx (2)
code/core/src/manager/components/preview/tools/zoom.tsx (1)
zoomTool(206-212)code/core/src/manager/components/preview/tools/share.tsx (1)
shareTool(152-184)
code/core/src/manager/components/preview/Viewport.tsx (2)
code/core/src/manager/components/preview/NumericInput.tsx (1)
NumericInput(66-152)code/core/src/manager/components/preview/Iframe.tsx (1)
IFrame(29-47)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: normal
- GitHub Check: nx
- GitHub Check: Core Unit Tests, windows-latest
- GitHub Check: nx
- GitHub Check: nx
🔇 Additional comments (25)
code/.storybook/bench/bench.stories.tsx (1)
72-72: LGTM! Verify fixed positioning works with zoom tool.The change to
position: 'fixed'andwidth: '100vw'ensures the bundle analyzer iframe properly fills the viewport regardless of zoom level, which aligns with the PR's viewport scaling updates.Please verify that the fixed positioning works correctly with the new zoom tool in fullscreen layout and doesn't cause any layering or overflow issues with other Storybook UI elements.
code/core/src/manager/components/preview/Viewport.tsx (9)
1-16: LGTM! Imports updated correctly.The additions of
useMemoandNumericInputalign with the new scale-aware frame styling and dimension controls.
127-183: Clean refactor of DragHandle with conditional rendering.The
isDefaultprop now drives visibility at the styled-component level, simplifying usage in JSX. Thedata-valueattribute pattern for displaying dimensions during drag is a nice approach.
185-202: Invisible scroll anchors for drag auto-scrolling.The
ScrollEdgecomponents serve as scroll targets forscrollIntoViewduring drag operations—good UX for large viewports that extend beyond the visible area.
204-208: LGTM!Simple styled wrapper for consistent input sizing.
250-267: Good addition of real-time dimension feedback and auto-scrolling.The
data-valueupdates provide immediate visual feedback during drag, and thescrollIntoViewcalls ensure the drag handle remains visible when resizing large viewports.
270-278: Scale-aware dimension calculation looks correct.Reading scale from
data-scaleand dividing the measured dimensions ensures the resize call receives the logical (unscaled) viewport size. The|| 1fallback handles missing/invalid scale gracefully.
297-300: LGTM!The
parseNumberhelper correctly extracts numeric values and units from dimension strings, with proper handling for decimals and various CSS units.
302-309: Verify scaling behavior for percentage-based dimensions.The calculation multiplies the numeric portion by
scale, which works intuitively forpxunits. For percentage units (e.g.,50%), this would produce100%at 2x scale—confirm this is the intended behavior for percentage-based viewports.
400-416: Scale transformation approach is correct.The wrapper-based scaling (inverse size + transform) maintains proper DOM dimensions for the iframe while achieving visual zoom. The
scale={1}prop onIFramecorrectly delegates scaling to the wrapper.code/core/src/manager/components/preview/tools/share.tsx (1)
20-20: LGTM!Import path correctly updated to reference the new shared
Shortcutcomponent location.code/core/src/manager/components/sidebar/ContextMenu.tsx (1)
22-22: LGTM!Import path correctly updated to the new shared
Shortcutcomponent.code/core/src/manager/container/Menu.stories.tsx (1)
10-10: LGTM!Import path correctly updated to reference the extracted
Shortcutcomponent.code/core/src/components/components/ActionList/ActionList.stories.tsx (1)
5-5: Consider alternative approaches for keyboard shortcut display in ActionList story.This story imports
Shortcutdirectly from the manager package, which maintains architectural separation in the codebase. All other manager-internal stories use relative imports within manager, and the components package does not export manager utilities via its public API. Either use an alternative pattern for demonstrating shortcuts in this story, or verify this cross-package dependency is acceptable for documentation purposes.code/core/src/manager/container/Preview.tsx (1)
25-26: LGTM!The tool grouping reorganization correctly moves
zoomTooltodefaultToolsExtra, positioning it on the right side of the toolbar as intended by the PR objectives.code/core/src/components/components/Zoom/ZoomIFrame.tsx (2)
38-50: LGTM!The updated scaling logic correctly implements the zoom behavior: the iframe dimensions are set to
(1/scale) * 100%to compensate for the CSSscale(scale)transform, ensuring the content fills the available space at the desired zoom level.
52-59: LGTM!The fallback
setIframeZoommethod correctly mirrors the inner zoom logic for cases where cross-origin restrictions prevent modifying the iframe's content document.code/core/src/manager/container/Menu.tsx (1)
20-21: LGTM!Clean refactor extracting the
Shortcutcomponent to a shared module. The import path and usage pattern are consistent throughout the file.code/core/src/manager/components/Shortcut.tsx (1)
30-36: LGTM!Well-structured centralized
Shortcutcomponent with appropriate theming and styling. The use ofkey={key}is acceptable since keyboard shortcuts typically don't contain duplicate keys.code/core/src/manager/components/preview/NumericInput.stories.tsx (2)
16-30: LGTM!Good interaction test coverage for
NumericInput. The play function correctly tests ArrowUp/ArrowDown keyboard behavior and verifies both the displayed value and thesetValuecallback invocations.
65-80: LGTM!The
WithBaseUnitstory correctly verifies that thebaseUnitis stripped from the display value ('11') while still being included in thesetValuecalls ('11em').code/core/src/manager/components/preview/NumericInput.tsx (1)
112-127: Arrow key handler doesn't support negative values.The condition
update >= 0on line 120 prevents decrementing below zero. If negative values are intentionally unsupported, this is fine; otherwise, consider allowing negative numbers or making this configurable.Is the restriction to non-negative values intentional for all
NumericInputuse cases (e.g., zoom percentages, dimensions)?code/core/src/manager/components/preview/tools/zoom.tsx (3)
15-16: LGTM!Good use of
as constforZOOM_LEVELSto enable precise array method types (e.g.,.at(-1)returning4notnumber | undefined).
109-111: Shortcut display mismatch with registered key.The UI shows
['alt', '+']but the shortcut is registered as['alt', '='](line 191). While these are the same physical key on US keyboards, this could cause confusion. Consider aligning the display with the registered shortcut or ensuringshortcutToHumanStringnormalizes this.Verify that
shortcutToHumanString(['alt', '+'])andshortcutToHumanString(['alt', '='])display consistently to users across different keyboard layouts.
54-153: LGTM!The
Zoomcomponent is well-structured with a clean popover-based UI. The memoization, accessibility labels, and disabled states for boundary conditions are properly implemented.
Package BenchmarksCommit: The following packages have significant changes to their size or dependencies:
|
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 2 | 🚨 +2 🚨 |
| Self size | 0 B | 181 KB | 🚨 +181 KB 🚨 |
| Dependency size | 0 B | 2.97 MB | 🚨 +2.97 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/addon-docs
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 18 | 🚨 +18 🚨 |
| Self size | 0 B | 1.79 MB | 🚨 +1.79 MB 🚨 |
| Dependency size | 0 B | 9.25 MB | 🚨 +9.25 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/addon-links
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 1 | 🚨 +1 🚨 |
| Self size | 0 B | 14 KB | 🚨 +14 KB 🚨 |
| Dependency size | 0 B | 5 KB | 🚨 +5 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/addon-onboarding
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 0 | 0 |
| Self size | 0 B | 331 KB | 🚨 +331 KB 🚨 |
| Dependency size | 0 B | 670 B | 🚨 +670 B 🚨 |
| Bundle Size Analyzer | Link | Link |
storybook-addon-pseudo-states
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 0 | 0 |
| Self size | 0 B | 21 KB | 🚨 +21 KB 🚨 |
| Dependency size | 0 B | 689 B | 🚨 +689 B 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/addon-themes
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 1 | 🚨 +1 🚨 |
| Self size | 0 B | 18 KB | 🚨 +18 KB 🚨 |
| Dependency size | 0 B | 28 KB | 🚨 +28 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/addon-vitest
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 2 | 🚨 +2 🚨 |
| Self size | 0 B | 376 KB | 🚨 +376 KB 🚨 |
| Dependency size | 0 B | 338 KB | 🚨 +338 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/builder-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 17 | 🚨 +17 🚨 |
| Self size | 0 B | 325 KB | 🚨 +325 KB 🚨 |
| Dependency size | 0 B | 2.00 MB | 🚨 +2.00 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/builder-webpack5
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 192 | 🚨 +192 🚨 |
| Self size | 0 B | 75 KB | 🚨 +75 KB 🚨 |
| Dependency size | 0 B | 32.16 MB | 🚨 +32.16 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
storybook
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 39 | 🚨 +39 🚨 |
| Self size | 0 B | 20.56 MB | 🚨 +20.56 MB 🚨 |
| Dependency size | 0 B | 16.41 MB | 🚨 +16.41 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/angular
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 191 | 🚨 +191 🚨 |
| Self size | 0 B | 118 KB | 🚨 +118 KB 🚨 |
| Dependency size | 0 B | 30.14 MB | 🚨 +30.14 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/ember
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 196 | 🚨 +196 🚨 |
| Self size | 0 B | 15 KB | 🚨 +15 KB 🚨 |
| Dependency size | 0 B | 28.88 MB | 🚨 +28.88 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/html-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 20 | 🚨 +20 🚨 |
| Self size | 0 B | 22 KB | 🚨 +22 KB 🚨 |
| Dependency size | 0 B | 2.36 MB | 🚨 +2.36 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/nextjs
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 538 | 🚨 +538 🚨 |
| Self size | 0 B | 645 KB | 🚨 +645 KB 🚨 |
| Dependency size | 0 B | 59.09 MB | 🚨 +59.09 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/nextjs-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 128 | 🚨 +128 🚨 |
| Self size | 0 B | 1.12 MB | 🚨 +1.12 MB 🚨 |
| Dependency size | 0 B | 21.96 MB | 🚨 +21.96 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/preact-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 20 | 🚨 +20 🚨 |
| Self size | 0 B | 13 KB | 🚨 +13 KB 🚨 |
| Dependency size | 0 B | 2.35 MB | 🚨 +2.35 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/react-native-web-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 160 | 🚨 +160 🚨 |
| Self size | 0 B | 30 KB | 🚨 +30 KB 🚨 |
| Dependency size | 0 B | 23.14 MB | 🚨 +23.14 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/react-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 118 | 🚨 +118 🚨 |
| Self size | 0 B | 35 KB | 🚨 +35 KB 🚨 |
| Dependency size | 0 B | 19.75 MB | 🚨 +19.75 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/react-webpack5
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 278 | 🚨 +278 🚨 |
| Self size | 0 B | 24 KB | 🚨 +24 KB 🚨 |
| Dependency size | 0 B | 44.04 MB | 🚨 +44.04 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/server-webpack5
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 204 | 🚨 +204 🚨 |
| Self size | 0 B | 16 KB | 🚨 +16 KB 🚨 |
| Dependency size | 0 B | 33.41 MB | 🚨 +33.41 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/svelte-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 24 | 🚨 +24 🚨 |
| Self size | 0 B | 55 KB | 🚨 +55 KB 🚨 |
| Dependency size | 0 B | 27.02 MB | 🚨 +27.02 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/sveltekit
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 25 | 🚨 +25 🚨 |
| Self size | 0 B | 56 KB | 🚨 +56 KB 🚨 |
| Dependency size | 0 B | 27.08 MB | 🚨 +27.08 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/vue3-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 114 | 🚨 +114 🚨 |
| Self size | 0 B | 35 KB | 🚨 +35 KB 🚨 |
| Dependency size | 0 B | 44.17 MB | 🚨 +44.17 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/web-components-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 21 | 🚨 +21 🚨 |
| Self size | 0 B | 19 KB | 🚨 +19 KB 🚨 |
| Dependency size | 0 B | 2.39 MB | 🚨 +2.39 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/cli
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 173 | 🚨 +173 🚨 |
| Self size | 0 B | 775 KB | 🚨 +775 KB 🚨 |
| Dependency size | 0 B | 67.49 MB | 🚨 +67.49 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/codemod
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 166 | 🚨 +166 🚨 |
| Self size | 0 B | 30 KB | 🚨 +30 KB 🚨 |
| Dependency size | 0 B | 66.06 MB | 🚨 +66.06 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/core-webpack
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 1 | 🚨 +1 🚨 |
| Self size | 0 B | 11 KB | 🚨 +11 KB 🚨 |
| Dependency size | 0 B | 28 KB | 🚨 +28 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
create-storybook
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 40 | 🚨 +40 🚨 |
| Self size | 0 B | 1000 KB | 🚨 +1000 KB 🚨 |
| Dependency size | 0 B | 36.97 MB | 🚨 +36.97 MB 🚨 |
| Bundle Size Analyzer | node | node |
@storybook/csf-plugin
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 9 | 🚨 +9 🚨 |
| Self size | 0 B | 7 KB | 🚨 +7 KB 🚨 |
| Dependency size | 0 B | 1.26 MB | 🚨 +1.26 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
eslint-plugin-storybook
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 20 | 🚨 +20 🚨 |
| Self size | 0 B | 131 KB | 🚨 +131 KB 🚨 |
| Dependency size | 0 B | 2.81 MB | 🚨 +2.81 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/react-dom-shim
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 0 | 0 |
| Self size | 0 B | 18 KB | 🚨 +18 KB 🚨 |
| Dependency size | 0 B | 788 B | 🚨 +788 B 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/preset-create-react-app
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 68 | 🚨 +68 🚨 |
| Self size | 0 B | 32 KB | 🚨 +32 KB 🚨 |
| Dependency size | 0 B | 5.98 MB | 🚨 +5.98 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/preset-react-webpack
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 170 | 🚨 +170 🚨 |
| Self size | 0 B | 18 KB | 🚨 +18 KB 🚨 |
| Dependency size | 0 B | 31.19 MB | 🚨 +31.19 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/preset-server-webpack
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 10 | 🚨 +10 🚨 |
| Self size | 0 B | 7 KB | 🚨 +7 KB 🚨 |
| Dependency size | 0 B | 1.20 MB | 🚨 +1.20 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/html
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 2 | 🚨 +2 🚨 |
| Self size | 0 B | 29 KB | 🚨 +29 KB 🚨 |
| Dependency size | 0 B | 32 KB | 🚨 +32 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/preact
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 2 | 🚨 +2 🚨 |
| Self size | 0 B | 16 KB | 🚨 +16 KB 🚨 |
| Dependency size | 0 B | 32 KB | 🚨 +32 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/react
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 57 | 🚨 +57 🚨 |
| Self size | 0 B | 716 KB | 🚨 +716 KB 🚨 |
| Dependency size | 0 B | 12.91 MB | 🚨 +12.91 MB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/server
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 3 | 🚨 +3 🚨 |
| Self size | 0 B | 8 KB | 🚨 +8 KB 🚨 |
| Dependency size | 0 B | 716 KB | 🚨 +716 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/svelte
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 2 | 🚨 +2 🚨 |
| Self size | 0 B | 45 KB | 🚨 +45 KB 🚨 |
| Dependency size | 0 B | 230 KB | 🚨 +230 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/vue3
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 3 | 🚨 +3 🚨 |
| Self size | 0 B | 55 KB | 🚨 +55 KB 🚨 |
| Dependency size | 0 B | 211 KB | 🚨 +211 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/web-components
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 3 | 🚨 +3 🚨 |
| Self size | 0 B | 41 KB | 🚨 +41 KB 🚨 |
| Dependency size | 0 B | 47 KB | 🚨 +47 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
What I did
This is an almost complete rewrite of the Zoom tool. Notable changes:
⌥+,⌥-and⌥0have been added for quick access.Screen.Recording.2025-12-16.at.11.20.15.mov
Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!
Documentation
MIGRATION.MD
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal,ci:mergedorci:dailyGH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found incode/lib/cli-storybook/src/sandbox-templates.tsMake 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/coreteam 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
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.