← Back to Yappy
Yappy Documentation

Basic Shapes

The fundamental building blocks for any diagram. These shapes form the foundation for flowcharts, wireframes, architecture diagrams, and general-purpose illustrations.

Quick Reference

ShapeShortcutCommon Uses
RectangleR or 2Process steps, containers, buttons, cards
CircleO or 3Start/end points, nodes, avatars, bullets
DiamondDDecision points, conditions, data flow
TriangleToolbarWarnings, hierarchy, directional indicators

Rectangle

The most versatile shape in any diagramming tool. Use rectangles as containers, process steps, UI components, or any bounded element.

Properties

PropertyDescription
RoundnessRound all four corners at once (0 = sharp, higher = more rounded)
Corner ↖ ↗ ↘ ↙Round each corner independently — one corner at 40 and the rest sharp, or any mix. See below.
Fill StyleSolid, hachure, cross-hatch, or none
Stroke StyleSolid, dashed, or dotted border
RoughnessHand-drawn appearance (0 = clean, higher = sketchy). Starts at 0 — turn it up once you have picked the Sketch drawing style

Independent corners

Below Roundness sit four per-corner sliders — Corner ↖, ↗, ↘, ↙ — for the shapes packaging, UI cards and logo work actually need: one rounded corner and three sharp, a rounded diagonal pair, a tab with only its top edge softened.

  • A corner you never touch follows Roundness, so setting one corner does not square the other three. Set a corner to 0 to make it explicitly sharp while the rest stay round.
  • Values are a percent of the shorter side, the same unit Roundness uses — so the corners keep their proportions when you resize the rectangle, and 50 is a half-round end.
  • Each corner is capped at half the shorter side, which is the point where the arcs would start crossing each other.

It is the real outline, not a decoration: the fill, gradient and image clipping follow it, both Sketch and Architectural styles draw it, SVG export writes one arc per rounded corner, and Convert to Path / Knife / Warp keep the corners you set.

Yappy.createRectangle(40, 40, 240, 140, { radiusTL: 40 });               // one rounded corner
Yappy.createRectangle(40, 40, 240, 140, { radiusTL: 40, radiusBR: 40 }); // rounded diagonal
Yappy.createRectangle(40, 40, 240, 140, { borderRadius: 25, radiusTR: 0 });  // all but one
Tip: Quick Squares

Hold Shift while drawing to constrain to a perfect square.

Circle / Ellipse

Draw circles for nodes, avatars, and state indicators. By default, circles maintain their aspect ratio, but you can create ellipses by adjusting width and height independently.

Properties

PropertyDescription
Fill StyleSolid, hachure, cross-hatch, or none
Stroke WidthBorder thickness
OpacityTransparency level (0-100%)
Tip: Perfect Circles

Hold Shift while drawing to maintain a 1:1 aspect ratio.

Diamond

The classic decision shape in flowcharts. Diamonds typically represent yes/no questions or conditional branching points in process flows.

Common Uses

  • Flowcharts - Decision points with yes/no branches
  • Data Flow Diagrams - Data transformation nodes
  • State Machines - Conditional transitions
Best Practice

Label diamond shapes with questions that have clear yes/no answers. Connect "Yes" and "No" branches to different paths.

Triangle

Triangles serve multiple purposes: warning indicators, hierarchy visualization, directional markers, and decorative elements.

Variants

TypeDescription
Equilateral TriangleAll sides equal - balanced, symmetrical look
Right TriangleHas a 90° angle - useful for corners and technical diagrams

Common Styling Options

All basic shapes share these styling options:

Fill Styles

StyleDescription
SolidCompletely filled with background color
HachureDiagonal line pattern (hand-drawn feel)
Cross-HatchCrossed diagonal lines
NoneTransparent fill, outline only

Stroke Styles

StyleShortcut
SolidPress S to cycle
DashedPress S to cycle
DottedPress S to cycle

Text labels

Give a shape a label in whichever way suits your hands: double-click it, or select it and press Enter (F2 does the same). Either way the existing text comes up selected, so typing replaces it. A shape you have just drawn is already selected — so drag out a box, press Enter, and type, without touching the mouse again.

Enter means "add a sibling" on a mindmap node, which keeps the outline flow; use F2 there. And once the editor is open Enter is a line break again — commit with Esc or Ctrl + Enter.

