htmlboard 0.3.0 โ†’ 0.4.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/README.md CHANGED
@@ -59,7 +59,7 @@ htmlboard
59
59
 
60
60
  ### Scaffold a Starter Project
61
61
 
62
- To start with sample designs (a folder of screens and a folder of components, each file describing itself):
62
+ To start with sample designs (a folder of screens and a folder of components, each file describing itself, all sharing one `styles.css`):
63
63
 
64
64
  ```bash
65
65
  npx htmlboard --init
@@ -180,6 +180,8 @@ Every `.html` file under the folder is a design (hidden folders, `node_modules`,
180
180
 
181
181
  **Categories** drive the filters. Left out, they come from words in the path, then from the size when it is a screen's (a phone's width, a tablet's 3:4, a desktop's landscape); flyers, boards and other formats get none and show under **All**.
182
182
 
183
+ **Shared styles.** Designs link one stylesheet for what they share (tokens, base styles, components) and keep only their own CSS in their `<style>`, so they stay consistent and each new design is shorter to write. The samples use a `styles.css` at the top of the folder (`<link rel="stylesheet" href="../styles.css">`), and the agent skill tells LLMs to read it, use it and grow it. Editing it reloads every design that links it.
184
+
183
185
  ---
184
186
 
185
187
  ## ๐Ÿ“‹ `designs.json` (Optional)
@@ -298,6 +300,7 @@ htmlboard/
298
300
  โ”‚ โ”‚ โ”œโ”€โ”€ favicon.svg, logo.svg, mark.svg
299
301
  โ”‚ โ”‚ โ””โ”€โ”€ fonts/ # Inter and Bricolage Grotesque (OFL)
300
302
  โ”‚ โ””โ”€โ”€ templates/ # The sample designs `--init` adds
303
+ โ”‚ โ”œโ”€โ”€ styles.css # Their shared tokens and components
301
304
  โ”‚ โ”œโ”€โ”€ 01-screens/ # Desktop dashboard, mobile feed
302
305
  โ”‚ โ””โ”€โ”€ 02-components/
303
306
  โ”œโ”€โ”€ skills/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "htmlboard",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Infinite canvas and design explorer for HTML artboards โ€” designed for humans and LLMs",
5
5
  "type": "module",
6
6
  "bin": {
@@ -23,7 +23,7 @@ npx htmlboard designs --open
23
23
 
24
24
  ## Write an artboard
25
25
 
26
- One design per file, self-contained so it renders on its own, with its facts in the `<head>`:
26
+ One design per file, with its facts in the `<head>`, linking the shared stylesheet (see below):
27
27
 
28
28
  ```html
29
29
  <!DOCTYPE html>
@@ -33,9 +33,9 @@ One design per file, self-contained so it renders on its own, with its facts in
33
33
  <title>Checkout ยท one page</title> <!-- its name on the canvas -->
34
34
  <meta name="description" content="Address and payment on one screen">
35
35
  <meta name="htmlboard" content="width=390, height=844"> <!-- its size -->
36
+ <link rel="stylesheet" href="../styles.css"> <!-- shared tokens and components -->
36
37
  <style>
37
- body { margin: 0; }
38
- .screen { width: 390px; height: 844px; /* โ€ฆ */ }
38
+ .screen { height: 844px; /* only what this design needs */ }
39
39
  </style>
40
40
  </head>
41
41
  <body>
@@ -47,9 +47,20 @@ One design per file, self-contained so it renders on its own, with its facts in
47
47
  - Always give the `width`: it is the frame's viewport, and the page's CSS needs it. Give the `height` for fixed sizes (a phone screen, a flyer: the frame cuts at it); leave it out for pages that should grow with their content.
48
48
  - Design at the real size of the target: phone 390ร—844, tablet 768ร—1024, desktop 1280ร—800 (or 1440ร—900), and the exact size for print or social formats (e.g. 1080ร—1350).
49
49
  - Use real content in the user's language, not lorem ipsum.
50
- - Relative links to shared CSS, images, scripts and fonts work (`assets/logo.svg`; `../css/theme.css` with `--root`). Reuse the project's own stylesheet and tokens when there is one.
50
+ - Relative links to CSS, images, scripts and fonts work (`assets/logo.svg`; `../css/theme.css` with `--root`).
51
51
  - No build step: plain HTML, CSS and browser JavaScript (ES modules and CDN scripts work).
52
52
 
53
+ ## Shared styles
54
+
55
+ Put what the designs share in one stylesheet instead of repeating it in every file: it keeps the designs consistent and spares writing the same CSS again.
56
+
57
+ - The designs folder has a `styles.css` at its top (sample projects start with one). Read it before writing a design and use its tokens (`var(--accent)`) and classes (`.btn`, `.card`, โ€ฆ).
58
+ - If there is none and the project already has a stylesheet or design tokens, link those. Otherwise create `styles.css` with your first design: colors, type and spacing as custom properties, the base styles, and the components you'll repeat.
59
+ - Link it with a relative path: `styles.css` from the top of the folder, `../styles.css` from a section folder.
60
+ - A design's own `<style>` holds only what is specific to it. When a second design needs the same thing, move it to `styles.css`.
61
+ - Split it when it grows (`components/forms.css`, `charts.css`) and link the extra files where they are used.
62
+ - Editing `styles.css` restyles every design that links it, which is the point for a product's screens. For one-off explorations that should keep their look (a different style, logo options), style them in their own file instead.
63
+
53
64
  More tags, all optional:
54
65
 
55
66
  - `category=โ€ฆ` in the `htmlboard` tag files the design under the explorer's filters: `mobile`, `tablet`, `desktop`, `components` or your own word. Usually not needed: it comes from words in the path, then from the size when it is a screen's.
@@ -6,30 +6,9 @@
6
6
  <title>Desktop Dashboard</title>
7
7
  <meta name="description" content="Main analytics dashboard with sidebar, metric cards, and charts">
8
8
  <meta name="htmlboard" content="width=1280, height=820">
