Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 18 additions & 17 deletions src/editor/CanvasOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export function CanvasOverlay({ gridSnapEnabled }: { gridSnapEnabled: boolean })
const [layoutSpacingY, setLayoutSpacingY] = useState('1');
const [layoutSetX, setLayoutSetX] = useState('');
const [layoutSetY, setLayoutSetY] = useState('');
const layoutActionButtonClassName = 'button button-compact';
const [groupPromptOpen, setGroupPromptOpen] = useState(false);
const [groupPromptPosition, setGroupPromptPosition] = useState<{ x: number; y: number } | null>(null);
const [groupPromptPopupSize, setGroupPromptPopupSize] = useState<Size | null>(null);
Expand Down Expand Up @@ -678,8 +679,8 @@ export function CanvasOverlay({ gridSnapEnabled }: { gridSnapEnabled: boolean })
<div className="canvas-selection-menu-section">
<div className="canvas-selection-menu-heading">Arrange items</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 6 }}>
<button className="canvas-selection-menu-item" data-testid="layout-distribute-x" type="button" onClick={() => applyLayoutPositions(distributeCenters(gatherLayoutItems(state.selection.ids), 'x'))}>Distribute X</button>
<button className="canvas-selection-menu-item" data-testid="layout-distribute-y" type="button" onClick={() => applyLayoutPositions(distributeCenters(gatherLayoutItems(state.selection.ids), 'y'))}>Distribute Y</button>
<button className={layoutActionButtonClassName} data-testid="layout-distribute-x" type="button" onClick={() => applyLayoutPositions(distributeCenters(gatherLayoutItems(state.selection.ids), 'x'))}>Distribute X</button>
<button className={layoutActionButtonClassName} data-testid="layout-distribute-y" type="button" onClick={() => applyLayoutPositions(distributeCenters(gatherLayoutItems(state.selection.ids), 'y'))}>Distribute Y</button>
</div>

<div className="canvas-selection-menu-heading" style={{ marginTop: 10 }}>Spacing</div>
Expand All @@ -691,7 +692,7 @@ export function CanvasOverlay({ gridSnapEnabled }: { gridSnapEnabled: boolean })
<span>Spacing X</span>
<input className="text-input" data-testid="layout-spacing-x" type="number" value={layoutSpacingX} onChange={(e) => setLayoutSpacingX(e.target.value)} />
</label>
<button className="canvas-selection-menu-item" data-testid="layout-apply-spacing-x" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-apply-spacing-x" type="button" onClick={() => {
const raw = Number(layoutSpacingX);
const spacing = layoutUnits === 'grid' ? raw * 8 : raw;
applyLayoutPositions(spacingByCenters(gatherLayoutItems(state.selection.ids), 'x', spacing));
Expand All @@ -701,7 +702,7 @@ export function CanvasOverlay({ gridSnapEnabled }: { gridSnapEnabled: boolean })
<span>Spacing Y</span>
<input className="text-input" data-testid="layout-spacing-y" type="number" value={layoutSpacingY} onChange={(e) => setLayoutSpacingY(e.target.value)} />
</label>
<button className="canvas-selection-menu-item" data-testid="layout-apply-spacing-y" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-apply-spacing-y" type="button" onClick={() => {
const raw = Number(layoutSpacingY);
const spacing = layoutUnits === 'grid' ? raw * 8 : raw;
applyLayoutPositions(spacingByCenters(gatherLayoutItems(state.selection.ids), 'y', spacing));
Expand All @@ -723,15 +724,15 @@ export function CanvasOverlay({ gridSnapEnabled }: { gridSnapEnabled: boolean })
</div>

