@mochabug/adapt-react 1.0.1-rc.12 → 1.0.1-rc.13

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
@@ -138,207 +138,140 @@ const redeemed = await redeemChallenge(client, solutions);
138
138
 
139
139
  ## Styling
140
140
 
141
- All visuals are controlled via CSS custom properties on `.mb-adapt`. The `darkMode` prop automatically switches to dark defaults, but you can override any variable for either mode.
141
+ Three ways to theme, from simplest to most powerful:
142
142
 
143
- ### Where to put the CSS
143
+ ### 1. `theme` prop (recommended)
144
144
 
145
- Add a CSS file (e.g. `adapt-theme.css`) and import it in your app:
145
+ Pass an `AdaptTheme` object for semantic theming. Derives 30+ CSS variables from a few tokens.
146
146
 
147
147
  ```tsx
148
- // App.tsx or layout
149
- import './adapt-theme.css';
148
+ import { AdaptAutomation, type AdaptTheme } from '@mochabug/adapt-react';
149
+
150
+ const theme: AdaptTheme = {
151
+ mode: 'dark',
152
+ primary: '#6366f1',
153
+ background: '#0f172a',
154
+ surface: '#1e293b',
155
+ text: '#f1f5f9',
156
+ border: '#334155',
157
+ font: '"Inter", sans-serif',
158
+ };
159
+
160
+ <AdaptAutomation automationId="auto-123" theme={theme} style={{ height: 600 }} />
150
161
  ```
151
162
 
152
- Or in Next.js, import from `app/layout.tsx` or `pages/_app.tsx`.
163
+ **`AdaptTheme` tokens:**
164
+
165
+ | Token | Effect |
166
+ |-------|--------|
167
+ | `mode` | `'light'` or `'dark'` — toggles dark mode class |
168
+ | `primary` | Accent color — derives separator, drop target, spinner colors |
169
+ | `background` | Root bg, active tab bg, status card bg |
170
+ | `surface` | Panel content bg, tab bar bg |
171
+ | `text` | Active tab text, status text, cap widget text |
172
+ | `textSecondary` | Inactive tab text |
173
+ | `border` | Tab separators, status card border, cap border |
174
+ | `font` | All panel UI text + cap widget |
175
+ | `vars` | `Record<string, string>` — direct variable overrides (key = name without `--mb-adapt-` prefix) |
176
+
177
+ The `vars` escape hatch lets you override any variable:
178
+
179
+ ```tsx
180
+ <AdaptAutomation
181
+ automationId="auto-123"
182
+ theme={{
183
+ primary: '#6366f1',
184
+ vars: {
185
+ 'floating-shadow': 'none',
186
+ 'floating-border': '2px solid #6366f1',
187
+ 'cap-border-radius': '0px',
188
+ },
189
+ }}
190
+ />
191
+ ```
153
192
 
154
- ### Matching your site's toolbar
193
+ ### 2. CSS custom properties
155
194
 
156
- Map your existing design tokens to the panel toolbar. These six variables control almost everything you see in the tab bar:
195
+ Set `--mb-adapt-*` variables on `.mb-adapt` or any ancestor. No Shadow DOM standard CSS inheritance works.
157
196
 
158
197
  ```css
159
198
  /* adapt-theme.css */
160
-
161
- /* Light mode — derive from your site's surface/text colors */
162
199
  .mb-adapt {
163
- --mb-adapt-fork-bg: #ffffff; /* panel content background */
164
- --mb-adapt-fork-tab-bg: #f5f5f5; /* inactive tab / toolbar background */
165
- --mb-adapt-fork-tab-active-bg: #ffffff; /* active tab background */
166
- --mb-adapt-fork-tab-color: #1a1a1a; /* active tab text */
167
- --mb-adapt-fork-tab-inactive-color: #888; /* inactive tab text */
168
- --mb-adapt-fork-separator: #e0e0e0; /* borders between tabs & panels */
200
+ --mb-adapt-fork-bg: #ffffff;
201
+ --mb-adapt-fork-tab-bg: #f5f5f5;
202
+ --mb-adapt-fork-tab-color: #1a1a1a;
203
+ --mb-adapt-fork-separator: #e0e0e0;
169
204
  }
170
205
 
171
- /* Dark mode — active when darkMode={true} */
172
- .mb-adapt[dark-mode] {
206
+ .mb-adapt--dark {
173
207
  --mb-adapt-fork-bg: #1e1e1e;
174
208
  --mb-adapt-fork-tab-bg: #2a2a2a;
175
- --mb-adapt-fork-tab-active-bg: #1e1e1e;
176
209
  --mb-adapt-fork-tab-color: #e0e0e0;
177
- --mb-adapt-fork-tab-inactive-color: #777;
178
210
  --mb-adapt-fork-separator: #3a3a3a;
179
211
  }
180
212
  ```
