forked from langflow-ai/langflow
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Flow's canvas actions design uplift (langflow-ai#4260)
* init * move panels and make custom * post review changes * [autofix.ci] apply automated fixes * pr comment fix * design review fixes * [autofix.ci] apply automated fixes * action toolbar positioning feedback * [autofix.ci] apply automated fixes * remove extra imports * test selector updates * missed a couple * one more --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
- Loading branch information
1 parent
fab2d9a
commit 20b3a6b
Showing
75 changed files
with
584 additions
and
452 deletions.
There are no files selected for viewing
118 changes: 118 additions & 0 deletions
118
src/frontend/src/components/canvasControlsComponent/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import IconComponent from "@/components/genericIconComponent"; | ||
import ShadTooltip from "@/components/shadTooltipComponent"; | ||
import { cn } from "@/utils/utils"; | ||
import { | ||
ControlButton, | ||
Panel, | ||
useReactFlow, | ||
useStore, | ||
useStoreApi, | ||
type ReactFlowState, | ||
} from "reactflow"; | ||
import { shallow } from "zustand/shallow"; | ||
|
||
type CustomControlButtonProps = { | ||
iconName: string; | ||
tooltipText: string; | ||
onClick: () => void; | ||
disabled?: boolean; | ||
backgroundClasses?: string; | ||
iconClasses?: string; | ||
testId?: string; | ||
}; | ||
|
||
export const CustomControlButton = ({ | ||
iconName, | ||
tooltipText, | ||
onClick, | ||
disabled, | ||
backgroundClasses, | ||
iconClasses, | ||
testId, | ||
}: CustomControlButtonProps): JSX.Element => { | ||
return ( | ||
<ControlButton | ||
data-testid={testId} | ||
className="!h-8 !w-8 rounded !p-0" | ||
onClick={onClick} | ||
disabled={disabled} | ||
> | ||
<ShadTooltip content={tooltipText}> | ||
<div className={cn("rounded p-2.5", backgroundClasses)}> | ||
<IconComponent | ||
name={iconName} | ||
aria-hidden="true" | ||
className={cn("scale-150 text-muted-foreground", iconClasses)} | ||
/> | ||
</div> | ||
</ShadTooltip> | ||
</ControlButton> | ||
); | ||
}; | ||
|
||
const selector = (s: ReactFlowState) => ({ | ||
isInteractive: s.nodesDraggable || s.nodesConnectable || s.elementsSelectable, | ||
minZoomReached: s.transform[2] <= s.minZoom, | ||
maxZoomReached: s.transform[2] >= s.maxZoom, | ||
}); | ||
|
||
const CanvasControls = ({ children }) => { | ||
const store = useStoreApi(); | ||
const { fitView, zoomIn, zoomOut } = useReactFlow(); | ||
const { isInteractive, minZoomReached, maxZoomReached } = useStore( | ||
selector, | ||
shallow, | ||
); | ||
|
||
const onToggleInteractivity = () => { | ||
store.setState({ | ||
nodesDraggable: !isInteractive, | ||
nodesConnectable: !isInteractive, | ||
elementsSelectable: !isInteractive, | ||
}); | ||
}; | ||
|
||
return ( | ||
<Panel | ||
data-testid="canvas_controls" | ||
className="react-flow__controls !m-2 flex gap-1.5 rounded-md border border-secondary-hover bg-background fill-foreground stroke-foreground p-1.5 text-primary shadow [&>button]:border-0 [&>button]:bg-background hover:[&>button]:bg-accent" | ||
position="bottom-left" | ||
> | ||
{/* Zoom In */} | ||
<CustomControlButton | ||
iconName="ZoomIn" | ||
tooltipText="Zoom In" | ||
onClick={zoomIn} | ||
disabled={maxZoomReached} | ||
testId="zoom_in" | ||
/> | ||
{/* Zoom Out */} | ||
<CustomControlButton | ||
iconName="ZoomOut" | ||
tooltipText="Zoom Out" | ||
onClick={zoomOut} | ||
disabled={minZoomReached} | ||
testId="zoom_out" | ||
/> | ||
{/* Zoom To Fit */} | ||
<CustomControlButton | ||
iconName="maximize" | ||
tooltipText="Fit To Zoom" | ||
onClick={fitView} | ||
testId="fit_view" | ||
/> | ||
{/* Lock/Unlock */} | ||
<CustomControlButton | ||
iconName={isInteractive ? "LockOpen" : "Lock"} | ||
tooltipText={isInteractive ? "Lock" : "Unlock"} | ||
onClick={onToggleInteractivity} | ||
backgroundClasses={isInteractive ? "" : "bg-destructive"} | ||
iconClasses={isInteractive ? "" : "text-primary-foreground"} | ||
testId="lock_unlock" | ||
/> | ||
{children} | ||
</Panel> | ||
); | ||
}; | ||
|
||
export default CanvasControls; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.