607 lines
16 KiB
HTML
607 lines
16 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">
|
|
<title>Acme — Card Variant Matrix</title>
|
|
<style>
|
|
:root {
|
|
--ivory: #FAF9F5;
|
|
--slate: #141413;
|
|
--clay: #D97757;
|
|
--oat: #E3DACC;
|
|
--olive: #788C5D;
|
|
--gray-100: #F0EEE6;
|
|
--gray-300: #D1CFC5;
|
|
--gray-500: #87867F;
|
|
--gray-700: #3D3D3A;
|
|
--white: #FFFFFF;
|
|
|
|
--serif: ui-serif, Georgia, serif;
|
|
--sans: system-ui, -apple-system, sans-serif;
|
|
--mono: ui-monospace, 'SF Mono', Menlo, monospace;
|
|
|
|
/* live-controlled tokens */
|
|
--card-pad: 20px;
|
|
--card-border: 1.5px solid var(--gray-300);
|
|
--card-shadow: 0 4px 14px rgba(20, 20, 19, 0.08);
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
|
|
body {
|
|
margin: 0;
|
|
background: var(--ivory);
|
|
color: var(--slate);
|
|
font-family: var(--sans);
|
|
font-size: 15px;
|
|
line-height: 1.5;
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
|
|
.page {
|
|
max-width: 1100px;
|
|
margin: 0 auto;
|
|
padding: 0 28px 80px;
|
|
}
|
|
|
|
header {
|
|
padding: 48px 0 20px;
|
|
}
|
|
header h1 {
|
|
font-family: var(--serif);
|
|
font-weight: 500;
|
|
font-size: 36px;
|
|
letter-spacing: -0.01em;
|
|
margin: 0 0 6px;
|
|
}
|
|
header p {
|
|
color: var(--gray-500);
|
|
font-size: 14px;
|
|
margin: 0;
|
|
max-width: 640px;
|
|
}
|
|
|
|
/* ---------- Toolbar ---------- */
|
|
.toolbar {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 10;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 28px;
|
|
padding: 16px 20px;
|
|
margin: 24px 0 36px;
|
|
background: var(--white);
|
|
border: 1.5px solid var(--gray-300);
|
|
border-radius: 12px;
|
|
}
|
|
.control {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
.control-label {
|
|
font-family: var(--mono);
|
|
font-size: 12px;
|
|
color: var(--gray-700);
|
|
}
|
|
.control-value {
|
|
font-family: var(--mono);
|
|
font-size: 12px;
|
|
color: var(--gray-500);
|
|
min-width: 36px;
|
|
}
|
|
|
|
input[type="range"] {
|
|
appearance: none;
|
|
width: 140px;
|
|
height: 4px;
|
|
background: var(--gray-300);
|
|
border-radius: 2px;
|
|
outline: none;
|
|
}
|
|
input[type="range"]::-webkit-slider-thumb {
|
|
appearance: none;
|
|
width: 16px; height: 16px;
|
|
background: var(--clay);
|
|
border-radius: 50%;
|
|
cursor: pointer;
|
|
}
|
|
input[type="range"]::-moz-range-thumb {
|
|
width: 16px; height: 16px;
|
|
background: var(--clay);
|
|
border: none;
|
|
border-radius: 50%;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.radio-group {
|
|
display: inline-flex;
|
|
border: 1.5px solid var(--gray-300);
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
}
|
|
.radio-group label {
|
|
padding: 6px 12px;
|
|
font-size: 13px;
|
|
cursor: pointer;
|
|
user-select: none;
|
|
color: var(--gray-700);
|
|
border-right: 1px solid var(--gray-300);
|
|
}
|
|
.radio-group label:last-child { border-right: none; }
|
|
.radio-group input { display: none; }
|
|
.radio-group input:checked + span {
|
|
color: var(--slate);
|
|
}
|
|
.radio-group label:has(input:checked) {
|
|
background: var(--gray-100);
|
|
}
|
|
|
|
.check {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-size: 13px;
|
|
cursor: pointer;
|
|
user-select: none;
|
|
}
|
|
.check input {
|
|
appearance: none;
|
|
width: 16px; height: 16px;
|
|
border: 1.5px solid var(--gray-300);
|
|
border-radius: 4px;
|
|
margin: 0;
|
|
cursor: pointer;
|
|
position: relative;
|
|
}
|
|
.check input:checked {
|
|
background: var(--clay);
|
|
border-color: var(--clay);
|
|
}
|
|
.check input:checked::after {
|
|
content: "";
|
|
position: absolute;
|
|
left: 4px; top: 0;
|
|
width: 4px; height: 9px;
|
|
border: solid var(--white);
|
|
border-width: 0 2px 2px 0;
|
|
transform: rotate(45deg);
|
|
}
|
|
|
|
/* ---------- Grid ---------- */
|
|
.grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 28px;
|
|
}
|
|
@media (max-width: 960px) {
|
|
.grid { grid-template-columns: repeat(2, 1fr); }
|
|
}
|
|
@media (max-width: 640px) {
|
|
.grid { grid-template-columns: 1fr; }
|
|
}
|
|
|
|
.cell {}
|
|
.variant-label {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
height: 22px;
|
|
padding: 0 9px;
|
|
font-family: var(--mono);
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
color: var(--gray-700);
|
|
background: var(--gray-100);
|
|
border-radius: 999px;
|
|
margin-bottom: 10px;
|
|
}
|
|
.variant-note {
|
|
font-size: 12px;
|
|
color: var(--gray-500);
|
|
margin-top: 10px;
|
|
}
|
|
|
|
/* ---------- Card base ---------- */
|
|
.card {
|
|
border-radius: 12px;
|
|
padding: var(--card-pad);
|
|
transition: padding 0.15s ease, box-shadow 0.15s ease, border 0.15s ease;
|
|
cursor: pointer;
|
|
}
|
|
.card:hover { outline: 2px solid var(--clay); outline-offset: 2px; }
|
|
|
|
.card-head {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
margin-bottom: 12px;
|
|
}
|
|
.avatar {
|
|
width: 36px; height: 36px;
|
|
border-radius: 50%;
|
|
background: var(--oat);
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: var(--gray-700);
|
|
}
|
|
.card-titles { min-width: 0; }
|
|
.card-title {
|
|
font-family: var(--serif);
|
|
font-size: 17px;
|
|
font-weight: 500;
|
|
margin: 0 0 2px;
|
|
line-height: 1.3;
|
|
}
|
|
.card-sub {
|
|
font-size: 13px;
|
|
color: var(--gray-500);
|
|
margin: 0;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
.chips {
|
|
display: flex;
|
|
gap: 6px;
|
|
margin-bottom: 14px;
|
|
}
|
|
.chip {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
height: 20px;
|
|
padding: 0 8px;
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
border-radius: 999px;
|
|
background: var(--gray-100);
|
|
color: var(--gray-700);
|
|
}
|
|
.chip.olive { background: rgba(120,140,93,0.16); color: var(--olive); }
|
|
.ghost-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
height: 30px;
|
|
padding: 0 12px;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
color: var(--gray-700);
|
|
background: transparent;
|
|
border: 1.5px solid var(--gray-300);
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
}
|
|
.ghost-btn:hover { background: var(--gray-100); }
|
|
|
|
/* ---------- Variant treatments ---------- */
|
|
.v-flat {
|
|
background: var(--white);
|
|
border: none;
|
|
box-shadow: none;
|
|
}
|
|
.v-outlined {
|
|
background: var(--white);
|
|
border: var(--card-border);
|
|
box-shadow: none;
|
|
}
|
|
.v-elevated {
|
|
background: var(--white);
|
|
border: none;
|
|
box-shadow: var(--card-shadow);
|
|
}
|
|
.v-stripe {
|
|
background: var(--white);
|
|
border: var(--card-border);
|
|
box-shadow: none;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
.v-stripe::before {
|
|
content: "";
|
|
position: absolute;
|
|
left: 0; right: 0; top: 0;
|
|
height: 4px;
|
|
background: var(--clay);
|
|
}
|
|
.v-inset {
|
|
background: var(--oat);
|
|
border: none;
|
|
box-shadow: none;
|
|
}
|
|
.v-inset .chip { background: rgba(255,255,255,0.6); }
|
|
.v-inset .ghost-btn { border-color: rgba(20,20,19,0.15); }
|
|
.v-inset .avatar { background: var(--white); }
|
|
|
|
.v-horizontal {
|
|
background: var(--white);
|
|
border: var(--card-border);
|
|
box-shadow: none;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
}
|
|
.v-horizontal .card-head { margin: 0; flex: 1; min-width: 0; }
|
|
.v-horizontal .chips { margin: 0; }
|
|
.v-horizontal .card-sub { display: none; }
|
|
.v-horizontal .ghost-btn { flex-shrink: 0; }
|
|
|
|
/* ---------- Snippet panel ---------- */
|
|
.snippet-panel {
|
|
margin-top: 40px;
|
|
border: 1.5px solid var(--gray-300);
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
}
|
|
.snippet-head {
|
|
padding: 10px 16px;
|
|
font-family: var(--mono);
|
|
font-size: 12px;
|
|
color: var(--gray-500);
|
|
background: var(--gray-100);
|
|
border-bottom: 1px solid var(--gray-300);
|
|
}
|
|
pre#snippet {
|
|
margin: 0;
|
|
padding: 20px;
|
|
background: var(--slate);
|
|
color: var(--ivory);
|
|
font-family: var(--mono);
|
|
font-size: 13px;
|
|
line-height: 1.6;
|
|
overflow-x: auto;
|
|
min-height: 120px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="page">
|
|
|
|
<header>
|
|
<h1>Card variant matrix</h1>
|
|
<p>Six structural treatments of the Acme <code style="font-family:var(--mono);font-size:13px"><Card /></code> component. Adjust density and emphasis with the controls, hover a variant to see its prop combo.</p>
|
|
</header>
|
|
|
|
<!-- ---------- Toolbar ---------- -->
|
|
<div class="toolbar">
|
|
<div class="control">
|
|
<span class="control-label">Padding</span>
|
|
<input id="ctl-pad" type="range" min="12" max="32" value="20" step="2">
|
|
<span class="control-value" id="pad-out">20px</span>
|
|
</div>
|
|
|
|
<div class="control">
|
|
<span class="control-label">Border</span>
|
|
<div class="radio-group">
|
|
<label><input type="radio" name="border" value="none"><span>none</span></label>
|
|
<label><input type="radio" name="border" value="hairline" checked><span>hairline</span></label>
|
|
<label><input type="radio" name="border" value="solid"><span>solid</span></label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="control">
|
|
<label class="check">
|
|
<input id="ctl-shadow" type="checkbox" checked>
|
|
Show shadow
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ---------- Grid ---------- -->
|
|
<div class="grid" id="grid">
|
|
|
|
<!-- A: Flat -->
|
|
<div class="cell">
|
|
<span class="variant-label">A · Flat</span>
|
|
<div class="card v-flat"
|
|
data-snippet='<Card variant="flat" padding={PAD}>
|
|
<Card.Header avatar title="Weekly planning" subtitle="12 tasks · due Friday" />
|
|
<Card.Meta tags={["Q2", "Roadmap"]} />
|
|
<Button variant="ghost">Open</Button>
|
|
</Card>'>
|
|
<div class="card-head">
|
|
<div class="avatar">WP</div>
|
|
<div class="card-titles">
|
|
<p class="card-title">Weekly planning</p>
|
|
<p class="card-sub">12 tasks · due Friday</p>
|
|
</div>
|
|
</div>
|
|
<div class="chips">
|
|
<span class="chip">Q2</span>
|
|
<span class="chip olive">Roadmap</span>
|
|
</div>
|
|
<button class="ghost-btn">Open</button>
|
|
</div>
|
|
<p class="variant-note">best for: dense lists on tinted backgrounds</p>
|
|
</div>
|
|
|
|
<!-- B: Outlined -->
|
|
<div class="cell">
|
|
<span class="variant-label">B · Outlined</span>
|
|
<div class="card v-outlined"
|
|
data-snippet='<Card variant="outlined" padding={PAD} border="BORDER">
|
|
<Card.Header avatar title="Weekly planning" subtitle="12 tasks · due Friday" />
|
|
<Card.Meta tags={["Q2", "Roadmap"]} />
|
|
<Button variant="ghost">Open</Button>
|
|
</Card>'>
|
|
<div class="card-head">
|
|
<div class="avatar">WP</div>
|
|
<div class="card-titles">
|
|
<p class="card-title">Weekly planning</p>
|
|
<p class="card-sub">12 tasks · due Friday</p>
|
|
</div>
|
|
</div>
|
|
<div class="chips">
|
|
<span class="chip">Q2</span>
|
|
<span class="chip olive">Roadmap</span>
|
|
</div>
|
|
<button class="ghost-btn">Open</button>
|
|
</div>
|
|
<p class="variant-note">best for: default content cards on ivory</p>
|
|
</div>
|
|
|
|
<!-- C: Elevated -->
|
|
<div class="cell">
|
|
<span class="variant-label">C · Elevated</span>
|
|
<div class="card v-elevated"
|
|
data-snippet='<Card variant="elevated" padding={PAD} shadow="md">
|
|
<Card.Header avatar title="Weekly planning" subtitle="12 tasks · due Friday" />
|
|
<Card.Meta tags={["Q2", "Roadmap"]} />
|
|
<Button variant="ghost">Open</Button>
|
|
</Card>'>
|
|
<div class="card-head">
|
|
<div class="avatar">WP</div>
|
|
<div class="card-titles">
|
|
<p class="card-title">Weekly planning</p>
|
|
<p class="card-sub">12 tasks · due Friday</p>
|
|
</div>
|
|
</div>
|
|
<div class="chips">
|
|
<span class="chip">Q2</span>
|
|
<span class="chip olive">Roadmap</span>
|
|
</div>
|
|
<button class="ghost-btn">Open</button>
|
|
</div>
|
|
<p class="variant-note">best for: draggable items, popovers</p>
|
|
</div>
|
|
|
|
<!-- D: Accent stripe -->
|
|
<div class="cell">
|
|
<span class="variant-label">D · Accent stripe</span>
|
|
<div class="card v-stripe"
|
|
data-snippet='<Card variant="outlined" accent="clay" padding={PAD} border="BORDER">
|
|
<Card.Header avatar title="Weekly planning" subtitle="12 tasks · due Friday" />
|
|
<Card.Meta tags={["Q2", "Roadmap"]} />
|
|
<Button variant="ghost">Open</Button>
|
|
</Card>'>
|
|
<div class="card-head">
|
|
<div class="avatar">WP</div>
|
|
<div class="card-titles">
|
|
<p class="card-title">Weekly planning</p>
|
|
<p class="card-sub">12 tasks · due Friday</p>
|
|
</div>
|
|
</div>
|
|
<div class="chips">
|
|
<span class="chip">Q2</span>
|
|
<span class="chip olive">Roadmap</span>
|
|
</div>
|
|
<button class="ghost-btn">Open</button>
|
|
</div>
|
|
<p class="variant-note">best for: pinned or priority items</p>
|
|
</div>
|
|
|
|
<!-- E: Inset / filled -->
|
|
<div class="cell">
|
|
<span class="variant-label">E · Inset</span>
|
|
<div class="card v-inset"
|
|
data-snippet='<Card variant="filled" tone="oat" padding={PAD}>
|
|
<Card.Header avatar title="Weekly planning" subtitle="12 tasks · due Friday" />
|
|
<Card.Meta tags={["Q2", "Roadmap"]} />
|
|
<Button variant="ghost">Open</Button>
|
|
</Card>'>
|
|
<div class="card-head">
|
|
<div class="avatar">WP</div>
|
|
<div class="card-titles">
|
|
<p class="card-title">Weekly planning</p>
|
|
<p class="card-sub">12 tasks · due Friday</p>
|
|
</div>
|
|
</div>
|
|
<div class="chips">
|
|
<span class="chip">Q2</span>
|
|
<span class="chip olive">Roadmap</span>
|
|
</div>
|
|
<button class="ghost-btn">Open</button>
|
|
</div>
|
|
<p class="variant-note">best for: nested cards inside white panels</p>
|
|
</div>
|
|
|
|
<!-- F: Horizontal / compact -->
|
|
<div class="cell">
|
|
<span class="variant-label">F · Horizontal</span>
|
|
<div class="card v-horizontal"
|
|
data-snippet='<Card variant="outlined" layout="row" padding={PAD} border="BORDER">
|
|
<Card.Header avatar title="Weekly planning" />
|
|
<Card.Meta tags={["Q2", "Roadmap"]} />
|
|
<Button variant="ghost">Open</Button>
|
|
</Card>'>
|
|
<div class="card-head">
|
|
<div class="avatar">WP</div>
|
|
<div class="card-titles">
|
|
<p class="card-title">Weekly planning</p>
|
|
<p class="card-sub">12 tasks · due Friday</p>
|
|
</div>
|
|
</div>
|
|
<div class="chips">
|
|
<span class="chip">Q2</span>
|
|
<span class="chip olive">Roadmap</span>
|
|
</div>
|
|
<button class="ghost-btn">Open</button>
|
|
</div>
|
|
<p class="variant-note">best for: compact row lists, sidebars</p>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- ---------- Snippet ---------- -->
|
|
<div class="snippet-panel">
|
|
<div class="snippet-head">JSX — hover a variant above</div>
|
|
<pre id="snippet">// hover a card to preview its props</pre>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
(function () {
|
|
var root = document.documentElement;
|
|
var pad = document.getElementById('ctl-pad');
|
|
var padOut = document.getElementById('pad-out');
|
|
var shadow = document.getElementById('ctl-shadow');
|
|
var snippet = document.getElementById('snippet');
|
|
var currentBorder = 'hairline';
|
|
|
|
var borderMap = {
|
|
none: 'none',
|
|
hairline: '1px solid var(--gray-300)',
|
|
solid: '1.5px solid var(--gray-300)'
|
|
};
|
|
|
|
function applyPad() {
|
|
root.style.setProperty('--card-pad', pad.value + 'px');
|
|
padOut.textContent = pad.value + 'px';
|
|
}
|
|
function applyBorder(v) {
|
|
currentBorder = v;
|
|
root.style.setProperty('--card-border', borderMap[v]);
|
|
}
|
|
function applyShadow() {
|
|
root.style.setProperty('--card-shadow',
|
|
shadow.checked ? '0 4px 14px rgba(20,20,19,0.08)' : 'none');
|
|
}
|
|
|
|
pad.addEventListener('input', applyPad);
|
|
shadow.addEventListener('change', applyShadow);
|
|
document.querySelectorAll('input[name="border"]').forEach(function (r) {
|
|
r.addEventListener('change', function () { applyBorder(r.value); });
|
|
});
|
|
|
|
document.querySelectorAll('.card').forEach(function (card) {
|
|
card.addEventListener('mouseenter', function () {
|
|
var raw = card.getAttribute('data-snippet') || '';
|
|
snippet.textContent = raw
|
|
.replace(/PAD/g, pad.value)
|
|
.replace(/BORDER/g, currentBorder);
|
|
});
|
|
});
|
|
|
|
applyPad(); applyBorder('hairline'); applyShadow();
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|