181
213
 
182
- **Typical mapping from your site's design system:**
183
-
184
- | Your site has | Maps to |
185
- |---|---|
186
- | Surface / card background | `--mb-adapt-fork-bg` |
187
- | Secondary / muted background | `--mb-adapt-fork-tab-bg` |
188
- | Primary text color | `--mb-adapt-fork-tab-color` |
189
- | Muted / secondary text | `--mb-adapt-fork-tab-inactive-color` |
190
- | Border / divider color | `--mb-adapt-fork-separator` |
191
- | Accent color | `--mb-adapt-separator-active` (resize handle highlight) |
192
- | Interactive hover tint | `--mb-adapt-button-hover-bg` |
193
-
194
- ### Custom theme (light & dark)
195
-
196
- A more complete example mapping a full brand palette — primary, secondary, and accent colors — to Adapt's CSS variables for both light and dark modes. Save this as a CSS file and import it:
197
-
198
214
  ```tsx
199
- // App.tsx or layout
200
- import './adapt-brand-theme.css';
201
- ```
202
-
203
- ```css
204
- /* adapt-brand-theme.css */
205
-
206
- /*
207
- * Example: brand theme using primary / secondary / accent colors.
208
- * Maps your design-system tokens to Adapt's CSS variables for both modes.
209
- */
210
-
211
- /* ── Light mode ────────────────────────────────── */
212
- .mb-adapt {
213
- /* Brand palette */
214
- --mb-adapt-fork-bg: #ffffff; /* surface */
215
- --mb-adapt-fork-tab-bg: #f0f4ff; /* primary-50 */
216
- --mb-adapt-fork-tab-active-bg: #ffffff; /* surface */
217
- --mb-adapt-fork-tab-color: #1e293b; /* on-surface */
218
- --mb-adapt-fork-tab-inactive-color: #64748b; /* on-surface-muted */
219
- --mb-adapt-fork-separator: #cbd5e1; /* outline */
220
-
221
- /* Accent — resize handle highlight */
222
- --mb-adapt-separator-active: rgba(79, 70, 229, 0.5); /* primary */
223
-
224
- /* Cap widget */
225
- --mb-adapt-cap-background: #ffffff;
226
- --mb-adapt-cap-border-color: #e2e8f0;
227
- --mb-adapt-cap-color: #1e293b;
228
- --mb-adapt-cap-spinner-color: #4f46e5; /* primary */
229
-
230
- /* Status cards */
231
- --mb-adapt-status-card-bg: #ffffff;
232
- --mb-adapt-status-card-border: #e2e8f0;
233
- --mb-adapt-status-text: #334155;
234
- }
235
-
236
- /* ── Dark mode ─────────────────────────────────── */
237
- .mb-adapt[dark-mode] {
238
- --mb-adapt-fork-bg: #0f172a; /* surface-dark */
239
- --mb-adapt-fork-tab-bg: #1e293b; /* primary-900 */
240
- --mb-adapt-fork-tab-active-bg: #0f172a; /* surface-dark */
241
- --mb-adapt-fork-tab-color: #f1f5f9; /* on-surface-dark */
242
- --mb-adapt-fork-tab-inactive-color: #94a3b8; /* muted-dark */
243
- --mb-adapt-fork-separator: #334155; /* outline-dark */
244
-
245
- --mb-adapt-separator-active: rgba(129, 140, 248, 0.6); /* primary-light */
246
-
247
- --mb-adapt-cap-background: #1e293b;
248
- --mb-adapt-cap-border-color: #334155;
249
- --mb-adapt-cap-color: #f1f5f9;
250
- --mb-adapt-cap-spinner-color: #818cf8; /* primary-light */
251
-
252
- --mb-adapt-status-card-bg: #1e293b;
253
- --mb-adapt-status-card-border: #334155;
254
- --mb-adapt-status-text: #e2e8f0;
255
- }
215
+ import './adapt-theme.css';
256
216
  ```
