Fluxo UIFluxo UIv0.1.1

Canvas Draw

A versatile drawing and annotation component for images, videos, and plain canvases. Supports 9 tools, timed annotations, groups, transitions, image export, and full theme support.

Image Annotation

Use an image as the background. Draw arrows, rectangles, text, step numbers, and more to annotate screenshots, photos, or diagrams.

Annotate an Image

Color
Stroke
Timing
Show at
Hide at
Transition
Sample Annotation
1
Image Annotation
import { CanvasDraw } from 'fluxo-ui';
import type { DrawItem } from 'fluxo-ui';

const [items, setItems] = useState<DrawItem[]>([]);

<CanvasDraw
  background={{ type: 'image', src: '/screenshot.png' }}
  items={items}
  onItemsChange={setItems}
  style={{ height: 400 }}
/>

Drawing Canvas

Use a solid color background for freeform drawing, wireframing, or whiteboard-style workflows.

Blank Canvas Drawing

Color
Stroke
Timing
Show at
Hide at
Transition
<CanvasDraw
  background={{ type: 'color', color: '#f8f9fa' }}
  items={items}
  onItemsChange={setItems}
  defaultTool="freehand"
  style={{ height: 350 }}
/>

Toolbar Placement

Place the toolbar at any edge of the canvas. Use toolbarPlacement="none" to hide it entirely.

Bottom Toolbar

Color
Stroke
Timing
Show at
Hide at
Transition

Left Toolbar

Color
Stroke
Timing
Show at
Hide at
Transition
// Toolbar on the bottom
<CanvasDraw
  background={{ type: 'color', color: '#eef2ff' }}
  toolbarPlacement="bottom"
/>

// Vertical toolbar on the left
<CanvasDraw
  background={{ type: 'color', color: '#fef3c7' }}
  toolbarPlacement="left"
/>

// Available: 'top' | 'bottom' | 'left' | 'right' | 'none'

Feature Flags

Use the features prop to enable or disable specific toolbar sections. By default, all features are enabled.

Minimal Toolbar — Drawing Only

Color
Stroke
<CanvasDraw
  background={{ type: 'color', color: '#f0fdf4' }}
  features={{
    timing: false,
    transitions: false,
    groups: false,
    export: false,
    fontControls: false,
    roundedCorners: false,
  }}
/>

Tool Subset

Use features.tools to show only specific drawing tools. Disabled tools are hidden from the toolbar.

Arrows & Rectangles Only

Color
Stroke
<CanvasDraw
  background={{ type: 'color', color: '#faf5ff' }}
  features={{
    tools: {
      select: true,
      arrow: true,
      rect: true,
      freehand: false,
      line: false,
      circle: false,
      text: false,
      balloon: false,
      step: false,
    },
    timing: false,
    transitions: false,
    groups: false,
  }}
/>

Timed Annotations

Each item has showAtMs, hideAtMs, and transition properties. When used with video or media, items appear and disappear at the correct timestamps with animated transitions (fade, scale, slide-*).

Timed Items — Enable Timing in Features

Color
Stroke
Timing
Show at
Hide at
Transition
Appears at 4s
const items: DrawItem[] = [
  {
    id: 'item-1',
    object: { type: 'rect', /* ... */ },
    showAtMs: 0,
    hideAtMs: 3000,
    transition: 'fade',
    groupId: null,
    xPct: 0.1, yPct: 0.15, wPct: 0.3, hPct: 0.3,
  },
  {
    id: 'item-2',
    object: { type: 'arrow', /* ... */ },
    showAtMs: 2000,
    hideAtMs: 5000,
    transition: 'scale',
    groupId: null,
    xPct: 0.5, yPct: 0.2, wPct: 0.3, hPct: 0.3,
  },
];

<CanvasDraw
  background={{ type: 'color', color: '#1a1a2e' }}
  items={items}
  currentMs={currentMs}
  mediaDurationMs={8000}
  features={{ timing: true, transitions: true, groups: true }}
/>

Media Timeline

The MediaTimeline companion component provides a video-editor-style timeline view. Items appear as draggable/resizable bars. Groups are shown with colored lanes.

Interactive Timeline

