Components · General
Illustration
One spot-art set, called by name — 20 multi-colour illustrations imported from Figma, rendered by the shared <aha-illustration>, never inline SVG.
Examples
Size
Illustration
Smart widget · one live
<aha-illustration> — the Size / Illustration controls below drive itMulti-colour spot art · each keeps its OWN palette (not currentColor) — call any by name
Plan tiers · a compact illustration heads each card
Size · one edge in px; the other edge follows the art's aspect ratio
Unknown name · a visible dashed error box (the
--aha-color-error token) — never a silent blank
Every illustration is called by
name from the shared registry — … pure-SVG illustrations imported from Figma, no inline SVG at the call site. Browse and copy any name in the Illustration library →. Multi-colour art keeps its own palette; size by a single edge and the aspect ratio is fixed by the source. Raster-backed art is intentionally excluded so the library stays pure-SVG.
<!-- Paste-and-run: save as .html and open in a browser. No build step.
Call any illustration BY NAME — never inline an <svg>. One import loads <aha-illustration> +
the multi-colour spot-art registry; art keeps its OWN palette, size is one edge (px), the
other edge follows the art's aspect ratio. -->
<script type="module">
import 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/illustrations.js'; // registers <aha-illustration> + registry
</script>
<!-- Empty state — a large spot illustration above the copy + a recovery action. -->
<div style="display:flex; flex-direction:column; align-items:center; gap:12px; text-align:center">
<aha-illustration name="empty-presentation-list" size="160" label="No presentations yet"></aha-illustration>
<p>No presentations yet — create your first one to get started.</p>
<button>Create presentation</button>
</div>
<!-- Plan-tier card — a compact illustration heads each tier. -->
<div style="display:flex; gap:24px">
<div><aha-illustration name="plan-essential" size="96" decorative></aha-illustration><div>Essential</div></div>
<div><aha-illustration name="plan-pro" size="96" decorative></aha-illustration><div>Pro</div></div>
<div><aha-illustration name="plan-enterprise" size="96" decorative></aha-illustration><div>Enterprise</div></div>
</div>
<!-- Onboarding choice — sized by a single edge; the aspect ratio is fixed by the source art. -->
<aha-illustration name="onboarding-business" size="56" label="Business"></aha-illustration>
import '@ahaslides-product/design/illustrations'; // registers <aha-illustration> + loads the spot-art registry (20 illustrations)
// Call any illustration BY NAME — never inline an <svg>. Browse names in the Illustration library,
// or read illustration.agent.json. Unlike <aha-icon>, an illustration is MULTI-COLOUR — it keeps
// its own palette, so there is no currentColor. Size is a single edge (px); aspect ratio is fixed.
// Empty state — a large illustration above the copy + a recovery action.
<div className="empty">
<aha-illustration name="empty-trash" size={160} label="Trash is empty" />
<p>Your trash is empty.</p>
</div>
// Plan-tier card — a compact illustration heads each tier (decorative when the label is adjacent text).
<div className="tiers">
<aha-illustration name="plan-essential" size={96} decorative />
<aha-illustration name="plan-pro" size={96} decorative />
<aha-illustration name="plan-enterprise" size={96} decorative />
</div>
// Onboarding / referral / error families are the same call, different name:
<aha-illustration name="onboarding-education" size={56} label="Education" />
<aha-illustration name="referral" size={128} label="Refer a friend" />
<aha-illustration name="error-ai-chatbot" size={120} label="The assistant hit an error" />
// main.ts — register the element + registry, and mark aha-* as custom elements
import '@ahaslides-product/design/illustrations'; // registers <aha-illustration> + loads the spot-art registry (20 illustrations)
app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('aha-');
// Component.vue — every surface renders spot art through the shared Illustration, BY NAME.
// Browse names in the Illustration library. An illustration is MULTI-COLOUR — it keeps its own
// palette (no currentColor). Size is a single edge (px); the aspect ratio is fixed by the source.
<template>
<!-- Empty state — a large illustration above the copy + a recovery action -->
<div class="empty">
<aha-illustration name="empty-templates" :size="160" label="No templates yet" />
<p>No templates yet.</p>
</div>
<!-- Plan-tier card — a compact illustration heads each tier (decorative beside a text label) -->
<div class="tiers">
<aha-illustration name="plan-essential" :size="96" decorative />
<aha-illustration name="plan-pro" :size="96" decorative />
<aha-illustration name="plan-enterprise" :size="96" decorative />
</div>
<!-- Onboarding / referral / error families are the same call, different name -->
<aha-illustration name="onboarding-others" :size="56" label="Something else" />
<aha-illustration name="referral" :size="128" label="Refer a friend" />
</template>
API
| Prop | Type | Default | Notes |
|---|---|---|---|
name | string | — | Registry illustration name, e.g. empty-team, onboarding-business, plan-pro |
size | number (px) | art intrinsic | Longer edge in px; the shorter edge scales to preserve aspect. Omit to use the art's own pixels |
label | string | — | Accessible name (role=img). Omit for a decorative illustration |
decorative | boolean | false | aria-hidden — for art that only repeats adjacent text |
Install
# .npmrc — once: point the @ahaslides-product scope at GitHub Packages
@ahaslides-product:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} # a GitHub token with read:packages
npm i @ahaslides-product/design
import '@ahaslides-product/design/tokens.css'; // once, at the app root
import '@ahaslides-product/design/illustrations'; // registers <aha-illustration>
Agent feed for this component (absolute, fetchable anywhere): illustration.agent.json · illustration.md · illustration.llms.txt
When to use
When to use
- empty-* illustration — an empty state — no presentations, empty trash, no templates, no team yet
- onboarding-* / plan-* illustration — onboarding choice cards and plan-tier cards (edu / essential / pro / enterprise)
- error-* / not-found illustration — a full-surface error or 404 state, paired with a recovery action
Call by name from the registry — never inline an <svg>, never paste a raster PNG. An illustration is multi-colour art: it does NOT follow currentColor (that is <aha-icon>). Size it by a single edge; the aspect ratio is fixed by the source. If an illustration is genuinely missing, add the SVG under illustrations/svg and re-run build-illustrations.mjs. Raster-backed art (embedded bitmaps) is intentionally excluded — the library stays pure-SVG.
Surfaces
dashboard editor settings audience
Spec
Set 20 illustrations · empty · onboarding · plan · offer · state · team · misc · Source Figma · Oldies library · file P764iQ6y4ZwW7W3f7FLZyW · Colour multi-colour — keeps its own palette (NOT currentColor) · Size one edge in px; the other follows the art's aspect ratio · Fallback unknown name → a dashed error box (var(--aha-color-error))