257
217
 
258
- ### Font
218
+ ### 3. Direct CSS on internal classes
259
219
 
260
- ```css
261
- .mb-adapt {
262
- --mb-adapt-font: "Inter", sans-serif;
263
- }
264
- ```
220
+ No Shadow DOM — all internal elements use plain CSS classes. Target them directly for effects that CSS variables can't express: animations, pseudo-elements, transitions, media queries.
265
221
 
266
- ### Elevation and borders
222
+ **Animated gradient toolbar (liquid glass):**
267
223
 
268
224
  ```css
269
- /* Subtle, modern elevation */
270
- .mb-adapt {
271
- --mb-adapt-floating-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
272
- --mb-adapt-floating-border: 1px solid rgba(0, 0, 0, 0.06);
273
- --mb-adapt-floating-radius: 12px;
274
- --mb-adapt-floating-backdrop: none;
275
-
276
- --mb-adapt-status-card-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
277
- --mb-adapt-drag-ghost-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
278
- --mb-adapt-border-radius: 8px; /* iframe border radius */
279
- }
280
-
281
- /* Dark mode */
282
- .mb-adapt[dark-mode] {
283
- --mb-adapt-floating-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
284
- --mb-adapt-floating-border: 1px solid rgba(255, 255, 255, 0.08);
285
- --mb-adapt-status-card-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
286
- --mb-adapt-drag-ghost-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
225
+ /* adapt-theme.css */
226
+ @keyframes toolbar-glow {
227
+ 0%, 100% { background-position: 0% 50%; }
228
+ 50% { background-position: 100% 50%; }
287
229
  }
288
- ```
289
-
290
- **Frosted glass effect:**
291
230
 
292
- ```css
293
- .mb-adapt {
294
- --mb-adapt-fork-bg: rgba(255, 255, 255, 0.7);
295
- --mb-adapt-fork-tab-bg: rgba(245, 245, 245, 0.5);
296
- --mb-adapt-floating-backdrop: blur(16px) saturate(180%);
297
- --mb-adapt-floating-border: 1px solid rgba(255, 255, 255, 0.2);
298
- --mb-adapt-floating-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
231
+ /* Light mode — warm aurora */
232
+ .mb-adapt .mb-group-header {
233
+ background: linear-gradient(
234
+ 135deg,
235
+ rgba(99, 102, 241, 0.08) 0%,
236
+ rgba(168, 85, 247, 0.08) 25%,
237
+ rgba(236, 72, 153, 0.06) 50%,
238
+ rgba(99, 102, 241, 0.08) 100%
239
+ ) !important;
240
+ background-size: 300% 300%;
241
+ animation: toolbar-glow 8s ease infinite;
299
242
  }
300
- ```
301
-
302
- **Flat / borderless:**
303
243
 
304
- ```css
305
- .mb-adapt {
306
- --mb-adapt-floating-shadow: none;
307
- --mb-adapt-floating-border: 1px solid var(--mb-adapt-fork-separator);
308
- --mb-adapt-floating-radius: 4px;
309
- --mb-adapt-status-card-shadow: none;
310
- --mb-adapt-drag-ghost-shadow: none;
244
+ /* Dark mode — deep neon */
245
+ .mb-adapt--dark .mb-group-header {
246
+ background: linear-gradient(
247
+ 135deg,
248
+ rgba(99, 102, 241, 0.15) 0%,
249
+ rgba(168, 85, 247, 0.12) 25%,
250
+ rgba(236, 72, 153, 0.10) 50%,
251
+ rgba(99, 102, 241, 0.15) 100%
252
+ ) !important;
253
+ background-size: 300% 300%;
254
+ animation: toolbar-glow 8s ease infinite;
311
255
  }
312
256
  ```