Timeline100%
0:00
0:01
0:02
0:03
0:04
0:05
0:06
0:07
0:08
0:09
0:10
import { MediaTimeline } from 'fluxo-ui';
import type { TimelineItem, TimelineGroup } from 'fluxo-ui';

const [items, setItems] = useState<TimelineItem[]>([
  { id: '1', label: 'Intro', showAtMs: 0, hideAtMs: 3000,
    groupId: null, transition: 'fade' },
]);
const [groups, setGroups] = useState<TimelineGroup[]>([]);
const [selected, setSelected] = useState<string | null>(null);
const [currentMs, setCurrentMs] = useState(0);

<MediaTimeline
  items={items}
  groups={groups}
  durationMs={10000}
  currentMs={currentMs}
  selectedItemId={selected}
  onSelectItem={setSelected}
  onUpdateItem={(id, patch) =>
    setItems(prev => prev.map(it => it.id === id ? { ...it, ...patch } : it))
  }
  onUpdateGroup={(id, patch) =>
    setGroups(prev => prev.map(g => g.id === id ? { ...g, ...patch } : g))
  }
  onAddGroup={() => setGroups(prev => [...prev, { id: `g-${Date.now()}`, label: 'New Group', showAtMs: 0, hideAtMs: null, transition: 'none' }])}
  onDeleteGroup={(id) => setGroups(prev => prev.filter(g => g.id !== id))}
  onSeek={setCurrentMs}
/>

Controlled Mode

Pass items and onItemsChange to fully control the drawing state externally. Without items, the component manages its own internal state.

Controlled — Item Count Tracked Externally

Color
Stroke
Timing
Show at
Hide at
Transition
Items drawn: 0
const [items, setItems] = useState<DrawItem[]>([]);

<CanvasDraw
  background={{ type: 'color', color: '#fff7ed' }}
  items={items}
  onItemsChange={setItems}
/>

// Uncontrolled — just omit items prop:
<CanvasDraw background={{ type: 'color', color: '#fff' }} />

Read-Only Mode

Set isEditing={false} to hide the toolbar and disable all interactions. Useful for playback/preview mode.

View-Only with Pre-drawn Items

Sample Annotation
1
<CanvasDraw
  background={{ type: 'image', src: '/screenshot.png' }}
  items={savedItems}
  isEditing={false}
/>

Export

Pass onExport to enable export buttons. SVG export works out of the box. PNG/JPG/WebP require the optional html2canvas package — if not installed, export gracefully logs a message and the component continues to work.

Export Drawing

Color
Stroke
Timing
Show at
Hide at
Transition
const handleExport = (dataUrl: string, format: ImageExportFormat) => {
  // dataUrl contains the image data
  // SVG export works without extra dependencies
  // PNG/JPG/WebP requires: npm install html2canvas
  console.log(`Exported ${format}:`, dataUrl.length, 'chars');
};

<CanvasDraw
  background={{ type: 'color', color: '#f0f9ff' }}
  onExport={handleExport}
  features={{ export: true }}
/>

Import

import { CanvasDraw, CanvasDrawOverlay, CanvasDrawToolbar, MediaTimeline } from 'fluxo-ui';

// Type imports
import type {
  CanvasDrawProps,
  CanvasDrawOverlayHandle,
  CanvasDrawToolbarProps,
  MediaTimelineProps,
  TimelineItem,
  TimelineGroup,
  DrawItem,
  DrawGroup,
  DrawTool,
  DrawColor,
  DrawObject,
  DrawToolDefaults,
  DrawTransition,
  CanvasBackground,
  CanvasDrawFeatures,
  ToolConfig,
  ImageExportFormat,
} from 'fluxo-ui';

// Utilities
import { colorMap, defaultToolDefaults, contrastColor, autoFontColor } from 'fluxo-ui';

CanvasDraw Props

backgroundreq
CanvasBackground

Background configuration — image, color, or video reference

items
DrawItem[]

Controlled items array. When provided, component is controlled

groups
DrawGroup[]

Controlled groups array for annotation grouping

currentMs
number"0"

Current playback position in milliseconds (for timed annotations)

mediaDurationMs
number"0"

