Illustrations
A collection of animated UI scenes for landing pages. Drop them into heroes and feature grids.
This is not a live screen. It is how you show the product on a marketing page. Need a real login, settings, or pricing page? That’s Blocks.
They ship in electrik/slate-illustrations as <x-slate-illustration::*>. Empty tags keep the sample copy. Pass your own to make the scene about your product. Clicks are off. prefers-reduced-motion freezes the last frame.
Install
composer require electrik/slate-illustrations
@source '../../vendor/electrik/slate-illustrations/resources/views/**/*.blade.php';
@import '../../vendor/electrik/slate-illustrations/resources/css/illustrations.css';
The @import is only required for the activity marquee and billing sparkline. The others still animate without it.
Deploy
Preview · <x-slate-illustration::deploy />
| Prop | Type | Default | Notes |
|---|---|---|---|
label |
string | Production deploy |
Window chrome title |
headline |
string | main · 4f2a9c1 |
Line under the chrome |
jobs |
list<{title, hint?}> |
four sample steps | One row per step; length drives the loop |
statuses |
list<string> |
queued → live copy | Indexed by animation step |
badges |
list<string> |
Queued, Building, Testing, Live |
Indexed by animation step |
interval |
int | 1600 |
Milliseconds per step |
class |
string | — | Width / placement |
<x-slate-illustration::deploy
class="max-w-md"
label="Acme production"
headline="main · ship-42"
:jobs="[
['title' => 'Install dependencies', 'hint' => 'composer + npm'],
['title' => 'Build application', 'hint' => 'vite build'],
['title' => 'Run tests', 'hint' => 'php artisan test'],
['title' => 'Deploy to production', 'hint' => 'Forge · acme.com'],
]"
:statuses="['Queued on Forge', 'Building application', 'Running the test suite', 'Live on acme.com']"
:badges="['Queued', 'Building', 'Testing', 'Live']"
/>
Billing
Preview · <x-slate-illustration::billing />
| Prop | Type | Default | Notes |
|---|---|---|---|
label |
string | Team billing |
Window chrome |
metric-label |
string | Monthly recurring |
Caption above the number |
amounts |
list<string> |
$2,840 … |
Length drives the loop |
deltas |
list<string> |
+4.2% … |
Same length as amounts |
delta-hint |
string | vs last period |
Trailing copy after the delta |
seats-label |
string | Seats on this team |
|
seats |
list<string> |
4 / 10 … |
Displayed seat counts |
seat-percents |
list<string> |
40% … |
Progress bar widths |
plan-name |
string | Studio |
|
plan-hint |
string | Stripe · team as customer |
|
plan-badge |
string | Active |
|
bars |
list<int> |
eight heights 40–96 |
Sparkline bar heights (%) |
interval |
int | 2000 |
<x-slate-illustration::billing
class="max-w-md"
label="Acme billing"
plan-name="Studio"
plan-hint="Stripe · team as customer"
:amounts="['$4,120', '$4,480', '$4,910', '$4,120']"
:deltas="['+6.4%', '+8.1%', '+9.8%', '+6.4%']"
:seats="['8 / 20', '11 / 20', '14 / 20', '8 / 20']"
:seat-percents="['40%', '55%', '70%', '40%']"
/>
Invites
Preview · <x-slate-illustration::invites />
| Prop | Type | Default | Notes |
|---|---|---|---|
label |
string | Team invites |
Window chrome |
title |
string | Acme workspace |
|
description |
string | Invite teammates to this team |
|
people |
list<{name, email?, initials?}> |
four sample people | Length drives the loop; initials fall back to the name |
interval |
int | 1700 |
<x-slate-illustration::invites
class="max-w-md"
title="Acme workspace"
description="Invite teammates to this team"
:people="[
['name' => 'Priya Shah', 'email' => 'priya@@acme.dev', 'initials' => 'PS'],
['name' => 'Owen Blake', 'email' => 'owen@@acme.dev', 'initials' => 'OB'],
['name' => 'Lina Cho', 'email' => 'lina@@acme.dev', 'initials' => 'LC'],
['name' => 'Noah Reid', 'email' => 'noah@@acme.dev', 'initials' => 'NR'],
]"
/>
Kanban
Preview · <x-slate-illustration::kanban />
| Prop | Type | Default | Notes |
|---|---|---|---|
label |
string | Board |
Window chrome |
columns |
list<string> |
To do, In progress, Done |
Column titles |
cards |
list<{title, owner?, lane}> |
three sample cards | lane is a list of column indexes, one per animation step (0 = first column) |
interval |
int | 1900 |
<x-slate-illustration::kanban
class="max-w-lg"
label="Acme board"
:columns="['To do', 'In progress', 'Done']"
:cards="[
['title' => 'Checkout flow', 'owner' => 'PS', 'lane' => [0, 1, 1, 2]],
['title' => 'Team invites', 'owner' => 'OB', 'lane' => [1, 1, 2, 2]],
['title' => 'Usage meter', 'owner' => 'LC', 'lane' => [0, 0, 1, 2]],
]"
/>
Activity
Preview · <x-slate-illustration::activity />
Scrolling feed. Needs the illustrations CSS import for the marquee.
| Prop | Type | Default | Notes |
|---|---|---|---|
label |
string | Activity |
Window chrome |
events |
list<{time?, title, detail?}> |
six sample events | Duplicated internally so the loop is seamless |
<x-slate-illustration::activity
class="max-w-md"
label="Acme activity"
:events="[
['time' => '09:14', 'title' => 'Member invited', 'detail' => 'priya@@acme.dev · pending'],
['time' => '09:16', 'title' => 'Invoice paid', 'detail' => 'Stripe · $149.00'],
['time' => '09:21', 'title' => 'Deploy succeeded', 'detail' => 'main · ship-42'],
['time' => '09:24', 'title' => 'Seat added', 'detail' => 'Owen Blake joined Acme'],
['time' => '09:28', 'title' => 'Plan changed', 'detail' => 'Studio · team billing'],
['time' => '09:31', 'title' => 'Webhook delivered', 'detail' => 'invoice.paid · 200'],
]"
/>
Chat
Preview · <x-slate-illustration::chat />
| Prop | Type | Default | Notes |
|---|---|---|---|
label |
string | Assistant |
Window chrome |
name |
string | Assistant |
Header name |
status |
string | Online |
Header subtitle |
badge |
string | Live |
Header badge; empty hides it |
messages |
list<{role, text}> |
four sample messages | role is user or assistant |
interval |
int | 1600 |
<x-slate-illustration::chat
class="max-w-md"
name="Acme assistant"
status="Online"
badge="Live"
:messages="[
['role' => 'user', 'text' => 'Can we bill the workspace, not the user?'],
['role' => 'assistant', 'text' => 'Yes. Cashier sits on the team — open /billing after install.'],
['role' => 'user', 'text' => 'Will Cursor pick that up?'],
['role' => 'assistant', 'text' => 'Point it at electrik.dev/llms.txt and keep product code in App\\.'],
]"
/>
Notes
- These are decorative. Don’t wire them to real billing, chat, or deploy APIs.
classlands on the window card.max-w-mdis a good default.- Compose a few in a grid:
<div class="grid gap-4 lg:grid-cols-3">
<x-slate-illustration::deploy />
<x-slate-illustration::billing />
<x-slate-illustration::chat />
</div>