313
257
 
314
- ### Using the `classNames` prop
315
-
316
- Override internal element classes for deeper customization:
317
-
318
- ```tsx
319
- <AdaptAutomation
320
- automationId="auto-123"
321
- classNames={{
322
- root: 'my-adapt-root',
323
- iframe: 'my-adapt-iframe',
324
- statusMessage: 'my-status-overlay',
325
- statusCard: 'my-status-card',
326
- }}
327
- />
328
- ```
329
-
330
- ### Using the `styles` prop
331
-
332
- Apply inline styles to the internal root element (useful for sizing):
258
+ **Key classes you can target:**
333
259
 
334
- ```tsx
335
- <AdaptAutomation
336
- automationId="auto-123"
337
- styles={{ height: '600px', maxWidth: '1200px', margin: '0 auto' }}
338
- />
339
- ```
260
+ | Class | Element |
261
+ |-------|---------|
262
+ | `.mb-group-header` | Tab toolbar |
263
+ | `.mb-tab` | Individual tab |
264
+ | `.mb-tab[data-active="true"]` | Active tab |
265
+ | `.mb-group-content` | Panel content area |
266
+ | `.mb-floating-overlay` | Floating panel container |
267
+ | `.mb-layout-separator` | Resize handle between panels |
268
+ | `.mb-drag-ghost` | Tab drag preview |
269
+ | `.mb-adapt__status-card` | Error/stopped status card |
270
+ | `.mb-adapt__status-icon` | Status card icon |
271
+ | `.mb-adapt-minimized-tab` | Minimized panel tab |
272
+ | `.mb-drop-overlay` | Drop target highlight |
340
273
 
341
- > **Note:** `styles` targets the internal `.mb-adapt` root. Use the React `style` prop for styles on the outer `<adapt-automation>` host element.
274
+ All three approaches compose use `theme` for colors, CSS variables for fine-tuning, and direct class targeting for animations.
342
275
 
343
276
  ### Tailwind
344
277
 
@@ -386,6 +319,16 @@ Or set variables in your Tailwind global CSS:
386
319
  | `--mb-adapt-fork-tab-color` | `rgb(51,51,51)` | `#ffffff` | Active tab text |
387
320
  | `--mb-adapt-fork-tab-inactive-color` | `rgba(51,51,51,0.7)` | `#969696` | Inactive tab text |
388
321
  | `--mb-adapt-fork-separator` | `rgba(128,128,128,0.35)` | `rgb(68,68,68)` | Tab/panel borders |
322
+ | `--mb-adapt-tab-radius` | `0` | | Tab border-radius (use `999px` for pill shape) |
323
+ | `--mb-adapt-tab-shadow` | `none` | | Tab box-shadow |
324
+ | `--mb-adapt-tab-active-shadow` | `none` | | Active tab box-shadow |
325
+ | `--mb-adapt-tab-gap` | `0px` | | Tab margin (spacing between tabs) |
326
+ | `--mb-adapt-tab-padding` | `0 14px` | | Tab padding |
327
+ | `--mb-adapt-tab-font-size` | `13px` | | Tab label font size |
328
+ | `--mb-adapt-toolbar-height` | `40px` | | Toolbar / tab bar height |
329
+ | `--mb-adapt-toolbar-padding` | `0` | | Toolbar inner padding (standard CSS shorthand) |
330
+ | `--mb-adapt-tab-min-width` | `100px` | | Tab minimum width |
331
+ | `--mb-adapt-tab-spacing` | `6px` | | Gap between tab label and action buttons |
389
332
 
