From ccf3189a49eeaa8c1e348a2e8b22edd1cc84dc2c Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 15 Jul 2024 17:54:51 +0200 Subject: [PATCH] tweak cell resize handles --- .../canvas-strategies/interaction-state.ts | 16 ++ .../canvas/controls/grid-controls.tsx | 151 ++++++++++-------- 2 files changed, 98 insertions(+), 69 deletions(-) diff --git a/editor/src/components/canvas/canvas-strategies/interaction-state.ts b/editor/src/components/canvas/canvas-strategies/interaction-state.ts index 52e118ef560e..8f73a19e2030 100644 --- a/editor/src/components/canvas/canvas-strategies/interaction-state.ts +++ b/editor/src/components/canvas/canvas-strategies/interaction-state.ts @@ -631,6 +631,22 @@ export function gridCellHandle(params: { id: string }): GridCellHandle { export const GridResizeEdges = ['row-start', 'row-end', 'column-start', 'column-end'] as const export type GridResizeEdge = (typeof GridResizeEdges)[number] +export type GridResizeEdgeProperties = { + isRow: boolean + isColumn: boolean + isStart: boolean + isEnd: boolean +} + +export function gridResizeEdgeProperties(edge: GridResizeEdge): GridResizeEdgeProperties { + return { + isRow: edge === 'row-start' || edge === 'row-end', + isColumn: edge === 'column-start' || edge === 'column-end', + isStart: edge === 'row-start' || edge === 'column-start', + isEnd: edge === 'row-end' || edge === 'column-end', + } +} + export interface GridResizeHandle { type: 'GRID_RESIZE_HANDLE' id: string diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index e4ab421f7280..3e08f9c12dc7 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -3,6 +3,7 @@ import { jsx } from '@emotion/react' import type { AnimationControls } from 'framer-motion' import { motion, useAnimationControls } from 'framer-motion' +import type { CSSProperties } from 'react' import React from 'react' import type { ElementPath } from 'utopia-shared/src/types' import type { GridCSSNumber } from '../../../components/inspector/common/css-utils' @@ -44,12 +45,16 @@ import { Substores, useEditorState, useRefEditorState } from '../../editor/store import { useRollYourOwnFeatures } from '../../navigator/left-pane/roll-your-own-pane' import CanvasActions from '../canvas-actions' import { controlForStrategyMemoized } from '../canvas-strategies/canvas-strategy-types' -import type { GridResizeEdge } from '../canvas-strategies/interaction-state' +import type { + GridResizeEdge, + GridResizeEdgeProperties, +} from '../canvas-strategies/interaction-state' import { GridResizeEdges, createInteractionViaMouse, gridAxisHandle, gridCellHandle, + gridResizeEdgeProperties, gridResizeHandle, } from '../canvas-strategies/interaction-state' import { windowToCanvasCoordinates } from '../dom-lookup' @@ -1054,9 +1059,12 @@ export const GridResizeControls = controlForStrategyMemoized(null) + const onMouseUp = React.useCallback(() => { setBounds(null) setStartingBounds(null) + setResizingEdge(null) }, []) React.useEffect(() => { @@ -1072,6 +1080,7 @@ export const GridResizeControls = controlForStrategyMemoized (event: React.MouseEvent) => { event.stopPropagation() const frame = zeroRectIfNullOrInfinity(element?.globalFrame ?? null) + setResizingEdge(edge) setBounds(frame) setStartingBounds(frame) const start = windowToCanvasCoordinates( @@ -1093,10 +1102,21 @@ export const GridResizeControls = controlForStrategyMemoized { + if (isResizing) { + return true + } + if (element?.globalFrame == null || isInfinityRectangle(element.globalFrame)) { + return false + } + return element.globalFrame.width * scale > 40 && element.globalFrame.height > 40 + }, [element, scale, isResizing]) + if ( element == null || element.globalFrame == null || - isInfinityRectangle(element.globalFrame) + isInfinityRectangle(element.globalFrame) || + !canShowHandles ) { return null } @@ -1113,62 +1133,67 @@ export const GridResizeControls = controlForStrategyMemoized - {GridResizeEdges.map((edge) => ( -
-
-
- ))} +
+ {GridResizeEdges.map((edge) => { + const properties = gridResizeEdgeProperties(edge) + const visible = !isResizing || resizingEdge === edge + return ( +
+
+
+ ) + })} +
) }, ) -function gridEdgeToGridArea(edge: GridResizeEdge): string { - switch (edge) { - case 'column-end': - return 'ce' - case 'column-start': - return 'cs' - case 'row-end': - return 're' - case 'row-start': - return 'rs' - default: - assertNever(edge) - } +const GRID_RESIZE_HANDLE_SIZES = { + long: 24, + short: 4, } function gridEdgeToEdgePosition(edge: GridResizeEdge): EdgePosition { @@ -1199,25 +1224,13 @@ function gridEdgeToCSSCursor(edge: GridResizeEdge): CSSCursor { } } -function gridEdgeToWidthHeight( - edge: GridResizeEdge, - scale: number, -): { - width: number - height: number - borderRadius: number -} { - const LONG_EDGE = 24 / scale - const SHORT_EDGE = 4 / scale - - switch (edge) { - case 'column-end': - case 'column-start': - return { width: SHORT_EDGE, height: LONG_EDGE, borderRadius: SHORT_EDGE / 2 } - case 'row-end': - case 'row-start': - return { width: LONG_EDGE, height: SHORT_EDGE, borderRadius: SHORT_EDGE / 2 } - default: - assertNever(edge) +function gridEdgeToWidthHeight(props: GridResizeEdgeProperties, scale: number): CSSProperties { + return { + width: props.isColumn ? (GRID_RESIZE_HANDLE_SIZES.short * 4) / scale : '100%', + height: props.isRow ? (GRID_RESIZE_HANDLE_SIZES.short * 4) / scale : '100%', + top: props.isStart ? 0 : undefined, + left: props.isStart ? 0 : undefined, + right: props.isEnd ? 0 : undefined, + bottom: props.isEnd ? 0 : undefined, } }