Shapes and Stacks
Circles and rectangles arranged with stackH and stackV - stacks nest to build up larger layouts
import { Graphic } from "@modular-svg/react";
export function ShapesAndStacks() {
return (
<Graphic
style={{
border: "1px solid #ddd",
borderRadius: "8px",
display: "inline-block",
}}
margin={15}
>
<stackV spacing={20}>
<stackH spacing={15}>
<circle r={15} fill="crimson" />
<circle r={15} fill="gold" />
<circle r={15} fill="limegreen" />
</stackH>
<stackH spacing={15}>
<rect width={30} height={30} fill="dodgerblue" />
<rect width={30} height={30} fill="mediumpurple" />
</stackH>
</stackV>
</Graphic>
);
}
React Components
Using React components to create reusable shapes
import { Graphic } from "@modular-svg/react";
function ColoredCircle({ color }: { color: string }) {
return <circle r={18} fill={color} />;
}
export function ReactComponents() {
return (
<Graphic
style={{
border: "1px solid #ddd",
borderRadius: "8px",
display: "inline-block",
}}
margin={10}
>
<stackH spacing={12}>
<ColoredCircle color="red" />
<ColoredCircle color="green" />
<ColoredCircle color="blue" />
</stackH>
</Graphic>
);
}
Custom Styling
Graphic accepts standard div props like className and style
import { Graphic } from "@modular-svg/react";
export function CustomStyling() {
return (
<Graphic
className="custom-canvas"
style={{
border: "3px solid #333",
borderRadius: "12px",
display: "inline-block",
backgroundColor: "#fafafa",
padding: "10px",
boxShadow: "0 4px 6px rgba(0,0,0,0.1)",
}}
margin={15}
>
<stackV spacing={15}>
<circle r={20} fill="indigo" />
<rect width={60} height={40} fill="tomato" />
</stackV>
</Graphic>
);
}
Distinct Colors
DistinctColors spreads the children's hues evenly around the wheel, so a set of shapes picks distinct colors automatically - none are chosen in the markup
import { Graphic } from "@modular-svg/react";
import { useState } from "react";
// A row of circles with no fill. DistinctColors spreads their hues evenly
// around the wheel, so each gets a different color automatically - no color
// is chosen in the markup.
export function DistinctColorsExample() {
const [count, setCount] = useState(5);
const [startHue, setStartHue] = useState(30);
const ids = Array.from({ length: count }, (_, i) => `c${i}`);
return (
<div>
<div style={{ marginBottom: "1rem" }}>
<label style={{ display: "block", marginBottom: "0.5rem" }}>
Circles: {count}
<input
type="range"
min="2"
max="8"
value={count}
onChange={(e) => setCount(Number(e.target.value))}
style={{ marginLeft: "1rem", width: "180px" }}
/>
</label>
<label style={{ display: "block", marginBottom: "0.5rem" }}>
Start hue: {startHue}°
<input
type="range"
min="0"
max="360"
value={startHue}
onChange={(e) => setStartHue(Number(e.target.value))}
style={{ marginLeft: "1rem", width: "180px" }}
/>
</label>
</div>
<Graphic
style={{
border: "1px solid #ddd",
borderRadius: "8px",
display: "inline-block",
}}
margin={12}
>
<group>
<stackH spacing={12} alignment="centerY">
{ids.map((id) => (
<circle key={id} r={22} stroke="#333" stroke-width={1} />
))}
</stackH>
<distinctColors startHue={startHue} saturation={0.6} lightness={0.55}>
{ids.map((id) => (
<ref key={id} target={id} />
))}
</distinctColors>
</group>
</Graphic>
</div>
);
}
Same Color
SameColor copies one source color onto every follower - the color analogue of a span. Change the source and they all follow
import { Graphic } from "@modular-svg/react";
import { useState } from "react";
// One source swatch defines the color; SameColor copies it onto every
// follower shape, whatever their kind. Change the source and they all follow.
export function SameColorExample() {
const [color, setColor] = useState("#2A9D8F");
return (
<div>
<label style={{ display: "block", marginBottom: "1rem" }}>
Source color
<input
type="color"
value={color}
onChange={(e) => setColor(e.target.value)}
style={{ marginLeft: "1rem", verticalAlign: "middle" }}
/>
</label>
<Graphic
style={{
border: "1px solid #ddd",
borderRadius: "8px",
display: "inline-block",
}}
margin={12}
>
<group>
<stackH spacing={16} alignment="centerY">
<rect key="source" width={44} height={44} fill={color} />
<circle key="f1" r={20} stroke="#333" stroke-width={1} />
<rect
key="f2"
width={40}
height={40}
stroke="#333"
stroke-width={1}
/>
<circle key="f3" r={14} stroke="#333" stroke-width={1} />
</stackH>
<sameColor>
<ref target="source" />
<ref target="f1" />
<ref target="f2" />
<ref target="f3" />
</sameColor>
</group>
</Graphic>
</div>
);
}
Readable Contrast
Contrast adjusts a label's lightness to meet a WCAG ratio against its background, so text stays legible over any color
import { Graphic } from "@modular-svg/react";
import { useState } from "react";
// The label has no readable color of its own - Contrast adjusts its
// lightness to meet a WCAG ratio against the background. Drag the background
// from light to dark and the text flips to stay legible.
export function ContrastExample() {
const [bg, setBg] = useState("#f4e04d");
return (
<div>
<label style={{ display: "block", marginBottom: "1rem" }}>
Background
<input
type="color"
value={bg}
onChange={(e) => setBg(e.target.value)}
style={{ marginLeft: "1rem", verticalAlign: "middle" }}
/>
</label>
<Graphic
style={{
border: "1px solid #ddd",
borderRadius: "8px",
display: "inline-block",
}}
margin={12}
>
<group>
<background key="box" padding={18} fill={bg} stroke-width={0} rx={8}>
<text key="label" font-size={18}>
Always readable
</text>
</background>
<contrast ratio={4.5}>
<ref target="label" />
<ref target="box" />
</contrast>
</group>
</Graphic>
</div>
);
}