A lightweight drawing application built with React, TypeScript, and the HTML Canvas API. Canvas Kit uses a floating island UI architecture inspired by tldraw and Excalidraw, where the canvas fills the entire viewport and all controls float over it as frosted glass islands.
- Floating Island UI: All controls live in frosted glass islands that float over a full-viewport canvas. No header, no sidebar, no drawers.
- Frosted Glass Effect: Every island uses
backdrop-blur-xlwith translucent backgrounds for a clean, modern look in both light and dark themes - Fade-on-Idle: Non-essential islands (logo, actions) fade to 30% opacity after 3 seconds of mouse inactivity, keeping the canvas uncluttered
- Micro-Animations: Hover lift on islands, glow and scale bounce on the active tool, smooth slide-up on panel popovers
- Keyboard Shortcut Hints: All tooltips display shortcuts with styled
<kbd>badges - Drawing Tools: Brush, eraser, rectangle, circle, and line tools
- Fill/Stroke Mode: Toggle between outline stroke and solid fill for rectangle and circle shapes
- Custom Cursor: Dynamic circle outline cursor for brush and eraser that matches the current tool size
- Layer Management: Add, remove, reorder, and toggle visibility of multiple layers with per-layer opacity control and live thumbnails
- Dark Mode: Toggle between light and dark themes, with system preference detection and localStorage persistence
- Canvas Zoom and Pan: Mouse wheel zoom toward cursor, Space+drag panning, and keyboard shortcuts for zoom control
- Keyboard Shortcuts: Single-key tool switching, modifier-key undo/redo, and zoom controls
- Color Palette: Preset colors plus a custom HSV color picker
- Tool Settings: Adjustable size (1-50px) and opacity sliders per tool
- Background Customization: Change the canvas background color
- Undo/Redo: Deep-copy canvas snapshots for reliable history traversal
- Clear Canvas: Wipe the active canvas in one click
- Export as PNG: Save your artwork as a PNG image
- Vite 6 - Build tool and dev server
- React 19 - UI library
- TypeScript 5.8 - Type-safe JavaScript
- Tailwind CSS 4 - Utility-first CSS framework
- Radix UI - Accessible UI primitives
- shadcn/ui - Component library built on Radix
- lucide-react - Icon library
- class-variance-authority - Variant-driven component styles
- Clone the repository:
git clone https://github.com/your-username/canvas-kit.git
cd canvas-kit- Install dependencies:
# Using Bun (recommended)
bun install
# OR using npm
npm install- Start the development server:
# Using Bun (recommended)
bun dev
# OR using npm
npm run dev- Open http://localhost:5173 in your browser.
canvas-kit/
├── public/ # Static assets
├── src/
│ ├── canvas/ # Canvas drawing engine
│ │ ├── hooks/ # Drawing, setup, and temp canvas hooks
│ │ ├── canvas.tsx # Main canvas component
│ │ └── operations.ts # Pure canvas utilities
│ ├── components/ # React components
│ │ ├── islands/ # Corner islands (logo, actions, history, zoom)
│ │ ├── panels/ # Panel popovers (color, settings, layers)
│ │ ├── ui/ # shadcn/ui primitives + island + popover
│ │ ├── floating-toolbar.tsx # Bottom-center toolbar dock
│ │ └── floating-ui.tsx # Overlay wrapper for all islands
│ ├── constants/ # Tool and color definitions
│ │ ├── tools.ts # Drawing tool config
│ │ └── colors.ts # Color palette config
│ ├── contexts/ # React context providers
│ │ ├── canvas-history-context.tsx
│ │ ├── colors-context.tsx
│ │ ├── layers-context.tsx
│ │ ├── theme-context.tsx
│ │ ├── tool-settings-context.tsx
│ │ └── viewport-context.tsx
│ ├── hooks/ # Reusable domain hooks
│ │ ├── use-canvas-history.ts
│ │ ├── use-idle.ts # Mouse inactivity tracking
│ │ ├── use-keyboard-shortcuts.ts
│ │ ├── use-layers.ts
│ │ ├── use-theme.ts
│ │ ├── use-tool-settings.ts
│ │ └── use-viewport.ts
│ ├── lib/ # Pure utilities (color conversion, export)
│ ├── styles/ # Global CSS
│ ├── app.tsx # Root application component
│ ├── main.tsx # Entry point
│ └── types.ts # Type definitions
├── index.html
├── vite.config.ts
├── package.json
└── tsconfig.json
The interface follows a floating island pattern. The canvas occupies the entire viewport, and all controls float above it as independent, frosted glass containers.
┌─────────────────────────────────────────────────┐
│ Canvas Kit [T] [S] │
│ (faded logo) (faded actions) │
│ │
│ 100% CANVAS │
│ (entire viewport) │
│ │
│ [U R X] [- 100% +] │
│ (history) (zoom) │
│ ╭───────────────────────────╮ │
│ │ B E R C L | P G Y │ │
│ ╰───────────────────────────╯ │
│ (floating toolbar dock) │
└─────────────────────────────────────────────────┘
Five islands, each positioned at a fixed spot over the canvas:
- Top-left: Logo island (branding, fades on idle)
- Top-right: Actions island (theme toggle + save, fades on idle)
- Bottom-left: History island (undo, redo, clear)
- Bottom-right: Zoom island (zoom in, zoom level, zoom out)
- Bottom-center: Toolbar dock (drawing tools + panel popover triggers)
The toolbar dock splits into two sections separated by a vertical divider. Drawing tools sit on the left as a toggle group. Panel triggers (color palette, tool settings, layers) sit on the right and open upward as Radix popovers.
- Brush: Freehand drawing with adjustable size and opacity
- Eraser: Remove parts of your drawing with adjustable size
- Rectangle: Draw rectangles with adjustable stroke width and opacity
- Circle: Draw circles with adjustable stroke width and opacity
- Line: Draw straight lines with adjustable stroke width and opacity
All shape tools (rectangle, circle) support a fill/stroke toggle. Stroke mode draws an outline only. Fill mode draws a solid shape. The line tool always uses stroke.
Brush and eraser display a dynamic circle outline cursor that scales with the current tool size, giving you a live preview of the stroke area.
Tools live in the floating toolbar dock at the bottom center of the viewport. The active tool gets a glow shadow and a subtle scale bounce.
- Predefined color palette with a range of common colors
- Custom HSV color picker for precise color selection
- Opens as a popover from the toolbar dock
- Adjustable size (1-50px) and opacity sliders per tool
- Opens as a popover from the toolbar dock
- Create multiple layers for complex artwork
- Toggle layer visibility on and off
- Select an active layer for editing
- Adjust per-layer opacity (0-100%)
- Reorder layers up and down
- Remove layers you no longer need
- Live thumbnail previews for each layer
- Background layer (layer 1) with customizable color, which cannot be deleted, reordered, or have its opacity changed
- Opens as a popover from the toolbar dock
- Mouse wheel zoom toward the cursor position (0.1x to 5x range, 1.2x step factor)
- Space+drag to pan across the canvas
- Zoom controls in the bottom-right floating island
- Keyboard shortcuts for zoom in, zoom out, and reset (see below)
- Toggle between light and dark themes from the top-right actions island
- Detects system preference (
prefers-color-scheme) on first visit - Persists your choice to localStorage
- Uses class-based toggling on the
<html>element
- Undo and redo support with deep-copy canvas snapshots
- Clear the entire canvas to start fresh
- Controls in the bottom-left floating island
- Export your finished artwork as a PNG file
- Save button in the top-right actions island
| Shortcut | Action |
|---|---|
| B | Brush tool |
| E | Eraser tool |
| R | Rectangle tool |
| C | Circle tool |
| L | Line tool |
| Ctrl+Z | Undo |
| Ctrl+Shift+Z | Redo |
| Ctrl+Y | Redo (alternate) |
| Ctrl+= / Ctrl++ | Zoom in |
| Ctrl+- | Zoom out |
| Ctrl+0 | Reset zoom to 100% |
| Space+Drag | Pan the canvas |
Shortcuts are automatically suppressed when focus is inside a text input or textarea, so they won't interfere with typing (for example, the hex color field).
Contributions are welcome. Feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request