From 5cfd07ea6ec102ef2ec9a04522ef835fee702ce0 Mon Sep 17 00:00:00 2001 From: Oleg Isonen Date: Thu, 5 May 2022 14:36:26 +0200 Subject: [PATCH] set initial width to the smallest mobile breakpoint, constraint the width resizing, unconstrained in preview --- app/designer/designer.tsx | 2 +- .../features/breakpoints/trigger-button.tsx | 2 +- .../breakpoints/use-update-canvas-width.ts | 23 ++++---- .../features/breakpoints/width-setting.tsx | 52 ++++++++++++++++--- .../features/style-panel/style-panel.tsx | 3 +- app/designer/shared/nano-values/index.ts | 2 +- 6 files changed, 64 insertions(+), 20 deletions(-) diff --git a/app/designer/designer.tsx b/app/designer/designer.tsx index fe357f2e38..e26c9e82ba 100644 --- a/app/designer/designer.tsx +++ b/app/designer/designer.tsx @@ -228,7 +228,7 @@ export const Designer = ({ config, project }: DesignerProps) => { height: "100%", minWidth, }} - style={{ width: canvasWidth || "100%" }} + style={{ width: canvasWidth }} /> diff --git a/app/designer/features/breakpoints/trigger-button.tsx b/app/designer/features/breakpoints/trigger-button.tsx index 44f3349cbf..b6acdc8518 100644 --- a/app/designer/features/breakpoints/trigger-button.tsx +++ b/app/designer/features/breakpoints/trigger-button.tsx @@ -36,7 +36,7 @@ export const TriggerButton = forwardRef< >((props, ref) => { const [zoom] = useZoom(); const [breakpoint] = useSelectedBreakpoint(); - const [canvasWidth = 0] = useCanvasWidth(); + const [canvasWidth] = useCanvasWidth(); if (breakpoint === undefined) return null; const variant = willRender(breakpoint, canvasWidth) ? "contrast" : "gray"; diff --git a/app/designer/features/breakpoints/use-update-canvas-width.ts b/app/designer/features/breakpoints/use-update-canvas-width.ts index abed3d20d6..6f358e63cd 100644 --- a/app/designer/features/breakpoints/use-update-canvas-width.ts +++ b/app/designer/features/breakpoints/use-update-canvas-width.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useRef } from "react"; +import { useCallback, useEffect } from "react"; import { useSelectedBreakpoint, useCanvasWidth, @@ -8,7 +8,6 @@ import { minWidth } from "./width-setting"; export const useUpdateCanvasWidth = () => { const [selectedBreakpoint] = useSelectedBreakpoint(); const [canvasWidth, setCanvasWidth] = useCanvasWidth(); - const initialCanvasWidthRef = useRef(); useEffect(() => { if (selectedBreakpoint === undefined) { @@ -16,21 +15,27 @@ export const useUpdateCanvasWidth = () => { } if (selectedBreakpoint.minWidth === 0) { - setCanvasWidth(initialCanvasWidthRef.current); + setCanvasWidth(minWidth); return; } setCanvasWidth(Math.max(selectedBreakpoint.minWidth, minWidth)); }, [selectedBreakpoint, setCanvasWidth]); + // Set the initial canvas width based on the selected breakpoint upper bound, which starts where the next breakpoint begins. return useCallback( (iframe: HTMLIFrameElement | null) => { - if (iframe === null || canvasWidth !== undefined) return; - initialCanvasWidthRef.current = Math.round( - iframe.getBoundingClientRect().width - ); - setCanvasWidth(initialCanvasWidthRef.current); + // Once canvasWidth is set, it means we have already set the initial width. + if ( + iframe === null || + selectedBreakpoint === undefined || + canvasWidth !== 0 + ) { + return; + } + + setCanvasWidth(minWidth); }, - [canvasWidth, setCanvasWidth] + [canvasWidth, selectedBreakpoint, setCanvasWidth] ); }; diff --git a/app/designer/features/breakpoints/width-setting.tsx b/app/designer/features/breakpoints/width-setting.tsx index 3a61e4274f..1a793a1259 100644 --- a/app/designer/features/breakpoints/width-setting.tsx +++ b/app/designer/features/breakpoints/width-setting.tsx @@ -1,20 +1,60 @@ -import { useCanvasWidth } from "~/designer/shared/nano-values"; +import { useMemo } from "react"; +import { + useCanvasWidth, + useIsPreviewMode, + useSelectedBreakpoint, + useBreakpoints, +} from "~/designer/shared/nano-values"; import { Slider, Text, Flex } from "~/shared/design-system"; +import { sort } from "./sort"; -// Doesn't make sense to allow resizing the canvas lower than this. -export const minWidth = 200; +// Doesn't make sense to allow resizing the canvas lower/higher than this. +export const minWidth = 360; export const maxWidth = 3000; +/** + * Return the next breakpoint from the currently selected one, sorted by the `sort()` + */ +const useNextBreakpoint = () => { + const [selectedBreakpoint] = useSelectedBreakpoint(); + const [breakpoints] = useBreakpoints(); + + const sortedBreakpoints = useMemo(() => sort(breakpoints), [breakpoints]); + + return useMemo(() => { + if (selectedBreakpoint === undefined) return; + const index = sortedBreakpoints.indexOf(selectedBreakpoint); + if (index === -1) return undefined; + return sortedBreakpoints[index + 1]; + }, [sortedBreakpoints, selectedBreakpoint]); +}; + export const WidthSetting = () => { - const [value = 0, setValue] = useCanvasWidth(); + const [value, setValue] = useCanvasWidth(); + const [selectedBreakpoint] = useSelectedBreakpoint(); + const nextBreakpoint = useNextBreakpoint(); + const [isPreviewMode] = useIsPreviewMode(); + + if (selectedBreakpoint === undefined) return null; + + // We want to enable unconstrained resizing in a preview mode + const min = isPreviewMode + ? minWidth + : Math.max(minWidth, selectedBreakpoint.minWidth); + const max = isPreviewMode + ? maxWidth + : Math.min( + maxWidth, + nextBreakpoint ? nextBreakpoint.minWidth - 1 : maxWidth + ); return ( Canvas width { setValue(value); diff --git a/app/designer/features/style-panel/style-panel.tsx b/app/designer/features/style-panel/style-panel.tsx index 9b75f4b362..858da6d6f6 100644 --- a/app/designer/features/style-panel/style-panel.tsx +++ b/app/designer/features/style-panel/style-panel.tsx @@ -33,8 +33,7 @@ export const StylePanel = ({ currentStyle === undefined || inheritedStyle === undefined || selectedInstanceData === undefined || - breakpoint === undefined || - canvasWidth === undefined + breakpoint === undefined ) { return null; } diff --git a/app/designer/shared/nano-values/index.ts b/app/designer/shared/nano-values/index.ts index f9b685d095..21f4fb3589 100644 --- a/app/designer/shared/nano-values/index.ts +++ b/app/designer/shared/nano-values/index.ts @@ -34,7 +34,7 @@ export const useBreakpoints = () => useValue(breakpointsContainer); const zoomContainer = createValueContainer(100); export const useZoom = () => useValue(zoomContainer); -const canvasWidthContainer = createValueContainer(); +const canvasWidthContainer = createValueContainer(0); export const useCanvasWidth = () => useValue(canvasWidthContainer); const syncStatusContainer = createValueContainer("idle");