Diagrams
Data-driven SVG diagram components that use organic, hand-drawn shapes from our shape library. They integrate with our tooltip system, support scroll-triggered animations, and work reliably across all browsers including mobile Safari.
OverlappingCircles
A Venn diagram component that renders 2 or 3 overlapping circles with blend modes for the overlap effect. Uses organic hand-drawn shapes rather than perfect geometric circles.
Two circles
Three circles with annotation
With scroll animation
Scroll down to see the circles animate into position.
Props reference
Shape configuration
Each shape (left, right, centre)
accepts:
| Prop | Type | Description |
|---|---|---|
label | string | Text displayed in the centre of the shape |
fillColor | string | CSS colour value, typically a design token like var(--fire) |
textColor | string | Label text colour (default: var(--gloaming-dark)) |
tooltip | string | Key for tooltip content (requires <Tooltips> component) |
link | string | Optional URL to make the shape clickable |
shape | ShapeType | Shape from the library (circle, circle2, circle3, rectangle, triangle, pentagon, etc.). Default: 'circle' |
texture | string | Texture image path for this shape (e.g., '/images/ink2.jpg'). Overrides component-level texture. |
textureOpacity | number | Texture opacity 0–1 for this shape. Overrides component-level textureOpacity. |
Component props
| Prop | Type | Default | Description |
|---|---|---|---|
left | OverlapCircle | required | Left shape configuration |
right | OverlapCircle | required | Right shape configuration |
centre | OverlapCircle | – | Optional third shape (creates 3-shape Venn) |
overlapAnnotation | string | – | Hand-written annotation pointing to the overlap |
radius | number | 220 | Shape radius in SVG units |
overlap | number | 0.4 | Overlap amount as fraction of radius (0–1) |
blendMode | string | 'overlay' | CSS blend mode for overlapping areas |
texture | string | – | Default texture for all shapes (can be overridden per shape) |
textureOpacity | number | 0.08 | Default texture opacity (can be overridden per shape) |
animateOnScroll | boolean | false | Enable scroll-triggered animation |
ariaLabel | string | 'Venn diagram...' | Accessible description for screen readers |
Usage
<OverlappingCircles
left={{
label: "Content",
fillColor: "var(--sunshine)",
textColor: "var(--limestone)",
tooltip: "content",
}}
right={{
label: "Digital",
fillColor: "var(--fire)",
textColor: "var(--limestone)",
tooltip: "digital",
shape: "circle2", // Different shape variant
}}
centre={{
label: "Design",
fillColor: "var(--wave)",
textColor: "var(--limestone)",
tooltip: "design",
shape: "circle3", // Different shape variant
}}
overlapAnnotation="We live here"
overlap={0.25}
blendMode="overlay"
texture="/images/ink2.jpg"
textureOpacity={0.04}
animateOnScroll={true}
ariaLabel="Content, design and digital. We live at the centre."
/>
<Tooltips
tooltips={{
content: "The words, the pictures, the numbers...",
design: "How things work and how they're structured.",
digital: "Using the full potential of modern technology.",
}}
/> FlowDiagram
A directional flow diagram that renders labelled circle nodes connected by organic arrow shapes. Arrows are auto-positioned at the midpoint between nodes and rotated to point from source to target. Ideal for pipelines, deployment flows, and process diagrams.
Basic flow
Branching flow with multi-line labels
Props reference
Node configuration
| Prop | Type | Description |
|---|---|---|
id | string | Unique identifier (referenced by connectors) |
label | string | Display text – use \n for line breaks |
position | { x, y } | Centre position in SVG units |
radius | number | Node radius in SVG units |
color | string | Fill colour – any CSS value (e.g. var(--wave)) |
textColor | string | Label colour (default: var(--gloaming-dark)) |
tooltip | string | Key for tooltip content (requires <Tooltips>) |
shape | ShapeType | Node shape from the library (default: circle2) |
texture | string | Overlay texture name (e.g. 'ink', 'wall') or raw path |
textureOpacity | number | Texture opacity 0–1 (default: 0.08) |
Connector configuration
| Prop | Type | Description |
|---|---|---|
from | string | Source node ID |
to | string | Target node ID |
color | string | Arrow colour (default: var(--sunshine)) |
Component props
| Prop | Type | Default | Description |
|---|---|---|---|
nodes | FlowNode[] | required | Array of flow nodes |
connectors | FlowConnector[] | required | Array of directional connectors |
viewBox | string | auto | SVG viewBox – calculated from nodes if omitted |
arrowSize | number | 60 | Rendered arrow size in SVG units |
animateOnScroll | boolean | false | Enable scroll-triggered animation |
ariaLabel | string | 'Flow diagram' | Accessible description for screen readers |
Usage
<FlowDiagram
nodes={[
{ id: "content", label: "Content", position: { x: 150, y: 150 }, radius: 100, color: "var(--sunshine)", tooltip: "content" },
{ id: "astro", label: "Astro", position: { x: 450, y: 150 }, radius: 100, color: "var(--wave)", tooltip: "astro" },
{ id: "netlify", label: "Netlify", position: { x: 750, y: 150 }, radius: 100, color: "var(--sapling)", tooltip: "netlify" },
]}
connectors={[
{ from: "content", to: "astro" },
{ from: "astro", to: "netlify" },
]}
ariaLabel="Content flows to Astro, then to Netlify"
/>
<!-- Add tooltips alongside the diagram -->
<Tooltips tooltips={{
content: "Raw content – text, images, structured data.",
astro: "The presentation engine.",
netlify: "Builds and hosts the finished site.",
}} /> Technical notes
Blend modes and mobile Safari
The component uses mix-blend-mode for the overlap effect. On mobile
Safari, blend modes can break during CSS transitions due to GPU layer promotion/demotion.
The component uses translateZ(0) throughout animations to maintain
a consistent GPU compositing layer, preventing the blend mode from breaking
mid-animation.
Organic shapes
Rather than perfect geometric circles, the component uses hand-drawn
organic shapes from the shape library at src/assets/shapes/.
Multiple circle variants are available (circle, circle2, circle3), and
each shape can use a different variant via the shape prop. Each
circle is also rotated differently to avoid repetition, creating a more natural,
crafted appearance.
Tooltips
Tooltips are handled by the separate <Tooltips> component
using Tippy.js. Add tooltip keys to circles and include a <Tooltips>
component with matching content. The tooltips reinitialise correctly after View
Transitions.
Accessibility
The SVG has role="img" and aria-label for screen readers.
A visually-hidden <figcaption> provides additional context.
When circles have links, they're wrapped in <a> tags for
keyboard navigation.