From d6da1ce5bfd5af0e4b0bcf7b115ffe24f3bc4ef4 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Fri, 29 Sep 2023 09:30:50 +0200 Subject: [PATCH] Group size label (#4257) * use "group" for group size label * type --- ...ze-bounding-box-strategy.spec.browser2.tsx | 26 ++++++++ .../select-mode/absolute-resize-control.tsx | 60 ++++++++++++++++--- 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/absolute-resize-bounding-box-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/absolute-resize-bounding-box-strategy.spec.browser2.tsx index c046cd7e65b3..6b3bec6bfe8f 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/absolute-resize-bounding-box-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/absolute-resize-bounding-box-strategy.spec.browser2.tsx @@ -1497,6 +1497,32 @@ export var storyboard = ( }) }) describe('groups', () => { + it('has a "Group" size label', async () => { + const renderResult = await renderTestEditorWithCode( + formatTestProjectCode(` + import * as React from 'react' + import { Storyboard, Group } from 'utopia-api' + + export var storyboard = ( + + +
+
+ + + ) + `), + 'await-first-dom-report', + ) + + await renderResult.dispatch( + [selectComponents([EP.fromString('storyboard/group')], false)], + true, + ) + + const label = await renderResult.renderedDOM.findByTestId(SizeLabelTestId) + expect(label.textContent).toEqual('Group') + }) it('resizes groups correctly when dragging from top/left without existing left/top props (left)', async () => { const renderResult = await renderTestEditorWithCode( formatTestProjectCode(` diff --git a/editor/src/components/canvas/controls/select-mode/absolute-resize-control.tsx b/editor/src/components/canvas/controls/select-mode/absolute-resize-control.tsx index 6f2cc0cdfde3..10c7e4b2929e 100644 --- a/editor/src/components/canvas/controls/select-mode/absolute-resize-control.tsx +++ b/editor/src/components/canvas/controls/select-mode/absolute-resize-control.tsx @@ -38,6 +38,7 @@ import { CanvasOffsetWrapper } from '../canvas-offset-wrapper' import { isZeroSizedElement } from '../outline-utils' import { useMaybeHighlightElement } from './select-mode-hooks' import { isEdgePositionEqualTo } from '../../canvas-utils' +import { treatElementAsGroupLike } from '../../canvas-strategies/strategies/group-helpers' export const AbsoluteResizeControlTestId = (targets: Array): string => `${targets.map(EP.toString).sort()}-absolute-resize-control` @@ -399,15 +400,45 @@ const sizeLabel = (state: FixedHugFill['type'], actualSize: number): string => { } } +export type SizeLabelSize = { + type: 'SIZE_LABEL_WITH_DIMENSIONS' + h: string + v: string +} + +function sizeLabelWithDimensions(h: string, v: string): SizeLabelSize { + return { + type: 'SIZE_LABEL_WITH_DIMENSIONS', + h: h, + v: v, + } +} + +export type SizeLabelGroup = { + type: 'SIZE_LABEL_GROUP' +} + +function sizeLabelGroup(): SizeLabelGroup { + return { + type: 'SIZE_LABEL_GROUP', + } +} + +export type SizeLabelContents = SizeLabelSize | SizeLabelGroup + function sizeLabelContents( metadata: ElementInstanceMetadataMap, selectedElements: Array, -): { h: string; v: string } | null { +): SizeLabelContents | null { if (selectedElements.length === 0) { return null } if (selectedElements.length === 1) { + if (treatElementAsGroupLike(metadata, selectedElements[0])) { + return sizeLabelGroup() + } + const globalFrame = MetadataUtils.findElementByElementPath( metadata, selectedElements[0], @@ -422,17 +453,17 @@ function sizeLabelContents( const vertical = detectFillHugFixedState('vertical', metadata, selectedElements[0]).fixedHugFill?.type ?? 'fixed' - return { - h: sizeLabel(horizontal, globalFrame.width), - v: sizeLabel(vertical, globalFrame.height), - } + return sizeLabelWithDimensions( + sizeLabel(horizontal, globalFrame.width), + sizeLabel(vertical, globalFrame.height), + ) } const boundingBox = boundingRectangleArray( selectedElements.map((t) => nullIfInfinity(MetadataUtils.getFrameInCanvasCoords(t, metadata))), ) if (boundingBox != null) { - return { h: `${boundingBox.width}`, v: `${boundingBox.height}` } + return sizeLabelWithDimensions(`${boundingBox.width}`, `${boundingBox.height}`) } return null @@ -449,6 +480,20 @@ const ExplicitHeightHacked = 20 const BorderRadius = 2 const SizeLabelMarginTop = 8 +function getLabelText(label: SizeLabelContents | null): string | null { + if (label == null) { + return null + } + switch (label.type) { + case 'SIZE_LABEL_GROUP': + return 'Group' + case 'SIZE_LABEL_WITH_DIMENSIONS': + return `${label.h} x ${label.v}` + default: + assertNever(label) + } +} + const SizeLabel = React.memo( React.forwardRef(({ targets }, ref) => { const scale = useEditorState( @@ -464,8 +509,7 @@ const SizeLabel = React.memo( ) const label = sizeLabelContents(metadata, targets) - - const labelText = label == null ? null : `${label.h} x ${label.v}` + const labelText = getLabelText(label) return (