@buttonschool/create-wireframe 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/template/AGENTS.md +3 -3
- package/template/_partials/nav.html +5 -0
- package/template/components.html +122 -0
- package/template/index.html +11 -12
- package/template/package.json +3 -1
- package/template/src/game.js +40 -9
- package/template/src/kit/components/button.css +53 -0
- package/template/src/kit/components/checkbox.css +26 -0
- package/template/src/kit/components/field.css +11 -0
- package/template/src/kit/components/input.css +31 -0
- package/template/src/kit/components/label.css +14 -0
- package/template/src/kit/components/radio.css +26 -0
- package/template/src/kit/components/select.css +69 -0
- package/template/src/kit/components/textarea.css +33 -0
- package/template/src/kit/tokens.css +4 -1
- package/template/src/strings.json +24 -0
- package/template/src/styles/components/nav.css +19 -4
- package/template/src/styles/main.css +9 -0
- package/template/src/styles/pages/components-showcase.css +38 -0
- package/template/src/styles/pages/start.css +26 -9
- package/template/src/styles/pages/tokens-showcase.css +14 -3
- package/template/tokens.html +15 -18
- package/template/vite.config.js +19 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buttonschool/create-wireframe",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Scaffold a Vite-based wireframe prototype with tokens, Comic Neue, and Lucide",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Scaffold a Vite-based wireframe prototype with tokens, components, Comic Neue, and Lucide",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": "index.js",
|
|
7
7
|
"files": [
|
package/template/AGENTS.md
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
This is a **wireframe prototype** scaffold. Stack: **Vite** (vanilla JS), design tokens, **Comic Neue** font, and **Lucide** icons. Keep structure minimal; suitable for code-gen and rapid iteration.
|
|
4
4
|
|
|
5
|
-
The project starts with **
|
|
5
|
+
The project starts with **three HTML pages**: **Start** (`index.html`) has a small word game (Spelling Bee–style); **Tokens** (`tokens.html`) showcases the design tokens; **Components** (`components.html`) showcases the wireframe kit controls. All share a nav linking to each other. The nav is a single **Nunjucks partial**: `_partials/nav.html` (uses `site.nav.*` from `src/strings.json` and `current` for `aria-current="page"`). Each HTML page includes it and receives a `current` value via `vite.config.js` so the active link is marked. To add a page: add the `.html` file, add a link in `_partials/nav.html`, add a `variables` entry in `vite.config.js` with `{ ...strings, current: "yourpage" }`, and add a link in `main.css` if you add page-specific styles. Styles are linked from each page’s `<head>` via `<link rel="stylesheet" href="/src/styles/main.css">`. Prefer writing markup in HTML files and using JS only for behavior. To add a page: add a new `.html` file at the project root and add a link to it in the nav; no need to edit Vite config (every root-level HTML file is automatically a page).
|
|
6
6
|
|
|
7
7
|
## Styles
|
|
8
8
|
|
|
9
|
-
Styles are organized under `src/styles/`: `main.css` (orchestration), `base.css`, `layout.css`, `components/` (e.g. nav
|
|
9
|
+
Styles are organized under `src/styles/`: `main.css` (orchestration), `base.css`, `layout.css`, `components/` (e.g. nav), and `pages/` (home, tokens-showcase, components-showcase). Reusable controls live under **`src/kit/components/`** — one CSS file per component (button, input, textarea, checkbox, radio, select, label, field), using `--wire-*` tokens and `.wire-*` class names (e.g. `.wire-button`, `.wire-input`). Use `.wire-field` to wrap a label and its control for consistent spacing. The select can be wrapped in `.wire-select-wrap` for a CSS-only chevron (pseudo-element, no icon element or JS). To remove or add a page or component, edit the corresponding file and the `@import` list in `styles/main.css`.
|
|
10
10
|
|
|
11
11
|
## Tokens
|
|
12
12
|
|
|
13
13
|
- **Location:** `src/kit/tokens.css`
|
|
14
|
-
- **Usage:** CSS custom properties on `:root` with `--wire-*` prefix: colors (grayscale + semantic aliases), spacing (`--wire-space-*`), radius (`--wire-radius-*`), typography (`--wire-font-family`, `--wire-line-height`), font sizes (`--wire-text-xs` through `--wire-text-2xl`, plus semantic aliases like `--wire-text-body`, `--wire-text-heading`, `--wire-text-subheading`, `--wire-text-caption`, `--wire-text-label`), and sizing (`--wire-size-icon-sm`, `--wire-size-icon-md`, `--wire-size-icon-lg`, `--wire-size-avatar-sm`, `--wire-size-avatar-md`, `--wire-size-avatar-lg`). Use them in your CSS, e.g. `color: var(--wire-text-primary);`, `padding: var(--wire-space-md);`, `font-size: var(--wire-text-body);`, `width: var(--wire-size-icon-md); height: var(--wire-size-icon-md);`.
|
|
14
|
+
- **Usage:** CSS custom properties on `:root` with `--wire-*` prefix: colors (grayscale + semantic aliases), spacing (`--wire-space-*`), radius (`--wire-radius-*`), border width (`--wire-border-width`, default 2px for controls and strokes), typography (`--wire-font-family`, `--wire-line-height`), font sizes (`--wire-text-xs` through `--wire-text-2xl`, plus semantic aliases like `--wire-text-body`, `--wire-text-heading`, `--wire-text-subheading`, `--wire-text-caption`, `--wire-text-label`), and sizing (`--wire-size-icon-sm`, `--wire-size-icon-md`, `--wire-size-icon-lg`, `--wire-size-avatar-sm`, `--wire-size-avatar-md`, `--wire-size-avatar-lg`). Use them in your CSS, e.g. `color: var(--wire-text-primary);`, `padding: var(--wire-space-md);`, `font-size: var(--wire-text-body);`, `width: var(--wire-size-icon-md); height: var(--wire-size-icon-md);`.
|
|
15
15
|
|
|
16
16
|
## Dev server
|
|
17
17
|
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<nav class="site-nav">
|
|
2
|
+
<a href="/" {% if current == "start" %}aria-current="page"{% endif %}>{{ site.nav.start }}</a>
|
|
3
|
+
<a href="/tokens.html" {% if current == "tokens" %}aria-current="page"{% endif %}>{{ site.nav.tokens }}</a>
|
|
4
|
+
<a href="/components.html" {% if current == "components" %}aria-current="page"{% endif %}>{{ site.nav.components }}</a>
|
|
5
|
+
</nav>
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<link rel="stylesheet" href="/src/styles/main.css" />
|
|
7
|
+
<title>Components – Wireframe</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
{% include "_partials/nav.html" %}
|
|
11
|
+
<main class="components-showcase">
|
|
12
|
+
<h1>Components</h1>
|
|
13
|
+
<p class="components-showcase-intro">Reusable controls from the wireframe kit. Use classes <code>.wire-button</code>, <code>.wire-input</code>, and the rest in your HTML.</p>
|
|
14
|
+
|
|
15
|
+
<section class="showcase-section">
|
|
16
|
+
<h2>Buttons</h2>
|
|
17
|
+
<div class="component-demo-row">
|
|
18
|
+
<button type="button" class="wire-button">Default</button>
|
|
19
|
+
<button type="button" class="wire-button wire-button--primary">Primary</button>
|
|
20
|
+
<button type="button" class="wire-button" disabled>Disabled</button>
|
|
21
|
+
</div>
|
|
22
|
+
</section>
|
|
23
|
+
|
|
24
|
+
<section class="showcase-section">
|
|
25
|
+
<h2>Text input</h2>
|
|
26
|
+
<div class="component-demo-block">
|
|
27
|
+
<div class="wire-field">
|
|
28
|
+
<label class="wire-label" for="demo-input">Label</label>
|
|
29
|
+
<input type="text" id="demo-input" class="wire-input" placeholder="Placeholder text" />
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="component-demo-block">
|
|
33
|
+
<input type="text" class="wire-input" placeholder="No label" disabled />
|
|
34
|
+
</div>
|
|
35
|
+
</section>
|
|
36
|
+
|
|
37
|
+
<section class="showcase-section">
|
|
38
|
+
<h2>Textarea</h2>
|
|
39
|
+
<div class="component-demo-block">
|
|
40
|
+
<div class="wire-field">
|
|
41
|
+
<label class="wire-label" for="demo-textarea">Message</label>
|
|
42
|
+
<textarea id="demo-textarea" class="wire-textarea" rows="4" placeholder="Enter text…"></textarea>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</section>
|
|
46
|
+
|
|
47
|
+
<section class="showcase-section">
|
|
48
|
+
<h2>Checkbox</h2>
|
|
49
|
+
<div class="component-demo-stack">
|
|
50
|
+
<label class="wire-checkbox">
|
|
51
|
+
<input type="checkbox" name="demo-cb" />
|
|
52
|
+
<span>Option one</span>
|
|
53
|
+
</label>
|
|
54
|
+
<label class="wire-checkbox">
|
|
55
|
+
<input type="checkbox" name="demo-cb" checked />
|
|
56
|
+
<span>Option two (checked)</span>
|
|
57
|
+
</label>
|
|
58
|
+
<label class="wire-checkbox">
|
|
59
|
+
<input type="checkbox" name="demo-cb" disabled />
|
|
60
|
+
<span>Option three (disabled)</span>
|
|
61
|
+
</label>
|
|
62
|
+
</div>
|
|
63
|
+
</section>
|
|
64
|
+
|
|
65
|
+
<section class="showcase-section">
|
|
66
|
+
<h2>Radio</h2>
|
|
67
|
+
<div class="component-demo-stack">
|
|
68
|
+
<label class="wire-radio">
|
|
69
|
+
<input type="radio" name="demo-radio" value="a" />
|
|
70
|
+
<span>Choice A</span>
|
|
71
|
+
</label>
|
|
72
|
+
<label class="wire-radio">
|
|
73
|
+
<input type="radio" name="demo-radio" value="b" checked />
|
|
74
|
+
<span>Choice B</span>
|
|
75
|
+
</label>
|
|
76
|
+
<label class="wire-radio">
|
|
77
|
+
<input type="radio" name="demo-radio" value="c" disabled />
|
|
78
|
+
<span>Choice C (disabled)</span>
|
|
79
|
+
</label>
|
|
80
|
+
</div>
|
|
81
|
+
</section>
|
|
82
|
+
|
|
83
|
+
<section class="showcase-section">
|
|
84
|
+
<h2>Select</h2>
|
|
85
|
+
<div class="component-demo-block">
|
|
86
|
+
<div class="wire-field">
|
|
87
|
+
<label class="wire-label" for="demo-select">Choose one</label>
|
|
88
|
+
<span class="wire-select-wrap">
|
|
89
|
+
<select id="demo-select">
|
|
90
|
+
<option value="">Select…</option>
|
|
91
|
+
<option value="1">Option 1</option>
|
|
92
|
+
<option value="2">Option 2</option>
|
|
93
|
+
<option value="3">Option 3</option>
|
|
94
|
+
</select>
|
|
95
|
+
</span>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
<div class="component-demo-block">
|
|
99
|
+
<span class="wire-select-wrap">
|
|
100
|
+
<select disabled>
|
|
101
|
+
<option>Disabled select</option>
|
|
102
|
+
</select>
|
|
103
|
+
</span>
|
|
104
|
+
</div>
|
|
105
|
+
</section>
|
|
106
|
+
|
|
107
|
+
<section class="showcase-section">
|
|
108
|
+
<h2>Label</h2>
|
|
109
|
+
<div class="component-demo-stack">
|
|
110
|
+
<div class="wire-field">
|
|
111
|
+
<label class="wire-label" for="demo-label-plain">Plain label</label>
|
|
112
|
+
<input type="text" id="demo-label-plain" class="wire-input" />
|
|
113
|
+
</div>
|
|
114
|
+
<div class="wire-field">
|
|
115
|
+
<label class="wire-label wire-label--required" for="demo-label-required">Required field</label>
|
|
116
|
+
<input type="text" id="demo-label-required" class="wire-input" />
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
</section>
|
|
120
|
+
</main>
|
|
121
|
+
</body>
|
|
122
|
+
</html>
|
package/template/index.html
CHANGED
|
@@ -4,31 +4,30 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<link rel="stylesheet" href="/src/styles/main.css" />
|
|
7
|
-
<title>
|
|
7
|
+
<title>{{ site.title }}</title>
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
10
|
-
|
|
11
|
-
<a href="/" aria-current="page">Start</a>
|
|
12
|
-
<a href="/tokens.html">Tokens</a>
|
|
13
|
-
</nav>
|
|
10
|
+
{% include "_partials/nav.html" %}
|
|
14
11
|
<main class="game-area">
|
|
15
|
-
<p class="bee-score" aria-live="polite"><i data-lucide="crown" class="bee-score-icon" aria-hidden="true"></i><span class="bee-score-value">0</span><span class="bee-score-label visually-hidden">
|
|
16
|
-
<div class="bee-
|
|
17
|
-
|
|
18
|
-
<
|
|
12
|
+
<p class="bee-score" aria-live="polite"><i data-lucide="crown" class="bee-score-icon" aria-hidden="true"></i><span class="bee-score-value">0</span><span class="bee-score-label visually-hidden">{{ game.scoreLabel }}</span></p>
|
|
13
|
+
<div class="bee-focus-region" tabindex="-1">
|
|
14
|
+
<div class="bee-honeycomb" aria-hidden="true"></div>
|
|
15
|
+
<div class="bee-input-row">
|
|
16
|
+
<label for="bee-word" class="visually-hidden">{{ game.inputLabel }}</label>
|
|
19
17
|
<input
|
|
20
18
|
type="text"
|
|
21
19
|
id="bee-word"
|
|
22
20
|
class="bee-input"
|
|
23
|
-
placeholder="
|
|
21
|
+
placeholder="{{ game.inputPlaceholder }}"
|
|
24
22
|
autocomplete="off"
|
|
25
23
|
autocapitalize="off"
|
|
26
24
|
maxlength="15"
|
|
27
25
|
/>
|
|
28
|
-
<button type="button" class="bee-submit">
|
|
26
|
+
<button type="button" class="bee-submit">{{ game.submitButton }}</button>
|
|
27
|
+
</div>
|
|
29
28
|
</div>
|
|
30
29
|
<p class="bee-feedback" aria-live="polite"></p>
|
|
31
|
-
<h2 class="bee-found-heading">
|
|
30
|
+
<h2 class="bee-found-heading">{{ game.foundHeading }}</h2>
|
|
32
31
|
<ul class="bee-found-list" aria-live="polite"></ul>
|
|
33
32
|
</main>
|
|
34
33
|
<script type="module" src="/src/main.js"></script>
|
package/template/package.json
CHANGED
package/template/src/game.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { createIcons, Crown } from "lucide";
|
|
7
|
+
import strings from "./strings.json";
|
|
7
8
|
|
|
8
9
|
const LETTERS = ["W", "I", "R", "E", "F", "A", "M"];
|
|
9
10
|
const CENTER_LETTER = "E";
|
|
@@ -164,10 +165,10 @@ function scoreWord(word) {
|
|
|
164
165
|
function validate(word) {
|
|
165
166
|
const w = word.trim().toLowerCase();
|
|
166
167
|
if (!w) return { ok: false, message: "" };
|
|
167
|
-
if (w.length < MIN_LENGTH) return { ok: false, message:
|
|
168
|
-
if (!hasCenterLetter(w)) return { ok: false, message:
|
|
169
|
-
if (!usesOnlyLetters(w)) return { ok: false, message:
|
|
170
|
-
if (!WORD_LIST.has(w)) return { ok: false, message:
|
|
168
|
+
if (w.length < MIN_LENGTH) return { ok: false, message: strings.game.feedback.tooShort };
|
|
169
|
+
if (!hasCenterLetter(w)) return { ok: false, message: strings.game.feedback.missingCenter };
|
|
170
|
+
if (!usesOnlyLetters(w)) return { ok: false, message: strings.game.feedback.invalidLetters };
|
|
171
|
+
if (!WORD_LIST.has(w)) return { ok: false, message: strings.game.feedback.notInList };
|
|
171
172
|
return { ok: true, word: w };
|
|
172
173
|
}
|
|
173
174
|
|
|
@@ -177,6 +178,7 @@ function init() {
|
|
|
177
178
|
const area = document.querySelector(".game-area");
|
|
178
179
|
if (!area) return;
|
|
179
180
|
|
|
181
|
+
const focusRegion = area.querySelector(".bee-focus-region");
|
|
180
182
|
const scoreEl = area.querySelector(".bee-score");
|
|
181
183
|
const honeycombEl = area.querySelector(".bee-honeycomb");
|
|
182
184
|
const inputEl = area.querySelector(".bee-input");
|
|
@@ -184,7 +186,7 @@ function init() {
|
|
|
184
186
|
const feedbackEl = area.querySelector(".bee-feedback");
|
|
185
187
|
const foundListEl = area.querySelector(".bee-found-list");
|
|
186
188
|
|
|
187
|
-
if (!scoreEl || !honeycombEl || !inputEl || !submitBtn || !feedbackEl || !foundListEl) return;
|
|
189
|
+
if (!focusRegion || !scoreEl || !honeycombEl || !inputEl || !submitBtn || !feedbackEl || !foundListEl) return;
|
|
188
190
|
|
|
189
191
|
const saved = JSON.parse(localStorage.getItem(STORAGE_KEY) || "[]");
|
|
190
192
|
const loaded = Array.isArray(saved)
|
|
@@ -224,19 +226,21 @@ function init() {
|
|
|
224
226
|
const raw = inputEl.value;
|
|
225
227
|
const result = validate(raw);
|
|
226
228
|
if (!result.ok) {
|
|
227
|
-
setFeedback(result.message ||
|
|
229
|
+
setFeedback(result.message || strings.game.feedback.tryAgain, false, true);
|
|
230
|
+
inputEl.value = "";
|
|
228
231
|
return;
|
|
229
232
|
}
|
|
230
233
|
const { word } = result;
|
|
231
234
|
if (found.has(word)) {
|
|
232
|
-
setFeedback(
|
|
235
|
+
setFeedback(strings.game.feedback.alreadyFound, false, true);
|
|
236
|
+
inputEl.value = "";
|
|
233
237
|
return;
|
|
234
238
|
}
|
|
235
239
|
foundOrdered.push(word);
|
|
236
240
|
found.add(word);
|
|
237
241
|
totalScore += scoreWord(word);
|
|
238
242
|
saveFound();
|
|
239
|
-
setFeedback(isPangram(word) ?
|
|
243
|
+
setFeedback(isPangram(word) ? strings.game.feedback.pangram : strings.game.feedback.good, true, false);
|
|
240
244
|
inputEl.value = "";
|
|
241
245
|
inputEl.focus();
|
|
242
246
|
updateScore();
|
|
@@ -246,26 +250,53 @@ function init() {
|
|
|
246
250
|
submitBtn.addEventListener("click", submitWord);
|
|
247
251
|
inputEl.addEventListener("keydown", (e) => {
|
|
248
252
|
if (e.key === "Enter") submitWord();
|
|
253
|
+
else if (!e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
254
|
+
const upper = (e.key || "").toUpperCase();
|
|
255
|
+
if (LETTERS.includes(upper)) {
|
|
256
|
+
const span = honeycombEl.querySelector(`[data-letter="${upper}"]`);
|
|
257
|
+
if (span) span.classList.add("bee-letter--typed-press");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
inputEl.addEventListener("keyup", (e) => {
|
|
262
|
+
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
|
263
|
+
const upper = (e.key || "").toUpperCase();
|
|
264
|
+
if (LETTERS.includes(upper)) {
|
|
265
|
+
const span = honeycombEl.querySelector(`[data-letter="${upper}"]`);
|
|
266
|
+
if (span) span.classList.remove("bee-letter--typed-press");
|
|
267
|
+
}
|
|
249
268
|
});
|
|
250
269
|
|
|
270
|
+
function appendLetter(letter) {
|
|
271
|
+
if (inputEl.value.length >= 15) return;
|
|
272
|
+
inputEl.value += letter.toLowerCase();
|
|
273
|
+
inputEl.focus();
|
|
274
|
+
}
|
|
275
|
+
|
|
251
276
|
honeycombEl.innerHTML = "";
|
|
252
277
|
const outer = LETTERS.filter((l) => l !== CENTER_LETTER);
|
|
253
278
|
const centerNode = document.createElement("span");
|
|
254
279
|
centerNode.className = "bee-letter bee-letter--center";
|
|
255
280
|
centerNode.textContent = CENTER_LETTER;
|
|
256
281
|
centerNode.setAttribute("aria-hidden", "true");
|
|
282
|
+
centerNode.setAttribute("data-letter", CENTER_LETTER);
|
|
283
|
+
centerNode.addEventListener("mousedown", () => focusRegion.focus());
|
|
284
|
+
centerNode.addEventListener("click", () => appendLetter(CENTER_LETTER));
|
|
257
285
|
honeycombEl.appendChild(centerNode);
|
|
258
286
|
outer.forEach((letter) => {
|
|
259
287
|
const span = document.createElement("span");
|
|
260
288
|
span.className = "bee-letter";
|
|
261
289
|
span.textContent = letter;
|
|
262
290
|
span.setAttribute("aria-hidden", "true");
|
|
291
|
+
span.setAttribute("data-letter", letter);
|
|
292
|
+
span.addEventListener("mousedown", () => focusRegion.focus());
|
|
293
|
+
span.addEventListener("click", () => appendLetter(letter));
|
|
263
294
|
honeycombEl.appendChild(span);
|
|
264
295
|
});
|
|
265
296
|
|
|
266
297
|
updateScore();
|
|
267
298
|
renderFoundWords();
|
|
268
|
-
setFeedback(
|
|
299
|
+
setFeedback(strings.game.hint);
|
|
269
300
|
}
|
|
270
301
|
|
|
271
302
|
init();
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/* Wireframe Kit – button component. Uses --wire-* tokens only. */
|
|
2
|
+
|
|
3
|
+
.wire-button {
|
|
4
|
+
padding: var(--wire-space-md) var(--wire-space-xl);
|
|
5
|
+
font-family: inherit;
|
|
6
|
+
font-size: var(--wire-text-body);
|
|
7
|
+
font-weight: var(--wire-font-weight-bold);
|
|
8
|
+
color: var(--wire-text-primary);
|
|
9
|
+
background-color: var(--wire-surface);
|
|
10
|
+
border: var(--wire-border-width) solid var(--wire-border);
|
|
11
|
+
border-radius: var(--wire-radius-lg);
|
|
12
|
+
cursor: pointer;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.wire-button:hover {
|
|
16
|
+
background-color: var(--wire-surface-alt);
|
|
17
|
+
border-color: var(--wire-dark);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.wire-button:focus {
|
|
21
|
+
outline: none;
|
|
22
|
+
border-color: var(--wire-dark);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.wire-button:disabled {
|
|
26
|
+
color: var(--wire-text-muted);
|
|
27
|
+
background-color: var(--wire-surface-alt);
|
|
28
|
+
border-width: var(--wire-border-width);
|
|
29
|
+
border-color: var(--wire-border-light);
|
|
30
|
+
cursor: not-allowed;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Primary: use sparingly (e.g. one per view). */
|
|
34
|
+
.wire-button--primary {
|
|
35
|
+
color: var(--wire-white);
|
|
36
|
+
background-color: var(--wire-dark);
|
|
37
|
+
border-color: var(--wire-dark);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.wire-button--primary:hover {
|
|
41
|
+
background-color: var(--wire-black);
|
|
42
|
+
border-color: var(--wire-black);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.wire-button--primary:focus {
|
|
46
|
+
border-color: var(--wire-black);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.wire-button--primary:disabled {
|
|
50
|
+
color: var(--wire-mid);
|
|
51
|
+
background-color: var(--wire-lighter);
|
|
52
|
+
border-color: var(--wire-lighter);
|
|
53
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* Wireframe Kit – checkbox component. Uses --wire-* tokens only. */
|
|
2
|
+
|
|
3
|
+
.wire-checkbox {
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: var(--wire-space-sm);
|
|
7
|
+
cursor: pointer;
|
|
8
|
+
font-size: var(--wire-text-body);
|
|
9
|
+
color: var(--wire-text-primary);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.wire-checkbox input {
|
|
13
|
+
width: var(--wire-size-icon-md);
|
|
14
|
+
height: var(--wire-size-icon-md);
|
|
15
|
+
accent-color: var(--wire-dark);
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.wire-checkbox:has(input:disabled) {
|
|
20
|
+
color: var(--wire-text-muted);
|
|
21
|
+
cursor: not-allowed;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.wire-checkbox:has(input:disabled) input {
|
|
25
|
+
cursor: not-allowed;
|
|
26
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* Wireframe Kit – text input component. Uses --wire-* tokens only. */
|
|
2
|
+
|
|
3
|
+
.wire-input {
|
|
4
|
+
display: block;
|
|
5
|
+
width: 100%;
|
|
6
|
+
min-inline-size: 0;
|
|
7
|
+
padding: var(--wire-space-md) var(--wire-space-lg);
|
|
8
|
+
font-family: inherit;
|
|
9
|
+
font-size: var(--wire-text-body);
|
|
10
|
+
color: var(--wire-text-primary);
|
|
11
|
+
background-color: var(--wire-surface);
|
|
12
|
+
border: var(--wire-border-width) solid var(--wire-border);
|
|
13
|
+
border-radius: var(--wire-radius-lg);
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.wire-input::placeholder {
|
|
18
|
+
color: var(--wire-text-placeholder);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.wire-input:focus {
|
|
22
|
+
outline: none;
|
|
23
|
+
border-color: var(--wire-dark);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.wire-input:disabled {
|
|
27
|
+
color: var(--wire-text-muted);
|
|
28
|
+
background-color: var(--wire-surface-alt);
|
|
29
|
+
border-color: var(--wire-border-light);
|
|
30
|
+
cursor: not-allowed;
|
|
31
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/* Wireframe Kit – label component. Uses --wire-* tokens only. */
|
|
2
|
+
|
|
3
|
+
.wire-label {
|
|
4
|
+
display: block;
|
|
5
|
+
font-size: var(--wire-text-label);
|
|
6
|
+
font-weight: var(--wire-font-weight-bold);
|
|
7
|
+
color: var(--wire-text-secondary);
|
|
8
|
+
margin-block-end: var(--wire-space-2xs);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.wire-label--required::after {
|
|
12
|
+
content: " *";
|
|
13
|
+
color: var(--wire-text-muted);
|
|
14
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* Wireframe Kit – radio component. Uses --wire-* tokens only. */
|
|
2
|
+
|
|
3
|
+
.wire-radio {
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: var(--wire-space-sm);
|
|
7
|
+
cursor: pointer;
|
|
8
|
+
font-size: var(--wire-text-body);
|
|
9
|
+
color: var(--wire-text-primary);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.wire-radio input {
|
|
13
|
+
width: var(--wire-size-icon-md);
|
|
14
|
+
height: var(--wire-size-icon-md);
|
|
15
|
+
accent-color: var(--wire-dark);
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.wire-radio:has(input:disabled) {
|
|
20
|
+
color: var(--wire-text-muted);
|
|
21
|
+
cursor: not-allowed;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.wire-radio:has(input:disabled) input {
|
|
25
|
+
cursor: not-allowed;
|
|
26
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/* Wireframe Kit – select component. Uses --wire-* tokens only. */
|
|
2
|
+
|
|
3
|
+
.wire-select,
|
|
4
|
+
.wire-select-wrap select {
|
|
5
|
+
display: block;
|
|
6
|
+
width: 100%;
|
|
7
|
+
min-inline-size: 0;
|
|
8
|
+
padding: var(--wire-space-md) var(--wire-space-lg);
|
|
9
|
+
font-family: inherit;
|
|
10
|
+
font-size: var(--wire-text-body);
|
|
11
|
+
color: var(--wire-text-primary);
|
|
12
|
+
background-color: var(--wire-surface);
|
|
13
|
+
border: var(--wire-border-width) solid var(--wire-border);
|
|
14
|
+
border-radius: var(--wire-radius-lg);
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
appearance: auto;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.wire-select:focus,
|
|
21
|
+
.wire-select-wrap select:focus {
|
|
22
|
+
outline: none;
|
|
23
|
+
border-color: var(--wire-dark);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.wire-select:disabled,
|
|
27
|
+
.wire-select-wrap select:disabled {
|
|
28
|
+
color: var(--wire-text-muted);
|
|
29
|
+
background-color: var(--wire-surface-alt);
|
|
30
|
+
border-color: var(--wire-border-light);
|
|
31
|
+
cursor: not-allowed;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Wrapper: hides native arrow and adds chevron via CSS (no icon element). */
|
|
35
|
+
.wire-select-wrap {
|
|
36
|
+
position: relative;
|
|
37
|
+
display: block;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.wire-select-wrap select {
|
|
41
|
+
appearance: none;
|
|
42
|
+
-webkit-appearance: none;
|
|
43
|
+
padding-inline-end: calc(var(--wire-space-lg) + var(--wire-size-icon-sm) + var(--wire-space-sm));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Chevron (Lucide-style) as pseudo-element so no JS or extra HTML is needed. */
|
|
47
|
+
.wire-select-wrap::after {
|
|
48
|
+
content: "";
|
|
49
|
+
position: absolute;
|
|
50
|
+
inset-inline-end: var(--wire-space-md);
|
|
51
|
+
top: 50%;
|
|
52
|
+
transform: translateY(-50%);
|
|
53
|
+
width: var(--wire-size-icon-sm);
|
|
54
|
+
height: var(--wire-size-icon-sm);
|
|
55
|
+
background-color: currentColor;
|
|
56
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat center;
|
|
57
|
+
mask-size: contain;
|
|
58
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat center;
|
|
59
|
+
-webkit-mask-size: contain;
|
|
60
|
+
pointer-events: none;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.wire-select-wrap {
|
|
64
|
+
color: var(--wire-text-muted);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.wire-select-wrap:has(select:disabled) {
|
|
68
|
+
color: var(--wire-text-placeholder);
|
|
69
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* Wireframe Kit – textarea component. Uses --wire-* tokens only. */
|
|
2
|
+
|
|
3
|
+
.wire-textarea {
|
|
4
|
+
display: block;
|
|
5
|
+
width: 100%;
|
|
6
|
+
min-inline-size: 0;
|
|
7
|
+
padding: var(--wire-space-md) var(--wire-space-lg);
|
|
8
|
+
font-family: inherit;
|
|
9
|
+
font-size: var(--wire-text-body);
|
|
10
|
+
line-height: var(--wire-line-height);
|
|
11
|
+
color: var(--wire-text-primary);
|
|
12
|
+
background-color: var(--wire-surface);
|
|
13
|
+
border: var(--wire-border-width) solid var(--wire-border);
|
|
14
|
+
border-radius: var(--wire-radius-lg);
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
resize: vertical;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.wire-textarea::placeholder {
|
|
20
|
+
color: var(--wire-text-placeholder);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.wire-textarea:focus {
|
|
24
|
+
outline: none;
|
|
25
|
+
border-color: var(--wire-dark);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.wire-textarea:disabled {
|
|
29
|
+
color: var(--wire-text-muted);
|
|
30
|
+
background-color: var(--wire-surface-alt);
|
|
31
|
+
border-color: var(--wire-border-light);
|
|
32
|
+
cursor: not-allowed;
|
|
33
|
+
}
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
/* Semantic type aliases */
|
|
42
42
|
--wire-text-body: var(--wire-text-sm);
|
|
43
43
|
--wire-text-caption: var(--wire-text-xs);
|
|
44
|
-
--wire-text-label: var(--wire-text-
|
|
44
|
+
--wire-text-label: var(--wire-text-sm);
|
|
45
45
|
--wire-text-heading: var(--wire-text-2xl);
|
|
46
46
|
--wire-text-subheading: var(--wire-text-xl);
|
|
47
47
|
|
|
@@ -55,6 +55,9 @@
|
|
|
55
55
|
--wire-space-2xl: 24px;
|
|
56
56
|
--wire-space-3xl: 32px;
|
|
57
57
|
|
|
58
|
+
/* Border width – controls and strokes */
|
|
59
|
+
--wire-border-width: 2px;
|
|
60
|
+
|
|
58
61
|
/* Border radius */
|
|
59
62
|
--wire-radius-sm: 4px;
|
|
60
63
|
--wire-radius-md: 6px;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"site": {
|
|
3
|
+
"title": "Wireframe",
|
|
4
|
+
"nav": { "start": "Start", "tokens": "Tokens", "components": "Components" }
|
|
5
|
+
},
|
|
6
|
+
"game": {
|
|
7
|
+
"scoreLabel": " points",
|
|
8
|
+
"inputLabel": "Your word",
|
|
9
|
+
"inputPlaceholder": "Enter a word",
|
|
10
|
+
"submitButton": "Guess",
|
|
11
|
+
"foundHeading": "Found words",
|
|
12
|
+
"hint": "Make words with the letters. Use the center letter in every word.",
|
|
13
|
+
"feedback": {
|
|
14
|
+
"tryAgain": "Try again.",
|
|
15
|
+
"tooShort": "Too short.",
|
|
16
|
+
"missingCenter": "Missing center letter.",
|
|
17
|
+
"invalidLetters": "Invalid letters.",
|
|
18
|
+
"notInList": "Not in word list.",
|
|
19
|
+
"alreadyFound": "Already found.",
|
|
20
|
+
"pangram": "Pangram!",
|
|
21
|
+
"good": "Good!"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
.site-nav {
|
|
2
2
|
display: flex;
|
|
3
|
-
gap:
|
|
4
|
-
padding:
|
|
5
|
-
border-bottom:
|
|
3
|
+
gap: 0;
|
|
4
|
+
padding: 0 var(--wire-space-lg);
|
|
5
|
+
border-bottom: var(--wire-border-width) solid var(--wire-border-light);
|
|
6
6
|
background-color: var(--wire-surface);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
.site-nav a {
|
|
10
10
|
color: var(--wire-text-secondary);
|
|
11
|
+
display: block;
|
|
12
|
+
font-weight: var(--wire-font-weight-bold);
|
|
13
|
+
padding: var(--wire-space-sm) var(--wire-space-md);
|
|
11
14
|
text-decoration: none;
|
|
12
15
|
}
|
|
13
16
|
|
|
@@ -17,5 +20,17 @@
|
|
|
17
20
|
|
|
18
21
|
.site-nav a[aria-current="page"] {
|
|
19
22
|
color: var(--wire-text-primary);
|
|
20
|
-
|
|
23
|
+
position: relative;
|
|
21
24
|
}
|
|
25
|
+
|
|
26
|
+
.site-nav a[aria-current="page"]::after {
|
|
27
|
+
content: "";
|
|
28
|
+
display: block;
|
|
29
|
+
height: var(--wire-border-width);
|
|
30
|
+
background-color: var(--wire-light);
|
|
31
|
+
border-radius: var(--wire-radius-sm) var(--wire-radius-sm) 0 0;
|
|
32
|
+
position: absolute;
|
|
33
|
+
bottom: 0;
|
|
34
|
+
left: 0;
|
|
35
|
+
right: 0;
|
|
36
|
+
}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
@import "../kit/tokens.css";
|
|
2
|
+
@import "../kit/components/button.css";
|
|
3
|
+
@import "../kit/components/input.css";
|
|
4
|
+
@import "../kit/components/textarea.css";
|
|
5
|
+
@import "../kit/components/checkbox.css";
|
|
6
|
+
@import "../kit/components/radio.css";
|
|
7
|
+
@import "../kit/components/select.css";
|
|
8
|
+
@import "../kit/components/label.css";
|
|
9
|
+
@import "../kit/components/field.css";
|
|
2
10
|
@import "base.css";
|
|
3
11
|
@import "layout.css";
|
|
4
12
|
@import "components/nav.css";
|
|
5
13
|
@import "pages/start.css";
|
|
6
14
|
@import "pages/tokens-showcase.css";
|
|
15
|
+
@import "pages/components-showcase.css";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* Components showcase page. Reuses .showcase-section from tokens-showcase. */
|
|
2
|
+
|
|
3
|
+
.components-showcase-intro {
|
|
4
|
+
margin-block-end: var(--wire-space-2xl);
|
|
5
|
+
color: var(--wire-text-muted);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.components-showcase code {
|
|
9
|
+
padding: var(--wire-space-2xs) 0;
|
|
10
|
+
background-color: var(--wire-surface-alt);
|
|
11
|
+
border-radius: var(--wire-radius-sm);
|
|
12
|
+
font-family: "Monaspace Argon", monospace;
|
|
13
|
+
font-size: var(--wire-text-xs);
|
|
14
|
+
color: #c41;
|
|
15
|
+
white-space: nowrap;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.component-demo-row {
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-wrap: wrap;
|
|
21
|
+
gap: var(--wire-space-md);
|
|
22
|
+
align-items: center;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.component-demo-block {
|
|
26
|
+
max-inline-size: 20rem;
|
|
27
|
+
margin-block-end: var(--wire-space-lg);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.component-demo-block:last-child {
|
|
31
|
+
margin-block-end: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.component-demo-stack {
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
gap: var(--wire-space-md);
|
|
38
|
+
}
|
|
@@ -48,47 +48,53 @@
|
|
|
48
48
|
--width: 3.25em;
|
|
49
49
|
--height: calc(var(--width) * 0.8660254);
|
|
50
50
|
--gap: var(--wire-space-xs);
|
|
51
|
+
box-sizing: content-box;
|
|
51
52
|
position: relative;
|
|
52
53
|
height: calc(3 * var(--height) + 2 * var(--gap));
|
|
53
54
|
width: calc(2.5 * var(--width) + 2 * 1.1547 * var(--gap));
|
|
54
55
|
margin-block-end: var(--wire-space-2xl);
|
|
55
56
|
margin-inline: auto;
|
|
57
|
+
padding: calc(var(--height) / 2 - var(--gap)) calc(var(--width) / 2 - var(--gap));
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
/* DOM order: 1=E(center), 2=W, 3=I, 4=R, 5=F, 6=A, 7=M */
|
|
61
|
+
.bee-honeycomb .bee-letter:nth-child(1) {
|
|
62
|
+
transform: scale(var(--bee-scale, 1));
|
|
63
|
+
}
|
|
59
64
|
.bee-honeycomb .bee-letter:nth-child(2) {
|
|
60
|
-
transform: translate(0, calc(-1 * var(--height) - var(--gap)));
|
|
65
|
+
transform: translate(0, calc(-1 * var(--height) - var(--gap))) scale(var(--bee-scale, 1));
|
|
61
66
|
}
|
|
62
67
|
.bee-honeycomb .bee-letter:nth-child(3) {
|
|
63
68
|
transform: translate(
|
|
64
69
|
calc(0.75 * var(--width) + 1.1547 * var(--gap)),
|
|
65
70
|
calc(-0.5 * var(--height) - 0.5 * var(--gap))
|
|
66
|
-
);
|
|
71
|
+
) scale(var(--bee-scale, 1));
|
|
67
72
|
}
|
|
68
73
|
.bee-honeycomb .bee-letter:nth-child(4) {
|
|
69
74
|
transform: translate(
|
|
70
75
|
calc(0.75 * var(--width) + 1.1547 * var(--gap)),
|
|
71
76
|
calc(0.5 * var(--height) + 0.5 * var(--gap))
|
|
72
|
-
);
|
|
77
|
+
) scale(var(--bee-scale, 1));
|
|
73
78
|
}
|
|
74
79
|
.bee-honeycomb .bee-letter:nth-child(5) {
|
|
75
80
|
transform: translate(
|
|
76
81
|
calc(-0.75 * var(--width) - 1.1547 * var(--gap)),
|
|
77
82
|
calc(-0.5 * var(--height) - 0.5 * var(--gap))
|
|
78
|
-
);
|
|
83
|
+
) scale(var(--bee-scale, 1));
|
|
79
84
|
}
|
|
80
85
|
.bee-honeycomb .bee-letter:nth-child(6) {
|
|
81
86
|
transform: translate(
|
|
82
87
|
calc(-0.75 * var(--width) - 1.1547 * var(--gap)),
|
|
83
88
|
calc(0.5 * var(--height) + 0.5 * var(--gap))
|
|
84
|
-
);
|
|
89
|
+
) scale(var(--bee-scale, 1));
|
|
85
90
|
}
|
|
86
91
|
.bee-honeycomb .bee-letter:nth-child(7) {
|
|
87
|
-
transform: translate(0, calc(var(--height) + var(--gap)));
|
|
92
|
+
transform: translate(0, calc(var(--height) + var(--gap))) scale(var(--bee-scale, 1));
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
.bee-letter {
|
|
91
96
|
--bee-hex: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
|
|
97
|
+
--bee-scale: 1;
|
|
92
98
|
position: absolute;
|
|
93
99
|
left: 50%;
|
|
94
100
|
top: 50%;
|
|
@@ -103,6 +109,12 @@
|
|
|
103
109
|
font-size: var(--wire-text-xl);
|
|
104
110
|
font-weight: var(--wire-font-weight-bold);
|
|
105
111
|
color: var(--wire-text-primary);
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
transition: transform 50ms ease-out;
|
|
114
|
+
}
|
|
115
|
+
.bee-letter:active,
|
|
116
|
+
.bee-letter.bee-letter--typed-press {
|
|
117
|
+
--bee-scale: 0.92;
|
|
106
118
|
}
|
|
107
119
|
|
|
108
120
|
.bee-letter::before {
|
|
@@ -134,6 +146,10 @@
|
|
|
134
146
|
background-color: var(--wire-dark);
|
|
135
147
|
}
|
|
136
148
|
|
|
149
|
+
.bee-focus-region:focus {
|
|
150
|
+
outline: none;
|
|
151
|
+
}
|
|
152
|
+
|
|
137
153
|
/* Word input row */
|
|
138
154
|
.bee-input-row {
|
|
139
155
|
display: flex;
|
|
@@ -149,7 +165,7 @@
|
|
|
149
165
|
font-size: var(--wire-text-body);
|
|
150
166
|
color: var(--wire-text-primary);
|
|
151
167
|
background-color: var(--wire-surface);
|
|
152
|
-
border:
|
|
168
|
+
border: var(--wire-border-width) solid var(--wire-border);
|
|
153
169
|
border-radius: var(--wire-radius-lg);
|
|
154
170
|
}
|
|
155
171
|
|
|
@@ -157,7 +173,8 @@
|
|
|
157
173
|
color: var(--wire-text-placeholder);
|
|
158
174
|
}
|
|
159
175
|
|
|
160
|
-
.bee-input:focus
|
|
176
|
+
.bee-input:focus,
|
|
177
|
+
.game-area:focus-within .bee-input {
|
|
161
178
|
outline: none;
|
|
162
179
|
border-color: var(--wire-dark);
|
|
163
180
|
}
|
|
@@ -169,7 +186,7 @@
|
|
|
169
186
|
font-weight: var(--wire-font-weight-bold);
|
|
170
187
|
color: var(--wire-white);
|
|
171
188
|
background-color: var(--wire-dark);
|
|
172
|
-
border:
|
|
189
|
+
border: var(--wire-border-width) solid var(--wire-dark);
|
|
173
190
|
border-radius: var(--wire-radius-lg);
|
|
174
191
|
cursor: pointer;
|
|
175
192
|
}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
+
/* Code font/color for this page only – not part of the wireframe kit. */
|
|
2
|
+
@import "@fontsource/monaspace-argon/400.css";
|
|
3
|
+
|
|
1
4
|
.token-showcase-intro {
|
|
2
5
|
margin-block-end: var(--wire-space-2xl);
|
|
3
6
|
color: var(--wire-text-muted);
|
|
4
7
|
}
|
|
5
8
|
|
|
6
9
|
.token-showcase code {
|
|
7
|
-
padding: var(--wire-space-2xs)
|
|
10
|
+
padding: var(--wire-space-2xs) 0;
|
|
8
11
|
background-color: var(--wire-surface-alt);
|
|
9
12
|
border-radius: var(--wire-radius-sm);
|
|
10
|
-
font-
|
|
13
|
+
font-family: "Monaspace Argon", monospace;
|
|
14
|
+
font-size: var(--wire-text-xs);
|
|
15
|
+
color: #c41;
|
|
16
|
+
white-space: nowrap;
|
|
11
17
|
}
|
|
12
18
|
|
|
13
19
|
.showcase-section {
|
|
@@ -69,7 +75,7 @@
|
|
|
69
75
|
aspect-ratio: 1;
|
|
70
76
|
border-radius: var(--wire-radius-md);
|
|
71
77
|
flex-shrink: 0;
|
|
72
|
-
border:
|
|
78
|
+
border: var(--wire-border-width) solid var(--wire-dark);
|
|
73
79
|
}
|
|
74
80
|
|
|
75
81
|
.swatch figcaption {
|
|
@@ -220,3 +226,8 @@
|
|
|
220
226
|
.type-scale-line:last-of-type {
|
|
221
227
|
margin-block-end: 0;
|
|
222
228
|
}
|
|
229
|
+
|
|
230
|
+
.type-scale--semantic .type-scale-line code {
|
|
231
|
+
display: block;
|
|
232
|
+
margin-block-start: var(--wire-space-2xs);
|
|
233
|
+
}
|
package/template/tokens.html
CHANGED
|
@@ -7,10 +7,7 @@
|
|
|
7
7
|
<title>Tokens – Wireframe</title>
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
10
|
-
|
|
11
|
-
<a href="/">Start</a>
|
|
12
|
-
<a href="/tokens.html" aria-current="page">Tokens</a>
|
|
13
|
-
</nav>
|
|
10
|
+
{% include "_partials/nav.html" %}
|
|
14
11
|
<main class="token-showcase">
|
|
15
12
|
<h1>Design tokens</h1>
|
|
16
13
|
<p class="token-showcase-intro">This page shows the wireframe kit tokens. Use them in your CSS with <code>var(--wire-*)</code>.</p>
|
|
@@ -154,24 +151,24 @@
|
|
|
154
151
|
<div class="typography-two-col">
|
|
155
152
|
<div>
|
|
156
153
|
<h3 class="type-scale-heading">Type scale</h3>
|
|
157
|
-
<div class="type-scale">
|
|
158
|
-
<p class="type-scale-line" style="font-size: var(--wire-text-2xs);">Sample text
|
|
159
|
-
<p class="type-scale-line" style="font-size: var(--wire-text-xs);">Sample text
|
|
160
|
-
<p class="type-scale-line" style="font-size: var(--wire-text-sm);">Sample text
|
|
161
|
-
<p class="type-scale-line" style="font-size: var(--wire-text-base);">Sample text
|
|
162
|
-
<p class="type-scale-line" style="font-size: var(--wire-text-lg);">Sample text
|
|
163
|
-
<p class="type-scale-line" style="font-size: var(--wire-text-xl);">Sample text
|
|
164
|
-
<p class="type-scale-line" style="font-size: var(--wire-text-2xl);">Sample text
|
|
154
|
+
<div class="type-scale type-scale--semantic">
|
|
155
|
+
<p class="type-scale-line" style="font-size: var(--wire-text-2xs);">Sample text<code>--wire-text-2xs</code></p>
|
|
156
|
+
<p class="type-scale-line" style="font-size: var(--wire-text-xs);">Sample text<code>--wire-text-xs</code></p>
|
|
157
|
+
<p class="type-scale-line" style="font-size: var(--wire-text-sm);">Sample text<code>--wire-text-sm</code></p>
|
|
158
|
+
<p class="type-scale-line" style="font-size: var(--wire-text-base);">Sample text<code>--wire-text-base</code></p>
|
|
159
|
+
<p class="type-scale-line" style="font-size: var(--wire-text-lg);">Sample text<code>--wire-text-lg</code></p>
|
|
160
|
+
<p class="type-scale-line" style="font-size: var(--wire-text-xl);">Sample text<code>--wire-text-xl</code></p>
|
|
161
|
+
<p class="type-scale-line" style="font-size: var(--wire-text-2xl);">Sample text<code>--wire-text-2xl</code></p>
|
|
165
162
|
</div>
|
|
166
163
|
</div>
|
|
167
164
|
<div>
|
|
168
165
|
<h3 class="type-scale-heading">Semantic type</h3>
|
|
169
|
-
<div class="type-scale">
|
|
170
|
-
<p class="type-scale-line" style="font-size: var(--wire-text-body);">Body text
|
|
171
|
-
<p class="type-scale-line" style="font-size: var(--wire-text-heading);">Heading
|
|
172
|
-
<p class="type-scale-line" style="font-size: var(--wire-text-subheading);">Subheading
|
|
173
|
-
<p class="type-scale-line" style="font-size: var(--wire-text-caption);">Caption
|
|
174
|
-
<p class="type-scale-line" style="font-size: var(--wire-text-label);">Label
|
|
166
|
+
<div class="type-scale type-scale--semantic">
|
|
167
|
+
<p class="type-scale-line" style="font-size: var(--wire-text-body);">Body text<code>--wire-text-body</code></p>
|
|
168
|
+
<p class="type-scale-line" style="font-size: var(--wire-text-heading);">Heading<code>--wire-text-heading</code></p>
|
|
169
|
+
<p class="type-scale-line" style="font-size: var(--wire-text-subheading);">Subheading<code>--wire-text-subheading</code></p>
|
|
170
|
+
<p class="type-scale-line" style="font-size: var(--wire-text-caption);">Caption<code>--wire-text-caption</code></p>
|
|
171
|
+
<p class="type-scale-line" style="font-size: var(--wire-text-label);">Label<code>--wire-text-label</code></p>
|
|
175
172
|
</div>
|
|
176
173
|
</div>
|
|
177
174
|
</div>
|
package/template/vite.config.js
CHANGED
|
@@ -1,14 +1,30 @@
|
|
|
1
|
-
import { readdirSync } from "fs";
|
|
2
|
-
import { resolve } from "path";
|
|
1
|
+
import { readFileSync, readdirSync } from "fs";
|
|
2
|
+
import { dirname, resolve } from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
3
4
|
import { defineConfig } from "vite";
|
|
5
|
+
import nunjucks from "vite-plugin-nunjucks";
|
|
4
6
|
|
|
5
|
-
const root =
|
|
7
|
+
const root = dirname(fileURLToPath(import.meta.url));
|
|
6
8
|
const htmlFiles = readdirSync(root).filter((f) => f.endsWith(".html"));
|
|
7
9
|
const input = Object.fromEntries(
|
|
8
10
|
htmlFiles.map((f) => [f.replace(/\.html$/, ""), resolve(root, f)])
|
|
9
11
|
);
|
|
10
12
|
|
|
13
|
+
const strings = JSON.parse(
|
|
14
|
+
readFileSync(resolve(root, "src/strings.json"), "utf-8")
|
|
15
|
+
);
|
|
16
|
+
|
|
11
17
|
export default defineConfig({
|
|
18
|
+
plugins: [
|
|
19
|
+
nunjucks({
|
|
20
|
+
templatesDir: root,
|
|
21
|
+
variables: {
|
|
22
|
+
"index.html": { ...strings, current: "start" },
|
|
23
|
+
"tokens.html": { ...strings, current: "tokens" },
|
|
24
|
+
"components.html": { ...strings, current: "components" },
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
|
+
],
|
|
12
28
|
build: {
|
|
13
29
|
rollupOptions: { input },
|
|
14
30
|
},
|