Type while you drag. The fastest way of all: pick a shape tool, start dragging, and just type — the characters go straight into the label of the shape you are drawing, and you can see them land as you size it. Release, and the shape arrives already labelled. Drag, type A, release; drag, type B, release. No double-click, no Enter, no mode to leave. Handy for lettering a diagram live in a workshop.

Backspace deletes a character while you drag (it will not delete the shape), and Space is a space, so multi-word labels like Load Balancer work. Modifier keys are untouched — Shift still constrains the proportions while you type. The whole thing is one undo step: Ctrl + Z removes the shape and its label together.

Freehand strokes (Fineliner, Marker, Ink Brush), connectors and the text tools deliberately ignore typing while drawing — those drags last a long time, and a stray keystroke should not end up as a caption.

Note that typing a bare letter on a selected shape that you are not dragging does not start a label — single letters are tool shortcuts (R for rectangle, V for select), and they keep that job.

Text is centred by default — both horizontally and vertically — which is what you want for almost every diagram box. Change it per shape with the alignment buttons in the Properties panel or the smart toolbar, or set textAlign to 'left' / 'right' from the API. Code blocks and UML attribute/method sections stay left-aligned, and table cells keep their own per-cell alignment.

While you type, the editor sits exactly where the label is drawn — same position, same line breaks, same vertical alignment — so nothing shifts when you start or finish editing. Shapes that can't use their full width for text (a circle, a diamond, a banner) wrap inside their inscribed area, and the editor wraps there too. Press Esc or Ctrl + Enter to commit, Enter for a new line.

Keyboard Shortcuts

Shift + Drag
Constrain proportions
Alt + Drag
Draw from center
S
Cycle stroke style
F
Cycle fill style

Scripting (API)

Create basic shapes from the console or a script via the global window.Yappy (usable as Yappy). Each returns the new element's id. Positions are canvas coordinates: (x, y) is the top-left corner, then width, height.

// Dedicated helpers
Yappy.createRectangle(80, 80, 160, 90, { borderRadius: 12, backgroundColor: '#a5d8ff' });
Yappy.createCircle(300, 80, 100, 100, { fillStyle: 'hachure' });
Yappy.createDiamond(80, 240, 140, 100);
Yappy.createTriangle(300, 240, 120, 120, { strokeColor: '#e03131' });

// Generic form (type strings: 'rectangle' | 'circle' | 'diamond' | 'triangle')
const id = Yappy.createElement('rectangle', 0, 0, 200, 120, { roughness: 1.5 });

// Restyle afterwards
Yappy.updateElement(id, { backgroundColor: '#ffd43b', strokeWidth: 3 });
MethodType string
createRectangle(x, y, w, h, opts?)'rectangle'
createCircle(x, y, w, h, opts?)'circle'
createDiamond(x, y, w, h, opts?)'diamond'
createTriangle(x, y, w, h, opts?)'triangle'

Many shapes at once: one undo step

Every create* call is its own undo step, and undo remembers 50 steps. A script that draws a figure from a hundred shapes would need a hundred presses to undo, and would push everything before it out of history. Wrap the script in Yappy.batch and the whole thing is one step:

Yappy.batch(y => {
  for (let i = 0; i < 100; i++) y.createCircle(i * 14, 0, 12, 12, { backgroundColor: '#ffd43b' });
});
Yappy.undo();   // removes all 100 circles

Or pass a list of shapes, which does the same thing:

const ids = Yappy.createElements([
  { type: 'rectangle', x: 0, y: 0, width: 160, height: 90, options: { backgroundColor: '#a5d8ff' } },
  { type: 'circle', x: 200, y: 0, width: 90, height: 90 },
]);
MethodWhat it does
batch(fn)Runs fn(Yappy) as one undo step and returns what fn returns. Batches nest; if fn throws, undo removes whatever it had made.
createElements(specs)Creates each { type, x, y, width, height, options? } in one undo step and returns the ids in order.

batch groups synchronous calls only. In an async function, calls made after the first await each become their own undo step again, and the console says so.

Common opts: backgroundColor, strokeColor, strokeWidth, fillStyle ('solid' | 'hachure' | 'cross-hatch'), strokeStyle ('solid' | 'dashed' | 'dotted'), roughness, opacity, borderRadius.