<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6, marginTop: 6 }}>
<button className="canvas-selection-menu-item" data-testid="layout-apply-set-x" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-apply-set-x" type="button" onClick={() => {
const x = Number(layoutSetX);
applyLayoutPositions(setSelectionCenter(gatherLayoutItems(state.selection.ids), { x }));
}}>Set X</button>
<button className="canvas-selection-menu-item" data-testid="layout-apply-set-y" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-apply-set-y" type="button" onClick={() => {
const y = Number(layoutSetY);
applyLayoutPositions(setSelectionCenter(gatherLayoutItems(state.selection.ids), { y }));
}}>Set Y</button>
<button className="canvas-selection-menu-item" data-testid="layout-apply-set-xy" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-apply-set-xy" type="button" onClick={() => {
const x = Number(layoutSetX);
const y = Number(layoutSetY);
applyLayoutPositions(setSelectionCenter(gatherLayoutItems(state.selection.ids), { x, y }));
Expand All @@ -740,22 +741,22 @@ export function CanvasOverlay({ gridSnapEnabled }: { gridSnapEnabled: boolean })

<div className="canvas-selection-menu-heading" style={{ marginTop: 10 }}>Align selection</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6 }}>
<button className="canvas-selection-menu-item" data-testid="layout-align-left" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-align-left" type="button" onClick={() => {
applyLayoutPositions(alignSelectionToWorld(gatherLayoutItems(state.selection.ids), 'left', scene.world.width, scene.world.height));
}}>Left</button>
<button className="canvas-selection-menu-item" data-testid="layout-align-center-x" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-align-center-x" type="button" onClick={() => {
applyLayoutPositions(alignSelectionToWorld(gatherLayoutItems(state.selection.ids), 'centerX', scene.world.width, scene.world.height));
}}>Center X</button>
<button className="canvas-selection-menu-item" data-testid="layout-align-right" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-align-right" type="button" onClick={() => {
applyLayoutPositions(alignSelectionToWorld(gatherLayoutItems(state.selection.ids), 'right', scene.world.width, scene.world.height));
}}>Right</button>
<button className="canvas-selection-menu-item" data-testid="layout-align-top" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-align-top" type="button" onClick={() => {
applyLayoutPositions(alignSelectionToWorld(gatherLayoutItems(state.selection.ids), 'top', scene.world.width, scene.world.height));
}}>Top</button>
<button className="canvas-selection-menu-item" data-testid="layout-align-center-y" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-align-center-y" type="button" onClick={() => {
applyLayoutPositions(alignSelectionToWorld(gatherLayoutItems(state.selection.ids), 'centerY', scene.world.width, scene.world.height));
}}>Center Y</button>
<button className="canvas-selection-menu-item" data-testid="layout-align-bottom" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-align-bottom" type="button" onClick={() => {
applyLayoutPositions(alignSelectionToWorld(gatherLayoutItems(state.selection.ids), 'bottom', scene.world.width, scene.world.height));
}}>Bottom</button>
</div>
Expand All @@ -765,19 +766,19 @@ export function CanvasOverlay({ gridSnapEnabled }: { gridSnapEnabled: boolean })
<div className="canvas-selection-menu-section">
<div className="canvas-selection-menu-heading">Advanced</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 6 }}>
<button className="canvas-selection-menu-item" data-testid="layout-stack-center-x" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-stack-center-x" type="button" onClick={() => {
const ids = state.selection.ids;
applyLayoutPositions(alignByBounds(gatherLayoutItems(ids), 'centerX', ids[0]!));
}}>Stack X centers</button>
<button className="canvas-selection-menu-item" data-testid="layout-stack-center-y" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-stack-center-y" type="button" onClick={() => {
const ids = state.selection.ids;
applyLayoutPositions(alignByBounds(gatherLayoutItems(ids), 'centerY', ids[0]!));
}}>Stack Y centers</button>
<button className="canvas-selection-menu-item" data-testid="layout-match-left-edges" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-match-left-edges" type="button" onClick={() => {
const ids = state.selection.ids;
applyLayoutPositions(alignByBounds(gatherLayoutItems(ids), 'left', ids[0]!));
}}>Match left edges</button>
<button className="canvas-selection-menu-item" data-testid="layout-match-top-edges" type="button" onClick={() => {
<button className={layoutActionButtonClassName} data-testid="layout-match-top-edges" type="button" onClick={() => {
const ids = state.selection.ids;
applyLayoutPositions(alignByBounds(gatherLayoutItems(ids), 'top', ids[0]!));
}}>Match top edges</button>
Expand Down
36 changes: 18 additions & 18 deletions src/editor/LayoutPopoverContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export function LayoutPopoverContent(props: LayoutPopoverContentProps) {
onMatchTopEdges,
onClose,
} = props;
const actionButtonClassName = 'button button-compact';

return (
<div className="canvas-layout-popover-content">
Expand All @@ -89,10 +90,10 @@ export function LayoutPopoverContent(props: LayoutPopoverContentProps) {
</div>

<div className="canvas-layout-grid-2">
<button className="canvas-selection-menu-item" data-testid="layout-distribute-x" type="button" onClick={onDistributeX}>
<button className={actionButtonClassName} data-testid="layout-distribute-x" type="button" onClick={onDistributeX}>
Distribute X
</button>
<button className="canvas-selection-menu-item" data-testid="layout-distribute-y" type="button" onClick={onDistributeY}>
<button className={actionButtonClassName} data-testid="layout-distribute-y" type="button" onClick={onDistributeY}>
Distribute Y
</button>
</div>
Expand Down Expand Up @@ -130,10 +131,10 @@ export function LayoutPopoverContent(props: LayoutPopoverContentProps) {
</div>

<div className="canvas-layout-grid-2">
<button className="canvas-selection-menu-item" data-testid="layout-apply-spacing-x" type="button" onClick={onApplySpacingX}>
<button className={actionButtonClassName} data-testid="layout-apply-spacing-x" type="button" onClick={onApplySpacingX}>
Apply X
</button>
<button className="canvas-selection-menu-item" data-testid="layout-apply-spacing-y" type="button" onClick={onApplySpacingY}>
<button className={actionButtonClassName} data-testid="layout-apply-spacing-y" type="button" onClick={onApplySpacingY}>
Apply Y
</button>
</div>
Expand All @@ -156,13 +157,13 @@ export function LayoutPopoverContent(props: LayoutPopoverContentProps) {
</div>

<div className="canvas-layout-grid-3">
<button className="canvas-selection-menu-item" data-testid="layout-apply-set-x" type="button" onClick={onApplySetX}>
<button className={actionButtonClassName} data-testid="layout-apply-set-x" type="button" onClick={onApplySetX}>
Set X
</button>
<button className="canvas-selection-menu-item" data-testid="layout-apply-set-y" type="button" onClick={onApplySetY}>
<button className={actionButtonClassName} data-testid="layout-apply-set-y" type="button" onClick={onApplySetY}>
Set Y
</button>
<button className="canvas-selection-menu-item" data-testid="layout-apply-set-xy" type="button" onClick={onApplySetXY}>
<button className={actionButtonClassName} data-testid="layout-apply-set-xy" type="button" onClick={onApplySetXY}>
Set X+Y
</button>
</div>
Expand All @@ -176,22 +177,22 @@ export function LayoutPopoverContent(props: LayoutPopoverContentProps) {
</div>

<div className="canvas-layout-grid-3">
<button className="canvas-selection-menu-item" data-testid="layout-align-left" type="button" onClick={onAlignLeft}>
<button className={actionButtonClassName} data-testid="layout-align-left" type="button" onClick={onAlignLeft}>
Left
</button>
<button className="canvas-selection-menu-item" data-testid="layout-align-center-x" type="button" onClick={onAlignCenterX}>
<button className={actionButtonClassName} data-testid="layout-align-center-x" type="button" onClick={onAlignCenterX}>
Center X
</button>
<button className="canvas-selection-menu-item" data-testid="layout-align-right" type="button" onClick={onAlignRight}>
<button className={actionButtonClassName} data-testid="layout-align-right" type="button" onClick={onAlignRight}>
Right
</button>
<button className="canvas-selection-menu-item" data-testid="layout-align-top" type="button" onClick={onAlignTop}>
<button className={actionButtonClassName} data-testid="layout-align-top" type="button" onClick={onAlignTop}>
Top
</button>
<button className="canvas-selection-menu-item" data-testid="layout-align-center-y" type="button" onClick={onAlignCenterY}>
<button className={actionButtonClassName} data-testid="layout-align-center-y" type="button" onClick={onAlignCenterY}>
Center Y
</button>
<button className="canvas-selection-menu-item" data-testid="layout-align-bottom" type="button" onClick={onAlignBottom}>
<button className={actionButtonClassName} data-testid="layout-align-bottom" type="button" onClick={onAlignBottom}>
Bottom
</button>
</div>
Expand All @@ -205,16 +206,16 @@ export function LayoutPopoverContent(props: LayoutPopoverContentProps) {
</div>

<div className="canvas-layout-grid-2">
<button className="canvas-selection-menu-item" data-testid="layout-stack-center-x" type="button" onClick={onStackCenterX}>
<button className={actionButtonClassName} data-testid="layout-stack-center-x" type="button" onClick={onStackCenterX}>
Stack X centers
</button>
<button className="canvas-selection-menu-item" data-testid="layout-stack-center-y" type="button" onClick={onStackCenterY}>
<button className={actionButtonClassName} data-testid="layout-stack-center-y" type="button" onClick={onStackCenterY}>
Stack Y centers
</button>
<button className="canvas-selection-menu-item" data-testid="layout-match-left-edges" type="button" onClick={onMatchLeftEdges}>
<button className={actionButtonClassName} data-testid="layout-match-left-edges" type="button" onClick={onMatchLeftEdges}>
Match left edges
</button>
<button className="canvas-selection-menu-item" data-testid="layout-match-top-edges" type="button" onClick={onMatchTopEdges}>
<button className={actionButtonClassName} data-testid="layout-match-top-edges" type="button" onClick={onMatchTopEdges}>
Match top edges
</button>
</div>
Expand All @@ -228,4 +229,3 @@ export function LayoutPopoverContent(props: LayoutPopoverContentProps) {
</div>
);
}

2 changes: 2 additions & 0 deletions tests/e2e/layout-popover.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ test('Layout popover applies fixed spacing by centers @critical', async ({ page
const layoutButton = page.getByTestId('canvas-layout-button');
await layoutButton.focus();
await layoutButton.press('Enter');
await expect(page.getByTestId('layout-distribute-x')).toHaveClass(/button/);
await expect(page.getByTestId('layout-apply-spacing-x')).toHaveClass(/button/);
await page.getByTestId('layout-units-pixels').click();
await page.getByTestId('layout-spacing-x').fill('64');
await page.getByTestId('layout-apply-spacing-x').click();
Expand Down
42 changes: 41 additions & 1 deletion tests/editor/layout-popover-content.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,45 @@ describe('LayoutPopoverContent', () => {
expect(markup).toContain('data-testid="layout-match-top-edges"');
expect(markup).toContain('data-testid="layout-close"');
});
});

it('renders layout actions with button styling instead of label-like menu styling', () => {
const markup = renderToStaticMarkup(
<LayoutPopoverContent
layoutUnits="pixels"
setLayoutUnits={() => {}}
layoutSpacingX="64"
setLayoutSpacingX={() => {}}
layoutSpacingY="32"
setLayoutSpacingY={() => {}}
layoutSetX="0"
setLayoutSetX={() => {}}
layoutSetY="0"
setLayoutSetY={() => {}}
onDistributeX={() => {}}
onDistributeY={() => {}}
onApplySpacingX={() => {}}
onApplySpacingY={() => {}}
onApplySetX={() => {}}
onApplySetY={() => {}}
onApplySetXY={() => {}}
onAlignLeft={() => {}}
onAlignCenterX={() => {}}
onAlignRight={() => {}}
onAlignTop={() => {}}
onAlignCenterY={() => {}}
onAlignBottom={() => {}}
onStackCenterX={() => {}}
onStackCenterY={() => {}}
onMatchLeftEdges={() => {}}
onMatchTopEdges={() => {}}
onClose={() => {}}
/>
);

expect(markup).toContain('class="button button-compact" data-testid="layout-distribute-x"');
expect(markup).toContain('class="button button-compact" data-testid="layout-apply-spacing-x"');
expect(markup).toContain('class="button button-compact" data-testid="layout-apply-set-xy"');
expect(markup).toContain('class="button button-compact" data-testid="layout-align-center-x"');
expect(markup).toContain('class="button button-compact" data-testid="layout-match-top-edges"');
});
});
Loading