Skip to content

Commit 1ba2d07

Browse files
authored
Merge pull request #33615 from storybookjs/viewport-complex-values
Core: Fix handling complex viewport sizes
2 parents c3424ab + ebe0233 commit 1ba2d07

File tree

4 files changed

+61
-32
lines changed

4 files changed

+61
-32
lines changed

code/core/src/manager/components/preview/NumericInput.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ const Wrapper = styled.div<{ after?: ReactNode; before?: ReactNode }>(
4646
outline: 'none',
4747
},
4848
},
49+
'input:disabled': {
50+
background: 'transparent',
51+
},
4952
'input + div': {
5053
paddingInline: 0,
5154
fontSize: 'inherit',
@@ -54,6 +57,10 @@ const Wrapper = styled.div<{ after?: ReactNode; before?: ReactNode }>(
5457
outline: `2px solid ${theme.color.secondary}`,
5558
outlineOffset: -2,
5659
},
60+
'&:has(input:disabled)': {
61+
background: theme.base === 'light' ? theme.color.lighter : theme.input.background,
62+
cursor: 'not-allowed',
63+
},
5764
...(after && { paddingRight: 2 }),
5865
...(before && { paddingLeft: 2 }),
5966
})

code/core/src/manager/components/preview/Viewport.stories.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ const customViewports = {
3838
},
3939
type: 'other',
4040
},
41+
calc: {
42+
name: 'Calculated',
43+
styles: {
44+
height: 'calc(100% - 50px)',
45+
width: 'calc(100% - 50px)',
46+
},
47+
type: 'other',
48+
},
4149
} as ViewportMap;
4250

4351
const meta = preview.meta({
@@ -106,6 +114,7 @@ export const Short = meta.story({
106114
},
107115
parameters: {
108116
viewport: { options: customViewports },
117+
chromatic: { disableSnapshot: true },
109118
},
110119
render: () => <></>,
111120
});
@@ -116,6 +125,19 @@ export const Narrow = meta.story({
116125
},
117126
parameters: {
118127
viewport: { options: customViewports },
128+
chromatic: { disableSnapshot: true },
129+
},
130+
render: () => <></>,
131+
});
132+
133+
export const Calculated = meta.story({
134+
globals: {
135+
viewport: { value: 'calc' },
136+
},
137+
parameters: {
138+
viewport: { options: customViewports },
139+
chromatic: { disableSnapshot: true },
119140
},
120141
render: () => <></>,
142+
tags: ['!test', '!vitest'], // Vitest browser does not support calculated viewports
121143
});

code/core/src/manager/components/preview/Viewport.tsx

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,6 @@ const SizeInput = styled(NumericInput)({
197197
minHeight: 28,
198198
});
199199

200-
const parseNumber = (value: string) => {
201-
const [match, number, unit] = value.match(/^(\d+(?:\.\d+)?)(\%|[a-z]{0,4})?$/) || [];
202-
return match ? { number: Number(number), unit } : undefined;
203-
};
204-
205200
export const Viewport = ({
206201
active,
207202
id,
@@ -278,18 +273,20 @@ export const Viewport = ({
278273
}, [resize, scale]);
279274

280275
const dimensions = useMemo(() => {
281-
const { number: nx, unit: ux = 'px' } = parseNumber(width) ?? { number: 0, unit: 'px' };
282-
const { number: ny, unit: uy = 'px' } = parseNumber(height) ?? { number: 0, unit: 'px' };
283-
const frameWidth = Math.max(VIEWPORT_MIN_WIDTH, nx * scale);
284-
const frameHeight = Math.max(VIEWPORT_MIN_HEIGHT, ny * scale);
276+
const [, nx = '', ux = 'px'] = width.match(/^(\d+(?:\.\d+)?)(\%|[a-z]{1,4})?$/) || [];
277+
const [, ny = '', uy = 'px'] = height.match(/^(\d+(?:\.\d+)?)(\%|[a-z]{1,4})?$/) || [];
285278
return {
286279
frame: {
287-
width: `${frameWidth}${ux}`,
288-
height: `${frameHeight}${uy}`,
280+
width: `calc(${width} * ${scale})`,
281+
height: `calc(${height} * ${scale})`,
289282
},
290283
display: {
291-
width: `${nx}${ux === 'px' ? '' : ux}`,
292-
height: `${ny}${uy === 'px' ? '' : uy}`,
284+
width: `${nx || width}${ux === 'px' ? '' : ux}`,
285+
height: `${ny || height}${uy === 'px' ? '' : uy}`,
286+
},
287+
locked: {
288+
width: !nx || !ny,
289+
height: !nx || !ny,
293290
},
294291
};
295292
}, [width, height, scale]);
@@ -311,6 +308,7 @@ export const Viewport = ({
311308
value={width}
312309
minValue={0}
313310
setValue={(value) => resize(value, height)}
311+
disabled={dimensions.locked.width}
314312
/>
315313
<ActionList.Button
316314
key="viewport-rotate"
@@ -333,6 +331,7 @@ export const Viewport = ({
333331
value={height}
334332
minValue={0}
335333
setValue={(value) => resize(width, value)}
334+
disabled={dimensions.locked.height}
336335
/>
337336
{isCustom && lastSelectedOption && (
338337
<ActionList.Button
@@ -372,19 +371,25 @@ export const Viewport = ({
372371
</>
373372
)}
374373
</div>
375-
<DragHandle
376-
ref={dragRefX}
377-
isDefault={isDefault}
378-
data-side="right"
379-
data-value={dimensions.display.width}
380-
/>
381-
<DragHandle
382-
ref={dragRefY}
383-
isDefault={isDefault}
384-
data-side="bottom"
385-
data-value={dimensions.display.height}
386-
/>
387-
<DragHandle ref={dragRefXY} isDefault={isDefault} data-side="both" />
374+
{!dimensions.locked.width && (
375+
<DragHandle
376+
ref={dragRefX}
377+
isDefault={isDefault}
378+
data-side="right"
379+
data-value={dimensions.display.width}
380+
/>
381+
)}
382+
{!dimensions.locked.height && (
383+
<DragHandle
384+
ref={dragRefY}
385+
isDefault={isDefault}
386+
data-side="bottom"
387+
data-value={dimensions.display.height}
388+
/>
389+
)}
390+
{!dimensions.locked.width && !dimensions.locked.height && (
391+
<DragHandle ref={dragRefXY} isDefault={isDefault} data-side="both" />
392+
)}
388393
</FrameWrapper>
389394
</ViewportWrapper>
390395
);

code/core/src/viewport/useViewport.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,7 @@ export const useViewport = () => {
179179
const w = width.replace(/px$/, '').replace(/%$/, 'pct');
180180
const h = height.replace(/px$/, '').replace(/%$/, 'pct');
181181
const value = isRotated ? `${h}-${w}` : `${w}-${h}`;
182-
const [match, vx, ux, vy, uy] = value.match(URL_VALUE_PATTERN) || [];
183-
184-
// Don't update to pixel values less than 40
185-
if (match && (ux || Number(vx) >= 40) && (uy || Number(vy) >= 40)) {
186-
update({ value: match, isRotated });
187-
}
182+
update({ value, isRotated });
188183
},
189184
[update, isRotated]
190185
);

0 commit comments

Comments
 (0)