390
333
  ### Floating panels (elevation)
391
334
 
@@ -464,6 +407,7 @@ Or set variables in your Tailwind global CSS:
464
407
  | `floatingAutoResize` | `boolean` — floating overlays auto-resize from iframe content (default `false`) |
465
408
  | `persist` | `boolean \| PersistOptions` |
466
409
  | `text` | `StatusText` |
410
+ | `theme` | `AdaptTheme` |
467
411
  | `onSession` | `(status, fork?) => void` |
468
412
  | `onOutput` | `(output) => void` |
469
413
  | `onForkActive` | `(active) => void` |
@@ -7,7 +7,7 @@ void AdaptAutomationElement;
7
7
  * React component for embedding Adapt automations.
8
8
  * Renders `<adapt-automation>` custom element and syncs non-serializable properties via ref.
9
9
  */
10
- export const AdaptAutomation = forwardRef(function AdaptAutomation({ automationId, sessionToken, authToken, transmitter, signals, challengeToken, requiresChallenge, capWidgetOptions, inheritToken, inheritFrom, forkDisplay, darkMode, autoResizing, allowFloating, allowDocking, allowDialogDocking, allowMinimize, allowMaximize, floatingAutoResize, onSession, onOutput, onForkActive, classNames, styles, persist, text, className, style, }, ref) {
10
+ export const AdaptAutomation = forwardRef(function AdaptAutomation({ automationId, sessionToken, authToken, transmitter, signals, challengeToken, requiresChallenge, capWidgetOptions, inheritToken, inheritFrom, forkDisplay, darkMode, autoResizing, allowFloating, allowDocking, allowDialogDocking, allowMinimize, allowMaximize, floatingAutoResize, onSession, onOutput, onForkActive, classNames, styles, persist, text, theme, className, style, }, ref) {
11
11
  const internalRef = useRef(null);
12
12
  // Merge refs
13
13
  const setRef = (element) => {
@@ -31,6 +31,7 @@ export const AdaptAutomation = forwardRef(function AdaptAutomation({ automationI
31
31
  el.styles = styles;
32
32
  el.persistOptions = typeof persist === "object" ? persist : undefined;
33
33
  el.text = text;
34
+ el.theme = theme;
34
35
  el.onSessionCallback = onSession;
35
36
  el.onOutputCallback = onOutput;
36
37
  el.onForkActiveCallback = onForkActive;
@@ -1,4 +1,4 @@
1
- import { AdaptAutomationElement, type AdaptWebClientOptions, type ForkDisplay, type Output, type PersistOptions, type SignalValue, type StatusJson, type StatusText } from "@mochabug/adapt-web/core";
1
+ import { AdaptAutomationElement, type AdaptTheme, type AdaptWebClientOptions, type ForkDisplay, type Output, type PersistOptions, type SignalValue, type StatusJson, type StatusText } from "@mochabug/adapt-web/core";
2
2
  declare module "react" {
3
3
  namespace JSX {
4
4
  interface IntrinsicElements {
@@ -61,6 +61,8 @@ export interface AdaptAutomationProps {
61
61
  styles?: Partial<CSSStyleDeclaration>;
62
62
  persist?: boolean | PersistOptions;
63
63
  text?: StatusText;
64
+ /** Theme configuration for semantic theming */
65
+ theme?: AdaptTheme;
64
66
  /** CSS class name for the host element */
65
67
  className?: string;
66
68
  /** Inline styles for the host element */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mochabug/adapt-react",
3
- "version": "1.0.1-rc.12",
3
+ "version": "1.0.1-rc.13",
4
4
  "description": "React component for Adapt automation platform",
5
5
  "type": "module",
6
6
  "main": "./dist/esm/index.js",
@@ -45,6 +45,6 @@
45
45
  "typescript": "^5.9.3"
46
46
  },
47
47
  "dependencies": {
48
- "@mochabug/adapt-web": "^1.0.1-rc.12"
48
+ "@mochabug/adapt-web": "^1.0.1-rc.13"
49
49
  }
50
50
  }