517 lines
14 KiB
HTML
517 lines
14 KiB
HTML
<!-- Copyright 2026 Anthropic PBC · SPDX-License-Identifier: Apache-2.0 -->
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Empty state — four visual directions</title>
|
|
<style>
|
|
:root {
|
|
--ivory: #FAF9F5;
|
|
--slate: #141413;
|
|
--clay: #D97757;
|
|
--oat: #E3DACC;
|
|
--olive: #788C5D;
|
|
--gray-150: #F0EEE6;
|
|
--gray-300: #D1CFC5;
|
|
--gray-500: #87867F;
|
|
--gray-700: #3D3D3A;
|
|
--white: #FFFFFF;
|
|
|
|
--serif: ui-serif, Georgia, 'Times New Roman', serif;
|
|
--sans: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
|
--mono: ui-monospace, 'SF Mono', Menlo, Monaco, monospace;
|
|
}
|
|
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
|
|
body {
|
|
font-family: var(--sans);
|
|
background: var(--ivory);
|
|
color: var(--gray-700);
|
|
line-height: 1.55;
|
|
-webkit-font-smoothing: antialiased;
|
|
padding-bottom: 96px;
|
|
}
|
|
|
|
/* ---------- sticky toolbar ---------- */
|
|
|
|
.toolbar {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 10;
|
|
background: var(--ivory);
|
|
border-bottom: 1.5px solid var(--gray-300);
|
|
padding: 14px 32px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 18px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.toolbar .title {
|
|
font-family: var(--mono);
|
|
font-size: 12px;
|
|
letter-spacing: 0.04em;
|
|
color: var(--gray-500);
|
|
margin-right: auto;
|
|
}
|
|
|
|
.toolbar .field {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
|
|
.toolbar .field > span {
|
|
color: var(--gray-700);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.seg {
|
|
display: inline-flex;
|
|
border: 1.5px solid var(--gray-300);
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
background: var(--white);
|
|
}
|
|
|
|
.seg label {
|
|
padding: 6px 14px;
|
|
cursor: pointer;
|
|
font-size: 13px;
|
|
color: var(--gray-700);
|
|
user-select: none;
|
|
}
|
|
|
|
.seg label + label {
|
|
border-left: 1.5px solid var(--gray-300);
|
|
}
|
|
|
|
.seg input { display: none; }
|
|
|
|
.seg input:checked + span {
|
|
color: var(--slate);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.seg label:has(input:checked) {
|
|
background: var(--oat);
|
|
}
|
|
|
|
/* ---------- page header ---------- */
|
|
|
|
.page {
|
|
max-width: 1240px;
|
|
margin: 0 auto;
|
|
padding: 48px 32px 0;
|
|
}
|
|
|
|
header.page-head {
|
|
max-width: 720px;
|
|
margin-bottom: 40px;
|
|
}
|
|
|
|
.eyebrow {
|
|
font-size: 12px;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
color: var(--gray-500);
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
h1 {
|
|
font-family: var(--serif);
|
|
font-weight: 500;
|
|
font-size: 38px;
|
|
line-height: 1.15;
|
|
color: var(--slate);
|
|
margin-bottom: 18px;
|
|
letter-spacing: -0.01em;
|
|
}
|
|
|
|
.prompt-box {
|
|
background: var(--gray-150);
|
|
border: 1.5px solid var(--gray-300);
|
|
border-radius: 12px;
|
|
padding: 16px 20px;
|
|
font-size: 14.5px;
|
|
}
|
|
|
|
.prompt-box .label {
|
|
font-family: var(--mono);
|
|
font-size: 11px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.06em;
|
|
color: var(--gray-500);
|
|
display: block;
|
|
margin-bottom: 6px;
|
|
}
|
|
|
|
/* ---------- artboard grid ---------- */
|
|
|
|
.board {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 32px;
|
|
}
|
|
|
|
@media (max-width: 960px) {
|
|
.board { grid-template-columns: 1fr; }
|
|
}
|
|
|
|
.artboard {
|
|
background: var(--white);
|
|
border: 1.5px solid var(--gray-300);
|
|
border-radius: 12px;
|
|
padding: 20px;
|
|
position: relative;
|
|
}
|
|
|
|
.tag {
|
|
position: absolute;
|
|
top: 14px;
|
|
left: 14px;
|
|
font-family: var(--mono);
|
|
font-size: 11px;
|
|
letter-spacing: 0.02em;
|
|
background: var(--oat);
|
|
color: var(--slate);
|
|
padding: 4px 10px;
|
|
border-radius: 8px;
|
|
z-index: 2;
|
|
}
|
|
|
|
.stage {
|
|
height: 280px;
|
|
border-radius: 8px;
|
|
border: 1.5px solid var(--gray-300);
|
|
background: var(--ivory);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 24px;
|
|
transition: background 0.15s, border-color 0.15s;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.stage.dark {
|
|
background: var(--slate);
|
|
border-color: var(--slate);
|
|
}
|
|
|
|
.rationale {
|
|
margin-top: 16px;
|
|
font-size: 13px;
|
|
color: var(--gray-500);
|
|
line-height: 1.5;
|
|
}
|
|
|
|
/* =========================================================
|
|
Empty-state variants — each scoped under .es-*
|
|
Theme tokens flip when .stage.dark is present.
|
|
========================================================= */
|
|
|
|
.stage { --fg: var(--slate); --muted: var(--gray-500); --line: var(--gray-300); --panel: var(--white); }
|
|
.stage.dark { --fg: #F0EEE6; --muted: #9C9A93; --line: #3D3D3A; --panel: #1F1E1B; }
|
|
|
|
/* ---- A · Minimal ---- */
|
|
|
|
.es-a {
|
|
text-align: center;
|
|
max-width: 300px;
|
|
}
|
|
.es-a h3 {
|
|
font-family: var(--serif);
|
|
font-weight: 500;
|
|
font-size: 19px;
|
|
color: var(--fg);
|
|
margin-bottom: 6px;
|
|
}
|
|
.es-a p {
|
|
font-size: 13px;
|
|
color: var(--muted);
|
|
margin-bottom: 18px;
|
|
}
|
|
.es-a .btn {
|
|
display: inline-block;
|
|
font-size: 13px;
|
|
color: var(--fg);
|
|
border: 1.5px solid var(--line);
|
|
border-radius: 8px;
|
|
padding: 8px 16px;
|
|
background: transparent;
|
|
}
|
|
|
|
/* ---- B · Illustrated ---- */
|
|
|
|
.es-b {
|
|
text-align: center;
|
|
max-width: 320px;
|
|
}
|
|
.es-b svg {
|
|
display: block;
|
|
margin: 0 auto 18px;
|
|
}
|
|
.es-b h3 {
|
|
font-family: var(--serif);
|
|
font-weight: 500;
|
|
font-size: 19px;
|
|
color: var(--fg);
|
|
margin-bottom: 6px;
|
|
}
|
|
.es-b p {
|
|
font-size: 13px;
|
|
color: var(--muted);
|
|
margin-bottom: 16px;
|
|
}
|
|
.es-b .btn {
|
|
display: inline-block;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
color: var(--white);
|
|
background: var(--clay);
|
|
border-radius: 8px;
|
|
padding: 8px 16px;
|
|
}
|
|
.stage.dark .es-b .btn { color: var(--slate); background: var(--oat); }
|
|
|
|
/* ---- C · Playful ---- */
|
|
|
|
.es-c {
|
|
text-align: center;
|
|
max-width: 300px;
|
|
}
|
|
.es-c .float {
|
|
width: 56px;
|
|
height: 56px;
|
|
margin: 0 auto 20px;
|
|
position: relative;
|
|
animation: bob 3.2s ease-in-out infinite;
|
|
}
|
|
.es-c .float .card {
|
|
position: absolute;
|
|
inset: 0;
|
|
border-radius: 10px;
|
|
background: var(--panel);
|
|
border: 1.5px solid var(--line);
|
|
}
|
|
.es-c .float .card:nth-child(1) { transform: rotate(-8deg) translate(-6px, 4px); opacity: 0.5; }
|
|
.es-c .float .card:nth-child(2) { transform: rotate( 6deg) translate( 6px, 2px); opacity: 0.75; }
|
|
.es-c .float .card:nth-child(3) { background: var(--oat); border-color: var(--oat); }
|
|
.stage.dark .es-c .float .card:nth-child(3) { background: var(--clay); border-color: var(--clay); }
|
|
.es-c .shadow {
|
|
width: 44px;
|
|
height: 8px;
|
|
margin: -8px auto 22px;
|
|
border-radius: 50%;
|
|
background: rgba(0,0,0,0.12);
|
|
filter: blur(2px);
|
|
animation: shadow 3.2s ease-in-out infinite;
|
|
}
|
|
.stage.dark .es-c .shadow { background: rgba(0,0,0,0.5); }
|
|
.es-c h3 {
|
|
font-family: var(--serif);
|
|
font-weight: 500;
|
|
font-size: 19px;
|
|
color: var(--fg);
|
|
margin-bottom: 6px;
|
|
}
|
|
.es-c p {
|
|
font-size: 13px;
|
|
color: var(--muted);
|
|
}
|
|
|
|
@keyframes bob {
|
|
0%, 100% { transform: translateY(0); }
|
|
50% { transform: translateY(-10px); }
|
|
}
|
|
@keyframes shadow {
|
|
0%, 100% { transform: scaleX(1); opacity: 0.9; }
|
|
50% { transform: scaleX(0.8); opacity: 0.5; }
|
|
}
|
|
|
|
/* ---- D · Instructional ---- */
|
|
|
|
.es-d {
|
|
width: 100%;
|
|
max-width: 360px;
|
|
}
|
|
.es-d h3 {
|
|
font-family: var(--serif);
|
|
font-weight: 500;
|
|
font-size: 18px;
|
|
color: var(--fg);
|
|
margin-bottom: 14px;
|
|
}
|
|
.es-d ol {
|
|
list-style: none;
|
|
counter-reset: step;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
}
|
|
.es-d li {
|
|
counter-increment: step;
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 12px;
|
|
background: var(--panel);
|
|
border: 1.5px solid var(--line);
|
|
border-radius: 8px;
|
|
padding: 10px 14px;
|
|
font-size: 13px;
|
|
color: var(--fg);
|
|
}
|
|
.es-d li::before {
|
|
content: counter(step);
|
|
font-family: var(--mono);
|
|
font-size: 11px;
|
|
flex: 0 0 20px;
|
|
height: 20px;
|
|
border-radius: 50%;
|
|
background: var(--oat);
|
|
color: var(--slate);
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-top: 1px;
|
|
}
|
|
.es-d li span { color: var(--muted); display: block; font-size: 12px; margin-top: 2px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="toolbar">
|
|
<div class="title">Acme · design exploration</div>
|
|
<div class="field">
|
|
<span>Background:</span>
|
|
<div class="seg" id="bg-seg">
|
|
<label><input type="radio" name="bg" value="light" checked><span>Light</span></label>
|
|
<label><input type="radio" name="bg" value="dark"><span>Dark</span></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="page">
|
|
|
|
<header class="page-head">
|
|
<div class="eyebrow">Exploration · Empty states</div>
|
|
<h1>Four visual directions for the “no tasks yet” state</h1>
|
|
<div class="prompt-box">
|
|
<span class="label">Prompt</span>
|
|
Explore four visual directions for our empty-state component. Render each
|
|
live so we can compare tone, density, and how well they hold up on light
|
|
and dark surfaces.
|
|
</div>
|
|
</header>
|
|
|
|
<section class="board">
|
|
|
|
<!-- ================= A — Minimal ================= -->
|
|
<article class="artboard">
|
|
<span class="tag">A — Minimal</span>
|
|
<div class="stage">
|
|
<div class="es-a">
|
|
<h3>No tasks yet</h3>
|
|
<p>When you create a task it will show up here.</p>
|
|
<span class="btn">New task</span>
|
|
</div>
|
|
</div>
|
|
<p class="rationale">
|
|
Pure typography, single quiet action. Reads as calm and confident;
|
|
assumes the surrounding UI already carries enough personality.
|
|
</p>
|
|
</article>
|
|
|
|
<!-- ================= B — Illustrated ================= -->
|
|
<article class="artboard">
|
|
<span class="tag">B — Illustrated</span>
|
|
<div class="stage">
|
|
<div class="es-b">
|
|
<svg width="120" height="90" viewBox="0 0 120 90" aria-hidden="true">
|
|
<rect x="14" y="20" width="72" height="54" rx="8"
|
|
fill="var(--panel)" stroke="var(--line)" stroke-width="1.5"/>
|
|
<rect x="34" y="10" width="72" height="54" rx="8"
|
|
fill="var(--oat)"/>
|
|
<line x1="46" y1="26" x2="92" y2="26"
|
|
stroke="var(--slate)" stroke-width="2" stroke-linecap="round"/>
|
|
<line x1="46" y1="38" x2="80" y2="38"
|
|
stroke="var(--slate)" stroke-width="2" stroke-linecap="round" opacity="0.5"/>
|
|
<circle cx="98" cy="60" r="12" fill="var(--clay)"/>
|
|
<path d="M98 55 v10 M93 60 h10"
|
|
stroke="white" stroke-width="2" stroke-linecap="round"/>
|
|
</svg>
|
|
<h3>Start your first list</h3>
|
|
<p>Group related work and watch progress roll up automatically.</p>
|
|
<span class="btn">Create a task</span>
|
|
</div>
|
|
</div>
|
|
<p class="rationale">
|
|
A small geometric spot illustration anchors the eye and explains the
|
|
object model (lists contain tasks) without a wall of copy.
|
|
</p>
|
|
</article>
|
|
|
|
<!-- ================= C — Playful ================= -->
|
|
<article class="artboard">
|
|
<span class="tag">C — Playful</span>
|
|
<div class="stage">
|
|
<div class="es-c">
|
|
<div class="float">
|
|
<div class="card"></div>
|
|
<div class="card"></div>
|
|
<div class="card"></div>
|
|
</div>
|
|
<div class="shadow"></div>
|
|
<h3>Nothing on your plate</h3>
|
|
<p>Enjoy the quiet, or add something to get moving.</p>
|
|
</div>
|
|
</div>
|
|
<p class="rationale">
|
|
A gently bobbing stack adds life to an otherwise static screen. Motion
|
|
is subtle enough to loop indefinitely without drawing complaints.
|
|
</p>
|
|
</article>
|
|
|
|
<!-- ================= D — Instructional ================= -->
|
|
<article class="artboard">
|
|
<span class="tag">D — Instructional</span>
|
|
<div class="stage">
|
|
<div class="es-d">
|
|
<h3>Set up this project</h3>
|
|
<ol>
|
|
<li>
|
|
Create your first task
|
|
<span>Give it a name and an owner.</span>
|
|
</li>
|
|
<li>
|
|
Add a due date
|
|
<span>Acme will surface it on the timeline.</span>
|
|
</li>
|
|
<li>
|
|
Invite a teammate
|
|
<span>Shared projects stay in sync automatically.</span>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
<p class="rationale">
|
|
Treats the empty state as onboarding. Higher density, but every line is
|
|
actionable — best when the user is new to the product, not just the view.
|
|
</p>
|
|
</article>
|
|
|
|
</section>
|
|
</div>
|
|
|
|
<script>
|
|
const stages = document.querySelectorAll('.stage');
|
|
document.getElementById('bg-seg').addEventListener('change', (e) => {
|
|
const dark = e.target.value === 'dark';
|
|
stages.forEach((s) => s.classList.toggle('dark', dark));
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|