Warm Editorial — primitives
Every button in this language is a pill. Primary, accent, outline and solid follow the theme; the two photo variants deliberately do not, because a button on an image must stay light-on-dark in both themes.
Paste this into Claude, Cursor or Copilot — or point the agent at
https://ui-deploy.com/r/warm-editorial/button-set/prompt.md
# Button Set — Warm Editorial
Paste this whole file into Claude, Cursor or Copilot.
---
## What to build
Five pill buttons. **Every button in this language is fully rounded (999px).**
There is no square button, no `rounded-lg`, no 8px corner. Height 44–52px,
`padding: 0 22px`, weight 500, 14px.
| Variant | Use |
|---|---|
| `primary` | The main action. Ink-coloured fill, page-coloured label. |
| `accent` | Bronze fill. Warmer, slightly softer than primary. |
| `outline` | Secondary. Transparent with a visible border. |
| `solid` | Tertiary. Raised surface, quiet. |
| `photo` / `photo-outline` | Sitting on a photograph. **Fixed colours, not tokens.** |
Forward or outbound actions take a `→` inline SVG arrow. Nothing else gets an icon.
---
## Tokens
```css
:root{
--bg:#EDE8DF; --bg2:#F6F3ED; --bg3:#E4DED2; --border2:#C6BDAC;
--text:#22201D;
--accent:#A38A6A; --accent-h:#8D7352; --on-accent:#FFFFFF;
--radius-pill:999px;
--font-body:'Inter',system-ui,sans-serif;
--ease:cubic-bezier(.22,.61,.36,1);
}
[data-theme="dark"]{
--bg:#151210; --bg2:#1E1A17; --bg3:#262119; --border2:#40382F;
--text:#EDE7DD;
--accent:#B39B7C; --accent-h:#C4AE91;
--on-accent:#1B1613; /* NOT white — see rule 1 */
}
```
---
## Rules — these are not preferences
1. **`--on-accent` is `#1B1613` in dark mode, not white.** Bronze is light enough
there that white text on it fails WCAG AA. This is the single most common
mistake made with this palette.
2. **Buttons on a photograph do not use theme tokens.** Use the fixed
`#fff` / `#1B1613` pair. If you use `--text` for the label, dark mode turns it
bone-white and you get white text on a white pill.
3. **Never use `--accent` for small text.** It is a fill colour. Text takes
`--accent-text`, which is darkened in light mode and lightened in dark.
4. **Every corner is 999px.** A square button breaks the language immediately.
5. **Minimum height 44px** — this is the touch target, not a style choice.
6. `:focus-visible` sets `outline` only. Setting `border-radius` in a focus rule
deforms the pill.
7. Transitions are `.2s`. Icons are inline SVG, `stroke="currentColor"`,
`fill="none"`. No emoji, no icon font.
---
## Reference implementation
See `code.html` in this component folder. The dark gradient panel around the photo
variants is demo scaffolding — drop it and put the buttons on your real image.
Paste this whole file into Claude, Cursor or Copilot.
Five pill buttons. Every button in this language is fully rounded (999px). There is no square button, no rounded-lg, no 8px corner. Height 44–52px, padding: 0 22px, weight 500, 14px.
| Variant | Use |
|---|---|
primary | The main action. Ink-coloured fill, page-coloured label. |
accent | Bronze fill. Warmer, slightly softer than primary. |
outline | Secondary. Transparent with a visible border. |
solid | Tertiary. Raised surface, quiet. |
photo / photo-outline | Sitting on a photograph. Fixed colours, not tokens. |
Forward or outbound actions take a → inline SVG arrow. Nothing else gets an icon.
:root{
--bg:#EDE8DF; --bg2:#F6F3ED; --bg3:#E4DED2; --border2:#C6BDAC;
--text:#22201D;
--accent:#A38A6A; --accent-h:#8D7352; --on-accent:#FFFFFF;
--radius-pill:999px;
--font-body:'Inter',system-ui,sans-serif;
--ease:cubic-bezier(.22,.61,.36,1);
}
[data-theme="dark"]{
--bg:#151210; --bg2:#1E1A17; --bg3:#262119; --border2:#40382F;
--text:#EDE7DD;
--accent:#B39B7C; --accent-h:#C4AE91;
--on-accent:#1B1613; /* NOT white — see rule 1 */
}
--on-accent is #1B1613 in dark mode, not white. Bronze is light enough there that white text on it fails WCAG AA. This is the single most common mistake made with this palette.#fff / #1B1613 pair. If you use --text for the label, dark mode turns it bone-white and you get white text on a white pill.--accent for small text. It is a fill colour. Text takes --accent-text, which is darkened in light mode and lightened in dark.:focus-visible sets outline only. Setting border-radius in a focus rule deforms the pill..2s. Icons are inline SVG, stroke="currentColor", fill="none". No emoji, no icon font.See code.html in this component folder. The dark gradient panel around the photo variants is demo scaffolding — drop it and put the buttons on your real image.
<!-- Warm Editorial — Button set
Requires tokens.css. Every button is a pill; nothing here is square. -->
<div class="we-btn-row">
<button class="we-btn we-btn-primary" type="button">
Book a visit
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M5 12h14"/><path d="M13 6l6 6-6 6"/>
</svg>
</button>
<button class="we-btn we-btn-accent" type="button">Reserve a room</button>
<button class="we-btn we-btn-outline" type="button">View the studio</button>
<button class="we-btn we-btn-solid" type="button">Read the journal</button>
</div>
<!-- On a photograph these two must NOT follow the theme tokens. -->
<div class="we-btn-photo-demo">
<div class="we-btn-row">
<button class="we-btn we-btn-photo" type="button">Book a visit</button>
<button class="we-btn we-btn-photo-outline" type="button">Our approach</button>
</div>
</div>
<style>
.we-btn-row{display:flex;flex-wrap:wrap;gap:12px;align-items:center}
.we-btn{
display:inline-flex;align-items:center;justify-content:center;gap:8px;
height:48px;padding:0 22px;
border:1px solid transparent;border-radius:var(--radius-pill);
font-family:var(--font-body);font-size:14px;font-weight:500;line-height:1;
text-decoration:none;cursor:pointer;
transition:background .2s var(--ease), color .2s var(--ease),
border-color .2s var(--ease), opacity .2s var(--ease);
}
.we-btn svg{width:16px;height:16px;flex:0 0 16px}
.we-btn-primary{background:var(--text);color:var(--bg)}
.we-btn-primary:hover{opacity:.85}
.we-btn-accent{background:var(--accent);color:var(--on-accent)}
.we-btn-accent:hover{background:var(--accent-h)}
.we-btn-outline{background:transparent;border-color:var(--border2);color:var(--text)}
.we-btn-outline:hover{background:var(--bg3)}
.we-btn-solid{background:var(--bg2);border-color:var(--border);color:var(--text)}
.we-btn-solid:hover{background:var(--bg3)}
/* Fixed light-on-dark. These two are the exception to the token rule and it is
deliberate: with --text the label turns bone-white in dark mode and vanishes
against the white pill. */
.we-btn-photo{background:#fff;color:#1B1613}
.we-btn-photo:hover{background:#F2ECE3}
.we-btn-photo-outline{
background:transparent;border-color:rgba(255,255,255,.35);color:#fff;
}
.we-btn-photo-outline:hover{
background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.55);
}
.we-btn:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.we-btn-photo:focus-visible,
.we-btn-photo-outline:focus-visible{outline-color:#fff}
/* Demo surface only — not part of the component. */
.we-btn-photo-demo{
margin-top:20px;padding:28px;border-radius:var(--radius);
background:linear-gradient(135deg,#3A2E24,#151210);
}
@media (prefers-reduced-motion:reduce){.we-btn{transition:none}}
</style>
Needs tokens.css on the page.