feat(apollo-react): multi-strategy Tidy up menu for CanvasZoomControls#957
feat(apollo-react): multi-strategy Tidy up menu for CanvasZoomControls#957dbacomputer wants to merge 2 commits into
Conversation
…rols Adds a "Tidy up" dropdown to CanvasZoomControls with four layout strategies (Subtle align, Compact layout, Horizontal layout, Vertical layout) plus a Reset to original action, backed by new subtleAlignNodes and compactAlignNodes utilities in canvas/utils/tidy-up.ts. Vertical layout also flips node handles to top/bottom via a new HandleConfigs.topBottom preset so edges stay straight instead of zigzagging around side-mounted handles. The single-action onOrganize prop used by AgentCanvas is unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Dependency License Review
License distribution
Excluded packages
|
📊 Coverage + size by packagePer-package coverage and bundle size on this PR. New-line coverage = of the source lines this PR adds or changes, the % hit by tests.
"Coverage" is each package's own |
There was a problem hiding this comment.
Pull request overview
Adds multi-strategy “Tidy up” support around CanvasZoomControls, including reusable layout utilities and Storybook demos, while preserving the existing single-action onOrganize behavior for current consumers.
Changes:
- Introduces new tidy-up utilities (
subtleAlignNodes,compactAlignNodes) with unit tests. - Extends
CanvasZoomControlsto optionally render a dropdown strategy menu (and exports the new option type). - Enhances Storybook demos and adds a new vertical-flow handle preset (
HandleConfigs.topBottom) for straighter vertical routing.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/apollo-react/src/canvas/utils/tidy-up.ts | Adds tidy-up strategy constants and two node-layout utilities (snap-to-grid + compact hierarchy layout). |
| packages/apollo-react/src/canvas/utils/tidy-up.test.ts | Adds unit tests covering subtle snapping behavior and compact layout direction overrides. |
| packages/apollo-react/src/canvas/storybook-utils/mocks/nodes.ts | Adds HandleConfigs.topBottom preset for vertical/top-down flows. |
| packages/apollo-react/src/canvas/components/CanvasZoomControls/index.ts | Re-exports the new TidyUpMenuOption type from the component. |
| packages/apollo-react/src/canvas/components/CanvasZoomControls/CanvasZoomControls.tsx | Implements the new dropdown menu variant for tidy-up strategies (while keeping onOrganize fallback). |
| packages/apollo-react/src/canvas/components/CanvasZoomControls/CanvasZoomControls.stories.tsx | Adds stories demonstrating the tidy-up menu and interactive application of strategies on a “messy” workflow. |
| <BrushCleaning /> | ||
| </ToolbarButton> | ||
| {tidyUpOptions && tidyUpOptions.length > 0 ? ( | ||
| <DropdownMenu> |
| > | ||
| <BrushCleaning /> | ||
| </ToolbarButton> | ||
| {tidyUpOptions && tidyUpOptions.length > 0 ? ( |
| /** | ||
| * Runs a single "Tidy up" action immediately on click. Ignored when | ||
| * `tidyUpOptions` is provided -- pass that instead to offer a choice of | ||
| * strategies via a menu. | ||
| */ |
…y point - Vertical/Horizontal now show the full toolbar (including Tidy up) instead of just zoom/fit, doubling as the canonical full-toolbar reference for each orientation; the now-redundant standalone "Tidy up menu" story is removed. - Tidy up: workflow (renamed from "Tidy up interactions") wires the same tidy-up strategies into a per-node NodeToolbar overflow menu, scoped to that one story via BaseNodeOverrideConfigProvider, alongside the existing corner control -- two entry points, one set of actions. - Tidy up menu items now render icon + label (matching NodeToolbar's overflow format) instead of label + description text. - Horizontal/Vertical layout use label-free handle presets and wider node spacing than Compact layout, fixing overlap between handle captions and neighboring node labels. Subtle align and Compact layout are unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (2)
packages/apollo-react/src/canvas/components/CanvasZoomControls/CanvasZoomControls.stories.tsx:120
- Storybook story titles contain an em dash with spaces (
—), which is disallowed in Storybook story copy per repo guidelines. Replace it with a colon or a period-separated phrase.
<StoryInfoPanel
title="Zoom controls — horizontal"
description={`Horizontal orientation. Buttons, including Tidy up, are laid out in a row. Last selected: ${lastSelected ?? 'none'}.`}
/>
packages/apollo-react/src/canvas/components/CanvasZoomControls/CanvasZoomControls.stories.tsx:140
- Storybook story titles contain an em dash with spaces (
—), which is disallowed in Storybook story copy per repo guidelines. Replace it with a colon or a period-separated phrase.
<StoryInfoPanel
title="Zoom controls — with organize"
description={`Uses "onOrganize" -- a single hardcoded action on click, no menu. This is what AgentCanvas uses in production today. Compare to Vertical/Horizontal, which use "tidyUpOptions" for a menu of strategies instead. Organize pressed: ${organizeCount} time${organizeCount === 1 ? '' : 's'}.`}
/>
| <StoryInfoPanel | ||
| title="Zoom controls — vertical" | ||
| description="Default vertical orientation. Zoom in, zoom out, and fit to screen buttons are stacked vertically." | ||
| description={`Default vertical orientation. Zoom in, zoom out, fit to screen, and Tidy up are stacked vertically. Last selected: ${lastSelected ?? 'none'}.`} | ||
| /> |
| import type { Edge, Node } from '@uipath/apollo-react/canvas/xyflow/react'; | ||
| import { d3HierarchyLayout } from './coded-agents/d3-layout'; | ||
|
|
||
| export type TidyUpStrategyId = 'subtle' | 'compact'; |
| {tidyUpOptions && tidyUpOptions.length > 0 ? ( | ||
| <DropdownMenu> | ||
| <Tooltip> | ||
| <TooltipTrigger asChild> | ||
| <DropdownMenuTrigger asChild> | ||
| <Button | ||
| data-testid="tidy-up-menu-button" | ||
| aria-label={_({ id: 'canvas.zoom.tidy_up', message: 'Tidy up' })} | ||
| variant="ghost" | ||
| size="xs" | ||
| icon | ||
| className={ZOOM_ICON_BUTTON_CLASS} | ||
| > | ||
| <BrushCleaning /> | ||
| </Button> | ||
| </DropdownMenuTrigger> | ||
| </TooltipTrigger> | ||
| <TooltipContent side={tooltipSide}> | ||
| {_({ id: 'canvas.zoom.tidy_up', message: 'Tidy up' })} | ||
| </TooltipContent> | ||
| </Tooltip> | ||
| <DropdownMenuContent align="end" side={tooltipSide} sideOffset={8} className="w-48"> | ||
| {tidyUpOptions.map((option) => ( | ||
| <Fragment key={option.id}> | ||
| {option.separatorBefore && <DropdownMenuSeparator />} | ||
| <DropdownMenuItem | ||
| data-testid={`tidy-up-option-${option.id}`} | ||
| disabled={option.disabled} | ||
| onSelect={() => onTidyUpSelect?.(option.id)} | ||
| > | ||
| {typeof option.icon === 'string' ? ( | ||
| <CanvasIcon icon={option.icon} size={16} /> | ||
| ) : ( | ||
| option.icon | ||
| )} | ||
| <span>{option.label}</span> | ||
| </DropdownMenuItem> | ||
| </Fragment> | ||
| ))} | ||
| </DropdownMenuContent> | ||
| </DropdownMenu> |
Summary
CanvasZoomControlsoffering four layout strategies (Subtle align, Compact layout, Horizontal layout, Vertical layout) plus a Reset to original action, on top of the existing single-actiononOrganizeprop (unchanged, still used byAgentCanvas).subtleAlignNodes/compactAlignNodesutilities incanvas/utils/tidy-up.ts, with unit tests.HandleConfigs-style presets) so edges stay straight instead of zigzagging around side-mounted handles; Horizontal/Vertical also use wider node spacing than Compact for a less cramped look. Compact layout and Subtle align are untouched throughout.NodeToolbar, scoped to the demo story only (viaBaseNodeOverrideConfigProvider) — no effect on any other story or on production usage of these node types.Components/Controls/CanvasZoomControls: Vertical, Horizontal (both now show the full toolbar including Tidy up), Tidy up (the single-actiononOrganizedemo, matching AgentCanvas's real production usage), and Tidy up: workflow (the full interactive demo — messy 8-node workflow, both entry points, real repositioning/handle-flipping).Test plan
vitest run src/canvas/utils/tidy-up.test.ts(7 passing)tsc --noEmitcleanbiome checkclean on touched filesonOrganize(AgentCanvas's existing single-action usage) still renders unchanged🤖 Generated with Claude Code