@schandlergarcia/sf-web-components 1.9.68 → 1.9.70
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/.a4drules/skills/command-center-builder/SKILL.md +22 -16
- package/CHANGELOG.md +56 -27
- package/data/engine-command-center-prd.md +81 -30
- package/dist/styles/global.css +238 -0
- package/package.json +1 -1
|
@@ -45,7 +45,8 @@ The component library (`@/components/library`) provides pre-built, themed, dark-
|
|
|
45
45
|
|------|----------|----------|
|
|
46
46
|
| KPI / stat | `MetricCard` | `<div className="bg-white border ..."><h3>Total Spend</h3><span>$4,903</span></div>` |
|
|
47
47
|
| List of items | `ListCard` | `<div className="bg-white ..."><div className="space-y-3">` with custom item rows |
|
|
48
|
-
| Activity feed | `ActivityCard` or `FeedPanel` | `<div>` with hand-rolled interaction rows |
|
|
48
|
+
| Activity feed (display only) | `ActivityCard` or `FeedPanel` | `<div>` with hand-rolled interaction rows |
|
|
49
|
+
| **Activity feed (with per-item actions like "Assign to Agent")** | **Custom markup inside `BaseCard`** | **`ActivityCard` (doesn't support per-item buttons — see Engine PRD Section 8a)** |
|
|
49
50
|
| Data table | `TableCard` | `<table>` or custom grid of rows |
|
|
50
51
|
| Stats panel | `WidgetCard` or `SectionCard` | `<div className="bg-white ... p-6">` with label/value pairs |
|
|
51
52
|
| Custom interactive content (expand/collapse, inline details) | `WidgetCard` (sections accept arbitrary JSX) or `ListCard` (with `onItemClick` + `itemActions`) | Hand-rolled `<div>` card with custom expand/collapse logic |
|
|
@@ -53,7 +54,7 @@ The component library (`@/components/library`) provides pre-built, themed, dark-
|
|
|
53
54
|
| Text summary | `NarrativeSummary` / `SectionCard` | `<div>` with headings and paragraphs |
|
|
54
55
|
| Alert / callout | `CalloutCard` | Custom banner div |
|
|
55
56
|
|
|
56
|
-
Every visible section of a dashboard should be a library component. If you're writing `<div className="bg-white border rounded-[10px] shadow-sm p-6">` with content inside, that's a hand-rolled card — use a library component instead.
|
|
57
|
+
Every visible section of a dashboard should be a library component. If you're writing `<div className="bg-white border rounded-[10px] shadow-sm p-6">` with content inside, that's a hand-rolled card — use a library component instead. Exception: when a panel needs per-item action buttons (like "Assign to Agent"), use custom markup inside `BaseCard`.
|
|
57
58
|
|
|
58
59
|
### Correct example:
|
|
59
60
|
|
|
@@ -103,7 +104,7 @@ No `<nav>`, header bar, tab bar, or content-swapping via `useState("activeTab")`
|
|
|
103
104
|
|
|
104
105
|
- Dashboard page files: `src/pages/` (e.g. `EngineDashboard.tsx`, `FleetDashboard.tsx`) — **NOT** `src/components/pages/`
|
|
105
106
|
- File format: `.tsx` (MUST be TypeScript) — this is a TypeScript project, all React components use `.tsx`, NEVER `.jsx`.
|
|
106
|
-
- `CommandCenter.tsx` wraps with `AppThemeProvider` + `DataModeProvider` + `
|
|
107
|
+
- `CommandCenter.tsx` wraps with `heroui-scope` div + `AppThemeProvider` + `DataModeProvider` + `Toast.Provider` from `@heroui/react`. **Never recreate these providers in dashboard pages.** When wiring a new dashboard, only change the import — preserve the `heroui-scope` wrapper and `Toast.Provider` exactly as-is. For toasts inside dashboards, use `toast` from `sonner` (not `addToast` from HeroUI).
|
|
107
108
|
|
|
108
109
|
### Wiring a new dashboard (REQUIRED STEPS)
|
|
109
110
|
|
|
@@ -124,22 +125,24 @@ export default function MyDashboard() {
|
|
|
124
125
|
}
|
|
125
126
|
```
|
|
126
127
|
|
|
127
|
-
**Step 2:** Update `CommandCenter.tsx` to import and render it
|
|
128
|
+
**Step 2:** Update `CommandCenter.tsx` to import and render it. Only change the import line — preserve `heroui-scope` and `Toast.Provider`:
|
|
128
129
|
```tsx
|
|
129
130
|
// src/components/workspace/CommandCenter.tsx
|
|
130
131
|
import AppThemeProvider from "@/components/library/theme/AppThemeProvider";
|
|
131
132
|
import DataModeProvider from "@/components/library/data/DataModeProvider";
|
|
132
|
-
import {
|
|
133
|
-
import MyDashboard from "../../pages/MyDashboard"; // ← change this import
|
|
133
|
+
import { Toast } from "@heroui/react";
|
|
134
|
+
import MyDashboard from "../../pages/MyDashboard"; // ← change ONLY this import
|
|
134
135
|
|
|
135
136
|
export default function CommandCenter() {
|
|
136
137
|
return (
|
|
137
|
-
<
|
|
138
|
-
<
|
|
139
|
-
<
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
138
|
+
<div className="heroui-scope"> {/* ← preserve this wrapper */}
|
|
139
|
+
<AppThemeProvider initialMode="light">
|
|
140
|
+
<DataModeProvider initialMode="sample">
|
|
141
|
+
<MyDashboard /> {/* ← change this */}
|
|
142
|
+
<Toast.Provider placement="bottom end" /> {/* ← preserve this */}
|
|
143
|
+
</DataModeProvider>
|
|
144
|
+
</AppThemeProvider>
|
|
145
|
+
</div>
|
|
143
146
|
);
|
|
144
147
|
}
|
|
145
148
|
```
|
|
@@ -224,7 +227,8 @@ Key rules:
|
|
|
224
227
|
| System health | `StatusCard` |
|
|
225
228
|
| Feed / item list | `ListCard` |
|
|
226
229
|
| Scrollable side panel | `FeedPanel` |
|
|
227
|
-
| Activity feed | `ActivityCard` |
|
|
230
|
+
| Activity feed (display only) | `ActivityCard` |
|
|
231
|
+
| Activity feed (per-item actions) | Custom markup in `BaseCard` |
|
|
228
232
|
| User avatar | `Avatar` |
|
|
229
233
|
| Text summary | `NarrativeSummary` (schema) / `SectionCard` |
|
|
230
234
|
| Actions | `ActionList` (schema) / `UIButton` group |
|
|
@@ -341,8 +345,9 @@ Define schemas outside component body. Always `required: true` on mandatory fiel
|
|
|
341
345
|
|
|
342
346
|
## AI Chat & Agent
|
|
343
347
|
|
|
344
|
-
Use `ChatBar`
|
|
348
|
+
Use `ChatBar` for dashboards, `ChatPanel` for full-page chat.
|
|
345
349
|
|
|
350
|
+
- Place `ChatBar` between the hero map and data panels (full-width, `px-4 pt-4`), NOT in the header
|
|
346
351
|
- Always provide 3–5 `suggestions` for starter prompts
|
|
347
352
|
- Return `components` for structured data — never markdown tables in text
|
|
348
353
|
- Always set height on `ChatPanel`
|
|
@@ -466,7 +471,7 @@ Every data component handles loading. Error messages are human-readable. Empty s
|
|
|
466
471
|
|
|
467
472
|
Before finishing a dashboard page, verify ALL of these:
|
|
468
473
|
|
|
469
|
-
- [ ] **Every card/panel is a library component** (MetricCard, ListCard, ActivityCard, WidgetCard, TableCard, etc.) — no hand-rolled `<div className="bg-white border ...">` cards
|
|
474
|
+
- [ ] **Every card/panel is a library component** (MetricCard, ListCard, ActivityCard, WidgetCard, TableCard, etc.) — no hand-rolled `<div className="bg-white border ...">` cards. Exception: panels that need per-item action buttons (e.g. "Assign to Agent") can use custom markup inside `BaseCard`.
|
|
470
475
|
- [ ] **Every chart/visualization is a library component** (ChartCard + D3Chart, GeoMap) — no hand-rolled SVG/canvas
|
|
471
476
|
- [ ] **No `<nav>`, header bar, or sticky tab bar** — navigation is handled by appLayout.tsx
|
|
472
477
|
- [ ] **Single scrollable page** — no multi-tab layout that swaps content
|
|
@@ -498,7 +503,8 @@ Instead, verify correctness by reviewing the code against the Pre-Completion Che
|
|
|
498
503
|
- Using `template` prop on D3Chart — use `renderChart={D3ChartTemplates.lineChart}`
|
|
499
504
|
- Passing D3Chart as children to ChartCard — use `chart={<D3Chart ... />}` prop
|
|
500
505
|
- Adding `<nav>` or tab-swapping (`useState("activeTab")`) inside dashboards
|
|
501
|
-
- Recreating providers — `CommandCenter.tsx` already provides them
|
|
506
|
+
- Recreating providers — `CommandCenter.tsx` already provides them. Do not replace `Toast.Provider` with `Toaster` from sonner, and do not remove the `heroui-scope` div
|
|
507
|
+
- Using `addToast` from `@heroui/react` — use `toast` / `toast.success` from `sonner` instead
|
|
502
508
|
- Using `text-black`, `text-white`, `bg-black` — use slate scale
|
|
503
509
|
- Hardcoded data without `useDataSource` — always support sample/live switching
|
|
504
510
|
- `position: fixed` without `createPortal`
|
package/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,25 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [1.9.
|
|
8
|
+
## [1.9.70] - 2026-04-02
|
|
9
|
+
|
|
10
|
+
### Updated
|
|
11
|
+
- **PRD (engine-command-center-prd.md)** - 5 edits for phasing clarity and toast API:
|
|
12
|
+
- Section 4 (Architecture): Added explicit rules to preserve `heroui-scope` wrapper and `Toast.Provider` in CommandCenter. Added `toast` from `sonner` as the correct toast API
|
|
13
|
+
- Section 6 (Header): Added "(Phase 4)" tag to "Powered by Agentforce" badge
|
|
14
|
+
- Section 8a (Escalations): Added "(Phase 4)" tag to "Assign to Agent" button, noted `toast.success` comes via `sonner`, added instruction to render button with empty `onClick` in Phase 2 and wire toast in Phase 4
|
|
15
|
+
- Section 10 (Signals): Changed `toast()` and `toast.success()` to include full call examples with "via sonner" annotation
|
|
16
|
+
- Section 13, Phase 3 prompt: Added file paths for queries and hook, code example showing how to wire `useEngineLiveData()` into `useDataSource({ sample: ..., live: live.xxx })`, clarified hook should match sample data shape
|
|
17
|
+
|
|
18
|
+
- **Builder skill (SKILL.md)** - 3 edits for toast API and wiring:
|
|
19
|
+
- Wiring section: Changed description from Toaster to `heroui-scope` + `Toast.Provider` from `@heroui/react`. Added rule to use `toast` from `sonner` for dashboard toasts
|
|
20
|
+
- Wiring example (Step 2): Replaced sonner Toaster code with actual pattern: `heroui-scope` div, `Toast.Provider` from `@heroui/react`, with comments marking "preserve this" vs "change this"
|
|
21
|
+
- Component table: Bolded "per-item actions" row and added "see Engine PRD Section 8a" cross-reference
|
|
22
|
+
- Anti-patterns: Added two entries: (1) don't replace `Toast.Provider` with sonner's `Toaster` or remove `heroui-scope`, (2) don't use `addToast` from HeroUI — use `toast` from `sonner`
|
|
23
|
+
|
|
24
|
+
**Context:** Clarified phasing tags for Phase 4 features (badge, agent buttons) and documented correct toast API pattern (HeroUI provider + sonner toast function).
|
|
25
|
+
|
|
26
|
+
## [1.9.69] - 2026-04-01
|
|
9
27
|
|
|
10
28
|
### Fixed
|
|
11
29
|
- **6 data bugs in engine-sample-data.js**:
|
|
@@ -17,39 +35,50 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
17
35
|
6. Updated TXL → BER throughout (Berlin airport code change)
|
|
18
36
|
|
|
19
37
|
### Updated
|
|
20
|
-
- **
|
|
38
|
+
- **Global styles** - Added `src/styles/global.css` with Engine brand tokens and command center styling
|
|
39
|
+
|
|
40
|
+
- **PRD (engine-command-center-prd.md)** - Updated to match actual built dashboard:
|
|
41
|
+
- Layout diagram now shows 4-section structure: Header → Hero Map → Eva ChatBar → Data Panels (was missing ChatBar section)
|
|
42
|
+
- Layout classes added Eva: `<div className="px-4 pt-4">` as distinct section
|
|
43
|
+
- Section 6 (Header): Explicitly says "No ChatBar in the header — Eva lives below the map." Added "Powered by Agentforce" badge description
|
|
44
|
+
- Section 7 (Hero Map): Added explicit KPI label styling (`text-[10px] font-medium uppercase tracking-wide text-slate-300`) and value/pill/icon specs
|
|
45
|
+
- Section 8a (Escalations): Replaced ActivityCard with custom inline panel in BaseCard. Added full code example with status icons (CheckCircleIcon/ArrowPathIcon/ClockIcon), conditional "Assign to Agent" buttons, and toast.success
|
|
46
|
+
- Section 8c (Active Travelers): Added "View in Salesforce" link in expanded detail
|
|
47
|
+
- Section 9 (Eva): Completely rewritten - ChatBar is now between map and data panels, full-width, with phasing notes (Phase 1 = skip, Phase 4 = add)
|
|
48
|
+
- Section 10 (Signals): Added "Assigned to Eva" toast row for Assign to Agent button
|
|
49
|
+
- Phase 4 build prompt: Updated to say "Add Eva below the map as a ChatBar" and mention "Assign to Agent" buttons on open escalations
|
|
21
50
|
- Applied Option A layout: Escalations + Disruptions in Row 1 (above fold), Active Travelers + Spend in Row 2
|
|
22
|
-
- Both rows
|
|
51
|
+
- Both rows use `lg:grid-cols-3` with left panel at 2/3 width
|
|
23
52
|
- Removed all "TDX26" and "demo" references
|
|
24
|
-
- Cut Section 14 "What NOT to Do" entirely
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
- `skills/command-center-builder/data-forms-ai.md` - 44 → 1 line
|
|
38
|
-
- `skills/command-center-builder/improved-build-process.md` - 20 → 1 line
|
|
39
|
-
|
|
40
|
-
- **Builder skill main file** - Trimmed (629 → 505 lines, -20%):
|
|
41
|
-
- `skills/command-center-builder/SKILL.md` - Removed wrong-example code blocks, condensed navigation section from 40 to 2 lines, trimmed map layout section, removed custom renderChart examples, cut anti-patterns list from 33 to 12 items
|
|
53
|
+
- Cut Section 14 "What NOT to Do" entirely
|
|
54
|
+
- Condensed Phase 1 placeholder rules from 75 to 8 lines
|
|
55
|
+
|
|
56
|
+
- **Builder skill (SKILL.md)** - Fixed 4 contradictions:
|
|
57
|
+
- Component table: Split "Activity feed" into two rows: "display only" → ActivityCard, "with per-item actions" → custom markup in BaseCard
|
|
58
|
+
- Component selection table: Same split applied
|
|
59
|
+
- AI Chat & Agent section: Added bullet: "Place ChatBar between the hero map and data panels, NOT in the header"
|
|
60
|
+
- Pre-Completion Checklist: Added exception: panels needing per-item action buttons can use custom markup inside BaseCard
|
|
61
|
+
- General library component rule: Added exception note for per-item action buttons
|
|
62
|
+
- Removed wrong-example code blocks, condensed navigation (40 → 2 lines), removed custom renderChart examples, cut anti-patterns (33 → 12 items)
|
|
63
|
+
|
|
64
|
+
- **Builder skill sub-files** - Replaced with single-line redirects:
|
|
65
|
+
- 7 files reduced from 630 total lines to 7 lines (100% duplicates eliminated)
|
|
42
66
|
|
|
43
67
|
- **Simplified .a4drules documentation** - Removed redundancy, contradictions, and AI coaching language:
|
|
44
|
-
- `features/engine-dashboard-rule.md` - Rewritten as "Project Conventions" (
|
|
68
|
+
- `features/engine-dashboard-rule.md` - Rewritten as "Project Conventions" (~65 lines)
|
|
45
69
|
- `features/command-center-dashboard-rule.md` - Rewritten as slim conventions (~30 lines)
|
|
46
|
-
- `features/pre-code-checklist.md` - Rewritten as "Quick Reference" (~25 lines
|
|
70
|
+
- `features/pre-code-checklist.md` - Rewritten as "Quick Reference" (~25 lines)
|
|
47
71
|
- `features/phase2-data-pattern.md` - Rewritten as "Sample Data" documentation (~20 lines)
|
|
48
|
-
- `skills/command-center-project/SKILL.md` - Fixed file path contradiction
|
|
49
|
-
- `skills/command-center-guide/SKILL.md` - Reduced from 270 to ~45 lines
|
|
50
|
-
- `skills/component-library/SKILL.md` - Description now lists all key component names
|
|
72
|
+
- `skills/command-center-project/SKILL.md` - Fixed file path contradiction
|
|
73
|
+
- `skills/command-center-guide/SKILL.md` - Reduced from 270 to ~45 lines
|
|
74
|
+
- `skills/component-library/SKILL.md` - Description now lists all key component names
|
|
75
|
+
|
|
76
|
+
**Context:** PRD now accurately reflects the actual built dashboard with Eva ChatBar between map and data panels. Eliminated contradictions about ActivityCard vs custom markup for action buttons.
|
|
51
77
|
|
|
52
|
-
|
|
78
|
+
## [1.9.68] - 2026-04-01
|
|
79
|
+
|
|
80
|
+
### Updated
|
|
81
|
+
- **Major documentation consolidation** - PRD reduced 39%, builder skill sub-files eliminated duplication, overall .a4drules reduced from ~2000 to ~800 lines
|
|
53
82
|
|
|
54
83
|
## [1.9.67] - 2026-04-01
|
|
55
84
|
|
|
@@ -18,7 +18,7 @@ The Engine Travel Command Center is a real-time operations dashboard for corpora
|
|
|
18
18
|
Manages Acme's travel program: bookings, policy enforcement, exceptions, traveler monitoring.
|
|
19
19
|
|
|
20
20
|
**Secondary — Eva (Agentforce Agent)**
|
|
21
|
-
Engine's Agentforce-powered AI agent. Handles traveler requests autonomously — booking changes, policy questions, itinerary lookups. Resolves ~30% of requests without human involvement. Surfaces via `ChatBar
|
|
21
|
+
Engine's Agentforce-powered AI agent. Handles traveler requests autonomously — booking changes, policy questions, itinerary lookups. Resolves ~30% of requests without human involvement. Surfaces via `ChatBar` below the hero map.
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
@@ -50,7 +50,8 @@ Use `brand-*` Tailwind classes for brand elements. Tailwind built-in colors (gre
|
|
|
50
50
|
## 4. Architecture
|
|
51
51
|
|
|
52
52
|
- **Dashboard file:** `src/pages/EngineDashboard.tsx`
|
|
53
|
-
- **Wiring:** `CommandCenter.tsx` imports and renders `EngineDashboard` inside the existing provider stack. Never recreate providers in the dashboard.
|
|
53
|
+
- **Wiring:** `CommandCenter.tsx` imports and renders `EngineDashboard` inside the existing provider stack. Never recreate providers in the dashboard. When updating `CommandCenter.tsx`, only change the dashboard import line — preserve the `heroui-scope` wrapper div and `Toast.Provider` from `@heroui/react` exactly as-is.
|
|
54
|
+
- **Toasts:** Import `toast` from `sonner` in dashboard pages. Use `toast.success("message")` for success toasts and `toast("message")` for informational ones. The `Toast.Provider` in CommandCenter handles rendering — do not add a second `Toaster` or replace the existing provider.
|
|
54
55
|
- **Imports:** Components from `@/components/library`. Theme from `@/components/library/theme/AppThemeProvider`.
|
|
55
56
|
|
|
56
57
|
---
|
|
@@ -62,7 +63,7 @@ Visualization-hero layout. Full-page scroll (no `h-screen`).
|
|
|
62
63
|
```
|
|
63
64
|
┌──────────────────────────────────────────────────────────────┐
|
|
64
65
|
│ HEADER (h-12, sticky, bg-slate-900) │
|
|
65
|
-
│ Engine logo + "Travel Command Center" | actions
|
|
66
|
+
│ Engine logo + "Travel Command Center" + badge | actions │
|
|
66
67
|
├──────────────────────────────────────────────────────────────┤
|
|
67
68
|
│ HERO MAP (h-[520px], GeoMap, relative) │
|
|
68
69
|
│ ┌─ glass KPI overlays (absolute top-left) ───────────────┐ │
|
|
@@ -72,11 +73,13 @@ Visualization-hero layout. Full-page scroll (no `h-screen`).
|
|
|
72
73
|
│ │ BA 286 · In Air | NH 109 · In Air | LH 431 · Delayed │ │
|
|
73
74
|
│ └────────────────────────────────────────────────────────┘ │
|
|
74
75
|
├──────────────────────────────────────────────────────────────┤
|
|
76
|
+
│ EVA CHATBAR (px-4 pt-4, full-width command palette strip) │
|
|
77
|
+
├──────────────────────────────────────────────────────────────┤
|
|
75
78
|
│ DATA PANELS (px-4 py-5 space-y-6) │
|
|
76
79
|
│ │
|
|
77
80
|
│ Row 1: grid grid-cols-1 items-start gap-4 lg:grid-cols-3 │
|
|
78
81
|
│ ┌── 2/3 (lg:col-span-2) ──────┐ ┌── 1/3 ───────────────┐ │
|
|
79
|
-
│ │ Escalations (
|
|
82
|
+
│ │ Escalations (custom panel) │ │ Disruptions (custom) │ │
|
|
80
83
|
│ └───────────────────────────────┘ └──────────────────────┘ │
|
|
81
84
|
│ │
|
|
82
85
|
│ Row 2: grid grid-cols-1 items-start gap-4 lg:grid-cols-3 │
|
|
@@ -90,13 +93,14 @@ Visualization-hero layout. Full-page scroll (no `h-screen`).
|
|
|
90
93
|
|
|
91
94
|
- **Outer:** `<div className="flex flex-col bg-slate-50 dark:bg-slate-950">`
|
|
92
95
|
- **Map:** `<div className="relative h-[520px]">`
|
|
96
|
+
- **Eva:** `<div className="px-4 pt-4"><ChatBar ... /></div>`
|
|
93
97
|
- **Panels:** `<div className="px-4 py-5"><div className="space-y-6">...</div></div>`
|
|
94
98
|
- **Row 1:** `grid grid-cols-1 items-start gap-4 lg:grid-cols-3` — Escalations `lg:col-span-2`, Disruptions auto
|
|
95
99
|
- **Row 2:** `grid grid-cols-1 items-start gap-4 lg:grid-cols-3` — Travelers `lg:col-span-2`, Spend auto
|
|
96
100
|
|
|
97
101
|
### Phase 1 placeholders
|
|
98
102
|
|
|
99
|
-
Phase 1 builds the header, map, glass overlays, and flight strip as real components. Only the 4 data panels below the map are placeholders:
|
|
103
|
+
Phase 1 builds the header, map, glass overlays, and flight strip as real components. Only the ChatBar and 4 data panels below the map are placeholders:
|
|
100
104
|
|
|
101
105
|
```tsx
|
|
102
106
|
<BaseCard>
|
|
@@ -112,11 +116,11 @@ The GeoMap renders the base world map with no data props. Glass overlays and fli
|
|
|
112
116
|
|
|
113
117
|
## 6. Header
|
|
114
118
|
|
|
115
|
-
Compact `h-12` sticky header (`bg-slate-900 dark:bg-slate-950`).
|
|
119
|
+
Compact `h-12` sticky header (`bg-slate-900 dark:bg-slate-950`). No ChatBar in the header — Eva lives below the map.
|
|
116
120
|
|
|
117
121
|
| Left | Right |
|
|
118
122
|
|------|-------|
|
|
119
|
-
| Engine logo (`GlobeAltIcon` in `bg-brand-600` square) + "ENGINE" wordmark + separator + "Travel Command Center"
|
|
123
|
+
| Engine logo (`GlobeAltIcon` in `bg-brand-600` square) + "ENGINE" wordmark + separator + "Travel Command Center" + "Powered by Agentforce" badge (Phase 4: `bg-brand-900/40 text-brand-400 rounded-full text-[10px]`) | Notification bell (badge count) + theme toggle (sun/moon) |
|
|
120
124
|
|
|
121
125
|
---
|
|
122
126
|
|
|
@@ -145,9 +149,13 @@ Compact `h-12` sticky header (`bg-slate-900 dark:bg-slate-950`).
|
|
|
145
149
|
|
|
146
150
|
**Glass KPI overlays** — 4 pills, `absolute left-3 top-3`:
|
|
147
151
|
Active Travelers (count), Spend MTD (`fmtK()`), Compliance %, Eva Resolved (count + "resolved").
|
|
148
|
-
Style: `bg-black/40 backdrop-blur-md border border-white/10 rounded-lg px-3 py-1.5`
|
|
149
152
|
|
|
150
|
-
|
|
153
|
+
Label styling: `text-[10px] font-medium uppercase tracking-wide text-slate-300`
|
|
154
|
+
Value styling: `text-sm font-semibold text-slate-50`
|
|
155
|
+
Pill styling: `bg-black/40 backdrop-blur-md border border-white/10 rounded-lg px-3 py-1.5`
|
|
156
|
+
Icon: `h-4 w-4 text-brand-400`
|
|
157
|
+
|
|
158
|
+
**Flight status strip** — `absolute bottom-3 left-3 right-3`, horizontal scroll. One pill per flight: flight number + status chip (green=On Time, amber=Delayed, sky=Boarding). Same glass styling.
|
|
151
159
|
|
|
152
160
|
---
|
|
153
161
|
|
|
@@ -157,18 +165,48 @@ Style: `bg-black/40 backdrop-blur-md border border-white/10 rounded-lg px-3 py-1
|
|
|
157
165
|
|
|
158
166
|
### 8a. Escalations (Row 1, 2/3 width)
|
|
159
167
|
|
|
160
|
-
|
|
168
|
+
Custom inline panel in BaseCard. Do NOT use ActivityCard — this panel has per-item "Assign to Agent" buttons.
|
|
169
|
+
|
|
170
|
+
Each escalation row:
|
|
171
|
+
- Status icon: `CheckCircleIcon` (complete, green), `ArrowPathIcon` (working, brand), `ClockIcon` (pending, amber)
|
|
172
|
+
- Title + subtitle + timestamp
|
|
173
|
+
- **"Assign to Agent" button** (Phase 4) on items where status is NOT `"complete"`: teal button (`bg-brand-600`) with `SparklesIcon` + "Assign to Agent" text. On click: `toast.success("Assigned to Eva")` via sonner. In Phase 2, render the button but leave the `onClick` empty — wire the toast in Phase 4.
|
|
161
174
|
|
|
162
175
|
```tsx
|
|
163
176
|
<BaseCard>
|
|
164
|
-
<
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
177
|
+
<div className="p-4">
|
|
178
|
+
<h3 className="mb-3 text-sm font-semibold text-slate-900 dark:text-slate-50">
|
|
179
|
+
Escalations
|
|
180
|
+
</h3>
|
|
181
|
+
<div className="divide-y divide-slate-100 dark:divide-slate-800">
|
|
182
|
+
{escalations.map((e) => {
|
|
183
|
+
const isOpen = e.status !== "complete";
|
|
184
|
+
return (
|
|
185
|
+
<div key={e.id} className="flex items-start gap-3 py-3">
|
|
186
|
+
<StatusIcon className={`mt-0.5 h-5 w-5 shrink-0 ${statusColor}`} />
|
|
187
|
+
<div className="min-w-0 flex-1">
|
|
188
|
+
<div className="text-sm font-medium text-slate-900 dark:text-slate-50">{e.title}</div>
|
|
189
|
+
<div className="mt-0.5 text-xs text-slate-500 dark:text-slate-400">
|
|
190
|
+
{e.subtitle} · {e.timestamp}
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
193
|
+
{isOpen && (
|
|
194
|
+
<button onClick={() => handleAssignToAgent(e)}
|
|
195
|
+
className="shrink-0 rounded-md bg-brand-600 px-2.5 py-1 text-xs font-medium text-slate-50 hover:bg-brand-700">
|
|
196
|
+
<span className="flex items-center gap-1">
|
|
197
|
+
<SparklesIcon className="h-3 w-3" /> Assign to Agent
|
|
198
|
+
</span>
|
|
199
|
+
</button>
|
|
200
|
+
)}
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
})}
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
168
206
|
</BaseCard>
|
|
169
207
|
```
|
|
170
208
|
|
|
171
|
-
|
|
209
|
+
Data: `ESCALATION_CARDS` from sample data.
|
|
172
210
|
|
|
173
211
|
### 8b. Disruptions (Row 1, 1/3 width)
|
|
174
212
|
|
|
@@ -186,8 +224,8 @@ Data: `DISRUPTION_CARDS` from sample data.
|
|
|
186
224
|
|
|
187
225
|
BaseCard with `maxBodyHeight={420}`. Expandable traveler cards.
|
|
188
226
|
|
|
189
|
-
Each row: `Avatar` (initials) + name + department + origin → destination +
|
|
190
|
-
Expand: 4-col grid — Flight, Hotel, Return, Destination.
|
|
227
|
+
Each row: `Avatar` (initials) + name + department + origin → destination + policy chip (compliant=green, exception=amber).
|
|
228
|
+
Expand: 4-col grid — Flight, Hotel, Return, Destination + "View in Salesforce" link.
|
|
191
229
|
|
|
192
230
|
Data: `TRAVELER_CARDS` from sample data.
|
|
193
231
|
|
|
@@ -223,23 +261,28 @@ const spendChartData = useDataSource({
|
|
|
223
261
|
|
|
224
262
|
---
|
|
225
263
|
|
|
226
|
-
## 9. Eva — ChatBar
|
|
264
|
+
## 9. Eva — ChatBar
|
|
227
265
|
|
|
228
|
-
ChatBar in the header.
|
|
266
|
+
Eva renders as a full-width `ChatBar` below the hero map, between the map and the data panels. NOT in the header. NOT a FAB or sliding panel.
|
|
229
267
|
|
|
230
268
|
```tsx
|
|
231
|
-
<
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
269
|
+
<div className="px-4 pt-4">
|
|
270
|
+
<ChatBar
|
|
271
|
+
title="Eva"
|
|
272
|
+
placeholder="Ask Eva anything about travelers, bookings, policy, or spend…"
|
|
273
|
+
suggestions={CHAT_SUGGESTIONS}
|
|
274
|
+
onSend={handleChat}
|
|
275
|
+
/>
|
|
276
|
+
</div>
|
|
237
277
|
```
|
|
238
278
|
|
|
239
279
|
Suggestions: "Who's traveling internationally right now?", "Show bookings pending approval", "What has Eva resolved today?", "Travelers returning this week"
|
|
240
280
|
|
|
241
281
|
Define `handleChat` and `CHAT_SUGGESTIONS` at module scope.
|
|
242
282
|
|
|
283
|
+
**Phase 1:** Placeholder — do NOT add ChatBar. Just leave the space empty.
|
|
284
|
+
**Phase 4:** Add the ChatBar between the map and data panels.
|
|
285
|
+
|
|
243
286
|
---
|
|
244
287
|
|
|
245
288
|
## 10. Salesforce Signals (Phase 4)
|
|
@@ -248,9 +291,10 @@ Subtle indicators, not banners.
|
|
|
248
291
|
|
|
249
292
|
| Signal | Location |
|
|
250
293
|
|--------|----------|
|
|
251
|
-
| "
|
|
252
|
-
| "Salesforce
|
|
253
|
-
| "
|
|
294
|
+
| "Powered by Agentforce" | Header, next to "Travel Command Center" (small rounded badge) |
|
|
295
|
+
| "View in Salesforce" | Traveler expanded view (micro-link, muted text) |
|
|
296
|
+
| "Salesforce updated" | After rebook/approve actions — `toast("Opening in Salesforce…")` via sonner |
|
|
297
|
+
| "Assigned to Eva" | After "Assign to Agent" button click — `toast.success("Assigned to Eva")` via sonner |
|
|
254
298
|
|
|
255
299
|
---
|
|
256
300
|
|
|
@@ -285,8 +329,15 @@ Build in 4 incremental phases.
|
|
|
285
329
|
|
|
286
330
|
### Phase 3: Real Data Integration
|
|
287
331
|
|
|
288
|
-
> Connect the dashboard to live Salesforce data using GraphQL. Read the sample data file to see which fields are needed, then build queries and hooks for each object. The
|
|
332
|
+
> Connect the dashboard to live Salesforce data using GraphQL. Read the sample data file to see which fields are needed, then build queries in `src/api/engine/queries.ts` and a hook in `src/hooks/useEngineLiveData.ts` for each object. The hook should return the same data shape as the sample data exports. Wire it into the dashboard by populating the `live` prop on each `useDataSource` call:
|
|
333
|
+
>
|
|
334
|
+
> ```tsx
|
|
335
|
+
> const live = useEngineLiveData();
|
|
336
|
+
> const markers = useDataSource({ sample: MAP_MARKERS, live: live.mapMarkers });
|
|
337
|
+
> ```
|
|
338
|
+
>
|
|
339
|
+
> The UI should stay identical — only the data source changes.
|
|
289
340
|
|
|
290
341
|
### Phase 4: Agentforce Integration
|
|
291
342
|
|
|
292
|
-
> Add Eva
|
|
343
|
+
> Add Eva below the map as a ChatBar. Add subtle Salesforce signals throughout — "Powered by Agentforce" badge in the header, "View in Salesforce" links in traveler details, success toasts, and "Assign to Agent" buttons on open escalations.
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
@import '@heroui/styles';
|
|
2
|
+
|
|
3
|
+
@layer base {
|
|
4
|
+
html,
|
|
5
|
+
body,
|
|
6
|
+
#root {
|
|
7
|
+
@apply min-h-screen;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
body {
|
|
11
|
+
@apply antialiased bg-white;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@import 'tw-animate-css';
|
|
16
|
+
@import 'shadcn/tailwind.css';
|
|
17
|
+
|
|
18
|
+
@custom-variant dark (&:is(.dark *));
|
|
19
|
+
|
|
20
|
+
@source "../components/library";
|
|
21
|
+
@source "../components/pages";
|
|
22
|
+
|
|
23
|
+
@theme inline {
|
|
24
|
+
--color-background: var(--background);
|
|
25
|
+
--color-foreground: var(--foreground);
|
|
26
|
+
--color-card: var(--card);
|
|
27
|
+
--color-card-foreground: var(--card-foreground);
|
|
28
|
+
--color-popover: var(--popover);
|
|
29
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
30
|
+
--color-primary: var(--primary);
|
|
31
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
32
|
+
--color-secondary: var(--secondary);
|
|
33
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
34
|
+
--color-muted: var(--muted);
|
|
35
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
36
|
+
--color-accent: var(--accent);
|
|
37
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
38
|
+
--color-destructive: var(--destructive);
|
|
39
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
40
|
+
--color-border: var(--border);
|
|
41
|
+
--color-input: var(--input);
|
|
42
|
+
--color-ring: var(--ring);
|
|
43
|
+
--color-chart-1: var(--chart-1);
|
|
44
|
+
--color-chart-2: var(--chart-2);
|
|
45
|
+
--color-chart-3: var(--chart-3);
|
|
46
|
+
--color-chart-4: var(--chart-4);
|
|
47
|
+
--color-chart-5: var(--chart-5);
|
|
48
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
49
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
50
|
+
--radius-lg: var(--radius);
|
|
51
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
52
|
+
--color-sidebar: var(--sidebar);
|
|
53
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
54
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
55
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
56
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
57
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
58
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
59
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
60
|
+
|
|
61
|
+
/* Engine brand palette */
|
|
62
|
+
--color-engine-black: #111111;
|
|
63
|
+
--color-engine-teal: #5BC8C8;
|
|
64
|
+
--color-engine-green: #3DAB5F;
|
|
65
|
+
--color-engine-coral: #FF5722;
|
|
66
|
+
--color-engine-orange: #F59E0B;
|
|
67
|
+
--color-engine-savings: #16A34A;
|
|
68
|
+
--color-engine-bg: #F7F8FA;
|
|
69
|
+
--color-engine-border: #E5E7EB;
|
|
70
|
+
--color-engine-text: #111111;
|
|
71
|
+
--color-engine-muted: #6B7280;
|
|
72
|
+
--color-engine-label: #9CA3AF;
|
|
73
|
+
|
|
74
|
+
/* Engine teal brand palette */
|
|
75
|
+
--color-brand-50: #ECFDF9;
|
|
76
|
+
--color-brand-100: #D1FAF0;
|
|
77
|
+
--color-brand-200: #A7F3E1;
|
|
78
|
+
--color-brand-300: #6EE7C8;
|
|
79
|
+
--color-brand-400: #34D3AB;
|
|
80
|
+
--color-brand-500: #5BC8C8;
|
|
81
|
+
--color-brand-600: #0D9488;
|
|
82
|
+
--color-brand-700: #0F766E;
|
|
83
|
+
--color-brand-800: #115E59;
|
|
84
|
+
--color-brand-900: #134E4A;
|
|
85
|
+
--color-brand-950: #042F2E;
|
|
86
|
+
|
|
87
|
+
--font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, sans-serif;
|
|
88
|
+
--font-mono: 'JetBrains Mono', ui-monospace, monospace;
|
|
89
|
+
|
|
90
|
+
/* Engine border radius tokens */
|
|
91
|
+
--radius-pill: 9999px;
|
|
92
|
+
--radius-card: 10px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
:root {
|
|
96
|
+
--radius: 0.625rem;
|
|
97
|
+
--background: oklch(1 0 0);
|
|
98
|
+
--foreground: oklch(0.145 0 0);
|
|
99
|
+
--card: oklch(1 0 0);
|
|
100
|
+
--card-foreground: oklch(0.145 0 0);
|
|
101
|
+
--popover: oklch(1 0 0);
|
|
102
|
+
--popover-foreground: oklch(0.145 0 0);
|
|
103
|
+
--primary: oklch(0.205 0 0);
|
|
104
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
105
|
+
--secondary: oklch(0.97 0 0);
|
|
106
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
107
|
+
--muted: oklch(0.97 0 0);
|
|
108
|
+
--muted-foreground: oklch(0.556 0 0);
|
|
109
|
+
--accent: oklch(0.97 0 0);
|
|
110
|
+
--accent-foreground: oklch(0.205 0 0);
|
|
111
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
112
|
+
--border: oklch(0.922 0 0);
|
|
113
|
+
--input: oklch(0.922 0 0);
|
|
114
|
+
--ring: oklch(0.708 0 0);
|
|
115
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
116
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
117
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
118
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
119
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
120
|
+
--sidebar: oklch(0.985 0 0);
|
|
121
|
+
--sidebar-foreground: oklch(0.145 0 0);
|
|
122
|
+
--sidebar-primary: oklch(0.205 0 0);
|
|
123
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
124
|
+
--sidebar-accent: oklch(0.97 0 0);
|
|
125
|
+
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
126
|
+
--sidebar-border: oklch(0.922 0 0);
|
|
127
|
+
--sidebar-ring: oklch(0.708 0 0);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.dark {
|
|
131
|
+
--background: oklch(0.145 0 0);
|
|
132
|
+
--foreground: oklch(0.985 0 0);
|
|
133
|
+
--card: oklch(0.205 0 0);
|
|
134
|
+
--card-foreground: oklch(0.985 0 0);
|
|
135
|
+
--popover: oklch(0.205 0 0);
|
|
136
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
137
|
+
--primary: oklch(0.922 0 0);
|
|
138
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
139
|
+
--secondary: oklch(0.269 0 0);
|
|
140
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
141
|
+
--muted: oklch(0.269 0 0);
|
|
142
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
143
|
+
--accent: oklch(0.269 0 0);
|
|
144
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
145
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
146
|
+
--border: oklch(1 0 0 / 10%);
|
|
147
|
+
--input: oklch(1 0 0 / 15%);
|
|
148
|
+
--ring: oklch(0.556 0 0);
|
|
149
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
150
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
151
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
152
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
153
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
154
|
+
--sidebar: oklch(0.205 0 0);
|
|
155
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
156
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
157
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
158
|
+
--sidebar-accent: oklch(0.269 0 0);
|
|
159
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
160
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
161
|
+
--sidebar-ring: oklch(0.556 0 0);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@layer base {
|
|
165
|
+
* {
|
|
166
|
+
@apply border-border outline-ring/50;
|
|
167
|
+
}
|
|
168
|
+
body {
|
|
169
|
+
@apply bg-background text-foreground;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/*
|
|
174
|
+
* Restore HeroUI theme variables inside the Command Center scope.
|
|
175
|
+
* shadcn redefines --muted, --accent, --accent-foreground with different
|
|
176
|
+
* semantics (bg colors vs text colors). This scope restores HeroUI's values
|
|
177
|
+
* so HeroUI components render correctly.
|
|
178
|
+
*/
|
|
179
|
+
.heroui-scope {
|
|
180
|
+
/* Engine HeroUI theme overrides */
|
|
181
|
+
--primary: #000000;
|
|
182
|
+
--primary-foreground: oklch(0.9911 0 0);
|
|
183
|
+
--secondary: #5BC8C8;
|
|
184
|
+
--secondary-foreground: oklch(0.2103 0.0059 285.89);
|
|
185
|
+
--success: #16A34A;
|
|
186
|
+
--success-foreground: oklch(0.9911 0 0);
|
|
187
|
+
--warning: #F59E0B;
|
|
188
|
+
--warning-foreground: oklch(0.2103 0.0059 285.89);
|
|
189
|
+
--danger: #FF5722;
|
|
190
|
+
--danger-foreground: oklch(0.9911 0 0);
|
|
191
|
+
|
|
192
|
+
--muted: oklch(0.5517 0.0138 285.94);
|
|
193
|
+
--accent: oklch(0.6204 0.195 253.83);
|
|
194
|
+
--accent-foreground: oklch(0.9911 0 0);
|
|
195
|
+
--background: oklch(0.9702 0 0);
|
|
196
|
+
--foreground: oklch(0.2103 0.0059 285.89);
|
|
197
|
+
--default: oklch(94% 0.001 286.375);
|
|
198
|
+
--default-foreground: oklch(0.2103 0.0059 285.89);
|
|
199
|
+
--border: oklch(90% 0.004 286.32);
|
|
200
|
+
--separator: oklch(92% 0.004 286.32);
|
|
201
|
+
--segment: oklch(100% 0 0);
|
|
202
|
+
--segment-foreground: oklch(0.2103 0.0059 285.89);
|
|
203
|
+
--surface: oklch(100% 0 0);
|
|
204
|
+
--surface-foreground: oklch(0.2103 0.0059 285.89);
|
|
205
|
+
--overlay: oklch(100% 0 0);
|
|
206
|
+
--overlay-foreground: oklch(0.2103 0.0059 285.89);
|
|
207
|
+
--focus: oklch(0.6204 0.195 253.83);
|
|
208
|
+
--link: oklch(0.2103 0.0059 285.89);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.dark .heroui-scope,
|
|
212
|
+
.heroui-scope.dark {
|
|
213
|
+
--muted: oklch(70.5% 0.015 286.067);
|
|
214
|
+
--background: oklch(12% 0.005 285.823);
|
|
215
|
+
--foreground: oklch(0.9911 0 0);
|
|
216
|
+
--default: oklch(27.4% 0.006 286.033);
|
|
217
|
+
--default-foreground: oklch(0.9911 0 0);
|
|
218
|
+
--border: oklch(28% 0.006 286.033);
|
|
219
|
+
--separator: oklch(25% 0.006 286.033);
|
|
220
|
+
--segment: oklch(0.3964 0.01 285.93);
|
|
221
|
+
--segment-foreground: oklch(0.9911 0 0);
|
|
222
|
+
--surface: oklch(0.2103 0.0059 285.89);
|
|
223
|
+
--surface-foreground: oklch(0.9911 0 0);
|
|
224
|
+
--overlay: oklch(0.2103 0.0059 285.89);
|
|
225
|
+
--overlay-foreground: oklch(0.9911 0 0);
|
|
226
|
+
--warning: oklch(0.8203 0.1388 76.34);
|
|
227
|
+
--warning-foreground: oklch(0.2103 0.0059 285.89);
|
|
228
|
+
--danger: oklch(0.594 0.1967 24.63);
|
|
229
|
+
--danger-foreground: oklch(0.9911 0 0);
|
|
230
|
+
--focus: oklch(0.6204 0.195 253.83);
|
|
231
|
+
--link: oklch(0.9911 0 0);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* ChatBar overlay — add horizontal padding so it doesn't hit window edges */
|
|
235
|
+
body > .fixed.inset-x-0.rounded-2xl {
|
|
236
|
+
left: 1.5rem !important;
|
|
237
|
+
right: 1.5rem !important;
|
|
238
|
+
}
|
package/package.json
CHANGED