Total media duration in milliseconds

isEditing
boolean"true"

Whether the canvas is in edit mode (shows toolbar, allows drawing)

toolbarPlacement
'top' | 'bottom' | 'left' | 'right' | 'none'"'top'"

Position of the drawing toolbar relative to the canvas

defaultTool
DrawTool"'select'"

Initially active tool when the component mounts

defaultToolDefaults
Partial<DrawToolDefaults>

Override default stroke color, fill, font settings, etc.

features
CanvasDrawFeatures"{}"

Feature flags to enable/disable toolbar sections and tools

className
string

Additional CSS class for the root element

style
React.CSSProperties

Inline styles for the root element

onItemsChange
(items: DrawItem[]) => void

Fires whenever items are added, modified, or removed

onExport
(dataUrl: string, format: ImageExportFormat) => void

Called when user exports. Enables export buttons when provided

DrawItem Properties

idreq
string

Unique identifier for the item

objectreq
DrawObject

The drawing object (arrow, rect, circle, text, etc.)

showAtMsreq
number

Time in ms when this item should appear

hideAtMsreq
number | null

Time in ms when this item should hide (null = never)

transitionreq
DrawTransition

Animation transition for show/hide (none, fade, scale, slide-*)

groupIdreq
string | null

Optional group membership for batch timing

xPctreq
number

Horizontal position as fraction (0-1) of canvas width

yPctreq
number

Vertical position as fraction (0-1) of canvas height

wPctreq
number | null

Width as fraction (0-1). Null for point-based items (steps)

hPctreq
number | null

Height as fraction (0-1). Null for point-based items (steps)

CanvasDrawFeatures

tools
ToolConfig

Enable/disable individual tools (select, arrow, rect, circle, etc.)

timing
boolean

Show timing controls (showAt / hideAt) in toolbar

groups
boolean

Show group management in toolbar

transitions
boolean

Show transition selector in toolbar

undo
boolean

Show undo/redo buttons

export
boolean

Show export buttons (also requires onExport prop)

clearAll
boolean

Show clear all button

strokeColor
boolean

Show stroke color picker

strokeWidth
boolean

Show stroke width control

fillColor
boolean

Show fill color picker

fontControls
boolean

Show font family, size, color, bold/italic/underline

roundedCorners
boolean

Show rounded corners toggle for rectangles

MediaTimeline Props

itemsreq
TimelineItem[]

Timeline items to display as bars

groupsreq
TimelineGroup[]

Timeline groups for organizing items

durationMsreq
number

Total duration of the media in milliseconds

currentMsreq
number

Current playback position in milliseconds

selectedItemIdreq
string | null

Currently selected item ID

tickCount
number"10"

Number of time ticks to display

defaultItemColor
string

Default color for items without a group color

onSelectItemreq
(id: string | null) => void

Called when an item is selected or deselected

onUpdateItemreq
(id: string, patch: Partial<TimelineItem>) => void

Called when an item is dragged/resized on the timeline

onUpdateGroupreq
(id: string, patch: Partial<TimelineGroup>) => void

Called when a group is modified

onAddGroupreq
() => void

Called when the add group button is clicked

onDeleteGroupreq
(id: string) => void

Called when a group is deleted

onSeekreq
(ms: number) => void

Called when the user clicks on the timeline to seek

Features

Drawing Tools

9 built-in tools: select, arrow, line, rectangle, circle, freehand, text, balloon, step numbers

Multi-Background

Support for image, video, and solid color backgrounds

Percentage Coords

Resolution-independent positioning using 0-1 fractions

Undo / Redo

Full undo/redo stack with snapshot-on-first-change batching

Timed Annotations

Show/hide items at specific timestamps with animated transitions

Groups

Group items for batch timing and transition control

Image Export

Export as PNG, JPG, WebP, or SVG. Raster export via optional html2canvas

Toolbar Placement

4 placement options: top, bottom, left, right — plus hidden mode

Feature Flags

Granular control over which tools and toolbar sections are visible

Controlled & Uncontrolled

Works with or without external state — pass items for controlled mode

Theming

Full dark/light mode support via CSS custom properties

Media Timeline

Companion timeline component for video editing workflows