Controls
Themed corner controls for a Canvas. Zoom in, zoom out, fit view and lock interaction, all skinned with Gremorie tokens.
Overview
Controls is a Gremorie skin over Controls from @xyflow/react. It docks to the bottom-left of a Canvas by default and exposes the standard interaction buttons: zoom in, zoom out, fit view, and a lock toggle that disables panning and node interaction.
The Gremorie chrome strips xyflow's heavy borders and shadows in favor of a single rounded border, a bg-card background and ghost-style buttons that pick up bg-secondary on hover. This keeps the controls visually quiet so they do not compete with the workflow content.
Use whenever a canvas needs zoom controls (any read-write graph editor) or read-only navigation aids (agent traces, large flow visualizations).
Preview
'use client';import '@xyflow/react/dist/style.css';import { Canvas, Controls } from '@gremorie/rx-ai';import { type Edge as FlowEdge, type Node as FlowNode, ReactFlowProvider,} from '@xyflow/react';const gridNodes: FlowNode[] = [ { id: '1', position: { x: 0, y: 0 }, data: { label: 'A' } }, { id: '2', position: { x: 200, y: 80 }, data: { label: 'B' } },];const gridEdges: FlowEdge[] = [{ id: 'e1-2', source: '1', target: '2' }];export function ControlsPreview() { return ( <div className="h-[360px] w-full"> <ReactFlowProvider> <Canvas edges={gridEdges} nodes={gridNodes}> <Controls /> </Canvas> </ReactFlowProvider> </div> );}Anatomy
Controls zoom · fit-view · interactivity cluster — leaf (inside Canvas)Installation
bash npx gremorie@latest add rx-controls bash pnpm dlx gremorie@latest add rx-controls bash yarn dlx gremorie@latest add rx-controls bash bunx --bun gremorie@latest add rx-controls Requires @xyflow/react.
Usage
import { Canvas, Controls } from "@gremorie/rx-ai";
export function Workflow() {
return (
<Canvas nodes={nodes} edges={edges}>
<Controls />
</Canvas>
);
}The Angular edition of this component is planned; the React edition is production-ready today.
API
<Controls>
Forwards all ControlProps from @xyflow/react. The Gremorie wrapper only restyles - it never overrides behavior props.
| Prop | Type | Default | Description |
|---|---|---|---|
position | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "bottom-left" | Corner the controls dock to. xyflow default. |
showZoom | boolean | true | Show the zoom in / out buttons. |
showFitView | boolean | true | Show the fit-view button. |
showInteractive | boolean | true | Show the lock toggle. Set to false for read-only canvases. |
fitViewOptions | FitViewOptions | - | Forwarded to the fit-view action (padding, duration, etc.). |
onZoomIn / onZoomOut / onFitView / onInteractiveChange | callbacks | - | Hooks into each control. |
children | ReactNode | - | Extra control buttons appended to the strip. Each child should follow xyflow's ControlButton API. |
className | string | - | Extra classes. |
Default chrome added by Gremorie: gap-px overflow-hidden rounded-md border bg-card p-1 shadow-none!. Child buttons are restyled to rounded-md, transparent background, hover state bg-secondary.
Composition
<Canvas>is the parent.Controlsmust be rendered as a child so xyflow's internalPanelmachinery can position it relative to the viewport.- Built-in buttons (zoom in, zoom out, fit view, lock) render automatically based on the
showZoom/showFitView/showInteractiveprops. - Custom buttons can be appended via
children. UseControlButtonfrom@xyflow/reactto keep the styling consistent.
Variations
Default
Bottom-left, all four buttons.
<Canvas nodes={nodes} edges={edges}>
<Controls />
</Canvas>Read-only canvas
Hide the lock toggle when the canvas is non-interactive anyway.
<Canvas nodes={nodes} edges={edges} nodesDraggable={false}>
<Controls showInteractive={false} />
</Canvas>Custom control button
Append a "reset" or "auto-layout" button using xyflow's ControlButton.
import { ControlButton } from '@xyflow/react';
import { LayoutGridIcon } from 'lucide-react';
<Canvas nodes={nodes} edges={edges}>
<Controls>
<ControlButton onClick={autoLayout} title="Auto-layout">
<LayoutGridIcon className="size-4" />
</ControlButton>
</Controls>
</Canvas>;Docked top-right
For canvases where the bottom-left is reserved for something else (status bar, agent thinking widget), move the controls.
<Canvas nodes={nodes} edges={edges}>
<Controls position="top-right" />
</Canvas>Accessibility
- Keyboard: Each built-in control is a real button. Tab focuses each one in order; Enter or Space activates.
- Labels: xyflow ships
titleattributes on the built-in buttons ("zoom in","zoom out","fit view","toggle interactivity"). For custom buttons, supplytitle(and ideallyaria-label) so the icon-only chrome is announced. - Focus visible: The Gremorie hover style (
bg-secondary) does not interfere with xyflow's default focus ring. Do not stripoutline. - Reduced motion: Zoom and pan animations are governed by xyflow and honor
prefers-reduced-motion.