9
+ <link rel="stylesheet" href="../styles.css">
9
10
  <style>
10
- * {
11
- box-sizing: border-box;
12
- margin: 0;
13
- padding: 0;
14
- -webkit-font-smoothing: antialiased;
15
- }
16
- :root {
17
- --bg: #0b0d13;
18
- --sidebar-bg: #10131d;
19
- --panel-bg: #151824;
20
- --border: #23283c;
21
- --accent: #6366f1;
22
- --accent-light: #818cf8;
23
- --text: #f1f5f9;
24
- --text-muted: #94a3b8;
25
- --emerald: #10b981;
26
- --amber: #f59e0b;
27
- --purple: #a855f7;
28
- }
29
11
  body {
30
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
31
- background: var(--bg);
32
- color: var(--text);
33
12
  display: flex;
34
13
  height: 100vh;
35
14
  overflow: hidden;
@@ -37,7 +16,7 @@
37
16
  /* Sidebar */
38
17
  .sidebar {
39
18
  width: 240px;
40
- background: var(--sidebar-bg);
19
+ background: #10131d;
41
20
  border-right: 1px solid var(--border);
42
21
  display: flex;
43
22
  flex-direction: column;
@@ -45,10 +24,8 @@
45
24
  flex-shrink: 0;
46
25
  }
47
26
  .logo-container {
48
- display: flex;
49
- align-items: center;
50
- gap: 10px;
51
27
  padding: 4px 8px 24px;
28
+ gap: 10px;
52
29
  font-weight: 700;
53
30
  font-size: 17px;
54
31
  letter-spacing: -0.02em;
@@ -56,8 +33,8 @@
56
33
  .logo-badge {
57
34
  width: 32px;
58
35
  height: 32px;
59
- background: linear-gradient(135deg, #6366f1, #3b82f6);
60
- border-radius: 8px;
36
+ background: linear-gradient(135deg, var(--accent), #3b82f6);
37
+ border-radius: var(--radius);
61
38
  display: flex;
62
39
  align-items: center;
63
40
  justify-content: center;
@@ -70,22 +47,14 @@
70
47
  gap: 4px;
71
48
  flex: 1;
72
49
  }
73
- .nav-label {
74
- font-size: 11px;
75
- text-transform: uppercase;
76
- letter-spacing: 0.08em;
77
- color: #64748b;
78
- padding: 8px 12px 4px;
79
- font-weight: 600;
80
- }
50
+ .nav-group .label { padding: 8px 12px 4px; font-size: 11px; }
81
51
  .nav-link {
82
52
  display: flex;
83
53
  align-items: center;
84
54
  gap: 12px;
85
55
  padding: 10px 12px;
86
- border-radius: 8px;
56
+ border-radius: var(--radius);
87
57
  color: var(--text-muted);
88
- text-decoration: none;
89
58
  font-size: 14px;
90
59
  font-weight: 500;
91
60
  transition: all 0.15s ease;
@@ -100,25 +69,12 @@
100
69
  font-weight: 600;
101
70
  }
102
71
  .user-footer {
103
- display: flex;
104
- align-items: center;
105
- gap: 12px;
106
72
  padding: 12px;
107
73
  border-radius: 10px;
108
74
  background: rgba(255, 255, 255, 0.03);
109
75
  border: 1px solid var(--border);
110
76
  }
111
- .user-avatar {
112
- width: 36px;
113
- height: 36px;
114
- border-radius: 50%;
115
- background: linear-gradient(135deg, #ec4899, #8b5cf6);
116
- display: flex;
117
- align-items: center;
118
- justify-content: center;
119
- font-weight: 600;
120
- font-size: 14px;
121
- }
77
+ .user-footer .avatar { background: linear-gradient(135deg, #ec4899, #8b5cf6); font-weight: 600; }
122
78
  /* Main Content */
123
79
  .main {
124
80
  flex: 1;
@@ -126,7 +82,6 @@
126
82
  flex-direction: column;
127
83
  overflow-y: auto;
128
84
  }
129
- /* Top Header */
130
85
  .topbar {
131
86
  height: 64px;
132
87
  border-bottom: 1px solid var(--border);
@@ -137,114 +92,51 @@
137
92
  background: rgba(11, 13, 19, 0.8);
138
93
  backdrop-filter: blur(12px);
139
94
  }
140
- .search-input {
141
- background: var(--panel-bg);
142
- border: 1px solid var(--border);
143
- padding: 8px 16px 8px 36px;
144
- border-radius: 8px;
145
- color: var(--text);
146
- font-size: 13px;
147
- width: 280px;
148
- position: relative;
149
- }
150
- .header-actions {
151
- display: flex;
152
- align-items: center;
153
- gap: 16px;
154
- }
155
- .primary-btn {
156
- background: var(--accent);
157
- color: #fff;
158
- border: none;
159
- padding: 8px 18px;
160
- border-radius: 8px;
161
- font-size: 13px;
162
- font-weight: 600;
163
- cursor: pointer;
164
- box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
165
- }
166
- /* Dashboard Area */
95
+ .topbar .input { width: 280px; padding: 8px 16px; }
96
+ .topbar .row { gap: 16px; font-size: 13px; }
167
97
  .content {
168
98
  padding: 28px 32px;
169
99
  display: flex;
170
100
  flex-direction: column;
171
101
  gap: 24px;
172
102
  }
173
- .page-header {
174
- display: flex;
175
- justify-content: space-between;
176
- align-items: flex-end;
177
- }
178
103
  .page-title {
179
104
  font-size: 24px;
180
105
  font-weight: 700;
181
106
  letter-spacing: -0.02em;
182
107
  }
183
- .page-sub {
184
- color: var(--text-muted);
185
- font-size: 14px;
186
- margin-top: 4px;
187
- }
108
+ .page-sub { font-size: 14px; margin-top: 4px; }
188
109
  /* Stat Cards */
189
110
  .stats-row {
190
111
  display: grid;
191
112
  grid-template-columns: repeat(4, 1fr);
192
113
  gap: 20px;
193
114
  }
194
- .stat-card {
195
- background: var(--panel-bg);
196
- border: 1px solid var(--border);
197
- border-radius: 14px;
198
- padding: 20px;
199
- }
200
- .stat-title {
201
- font-size: 13px;
202
- color: var(--text-muted);
203
- margin-bottom: 8px;
204
- }
115
+ .stat-title { font-size: 13px; margin-bottom: 8px; }
205
116
  .stat-val {
206
117
  font-size: 26px;
207
118
  font-weight: 700;
208
119
  margin-bottom: 8px;
209
120
  }
210
- .stat-badge {
211
- font-size: 12px;
212
- font-weight: 600;
213
- display: inline-flex;
214
- align-items: center;
215
- gap: 4px;
216
- }
121
+ .stat-badge { font-size: 12px; font-weight: 600; }
217
122
  .stat-badge.pos { color: var(--emerald); }
218
123
  .stat-badge.warn { color: var(--amber); }
219
-
220
- /* Visual Grid */
124
+ /* Panels */
221
125
  .grid-2 {
222
126
  display: grid;
223
127
  grid-template-columns: 2fr 1fr;
224
128
  gap: 20px;
225
129
  }
226
- .panel {
227
- background: var(--panel-bg);
228
- border: 1px solid var(--border);
229
- border-radius: 14px;
230
- padding: 22px;
231
- }
130
+ .grid-2 .card { padding: 22px; }
232
131
  .panel-header {
233
132
  display: flex;
234
133
  justify-content: space-between;
235
134
  align-items: center;
236
135
  margin-bottom: 20px;
136
+ font-size: 12px;
237
137
  }
238
- .panel-title {
239
- font-size: 16px;
240
- font-weight: 600;
241
- }
242
- /* Chart SVG */
243
- .chart-container {
244
- width: 100%;
245
- height: 180px;
246
- }
247
- /* Table */
138
+ .panel-title { font-size: 16px; font-weight: 600; }
139
+ .chart-container { width: 100%; height: 180px; }
248
140
  .data-table {
249
141
  width: 100%;
250
142
  border-collapse: collapse;
@@ -252,7 +144,7 @@
252
144
  }
253
145
  .data-table th {
254
146
  text-align: left;
255
- color: #64748b;
147
+ color: var(--text-subtle);
256
148
  font-weight: 500;
257
149
  padding-bottom: 12px;
258
150
  border-bottom: 1px solid var(--border);
@@ -261,90 +153,80 @@
261
153
  padding: 12px 0;
262
154
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
263
155
  }
264
- .status-pill {
265
- display: inline-block;
266
- padding: 3px 8px;
267
- border-radius: 12px;
268
- font-size: 11px;
269
- font-weight: 600;
270
- }
271
- .status-pill.success { background: rgba(16, 185, 129, 0.15); color: var(--emerald); }
272
- .status-pill.pending { background: rgba(245, 158, 11, 0.15); color: var(--amber); }
156
+ .data-table .badge { padding: 3px 8px; font-size: 11px; }
273
157
  </style>
274
158
  </head>
275
159
  <body>
276
160
  <aside class="sidebar">
277
- <div class="logo-container">
161
+ <div class="logo-container row">
278
162
  <div class="logo-badge">โšก</div>
279
163
  <span>Nexus Platform</span>
280
164
  </div>
281
165
 
282
166
  <nav class="nav-group">
283
- <div class="nav-label">Core</div>
167
+ <div class="label">Core</div>
284
168
  <a href="#" class="nav-link active">๐Ÿ“Š Dashboard</a>
285
169
  <a href="#" class="nav-link">๐Ÿ‘ฅ Customers</a>
286
170
  <a href="#" class="nav-link">๐Ÿ’ณ Invoices</a>
287
171
  <a href="#" class="nav-link">๐Ÿ“ˆ Analytics</a>
288
172
 
289
- <div class="nav-label" style="margin-top: 16px;">System</div>
173
+ <div class="label" style="margin-top: 16px">System</div>
290
174
  <a href="#" class="nav-link">โš™๏ธ Settings</a>
291
175
  <a href="#" class="nav-link">๐Ÿ›ก๏ธ Security</a>
292
176
  </nav>
293
177
 
294
- <div class="user-footer">
295
- <div class="user-avatar">AD</div>
178
+ <div class="user-footer row">
179
+ <div class="avatar">AD</div>
296
180
  <div>
297
- <div style="font-size: 13px; font-weight: 600;">Alex Morgan</div>
298
- <div style="font-size: 11px; color: var(--text-muted);">alex@nexus.io</div>
181
+ <div style="font-size: 13px; font-weight: 600">Alex Morgan</div>
182
+ <div class="muted" style="font-size: 11px">alex@nexus.io</div>
299
183
  </div>
300
184
  </div>
301
185
  </aside>
302
186
 
303
187
  <main class="main">
304
188
  <header class="topbar">
305
- <input type="text" class="search-input" placeholder="Search resources, clients, reports...">
306
- <div class="header-actions">
307
- <span style="font-size: 13px; color: var(--text-muted);">Last sync: Just now</span>
308
- <button class="primary-btn">+ New Deployment</button>
189
+ <input type="text" class="input" placeholder="Search resources, clients, reports...">
190
+ <div class="row">
191
+ <span class="muted">Last sync: Just now</span>
192
+ <button class="btn btn-primary">+ New Deployment</button>
309
193
  </div>
310
194
  </header>
311
195
 
312
196
  <div class="content">
313
- <div class="page-header">
314
- <div>
315
- <h1 class="page-title">Executive Overview</h1>
316
- <p class="page-sub">Performance metrics and active client deployments</p>
317
- </div>
197
+ <div>
198
+ <h1 class="page-title">Executive Overview</h1>
199
+ <p class="page-sub muted">Performance metrics and active client deployments</p>
318
200
  </div>
319
201
 
320
202
  <div class="stats-row">
321
- <div class="stat-card">
322
- <div class="stat-title">Monthly Recurring Revenue</div>
203
+ <div class="card">
204
+ <div class="stat-title muted">Monthly Recurring Revenue</div>
323
205
  <div class="stat-val">$184,290</div>
324
206
  <div class="stat-badge pos">โ–ฒ +12.4% vs last mo</div>
325
207
  </div>
326
- <div class="stat-card">
327
- <div class="stat-title">Active Organizations</div>
208
+ <div class="card">
209
+ <div class="stat-title muted">Active Organizations</div>
328
210
  <div class="stat-val">1,428</div>
329
211
  <div class="stat-badge pos">โ–ฒ +48 new</div>
330
212
  </div>
331
- <div class="stat-card">
332
- <div class="stat-title">API Requests (24h)</div>
213
+ <div class="card">
214
+ <div class="stat-title muted">API Requests (24h)</div>
333
215
  <div class="stat-val">42.8M</div>
334
216
  <div class="stat-badge pos">โ–ฒ 99.98% uptime</div>
335
217
  </div>
336
- <div class="stat-card">
337
- <div class="stat-title">Average Latency</div>
218
+ <div class="card">
219
+ <div class="stat-title muted">Average Latency</div>
338
220
  <div class="stat-val">34ms</div>
339
221
  <div class="stat-badge warn">โ–ผ -2ms target</div>
340
222
  </div>
341
223
  </div>
342
224
 
343
225
  <div class="grid-2">
344
- <div class="panel">
226
+ <div class="card">
345
227
  <div class="panel-header">
346
228
  <h2 class="panel-title">Throughput & Workload Trends</h2>
347
- <span style="font-size: 12px; color: var(--text-muted);">Trailing 7 Days</span>
229
+ <span class="muted">Trailing 7 Days</span>
348
230
  </div>
349
231
  <div class="chart-container">
350
232
  <svg viewBox="0 0 500 150" width="100%" height="100%" preserveAspectRatio="none">
@@ -361,7 +243,7 @@
361
243
  </div>
362
244
  </div>
363
245
 
364
- <div class="panel">
246
+ <div class="card">
365
247
  <div class="panel-header">
366
248
  <h2 class="panel-title">Recent Audits</h2>
367
249
  </div>
@@ -375,19 +257,19 @@
375
257
  <tbody>
376
258
  <tr>
377
259
  <td>us-east-cluster-01</td>
378
- <td><span class="status-pill success">Optimal</span></td>
260
+ <td><span class="badge badge-emerald">Optimal</span></td>
379
261
  </tr>
380
262
  <tr>
381
263
  <td>auth-gateway-proxy</td>
382
- <td><span class="status-pill success">Optimal</span></td>
264
+ <td><span class="badge badge-emerald">Optimal</span></td>
383
265
  </tr>
384
266
  <tr>
385
267
  <td>edge-cache-frankfurt</td>
386
- <td><span class="status-pill pending">Rebalancing</span></td>
268
+ <td><span class="badge badge-amber">Rebalancing</span></td>
387
269
  </tr>
388
270
  <tr>
389
271
  <td>db-replica-primary</td>
390
- <td><span class="status-pill success">Optimal</span></td>
272
+ <td><span class="badge badge-emerald">Optimal</span></td>
391
273
  </tr>
392
274
  </tbody>
393
275
  </table>
@@ -6,39 +6,19 @@
6
6
  <title>Mobile Feed Screen</title>
7
7
  <meta name="description" content="Smartphone screen with balance card, quick actions, and transaction feed">
8
8
  <meta name="htmlboard" content="width=390, height=844">
9
+ <link rel="stylesheet" href="../styles.css">
9
10
  <style>
10
- * {
11
- box-sizing: border-box;
12
- margin: 0;
13
- padding: 0;
14
- -webkit-font-smoothing: antialiased;
15
- }
16
- :root {
17
- --bg: #090a0f;
18
- --card-bg: #13151f;
19
- --card-border: #232738;
20
- --accent: #6366f1;
21
- --accent-glow: rgba(99, 102, 241, 0.35);
22
- --emerald: #10b981;
23
- --rose: #f43f5e;
24
- --text-main: #f8fafc;
25
- --text-muted: #94a3b8;
26
- }
27
11
  body {
28
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
29
- background: var(--bg);
30
- color: var(--text-main);
31
12
  min-height: 100vh;
32
13
  display: flex;
33
14
  flex-direction: column;
34
15
  overflow-x: hidden;
35
16
  padding-bottom: 80px;
17
+ background: #090a0f;
36
18
  }
37
- /* Status bar simulated */
38
19
  .status-bar {
39
20
  display: flex;
40
21
  justify-content: space-between;
41
- align-items: center;
42
22
  padding: 14px 24px 8px;
43
23
  font-size: 13px;
44
24
  font-weight: 600;
@@ -51,49 +31,29 @@
51
31
  align-items: center;
52
32
  padding: 16px 20px;
53
33
  }
54
- .user-info {
55
- display: flex;
56
- align-items: center;
57
- gap: 12px;
58
- }
59
- .avatar {
34
+ .header .avatar {
60
35
  width: 44px;
61
36
  height: 44px;
62
- border-radius: 50%;
63
- background: linear-gradient(135deg, #6366f1, #a855f7);
64
- display: flex;
65
- align-items: center;
66
- justify-content: center;
67
- font-weight: 700;
68
37
  font-size: 16px;
69
38
  box-shadow: 0 0 16px var(--accent-glow);
70
39
  }
71
- .greeting {
72
- font-size: 13px;
73
- color: var(--text-muted);
74
- }
75
- .username {
76
- font-size: 17px;
77
- font-weight: 700;
78
- }
40
+ .greeting { font-size: 13px; }
41
+ .username { font-size: 17px; font-weight: 700; }
79
42
  .icon-btn {
80
43
  width: 40px;
81
44
  height: 40px;
82
45
  border-radius: 12px;
83
- background: var(--card-bg);
84
- border: 1px solid var(--card-border);
85
- color: var(--text-main);
46
+ background: var(--surface);
47
+ border: 1px solid var(--border);
86
48
  display: flex;
87
49
  align-items: center;
88
50
  justify-content: center;
89
- cursor: pointer;
90
51
  position: relative;
91
52
  }
92
- .badge-dot {
53
+ .icon-btn .badge-dot {
93
54
  width: 8px;
94
55
  height: 8px;
95
56
  background: var(--rose);
96
- border-radius: 50%;
97
57
  position: absolute;
98
58
  top: 10px;
99
59
  right: 10px;
@@ -105,7 +65,7 @@
105
65
  background: linear-gradient(135deg, #1e1b4b 0%, #1e293b 100%);
106
66
  border: 1px solid rgba(99, 102, 241, 0.3);
107
67
  border-radius: 24px;
108
- box-shadow: 0 12px 30px -10px rgba(99, 102, 241, 0.35);
68
+ box-shadow: 0 12px 30px -10px var(--accent-glow);
109
69
  position: relative;
110
70
  overflow: hidden;
111
71
  }
@@ -119,30 +79,13 @@
119
79
  background: radial-gradient(circle, rgba(99, 102, 241, 0.4) 0%, transparent 70%);
120
80
  pointer-events: none;
121
81
  }
122
- .balance-label {
123
- font-size: 13px;
124
- color: #cbd5e1;
125
- text-transform: uppercase;
126
- letter-spacing: 0.05em;
127
- margin-bottom: 6px;
128
- }
82
+ .hero-card .label { color: #cbd5e1; font-size: 13px; margin-bottom: 6px; }
129
83
  .balance-value {
130
84
  font-size: 34px;
131
85
  font-weight: 800;
132
86
  letter-spacing: -0.02em;
133
87
  margin-bottom: 12px;
134
88
  }
135
- .balance-trend {
136
- display: inline-flex;
137
- align-items: center;
138
- gap: 6px;
139
- background: rgba(16, 185, 129, 0.15);
140
- color: var(--emerald);
141
- padding: 4px 10px;
142
- border-radius: 20px;
143
- font-size: 12px;
144
- font-weight: 600;
145
- }
146
89
  /* Quick Actions */
147
90
  .actions-grid {
148
91
  display: grid;
@@ -155,14 +98,14 @@
155
98
  flex-direction: column;
156
99
  align-items: center;
157
100
  gap: 8px;
158
- cursor: pointer;
101
+ font-size: 12px;
102
+ font-weight: 500;
159
103
  }
160
104
  .action-circle {
161
105
  width: 52px;
162
106
  height: 52px;
107
+ padding: 0;
163
108
  border-radius: 18px;
164
- background: var(--card-bg);
165
- border: 1px solid var(--card-border);
166
109
  display: flex;
167
110
  align-items: center;
168
111
  justify-content: center;
@@ -174,29 +117,15 @@
174
117
  border-color: var(--accent);
175
118
  transform: translateY(-2px);
176
119
  }
177
- .action-label {
178
- font-size: 12px;
179
- font-weight: 500;
180
- color: var(--text-muted);
181
- }
182
- /* Section Title */
120
+ /* Transactions */
183
121
  .section-header {
184
122
  display: flex;
185
123
  justify-content: space-between;
186
124
  align-items: center;
187
125
  padding: 16px 20px 8px;
188
126
  }
189
- .section-title {
190
- font-size: 17px;
191
- font-weight: 700;
192
- }
193
- .see-all {
194
- font-size: 13px;
195
- color: var(--accent);
196
- text-decoration: none;
197
- font-weight: 600;
198
- }
199
- /* Transactions */
127
+ .section-title { font-size: 17px; font-weight: 700; }
128
+ .see-all { font-size: 13px; color: var(--accent); font-weight: 600; }
200
129
  .tx-list {
201
130
  display: flex;
202
131
  flex-direction: column;
@@ -208,41 +137,23 @@
208
137
  align-items: center;
209
138
  justify-content: space-between;
210
139
  padding: 14px 16px;
211
- background: var(--card-bg);
212
- border: 1px solid var(--card-border);
213
140
  border-radius: 16px;
214
141
  }
215
- .tx-left {
216
- display: flex;
217
- align-items: center;
218
- gap: 14px;
219
- }
142
+ .tx-item .row { gap: 14px; }
220
143
  .tx-icon {
221
144
  width: 40px;
222
145
  height: 40px;
223
146
  border-radius: 12px;
224
- background: #1c2030;
147
+ background: var(--surface-2);
225
148
  display: flex;
226
149
  align-items: center;
227
150
  justify-content: center;
228
151
  font-size: 18px;
229
152
  }
230
- .tx-name {
231
- font-size: 14px;
232
- font-weight: 600;
233
- }
234
- .tx-date {
235
- font-size: 12px;
236
- color: var(--text-muted);
237
- margin-top: 2px;
238
- }
239
- .tx-amount {
240
- font-size: 14px;
241
- font-weight: 700;
242
- }
243
- .tx-amount.positive {
244
- color: var(--emerald);
245
- }
153
+ .tx-name, .tx-amount { font-size: 14px; font-weight: 600; }
154
+ .tx-amount { font-weight: 700; }
155
+ .tx-amount.positive { color: var(--emerald); }
156
+ .tx-date { font-size: 12px; margin-top: 2px; }
246
157
  /* Bottom Navigation */
247
158
  .bottom-nav {
248
159
  position: fixed;
@@ -252,7 +163,7 @@
252
163
  height: 72px;
253
164
  background: rgba(9, 10, 15, 0.85);
254
165
  backdrop-filter: blur(16px);
255
- border-top: 1px solid var(--card-border);
166
+ border-top: 1px solid var(--border);
256
167
  display: flex;
257
168
  justify-content: space-around;
258
169
  align-items: center;
@@ -265,15 +176,9 @@
265
176
  gap: 4px;
266
177
  color: var(--text-muted);
267
178
  font-size: 11px;
268
- text-decoration: none;
269
- cursor: pointer;
270
- }
271
- .nav-btn.active {
272
- color: var(--accent);
273
- }
274
- .nav-icon {
275
- font-size: 20px;
276
179
  }
180
+ .nav-btn.active { color: var(--accent); }
181
+ .nav-icon { font-size: 20px; }
277
182
  </style>
278
183
  </head>
279
184
  <body>
@@ -283,10 +188,10 @@
283
188
  </div>
284
189
 
285
190
  <header class="header">
286
- <div class="user-info">
191
+ <div class="row">
287
192
  <div class="avatar">LC</div>
288
193
  <div>
289
- <div class="greeting">Welcome back,</div>
194
+ <div class="greeting muted">Welcome back,</div>
290
195
  <div class="username">Luiz Carlos</div>
291
196
  </div>
292
197
  </div>
@@ -297,29 +202,27 @@
297
202
  </header>
298
203
 
299
204
  <section class="hero-card">
300
- <div class="balance-label">Total Portfolio Value</div>
205
+ <div class="label">Total Portfolio Value</div>
301
206
  <div class="balance-value">$42,850.75</div>
302
- <div class="balance-trend">
303
- โ–ฒ +14.2% this month
304
- </div>
207
+ <div class="badge badge-emerald">โ–ฒ +14.2% this month</div>
305
208
  </section>
306
209
 
307
210
  <nav class="actions-grid">
308
211
  <div class="action-item">
309
- <div class="action-circle">โ†—</div>
310
- <div class="action-label">Send</div>
212
+ <div class="action-circle card">โ†—</div>
213
+ <div class="muted">Send</div>
311
214
  </div>
312
215
  <div class="action-item">
313
- <div class="action-circle">โ†™</div>
314
- <div class="action-label">Receive</div>
216
+ <div class="action-circle card">โ†™</div>
217
+ <div class="muted">Receive</div>
315
218
  </div>
316
219
  <div class="action-item">
317
- <div class="action-circle">โšก</div>
318
- <div class="action-label">Swap</div>
220
+ <div class="action-circle card">โšก</div>
221
+ <div class="muted">Swap</div>
319
222
  </div>
320
223
  <div class="action-item">
321
- <div class="action-circle">โ‹ฏ</div>
322
- <div class="action-label">More</div>
224
+ <div class="action-circle card">โ‹ฏ</div>
225
+ <div class="muted">More</div>
323
226
  </div>
324
227
  </nav>
325
228
 
@@ -329,34 +232,34 @@
329
232
  </div>
330
233
 
331
234
  <div class="tx-list">
332
- <div class="tx-item">
333
- <div class="tx-left">
235
+ <div class="tx-item card">
236
+ <div class="row">
334
237
  <div class="tx-icon">๐Ÿ›๏ธ</div>
335
238
  <div>
336
239
  <div class="tx-name">Apple Store</div>
337
- <div class="tx-date">Today, 2:15 PM โ€ข Electronics</div>
240
+ <div class="tx-date muted">Today, 2:15 PM โ€ข Electronics</div>
338
241
  </div>
339
242
  </div>
340
243
  <div class="tx-amount">-$199.00</div>
341
244
  </div>
342
245
 
343
- <div class="tx-item">
344
- <div class="tx-left">
246
+ <div class="tx-item card">
247
+ <div class="row">
345
248
  <div class="tx-icon">๐Ÿ’ผ</div>
346
249
  <div>
347
250
  <div class="tx-name">Client Invoice #1042</div>
348
- <div class="tx-date">Yesterday โ€ข Wire Transfer</div>
251
+ <div class="tx-date muted">Yesterday โ€ข Wire Transfer</div>
349
252
  </div>
350
253
  </div>
351
254
  <div class="tx-amount positive">+$3,450.00</div>
352
255
  </div>
353
256
 
354
- <div class="tx-item">
355
- <div class="tx-left">
257
+ <div class="tx-item card">
258
+ <div class="row">
356
259
  <div class="tx-icon">โ˜•</div>
357
260
  <div>
358
261
  <div class="tx-name">Blue Bottle Coffee</div>
359
- <div class="tx-date">Oct 26 โ€ข Food & Beverage</div>
262
+ <div class="tx-date muted">Oct 26 โ€ข Food & Beverage</div>
360
263
  </div>
361
264
  </div>
362
265
  <div class="tx-amount">-$6.75</div>
@@ -6,29 +6,9 @@
6
6
  <title>Component Library Preview</title>
7
7
  <meta name="description" content="Buttons, inputs, badges, cards, and interactive elements">
8
8
  <meta name="htmlboard" content="width=780, height=720, category=components">
9
+ <link rel="stylesheet" href="../styles.css">
9
10
  <style>
10
- * {
11
- box-sizing: border-box;
12
- margin: 0;
13
- padding: 0;
14
- -webkit-font-smoothing: antialiased;
15
- }
16
- :root {
17
- --bg: #0d0f17;
18
- --card-bg: #141724;
19
- --border: #24293e;
20
- --text: #f8fafc;
21
- --text-muted: #94a3b8;
22
- --accent: #6366f1;
23
- --accent-hover: #4f46e5;
24
- --emerald: #10b981;
25
- --rose: #f43f5e;
26
- --amber: #f59e0b;
27
- }
28
11
  body {
29
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
30
- background: var(--bg);
31
- color: var(--text);
32
12
  padding: 24px;
33
13
  display: flex;
34
14
  flex-direction: column;
@@ -38,135 +18,22 @@
38
18
  border-bottom: 1px solid var(--border);
39
19
  padding-bottom: 16px;
40
20
  }
41
- .title {
42
- font-size: 20px;
43
- font-weight: 700;
44
- }
45
- .subtitle {
46
- font-size: 13px;
47
- color: var(--text-muted);
48
- margin-top: 4px;
49
- }
50
- .section {
51
- background: var(--card-bg);
52
- border: 1px solid var(--border);
53
- border-radius: 12px;
54
- padding: 20px;
55
- display: flex;
56
- flex-direction: column;
57
- gap: 16px;
58
- }
59
- .section-title {
60
- font-size: 14px;
61
- font-weight: 600;
62
- color: #cbd5e1;
63
- text-transform: uppercase;
64
- letter-spacing: 0.05em;
65
- }
66
- .flex-row {
67
- display: flex;
68
- align-items: center;
69
- gap: 12px;
70
- flex-wrap: wrap;
71
- }
72
- /* Buttons */
73
- .btn {
74
- padding: 9px 16px;
75
- border-radius: 8px;
76
- font-size: 13px;
77
- font-weight: 600;
78
- cursor: pointer;
79
- display: inline-flex;
80
- align-items: center;
81
- gap: 8px;
82
- border: 1px solid transparent;
83
- transition: all 0.15s ease;
84
- }
85
- .btn-primary {
86
- background: var(--accent);
87
- color: #fff;
88
- }
89
- .btn-primary:hover { background: var(--accent-hover); }
90
- .btn-secondary {
91
- background: #1e2336;
92
- border-color: var(--border);
93
- color: var(--text);
94
- }
95
- .btn-secondary:hover { background: #262c44; }
96
- .btn-outline {
97
- background: transparent;
98
- border-color: #3b4260;
99
- color: var(--text);
100
- }
101
- .btn-outline:hover { background: rgba(255, 255, 255, 0.05); }
102
- .btn-danger {
103
- background: rgba(244, 63, 94, 0.15);
104
- border-color: rgba(244, 63, 94, 0.3);
105
- color: var(--rose);
106
- }
107
- .btn-danger:hover { background: rgba(244, 63, 94, 0.25); }
108
-
109
- /* Badges */
110
- .badge {
111
- padding: 4px 10px;
112
- border-radius: 20px;
113
- font-size: 12px;
114
- font-weight: 600;
115
- display: inline-flex;
116
- align-items: center;
117
- gap: 6px;
118
- }
119
- .badge-dot {
120
- width: 6px;
121
- height: 6px;
122
- border-radius: 50%;
123
- }
124
- .badge-indigo { background: rgba(99, 102, 241, 0.15); color: #818cf8; }
125
- .badge-indigo .badge-dot { background: #818cf8; }
126
- .badge-emerald { background: rgba(16, 185, 129, 0.15); color: var(--emerald); }
127
- .badge-emerald .badge-dot { background: var(--emerald); }
128
- .badge-amber { background: rgba(245, 158, 11, 0.15); color: var(--amber); }
129
- .badge-amber .badge-dot { background: var(--amber); }
130
- .badge-rose { background: rgba(244, 63, 94, 0.15); color: var(--rose); }
131
- .badge-rose .badge-dot { background: var(--rose); }
132
-
133
- /* Inputs */
134
- .input-group {
135
- display: flex;
136
- flex-direction: column;
137
- gap: 6px;
138
- flex: 1;
139
- min-width: 200px;
140
- }
141
- .input-label {
142
- font-size: 12px;
143
- font-weight: 500;
144
- color: var(--text-muted);
145
- }
146
- .input-field {
147
- background: #0d0f17;
148
- border: 1px solid var(--border);
149
- border-radius: 8px;
150
- padding: 9px 12px;
151
- color: var(--text);
152
- font-size: 13px;
153
- outline: none;
154
- transition: border-color 0.15s ease;
155
- }
156
- .input-field:focus {
157
- border-color: var(--accent);
158
- }
21
+ .title { font-size: 20px; font-weight: 700; }
22
+ .subtitle { font-size: 13px; margin-top: 4px; }
23
+ .card { display: flex; flex-direction: column; gap: 16px; }
24
+ .row { flex-wrap: wrap; }
25
+ .field { flex: 1; min-width: 200px; }
159
26
  </style>
160
27
  </head>
161
28
  <body>
162
29
  <div class="header">
163
30
  <h1 class="title">Design System Components</h1>
164
- <p class="subtitle">Reusable UI atoms for consistency across platforms</p>
31
+ <p class="subtitle muted">Everything here comes from styles.css, shared by all the designs</p>
165
32
  </div>
166
33
 
167
- <div class="section">
168
- <div class="section-title">Buttons & Interactive Triggers</div>
169
- <div class="flex-row">
34
+ <div class="card">
35
+ <div class="label">Buttons & Interactive Triggers</div>
36
+ <div class="row">
170
37
  <button class="btn btn-primary"><span>โœจ</span> Primary Action</button>
171
38
  <button class="btn btn-secondary">Secondary Action</button>
172
39
  <button class="btn btn-outline">Outline Button</button>
@@ -174,27 +41,36 @@
174
41
  </div>
175
42
  </div>
176
43
 
177
- <div class="section">
178
- <div class="section-title">Status Pills & Badges</div>
179
- <div class="flex-row">
180
- <div class="badge badge-indigo"><span class="badge-dot"></span> In Progress</div>
44
+ <div class="card">
45
+ <div class="label">Status Pills & Badges</div>
46
+ <div class="row">
47
+ <div class="badge"><span class="badge-dot"></span> In Progress</div>
181
48
  <div class="badge badge-emerald"><span class="badge-dot"></span> Active / Healthy</div>
182
49
  <div class="badge badge-amber"><span class="badge-dot"></span> Review Required</div>
183
50
  <div class="badge badge-rose"><span class="badge-dot"></span> Error / Offline</div>
184
51
  </div>
185
52
  </div>
186
53
 
187
- <div class="section">
188
- <div class="section-title">Form Controls</div>
189
- <div class="flex-row">
190
- <div class="input-group">
191
- <label class="input-label">Project Name</label>
192
- <input type="text" class="input-field" value="HtmlBoard Studio" />
193
- </div>
194
- <div class="input-group">
195
- <label class="input-label">Environment Target</label>
196
- <input type="text" class="input-field" value="production-edge-01" />
197
- </div>
54
+ <div class="card">
55
+ <div class="label">Form Controls</div>
56
+ <div class="row">
57
+ <label class="field">
58
+ <span>Project Name</span>
59
+ <input type="text" class="input" value="HtmlBoard Studio">
60
+ </label>
61
+ <label class="field">
62
+ <span>Environment Target</span>
63
+ <input type="text" class="input" value="production-edge-01">
64
+ </label>
65
+ </div>
66
+ </div>
67
+
68
+ <div class="card">
69
+ <div class="label">Avatars</div>
70
+ <div class="row">
71
+ <div class="avatar">LC</div>
72
+ <div class="avatar" style="background: linear-gradient(135deg, #ec4899, #8b5cf6)">AM</div>
73
+ <div class="avatar" style="width: 44px; height: 44px; font-size: 16px">JS</div>
198
74
  </div>
199
75
  </div>
200
76
  </body>
@@ -0,0 +1,133 @@
1
+ /*
2
+ * Shared styles for every design in this folder: tokens, base and components.
3
+ * Designs link it (<link rel="stylesheet" href="../styles.css">) and keep only
4
+ * what is specific to them in their own <style>.
5
+ */
6
+
7
+ /* Tokens */
8
+ :root {
9
+ --bg: #0b0d13;
10
+ --surface: #141724;
11
+ --surface-2: #1c2030;
12
+ --border: #23283c;
13
+ --text: #f1f5f9;
14
+ --text-muted: #94a3b8;
15
+ --text-subtle: #64748b;
16
+ --accent: #6366f1;
17
+ --accent-hover: #4f46e5;
18
+ --accent-light: #818cf8;
19
+ --accent-glow: rgba(99, 102, 241, 0.35);
20
+ --emerald: #10b981;
21
+ --amber: #f59e0b;
22
+ --rose: #f43f5e;
23
+ --purple: #a855f7;
24
+ --radius: 8px;
25
+ --radius-lg: 14px;
26
+ --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
27
+ }
28
+
29
+ /* Base */
30
+ * {
31
+ box-sizing: border-box;
32
+ margin: 0;
33
+ padding: 0;
34
+ -webkit-font-smoothing: antialiased;
35
+ }
36
+ body {
37
+ font-family: var(--font);
38
+ background: var(--bg);
39
+ color: var(--text);
40
+ }
41
+ a { color: inherit; text-decoration: none; }
42
+
43
+ /* Text */
44
+ .muted { color: var(--text-muted); }
45
+ .label {
46
+ font-size: 12px;
47
+ font-weight: 600;
48
+ color: var(--text-subtle);
49
+ text-transform: uppercase;
50
+ letter-spacing: 0.06em;
51
+ }
52
+ .row {
53
+ display: flex;
54
+ align-items: center;
55
+ gap: 12px;
56
+ }
57
+
58
+ /* Card */
59
+ .card {
60
+ background: var(--surface);
61
+ border: 1px solid var(--border);
62
+ border-radius: var(--radius-lg);
63
+ padding: 20px;
64
+ }
65
+
66
+ /* Buttons */
67
+ .btn {
68
+ display: inline-flex;
69
+ align-items: center;
70
+ gap: 8px;
71
+ padding: 9px 16px;
72
+ border: 1px solid transparent;
73
+ border-radius: var(--radius);
74
+ font: 600 13px var(--font);
75
+ color: var(--text);
76
+ background: var(--surface-2);
77
+ cursor: pointer;
78
+ transition: background 0.15s ease;
79
+ }
80
+ .btn-primary { background: var(--accent); color: #fff; box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3); }
81
+ .btn-primary:hover { background: var(--accent-hover); }
82
+ .btn-secondary { border-color: var(--border); }
83
+ .btn-secondary:hover { background: #262c44; }
84
+ .btn-outline { background: transparent; border-color: #3b4260; }
85
+ .btn-outline:hover { background: rgba(255, 255, 255, 0.05); }
86
+ .btn-danger { background: rgba(244, 63, 94, 0.15); border-color: rgba(244, 63, 94, 0.3); color: var(--rose); }
87
+ .btn-danger:hover { background: rgba(244, 63, 94, 0.25); }
88
+
89
+ /* Badges */
90
+ .badge {
91
+ display: inline-flex;
92
+ align-items: center;
93
+ gap: 6px;
94
+ padding: 4px 10px;
95
+ border-radius: 20px;
96
+ font-size: 12px;
97
+ font-weight: 600;
98
+ background: rgba(99, 102, 241, 0.15);
99
+ color: var(--accent-light);
100
+ }
101
+ .badge-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
102
+ .badge-emerald { background: rgba(16, 185, 129, 0.15); color: var(--emerald); }
103
+ .badge-amber { background: rgba(245, 158, 11, 0.15); color: var(--amber); }
104
+ .badge-rose { background: rgba(244, 63, 94, 0.15); color: var(--rose); }
105
+
106
+ /* Inputs */
107
+ .field { display: flex; flex-direction: column; gap: 6px; }
108
+ .field > span { font-size: 12px; font-weight: 500; color: var(--text-muted); }
109
+ .input {
110
+ background: var(--bg);
111
+ border: 1px solid var(--border);
112
+ border-radius: var(--radius);
113
+ padding: 9px 12px;
114
+ font: 13px var(--font);
115
+ color: var(--text);
116
+ outline: none;
117
+ transition: border-color 0.15s ease;
118
+ }
119
+ .input:focus { border-color: var(--accent); }
120
+
121
+ /* Avatar */
122
+ .avatar {
123
+ display: flex;
124
+ align-items: center;
125
+ justify-content: center;
126
+ flex-shrink: 0;
127
+ width: 36px;
128
+ height: 36px;
129
+ border-radius: 50%;
130
+ background: linear-gradient(135deg, var(--accent), var(--purple));
131
+ font-size: 14px;
132
+ font-weight: 700;
133
+ }