@sunboard/react 0.1.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.
@@ -0,0 +1,560 @@
1
+ /*
2
+ * Sunboard owns its own variable namespace. Defaults are plain color literals
3
+ * so they render correctly under any host theme system (Tailwind, shadcn v3
4
+ * HSL, shadcn v4 OKLCH, vanilla CSS, etc.). To theme Sunboard to match your
5
+ * app, override the `--sunboard-*` variables below in your own stylesheet —
6
+ * map them to your design tokens (e.g. `var(--card)`, `var(--primary)`) or
7
+ * set explicit colors. Make sure your stylesheet imports AFTER
8
+ * `@sunboard/react/styles.css` so your overrides win the cascade.
9
+ */
10
+ :root {
11
+ --sunboard-font:
12
+ Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
13
+ sans-serif;
14
+ --sunboard-radius: 12px;
15
+
16
+ --sunboard-checklist-background: #ffffff;
17
+ --sunboard-checklist-foreground: #111827;
18
+ --sunboard-checklist-border: #e5e7eb;
19
+ --sunboard-checklist-shadow: 0 18px 60px rgb(15 23 42 / 16%);
20
+ --sunboard-checklist-muted: #f3f4f6;
21
+ --sunboard-checklist-muted-foreground: #6b7280;
22
+ --sunboard-checklist-primary: #2563eb;
23
+ --sunboard-checklist-primary-foreground: #ffffff;
24
+ --sunboard-checklist-success: #16a34a;
25
+
26
+ --sunboard-launcher-background: var(--sunboard-checklist-primary);
27
+ --sunboard-launcher-foreground: var(--sunboard-checklist-primary-foreground);
28
+ --sunboard-launcher-border: var(--sunboard-checklist-border);
29
+ --sunboard-launcher-shadow: var(--sunboard-checklist-shadow);
30
+ --sunboard-launcher-count-background: color-mix(
31
+ in srgb,
32
+ var(--sunboard-launcher-foreground) 18%,
33
+ transparent
34
+ );
35
+
36
+ --sunboard-tour-background: var(--sunboard-checklist-background);
37
+ --sunboard-tour-foreground: var(--sunboard-checklist-foreground);
38
+ --sunboard-tour-border: var(--sunboard-checklist-border);
39
+ --sunboard-tour-shadow: var(--sunboard-checklist-shadow);
40
+ --sunboard-tour-muted-foreground: var(
41
+ --sunboard-checklist-muted-foreground
42
+ );
43
+ --sunboard-tour-primary: var(--sunboard-checklist-primary);
44
+ --sunboard-tour-primary-foreground: var(
45
+ --sunboard-checklist-primary-foreground
46
+ );
47
+ --sunboard-tour-secondary-background: var(--sunboard-tour-background);
48
+ --sunboard-tour-secondary-foreground: var(--sunboard-tour-foreground);
49
+ --sunboard-tour-secondary-border: var(--sunboard-tour-border);
50
+
51
+ --sunboard-overlay-color: rgb(15 23 42 / 18%);
52
+
53
+ --sunboard-hotspot-background: var(--sunboard-checklist-primary);
54
+ --sunboard-hotspot-border: var(--sunboard-checklist-primary-foreground);
55
+ --sunboard-hotspot-dot: var(--sunboard-checklist-primary-foreground);
56
+ --sunboard-hotspot-shadow: var(--sunboard-checklist-shadow);
57
+ --sunboard-hotspot-pulse-ring: rgb(37 99 235 / 28%);
58
+
59
+ --sunboard-debug-background: var(--sunboard-checklist-background);
60
+ --sunboard-debug-foreground: var(--sunboard-checklist-foreground);
61
+ --sunboard-debug-border: var(--sunboard-checklist-border);
62
+ --sunboard-debug-shadow: var(--sunboard-checklist-shadow);
63
+ }
64
+
65
+ .sunboard-root {
66
+ position: fixed;
67
+ right: max(16px, env(safe-area-inset-right));
68
+ bottom: max(16px, env(safe-area-inset-bottom));
69
+ z-index: 2147483000;
70
+ width: min(360px, calc(100vw - 32px));
71
+ max-height: min(680px, calc(100vh - 32px));
72
+ overflow: auto;
73
+ box-sizing: border-box;
74
+ border: 1px solid var(--sunboard-checklist-border);
75
+ border-radius: var(--sunboard-radius);
76
+ background: var(--sunboard-checklist-background);
77
+ box-shadow: var(--sunboard-checklist-shadow);
78
+ color: var(--sunboard-checklist-foreground);
79
+ font-family: var(--sunboard-font);
80
+ padding: 16px;
81
+ }
82
+
83
+ .sunboard-launcher {
84
+ position: fixed;
85
+ right: max(16px, env(safe-area-inset-right));
86
+ bottom: max(16px, env(safe-area-inset-bottom));
87
+ z-index: 2147483000;
88
+ display: grid;
89
+ width: 56px;
90
+ height: 56px;
91
+ place-items: center;
92
+ border: 1px solid var(--sunboard-launcher-border);
93
+ border-radius: 999px;
94
+ background: var(--sunboard-launcher-background);
95
+ box-shadow: var(--sunboard-launcher-shadow);
96
+ color: var(--sunboard-launcher-foreground);
97
+ cursor: pointer;
98
+ font-family: var(--sunboard-font);
99
+ padding: 0;
100
+ }
101
+
102
+ .sunboard-launcher-count {
103
+ display: grid;
104
+ min-width: 24px;
105
+ height: 24px;
106
+ place-items: center;
107
+ border-radius: 999px;
108
+ background: var(--sunboard-launcher-count-background);
109
+ font-size: 14px;
110
+ font-weight: 800;
111
+ line-height: 1;
112
+ }
113
+
114
+ .sunboard-launcher:focus-visible,
115
+ .sunboard-close:focus-visible {
116
+ outline: 2px solid var(--sunboard-checklist-primary);
117
+ outline-offset: 3px;
118
+ }
119
+
120
+ .sunboard-root *,
121
+ .sunboard-root *::before,
122
+ .sunboard-root *::after {
123
+ box-sizing: border-box;
124
+ }
125
+
126
+ .sunboard-header {
127
+ display: flex;
128
+ align-items: flex-start;
129
+ justify-content: space-between;
130
+ gap: 16px;
131
+ }
132
+
133
+ .sunboard-header-actions {
134
+ display: flex;
135
+ flex: 0 0 auto;
136
+ align-items: center;
137
+ gap: 8px;
138
+ }
139
+
140
+ .sunboard-eyebrow,
141
+ .sunboard-title,
142
+ .sunboard-progress-count,
143
+ .sunboard-step-title,
144
+ .sunboard-step-description {
145
+ margin: 0;
146
+ }
147
+
148
+ .sunboard-eyebrow {
149
+ color: var(--sunboard-checklist-muted-foreground);
150
+ font-size: 12px;
151
+ font-weight: 650;
152
+ line-height: 1.2;
153
+ }
154
+
155
+ .sunboard-title {
156
+ margin-top: 3px;
157
+ font-size: 16px;
158
+ font-weight: 700;
159
+ line-height: 1.3;
160
+ }
161
+
162
+ .sunboard-progress-count {
163
+ flex: 0 0 auto;
164
+ border-radius: 999px;
165
+ background: var(--sunboard-checklist-muted);
166
+ color: var(--sunboard-checklist-muted-foreground);
167
+ font-size: 12px;
168
+ font-weight: 650;
169
+ line-height: 1;
170
+ padding: 7px 9px;
171
+ }
172
+
173
+ .sunboard-close {
174
+ display: grid;
175
+ width: 28px;
176
+ height: 28px;
177
+ place-items: center;
178
+ border: 1px solid var(--sunboard-checklist-border);
179
+ border-radius: 999px;
180
+ background: var(--sunboard-checklist-background);
181
+ color: var(--sunboard-checklist-muted-foreground);
182
+ cursor: pointer;
183
+ font: inherit;
184
+ font-size: 14px;
185
+ font-weight: 800;
186
+ line-height: 1;
187
+ padding: 0;
188
+ }
189
+
190
+ .sunboard-progress {
191
+ height: 8px;
192
+ overflow: hidden;
193
+ border-radius: 999px;
194
+ background: var(--sunboard-checklist-muted);
195
+ margin-top: 14px;
196
+ }
197
+
198
+ .sunboard-progress-fill {
199
+ height: 100%;
200
+ border-radius: inherit;
201
+ background: var(--sunboard-checklist-primary);
202
+ transition: width 160ms ease;
203
+ }
204
+
205
+ .sunboard-step-list {
206
+ display: grid;
207
+ gap: 20px;
208
+ list-style: none;
209
+ margin: 16px 0 0;
210
+ padding: 0;
211
+ }
212
+
213
+ .sunboard-step-row {
214
+ display: grid;
215
+ width: 100%;
216
+ grid-template-columns: 24px minmax(0, 1fr);
217
+ gap: 10px;
218
+ align-items: start;
219
+ border: 0;
220
+ background: transparent;
221
+ color: inherit;
222
+ cursor: default;
223
+ font: inherit;
224
+ text-align: left;
225
+ padding: 6px;
226
+ margin: -6px;
227
+ border-radius: 8px;
228
+ }
229
+
230
+ button.sunboard-step-row {
231
+ cursor: pointer;
232
+ }
233
+
234
+ button.sunboard-step-row:hover {
235
+ background: var(--sunboard-checklist-muted);
236
+ }
237
+
238
+ button.sunboard-step-row:focus-visible {
239
+ outline: 2px solid var(--sunboard-checklist-primary);
240
+ outline-offset: 2px;
241
+ }
242
+
243
+ .sunboard-step-status {
244
+ display: grid;
245
+ width: 22px;
246
+ height: 22px;
247
+ place-items: center;
248
+ border: 1px solid var(--sunboard-checklist-border);
249
+ border-radius: 999px;
250
+ color: var(--sunboard-checklist-primary-foreground);
251
+ font-size: 13px;
252
+ font-weight: 800;
253
+ line-height: 1;
254
+ }
255
+
256
+ .sunboard-step-status svg {
257
+ width: 14px;
258
+ height: 14px;
259
+ }
260
+
261
+ .sunboard-step[data-completed="true"] .sunboard-step-status {
262
+ border-color: var(--sunboard-checklist-success);
263
+ background: var(--sunboard-checklist-success);
264
+ }
265
+
266
+ .sunboard-step-content {
267
+ min-width: 0;
268
+ }
269
+
270
+ .sunboard-step-heading {
271
+ display: flex;
272
+ align-items: flex-start;
273
+ justify-content: space-between;
274
+ gap: 8px;
275
+ }
276
+
277
+ .sunboard-step-title {
278
+ min-width: 0;
279
+ overflow-wrap: anywhere;
280
+ font-size: 14px;
281
+ font-weight: 650;
282
+ line-height: 1.35;
283
+ }
284
+
285
+ .sunboard-step-badge {
286
+ flex: 0 0 auto;
287
+ color: var(--sunboard-checklist-muted-foreground);
288
+ font-size: 11px;
289
+ font-weight: 650;
290
+ line-height: 1.5;
291
+ white-space: nowrap;
292
+ }
293
+
294
+ .sunboard-step-description {
295
+ color: var(--sunboard-checklist-muted-foreground);
296
+ font-size: 13px;
297
+ line-height: 1.4;
298
+ margin-top: 3px;
299
+ }
300
+
301
+ .sunboard-hotspot {
302
+ z-index: 2147483001;
303
+ display: grid;
304
+ width: 18px;
305
+ height: 18px;
306
+ place-items: center;
307
+ border: 2px solid var(--sunboard-hotspot-border);
308
+ border-radius: 999px;
309
+ background: var(--sunboard-hotspot-background);
310
+ box-shadow: var(--sunboard-hotspot-shadow);
311
+ color: var(--sunboard-hotspot-dot);
312
+ cursor: pointer;
313
+ font-family: var(--sunboard-font);
314
+ padding: 0;
315
+ }
316
+
317
+ .sunboard-hotspot-dot {
318
+ width: 6px;
319
+ height: 6px;
320
+ border-radius: 999px;
321
+ background: currentColor;
322
+ }
323
+
324
+ .sunboard-hotspot[data-pulse="true"] {
325
+ animation: sunboard-hotspot-pulse 1.8s ease-out infinite;
326
+ box-shadow:
327
+ var(--sunboard-hotspot-shadow),
328
+ 0 0 0 8px var(--sunboard-hotspot-pulse-ring);
329
+ }
330
+
331
+ .sunboard-hotspot:focus-visible {
332
+ outline: 2px solid var(--sunboard-hotspot-background);
333
+ outline-offset: 3px;
334
+ }
335
+
336
+ @keyframes sunboard-hotspot-pulse {
337
+ 0% {
338
+ box-shadow:
339
+ var(--sunboard-hotspot-shadow),
340
+ 0 0 0 0 var(--sunboard-hotspot-pulse-ring);
341
+ }
342
+
343
+ 70% {
344
+ box-shadow:
345
+ var(--sunboard-hotspot-shadow),
346
+ 0 0 0 10px transparent;
347
+ }
348
+
349
+ 100% {
350
+ box-shadow:
351
+ var(--sunboard-hotspot-shadow),
352
+ 0 0 0 0 transparent;
353
+ }
354
+ }
355
+
356
+ .sunboard-tour-scrim {
357
+ position: fixed;
358
+ inset: 0;
359
+ z-index: 2147483001;
360
+ background: var(--sunboard-overlay-color);
361
+ pointer-events: none;
362
+ }
363
+
364
+ .sunboard-tour-spotlight {
365
+ width: 100vw;
366
+ height: 100vh;
367
+ background: transparent;
368
+ }
369
+
370
+ .sunboard-tour {
371
+ z-index: 2147483002;
372
+ width: min(320px, calc(100vw - 32px));
373
+ box-sizing: border-box;
374
+ border: 1px solid var(--sunboard-tour-border);
375
+ border-radius: var(--sunboard-radius);
376
+ background: var(--sunboard-tour-background);
377
+ box-shadow: var(--sunboard-tour-shadow);
378
+ color: var(--sunboard-tour-foreground);
379
+ font-family: var(--sunboard-font);
380
+ padding: 14px;
381
+ }
382
+
383
+ .sunboard-tour-arrow {
384
+ color: var(--sunboard-tour-background);
385
+ }
386
+
387
+ .sunboard-tour-meta {
388
+ color: var(--sunboard-tour-muted-foreground);
389
+ font-size: 12px;
390
+ font-weight: 700;
391
+ line-height: 1;
392
+ }
393
+
394
+ .sunboard-tour-title {
395
+ margin: 6px 0 0;
396
+ font-size: 15px;
397
+ font-weight: 750;
398
+ line-height: 1.35;
399
+ }
400
+
401
+ .sunboard-tour-body {
402
+ color: var(--sunboard-tour-muted-foreground);
403
+ font-size: 13px;
404
+ line-height: 1.45;
405
+ margin: 6px 0 0;
406
+ }
407
+
408
+ .sunboard-tour-actions {
409
+ display: flex;
410
+ justify-content: flex-end;
411
+ gap: 8px;
412
+ margin-top: 13px;
413
+ }
414
+
415
+ .sunboard-tour-primary,
416
+ .sunboard-tour-secondary,
417
+ .sunboard-debug button {
418
+ display: inline-flex;
419
+ align-items: center;
420
+ justify-content: center;
421
+ min-height: 30px;
422
+ border-radius: 8px;
423
+ cursor: pointer;
424
+ font: inherit;
425
+ font-size: 12px;
426
+ font-weight: 700;
427
+ line-height: 1;
428
+ padding: 8px 11px;
429
+ }
430
+
431
+ .sunboard-tour-primary {
432
+ border: 0;
433
+ background: var(--sunboard-tour-primary);
434
+ color: var(--sunboard-tour-primary-foreground);
435
+ }
436
+
437
+ .sunboard-tour-secondary,
438
+ .sunboard-debug button {
439
+ border: 1px solid var(--sunboard-tour-secondary-border);
440
+ background: var(--sunboard-tour-secondary-background);
441
+ color: var(--sunboard-tour-secondary-foreground);
442
+ }
443
+
444
+ .sunboard-debug {
445
+ position: fixed;
446
+ right: max(16px, env(safe-area-inset-right));
447
+ top: max(16px, env(safe-area-inset-top));
448
+ z-index: 2147483003;
449
+ display: grid;
450
+ width: min(380px, calc(100vw - 32px));
451
+ gap: 6px;
452
+ box-sizing: border-box;
453
+ border: 1px solid var(--sunboard-debug-border);
454
+ border-radius: var(--sunboard-radius);
455
+ background: var(--sunboard-debug-background);
456
+ box-shadow: var(--sunboard-debug-shadow);
457
+ color: var(--sunboard-debug-foreground);
458
+ font-family: var(--sunboard-font);
459
+ font-size: 12px;
460
+ line-height: 1.4;
461
+ padding: 12px;
462
+ }
463
+
464
+ .sunboard-root-completion {
465
+ text-align: center;
466
+ animation: sunboard-completion-in 260ms ease-out both;
467
+ }
468
+
469
+ .sunboard-completion-close {
470
+ position: absolute;
471
+ top: 12px;
472
+ right: 12px;
473
+ }
474
+
475
+ .sunboard-completion {
476
+ display: flex;
477
+ flex-direction: column;
478
+ align-items: center;
479
+ gap: 8px;
480
+ padding: 8px 8px 4px;
481
+ }
482
+
483
+ .sunboard-completion-check {
484
+ display: grid;
485
+ place-items: center;
486
+ width: 56px;
487
+ height: 56px;
488
+ margin-bottom: 4px;
489
+ border-radius: 999px;
490
+ background: color-mix(
491
+ in srgb,
492
+ var(--sunboard-checklist-success) 14%,
493
+ transparent
494
+ );
495
+ color: var(--sunboard-checklist-success);
496
+ animation: sunboard-completion-check-in 380ms cubic-bezier(0.34, 1.56, 0.64, 1)
497
+ both;
498
+ }
499
+
500
+ .sunboard-completion-check svg {
501
+ width: 30px;
502
+ height: 30px;
503
+ }
504
+
505
+ .sunboard-completion-subtitle {
506
+ margin: 0;
507
+ color: var(--sunboard-checklist-muted-foreground);
508
+ font-size: 12px;
509
+ font-weight: 650;
510
+ line-height: 1.2;
511
+ text-transform: uppercase;
512
+ letter-spacing: 0.04em;
513
+ }
514
+
515
+ .sunboard-completion-title {
516
+ margin: 0;
517
+ font-size: 18px;
518
+ font-weight: 700;
519
+ line-height: 1.3;
520
+ }
521
+
522
+ .sunboard-completion-message {
523
+ margin: 0;
524
+ color: var(--sunboard-checklist-muted-foreground);
525
+ font-size: 14px;
526
+ line-height: 1.5;
527
+ }
528
+
529
+ @keyframes sunboard-completion-in {
530
+ from {
531
+ opacity: 0;
532
+ transform: scale(0.96);
533
+ }
534
+ to {
535
+ opacity: 1;
536
+ transform: scale(1);
537
+ }
538
+ }
539
+
540
+ @keyframes sunboard-completion-check-in {
541
+ 0% {
542
+ opacity: 0;
543
+ transform: scale(0.4);
544
+ }
545
+ 60% {
546
+ opacity: 1;
547
+ transform: scale(1.1);
548
+ }
549
+ 100% {
550
+ opacity: 1;
551
+ transform: scale(1);
552
+ }
553
+ }
554
+
555
+ @media (prefers-reduced-motion: reduce) {
556
+ .sunboard-root-completion,
557
+ .sunboard-completion-check {
558
+ animation: none;
559
+ }
560
+ }
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@sunboard/react",
3
+ "version": "0.1.0",
4
+ "description": "React SDK for the Sunboard onboarding runtime.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "homepage": "https://sunboardhq.com",
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "sideEffects": [
17
+ "./src/styles.css",
18
+ "./dist/styles.css"
19
+ ],
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.mts",
23
+ "import": "./dist/index.mjs"
24
+ },
25
+ "./styles.css": "./dist/styles.css"
26
+ },
27
+ "dependencies": {
28
+ "@floating-ui/react": "^0.27.19",
29
+ "@sunboard/core": "0.1.0"
30
+ },
31
+ "peerDependencies": {
32
+ "react": ">=18.3.0 || >=19.0.0",
33
+ "react-dom": ">=18.3.0 || >=19.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "@testing-library/jest-dom": "^6.9.1",
37
+ "@testing-library/react": "^16.3.1",
38
+ "@testing-library/user-event": "^14.6.1",
39
+ "@types/node": "^22.19.3",
40
+ "@types/react": "19.2.2",
41
+ "@types/react-dom": "19.2.2",
42
+ "eslint": "^9.39.1",
43
+ "jsdom": "^27.3.0",
44
+ "react": "^19.2.0",
45
+ "react-dom": "^19.2.0",
46
+ "tsdown": "^0.16.7",
47
+ "typescript": "5.9.2",
48
+ "vitest": "^4.0.15",
49
+ "@repo/eslint-config": "0.0.0",
50
+ "@repo/typescript-config": "0.0.0"
51
+ },
52
+ "scripts": {
53
+ "build": "tsdown && pnpm run copy-styles",
54
+ "copy-styles": "node scripts/copy-styles.mjs",
55
+ "check-types": "tsc --noEmit",
56
+ "lint": "eslint .",
57
+ "test": "vitest run"
58
+ }
59
+ }