@sonata-innovations/fiber-fbre 3.1.0 → 3.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/README.md CHANGED
@@ -226,7 +226,7 @@ import type {
226
226
  Flow
227
227
  ├── uuid: string
228
228
  ├── metadata: { name?, description?, ...}
229
- ├── config?: { mode?, theme?: { color?, darkMode?, style? }, navigation?: { transition?, allowInvalidTransition? }, controls?: { show?, layout?, showStepper? }, summary? }
229
+ ├── config?: { mode?, theme?: { color?, colorScheme?, style?, background?, surface?, text?, border?, radius?, fontFamily?, error?, success?, warning? }, navigation?: { transition?, allowInvalidTransition? }, controls?: { show?, layout?, showStepper? }, summary? }
230
230
  └── screens: FlowScreen[]
231
231
  ├── uuid: string
232
232
  ├── label?: string
@@ -407,42 +407,111 @@ const flow = {
407
407
 
408
408
  ## Theming
409
409
 
410
- FBRE uses CSS custom properties. Override on the container:
410
+ FBRE's appearance is driven entirely by CSS custom properties (the `--fbre-*` tokens). There are two independent axes — **`style`** controls the *shape* (borders vs. underlines, fills, spacing; set via `theme.style`), and the **palette** controls the *colors*. This section is a complete reference for the palette.
411
411
 
412
- ```css
413
- .fbre-container {
414
- --fbre-theme-color: #1976d2;
415
- --fbre-theme-light: #e3f2fd;
416
- --fbre-theme-dark: #1565c0;
417
- --fbre-error: #d32f2f;
418
- --fbre-text: #212121;
419
- --fbre-text-secondary: #666;
420
- --fbre-border: #ccc;
421
- --fbre-bg: #fff;
422
- --fbre-radius: 4px;
423
- --fbre-font: "Segoe UI", system-ui, sans-serif;
424
- }
412
+ Palette values resolve through four layers, each overriding the one above, so you only specify what you want to change:
413
+
414
+ ```
415
+ 1. Light defaults base.css (lowest)
416
+ 2. Preset: colorScheme: "dark" base.css [data-mode="dark"]
417
+ 3. Knobs: theme.{surface,text…} inline custom properties
418
+ 4. Raw CSS: your own --fbre-* rules your stylesheet (highest)
419
+ ```
420
+
421
+ ### Color scheme (presets)
422
+
423
+ `theme.colorScheme` (`"light"` default | `"dark"`) seeds the **entire** token set with a coherent light or dark palette and sets `data-mode` on the container. Set it on the `theme` prop or in the flow config (the prop takes precedence):
424
+
425
+ ```tsx
426
+ <FBRE flow={myFlow} theme={{ colorScheme: "dark" }} onFlowComplete={handleComplete} />
425
427
  ```
426
428
 
427
- `theme.color` from `flow.config.theme.color` is applied automatically via inline style.
429
+ > Replaces the former `darkMode: boolean`: `darkMode: true` `colorScheme: "dark"`, `darkMode: false`/absent → `colorScheme: "light"`. There is no runtime fallback migrate stored flows before upgrading.
428
430
 
429
- ### Dark Mode
431
+ ### Theme knobs
430
432
 
431
- Enable dark mode via the `theme` prop or config:
433
+ Layer brand colors on top of the preset with the `theme` palette knobs. Each knob sets its primary `--fbre-*` token **plus the tokens derived from it** (e.g. `surface` also drives the input fills and hover/alt surfaces, via mode-aware `color-mix`). Any subset may be set; unset knobs fall through to the preset.
432
434
 
433
435
  ```tsx
434
- // Via theme prop (takes precedence)
435
- <FBRE flow={myFlow} theme={{ darkMode: true }} onFlowComplete={handleComplete} />
436
+ <FBRE
437
+ flow={myFlow}
438
+ theme={{
439
+ colorScheme: "dark",
440
+ color: "#bcd3cd", // accent
441
+ background: "#1a2a3a", // form ground
442
+ surface: "#243244", // input fills / cards
443
+ text: "#e8ede9",
444
+ border: "#2e4158",
445
+ radius: "3px",
446
+ fontFamily: '"Inter", system-ui, sans-serif',
447
+ }}
448
+ onFlowComplete={handleComplete}
449
+ />
450
+ ```
436
451
 
437
- // Via flow config
438
- const flow = {
439
- ...myFlow,
440
- config: { ...myFlow.config, theme: { darkMode: true } }
441
- };
442
- <FBRE flow={flow} onFlowComplete={handleComplete} />
452
+ | Knob | Primary token | Also derives |
453
+ | --- | --- | --- |
454
+ | `color` | `--fbre-theme-color` | light/dark accent tints |
455
+ | `background` | `--fbre-bg` | |
456
+ | `surface` | `--fbre-surface` | input fills, hover/alt/subtle surfaces, control surface |
457
+ | `text` | `--fbre-text` | secondary/placeholder/disabled, label |
458
+ | `border` | `--fbre-border` | hover/light/subtle |
459
+ | `radius` | `--fbre-radius` | — |
460
+ | `fontFamily` | `--fbre-font` | — |
461
+ | `error` / `success` / `warning` | `--fbre-{error,success,warning}` | their `-bg` / `-border` (and `error-light`) |
462
+
463
+ ### Raw CSS (escape hatch)
464
+
465
+ For tokens not exposed as a knob (e.g. `--fbre-star-filled`, `--fbre-shadow-color`) — or for surgical control — override the `--fbre-*` variables directly. Scope to your wrapper so you out-specify the engine defaults regardless of load order:
466
+
467
+ ```css
468
+ .my-form-wrapper .fbre-container {
469
+ --fbre-surface: #243244;
470
+ --fbre-star-filled: #bcd3cd;
471
+ }
443
472
  ```
444
473
 
445
- Dark mode applies `data-mode="dark"` on the container and overrides all CSS custom properties with a dark palette. Custom `theme.color` values are preserved the inline style takes precedence over the dark mode default.
474
+ Knobs are inline (highest specificity among engine-supplied values), so a knob and a raw rule on the *same* token: the knob wins unless your selector is also high-specificity. Use knobs for the common palette, raw CSS for the long tail.
475
+
476
+ ### Token catalog
477
+
478
+ Every themeable value, with light/dark preset defaults. Tokens marked **(derived)** are produced from a knob when it's set; you can also set any of them raw.
479
+
480
+ **Accent** — `--fbre-theme-color` (`#1976d2` / `#42a5f5`, knob `color`), `--fbre-theme-light` (`#e3f2fd` / `#1a2332`, derived), `--fbre-theme-dark` (`#1565c0` / `#1e88e5`, derived), `--fbre-on-primary` (`#fff` / `#fff`).
481
+
482
+ **Ground & surfaces**
483
+
484
+ | Token | Light | Dark | Knob |
485
+ | --- | --- | --- | --- |
486
+ | `--fbre-bg` | `#fff` | `#121212` | `background` |
487
+ | `--fbre-surface` | `#fff` | `#1e1e1e` | `surface` |
488
+ | `--fbre-surface-hover` | `#f5f5f5` | `#2a2a2a` | (derived) |
489
+ | `--fbre-surface-alt` | `#e0e0e0` | `#333` | (derived) |
490
+ | `--fbre-surface-subtle` | `#e8e8e8` | `#2a2a2a` | (derived) |
491
+ | `--fbre-control-surface` | `#fff` | `#e0e0e0` | (derived) |
492
+ | `--fbre-input-bg` | `var(--fbre-surface)` | `var(--fbre-surface)` | (derived) |
493
+ | `--fbre-input-bg-focus` | `var(--fbre-bg)` | `var(--fbre-bg)` | (derived) |
494
+
495
+ **Text** — `--fbre-text` (`#212121` / `#e0e0e0`, knob `text`), `--fbre-text-secondary` (`#666` / `#9e9e9e`, derived), `--fbre-text-placeholder` (`#aaa` / `#666`, derived), `--fbre-text-disabled` (`#bbb` / `#555`, derived), `--fbre-label` (`var(--fbre-text-secondary)`, derived).
496
+
497
+ **Borders** — `--fbre-border` (`#ccc` / `#444`, knob `border`), `--fbre-border-hover` (`#999` / `#666`, derived), `--fbre-border-light` (`#ddd` / `#444`, derived), `--fbre-border-subtle` (`#eee` / `#333`, derived).
498
+
499
+ **State colors**
500
+
501
+ | Token | Light | Dark | Knob |
502
+ | --- | --- | --- | --- |
503
+ | `--fbre-error` | `#d32f2f` | `#ef5350` | `error` |
504
+ | `--fbre-error-light` | `#fdecea` | `#2c1b1b` | (derived) |
505
+ | `--fbre-success` | `#2d6a28` | `#a8e6a0` | `success` |
506
+ | `--fbre-success-bg` | `#ddffda` | `#1a3318` | (derived) |
507
+ | `--fbre-success-border` | `#b8e6b4` | `#2d5a28` | (derived) |
508
+ | `--fbre-warning` | `#7a5900` | `#ffe082` | `warning` |
509
+ | `--fbre-warning-bg` | `#fff8e1` | `#332b00` | (derived) |
510
+ | `--fbre-warning-border` | `#ffe082` | `#665500` | (derived) |
511
+
512
+ **Controls (no knob — set raw)** — `--fbre-toggle-track` (`#ccc` / `#555`), `--fbre-star-empty` (`#ddd` / `#444`), `--fbre-star-filled` (`#ffc107` / `#ffca28`), `--fbre-slider-track` (`#ddd` / `#444`), `--fbre-shadow-color` (`rgba(0,0,0,.12)` / `rgba(0,0,0,.4)`).
513
+
514
+ **Shape & motion** — `--fbre-radius` (`4px`, knob `radius`), `--fbre-font` (`"Segoe UI", system-ui, sans-serif`, knob `fontFamily`), `--fbre-layout-gap` (`4px`, varies by style), `--fbre-transition-duration` (`250ms`), `--fbre-transition-easing` (`cubic-bezier(0.4, 0, 0.2, 1)`).
446
515
 
447
516
  ### Screen Transitions
448
517