@schandlergarcia/sf-web-components 1.9.68 → 1.9.69
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.
|
@@ -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) | Custom markup inside `BaseCard` | `ActivityCard` (doesn't support per-item buttons) |
|
|
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
|
|
|
@@ -224,7 +225,8 @@ Key rules:
|
|
|
224
225
|
| System health | `StatusCard` |
|
|
225
226
|
| Feed / item list | `ListCard` |
|
|
226
227
|
| Scrollable side panel | `FeedPanel` |
|
|
227
|
-
| Activity feed | `ActivityCard` |
|
|
228
|
+
| Activity feed (display only) | `ActivityCard` |
|
|
229
|
+
| Activity feed (per-item actions) | Custom markup in `BaseCard` |
|
|
228
230
|
| User avatar | `Avatar` |
|
|
229
231
|
| Text summary | `NarrativeSummary` (schema) / `SectionCard` |
|
|
230
232
|
| Actions | `ActionList` (schema) / `UIButton` group |
|
|
@@ -341,8 +343,9 @@ Define schemas outside component body. Always `required: true` on mandatory fiel
|
|
|
341
343
|
|
|
342
344
|
## AI Chat & Agent
|
|
343
345
|
|
|
344
|
-
Use `ChatBar`
|
|
346
|
+
Use `ChatBar` for dashboards, `ChatPanel` for full-page chat.
|
|
345
347
|
|
|
348
|
+
- Place `ChatBar` between the hero map and data panels (full-width, `px-4 pt-4`), NOT in the header
|
|
346
349
|
- Always provide 3–5 `suggestions` for starter prompts
|
|
347
350
|
- Return `components` for structured data — never markdown tables in text
|
|
348
351
|
- Always set height on `ChatPanel`
|
|
@@ -466,7 +469,7 @@ Every data component handles loading. Error messages are human-readable. Empty s
|
|
|
466
469
|
|
|
467
470
|
Before finishing a dashboard page, verify ALL of these:
|
|
468
471
|
|
|
469
|
-
- [ ] **Every card/panel is a library component** (MetricCard, ListCard, ActivityCard, WidgetCard, TableCard, etc.) — no hand-rolled `<div className="bg-white border ...">` cards
|
|
472
|
+
- [ ] **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
473
|
- [ ] **Every chart/visualization is a library component** (ChartCard + D3Chart, GeoMap) — no hand-rolled SVG/canvas
|
|
471
474
|
- [ ] **No `<nav>`, header bar, or sticky tab bar** — navigation is handled by appLayout.tsx
|
|
472
475
|
- [ ] **Single scrollable page** — no multi-tab layout that swaps content
|
package/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,7 @@ 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.69] - 2026-04-01
|
|
9
9
|
|
|
10
10
|
### Fixed
|
|
11
11
|
- **6 data bugs in engine-sample-data.js**:
|
|
@@ -17,39 +17,50 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
17
17
|
6. Updated TXL → BER throughout (Berlin airport code change)
|
|
18
18
|
|
|
19
19
|
### Updated
|
|
20
|
-
- **
|
|
20
|
+
- **Global styles** - Added `src/styles/global.css` with Engine brand tokens and command center styling
|
|
21
|
+
|
|
22
|
+
- **PRD (engine-command-center-prd.md)** - Updated to match actual built dashboard:
|
|
23
|
+
- Layout diagram now shows 4-section structure: Header → Hero Map → Eva ChatBar → Data Panels (was missing ChatBar section)
|
|
24
|
+
- Layout classes added Eva: `<div className="px-4 pt-4">` as distinct section
|
|
25
|
+
- Section 6 (Header): Explicitly says "No ChatBar in the header — Eva lives below the map." Added "Powered by Agentforce" badge description
|
|
26
|
+
- Section 7 (Hero Map): Added explicit KPI label styling (`text-[10px] font-medium uppercase tracking-wide text-slate-300`) and value/pill/icon specs
|
|
27
|
+
- 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
|
|
28
|
+
- Section 8c (Active Travelers): Added "View in Salesforce" link in expanded detail
|
|
29
|
+
- Section 9 (Eva): Completely rewritten - ChatBar is now between map and data panels, full-width, with phasing notes (Phase 1 = skip, Phase 4 = add)
|
|
30
|
+
- Section 10 (Signals): Added "Assigned to Eva" toast row for Assign to Agent button
|
|
31
|
+
- 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
32
|
- Applied Option A layout: Escalations + Disruptions in Row 1 (above fold), Active Travelers + Spend in Row 2
|
|
22
|
-
- Both rows
|
|
33
|
+
- Both rows use `lg:grid-cols-3` with left panel at 2/3 width
|
|
23
34
|
- 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
|
|
35
|
+
- Cut Section 14 "What NOT to Do" entirely
|
|
36
|
+
- Condensed Phase 1 placeholder rules from 75 to 8 lines
|
|
37
|
+
|
|
38
|
+
- **Builder skill (SKILL.md)** - Fixed 4 contradictions:
|
|
39
|
+
- Component table: Split "Activity feed" into two rows: "display only" → ActivityCard, "with per-item actions" → custom markup in BaseCard
|
|
40
|
+
- Component selection table: Same split applied
|
|
41
|
+
- AI Chat & Agent section: Added bullet: "Place ChatBar between the hero map and data panels, NOT in the header"
|
|
42
|
+
- Pre-Completion Checklist: Added exception: panels needing per-item action buttons can use custom markup inside BaseCard
|
|
43
|
+
- General library component rule: Added exception note for per-item action buttons
|
|
44
|
+
- Removed wrong-example code blocks, condensed navigation (40 → 2 lines), removed custom renderChart examples, cut anti-patterns (33 → 12 items)
|
|
45
|
+
|
|
46
|
+
- **Builder skill sub-files** - Replaced with single-line redirects:
|
|
47
|
+
- 7 files reduced from 630 total lines to 7 lines (100% duplicates eliminated)
|
|
42
48
|
|
|
43
49
|
- **Simplified .a4drules documentation** - Removed redundancy, contradictions, and AI coaching language:
|
|
44
|
-
- `features/engine-dashboard-rule.md` - Rewritten as "Project Conventions" (
|
|
50
|
+
- `features/engine-dashboard-rule.md` - Rewritten as "Project Conventions" (~65 lines)
|
|
45
51
|
- `features/command-center-dashboard-rule.md` - Rewritten as slim conventions (~30 lines)
|
|
46
|
-
- `features/pre-code-checklist.md` - Rewritten as "Quick Reference" (~25 lines
|
|
52
|
+
- `features/pre-code-checklist.md` - Rewritten as "Quick Reference" (~25 lines)
|
|
47
53
|
- `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
|
|
54
|
+
- `skills/command-center-project/SKILL.md` - Fixed file path contradiction
|
|
55
|
+
- `skills/command-center-guide/SKILL.md` - Reduced from 270 to ~45 lines
|
|
56
|
+
- `skills/component-library/SKILL.md` - Description now lists all key component names
|
|
57
|
+
|
|
58
|
+
**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
59
|
|
|
52
|
-
|
|
60
|
+
## [1.9.68] - 2026-04-01
|
|
61
|
+
|
|
62
|
+
### Updated
|
|
63
|
+
- **Major documentation consolidation** - PRD reduced 39%, builder skill sub-files eliminated duplication, overall .a4drules reduced from ~2000 to ~800 lines
|
|
53
64
|
|
|
54
65
|
## [1.9.67] - 2026-04-01
|
|
55
66
|
|
|
@@ -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
|
|
|
@@ -62,7 +62,7 @@ Visualization-hero layout. Full-page scroll (no `h-screen`).
|
|
|
62
62
|
```
|
|
63
63
|
┌──────────────────────────────────────────────────────────────┐
|
|
64
64
|
│ HEADER (h-12, sticky, bg-slate-900) │
|
|
65
|
-
│ Engine logo + "Travel Command Center" | actions
|
|
65
|
+
│ Engine logo + "Travel Command Center" + badge | actions │
|
|
66
66
|
├──────────────────────────────────────────────────────────────┤
|
|
67
67
|
│ HERO MAP (h-[520px], GeoMap, relative) │
|
|
68
68
|
│ ┌─ glass KPI overlays (absolute top-left) ───────────────┐ │
|
|
@@ -72,11 +72,13 @@ Visualization-hero layout. Full-page scroll (no `h-screen`).
|
|
|
72
72
|
│ │ BA 286 · In Air | NH 109 · In Air | LH 431 · Delayed │ │
|
|
73
73
|
│ └────────────────────────────────────────────────────────┘ │
|
|
74
74
|
├──────────────────────────────────────────────────────────────┤
|
|
75
|
+
│ EVA CHATBAR (px-4 pt-4, full-width command palette strip) │
|
|
76
|
+
├──────────────────────────────────────────────────────────────┤
|
|
75
77
|
│ DATA PANELS (px-4 py-5 space-y-6) │
|
|
76
78
|
│ │
|
|
77
79
|
│ Row 1: grid grid-cols-1 items-start gap-4 lg:grid-cols-3 │
|
|
78
80
|
│ ┌── 2/3 (lg:col-span-2) ──────┐ ┌── 1/3 ───────────────┐ │
|
|
79
|
-
│ │ Escalations (
|
|
81
|
+
│ │ Escalations (custom panel) │ │ Disruptions (custom) │ │
|
|
80
82
|
│ └───────────────────────────────┘ └──────────────────────┘ │
|
|
81
83
|
│ │
|
|
82
84
|
│ Row 2: grid grid-cols-1 items-start gap-4 lg:grid-cols-3 │
|
|
@@ -90,13 +92,14 @@ Visualization-hero layout. Full-page scroll (no `h-screen`).
|
|
|
90
92
|
|
|
91
93
|
- **Outer:** `<div className="flex flex-col bg-slate-50 dark:bg-slate-950">`
|
|
92
94
|
- **Map:** `<div className="relative h-[520px]">`
|
|
95
|
+
- **Eva:** `<div className="px-4 pt-4"><ChatBar ... /></div>`
|
|
93
96
|
- **Panels:** `<div className="px-4 py-5"><div className="space-y-6">...</div></div>`
|
|
94
97
|
- **Row 1:** `grid grid-cols-1 items-start gap-4 lg:grid-cols-3` — Escalations `lg:col-span-2`, Disruptions auto
|
|
95
98
|
- **Row 2:** `grid grid-cols-1 items-start gap-4 lg:grid-cols-3` — Travelers `lg:col-span-2`, Spend auto
|
|
96
99
|
|
|
97
100
|
### Phase 1 placeholders
|
|
98
101
|
|
|
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:
|
|
102
|
+
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
103
|
|
|
101
104
|
```tsx
|
|
102
105
|
<BaseCard>
|
|
@@ -112,11 +115,11 @@ The GeoMap renders the base world map with no data props. Glass overlays and fli
|
|
|
112
115
|
|
|
113
116
|
## 6. Header
|
|
114
117
|
|
|
115
|
-
Compact `h-12` sticky header (`bg-slate-900 dark:bg-slate-950`).
|
|
118
|
+
Compact `h-12` sticky header (`bg-slate-900 dark:bg-slate-950`). No ChatBar in the header — Eva lives below the map.
|
|
116
119
|
|
|
117
120
|
| Left | Right |
|
|
118
121
|
|------|-------|
|
|
119
|
-
| Engine logo (`GlobeAltIcon` in `bg-brand-600` square) + "ENGINE" wordmark + separator + "Travel Command Center"
|
|
122
|
+
| Engine logo (`GlobeAltIcon` in `bg-brand-600` square) + "ENGINE" wordmark + separator + "Travel Command Center" + "Powered by Agentforce" badge (`bg-brand-900/40 text-brand-400 rounded-full text-[10px]`) | Notification bell (badge count) + theme toggle (sun/moon) |
|
|
120
123
|
|
|
121
124
|
---
|
|
122
125
|
|
|
@@ -145,9 +148,13 @@ Compact `h-12` sticky header (`bg-slate-900 dark:bg-slate-950`).
|
|
|
145
148
|
|
|
146
149
|
**Glass KPI overlays** — 4 pills, `absolute left-3 top-3`:
|
|
147
150
|
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
151
|
|
|
150
|
-
|
|
152
|
+
Label styling: `text-[10px] font-medium uppercase tracking-wide text-slate-300`
|
|
153
|
+
Value styling: `text-sm font-semibold text-slate-50`
|
|
154
|
+
Pill styling: `bg-black/40 backdrop-blur-md border border-white/10 rounded-lg px-3 py-1.5`
|
|
155
|
+
Icon: `h-4 w-4 text-brand-400`
|
|
156
|
+
|
|
157
|
+
**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
158
|
|
|
152
159
|
---
|
|
153
160
|
|
|
@@ -157,18 +164,48 @@ Style: `bg-black/40 backdrop-blur-md border border-white/10 rounded-lg px-3 py-1
|
|
|
157
164
|
|
|
158
165
|
### 8a. Escalations (Row 1, 2/3 width)
|
|
159
166
|
|
|
160
|
-
|
|
167
|
+
Custom inline panel in BaseCard. Do NOT use ActivityCard — this panel has per-item "Assign to Agent" buttons.
|
|
168
|
+
|
|
169
|
+
Each escalation row:
|
|
170
|
+
- Status icon: `CheckCircleIcon` (complete, green), `ArrowPathIcon` (working, brand), `ClockIcon` (pending, amber)
|
|
171
|
+
- Title + subtitle + timestamp
|
|
172
|
+
- **"Assign to Agent" button** 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")`
|
|
161
173
|
|
|
162
174
|
```tsx
|
|
163
175
|
<BaseCard>
|
|
164
|
-
<
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
176
|
+
<div className="p-4">
|
|
177
|
+
<h3 className="mb-3 text-sm font-semibold text-slate-900 dark:text-slate-50">
|
|
178
|
+
Escalations
|
|
179
|
+
</h3>
|
|
180
|
+
<div className="divide-y divide-slate-100 dark:divide-slate-800">
|
|
181
|
+
{escalations.map((e) => {
|
|
182
|
+
const isOpen = e.status !== "complete";
|
|
183
|
+
return (
|
|
184
|
+
<div key={e.id} className="flex items-start gap-3 py-3">
|
|
185
|
+
<StatusIcon className={`mt-0.5 h-5 w-5 shrink-0 ${statusColor}`} />
|
|
186
|
+
<div className="min-w-0 flex-1">
|
|
187
|
+
<div className="text-sm font-medium text-slate-900 dark:text-slate-50">{e.title}</div>
|
|
188
|
+
<div className="mt-0.5 text-xs text-slate-500 dark:text-slate-400">
|
|
189
|
+
{e.subtitle} · {e.timestamp}
|
|
190
|
+
</div>
|
|
191
|
+
</div>
|
|
192
|
+
{isOpen && (
|
|
193
|
+
<button onClick={() => handleAssignToAgent(e)}
|
|
194
|
+
className="shrink-0 rounded-md bg-brand-600 px-2.5 py-1 text-xs font-medium text-slate-50 hover:bg-brand-700">
|
|
195
|
+
<span className="flex items-center gap-1">
|
|
196
|
+
<SparklesIcon className="h-3 w-3" /> Assign to Agent
|
|
197
|
+
</span>
|
|
198
|
+
</button>
|
|
199
|
+
)}
|
|
200
|
+
</div>
|
|
201
|
+
);
|
|
202
|
+
})}
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
168
205
|
</BaseCard>
|
|
169
206
|
```
|
|
170
207
|
|
|
171
|
-
|
|
208
|
+
Data: `ESCALATION_CARDS` from sample data.
|
|
172
209
|
|
|
173
210
|
### 8b. Disruptions (Row 1, 1/3 width)
|
|
174
211
|
|
|
@@ -186,8 +223,8 @@ Data: `DISRUPTION_CARDS` from sample data.
|
|
|
186
223
|
|
|
187
224
|
BaseCard with `maxBodyHeight={420}`. Expandable traveler cards.
|
|
188
225
|
|
|
189
|
-
Each row: `Avatar` (initials) + name + department + origin → destination +
|
|
190
|
-
Expand: 4-col grid — Flight, Hotel, Return, Destination.
|
|
226
|
+
Each row: `Avatar` (initials) + name + department + origin → destination + policy chip (compliant=green, exception=amber).
|
|
227
|
+
Expand: 4-col grid — Flight, Hotel, Return, Destination + "View in Salesforce" link.
|
|
191
228
|
|
|
192
229
|
Data: `TRAVELER_CARDS` from sample data.
|
|
193
230
|
|
|
@@ -223,23 +260,28 @@ const spendChartData = useDataSource({
|
|
|
223
260
|
|
|
224
261
|
---
|
|
225
262
|
|
|
226
|
-
## 9. Eva — ChatBar
|
|
263
|
+
## 9. Eva — ChatBar
|
|
227
264
|
|
|
228
|
-
ChatBar in the header.
|
|
265
|
+
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
266
|
|
|
230
267
|
```tsx
|
|
231
|
-
<
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
268
|
+
<div className="px-4 pt-4">
|
|
269
|
+
<ChatBar
|
|
270
|
+
title="Eva"
|
|
271
|
+
placeholder="Ask Eva anything about travelers, bookings, policy, or spend…"
|
|
272
|
+
suggestions={CHAT_SUGGESTIONS}
|
|
273
|
+
onSend={handleChat}
|
|
274
|
+
/>
|
|
275
|
+
</div>
|
|
237
276
|
```
|
|
238
277
|
|
|
239
278
|
Suggestions: "Who's traveling internationally right now?", "Show bookings pending approval", "What has Eva resolved today?", "Travelers returning this week"
|
|
240
279
|
|
|
241
280
|
Define `handleChat` and `CHAT_SUGGESTIONS` at module scope.
|
|
242
281
|
|
|
282
|
+
**Phase 1:** Placeholder — do NOT add ChatBar. Just leave the space empty.
|
|
283
|
+
**Phase 4:** Add the ChatBar between the map and data panels.
|
|
284
|
+
|
|
243
285
|
---
|
|
244
286
|
|
|
245
287
|
## 10. Salesforce Signals (Phase 4)
|
|
@@ -248,9 +290,10 @@ Subtle indicators, not banners.
|
|
|
248
290
|
|
|
249
291
|
| Signal | Location |
|
|
250
292
|
|--------|----------|
|
|
251
|
-
| "
|
|
293
|
+
| "Powered by Agentforce" | Header, next to "Travel Command Center" (small rounded badge) |
|
|
294
|
+
| "View in Salesforce" | Traveler expanded view (micro-link, muted text) |
|
|
252
295
|
| "Salesforce updated" | After rebook/approve actions (`toast()`) |
|
|
253
|
-
| "
|
|
296
|
+
| "Assigned to Eva" | After "Assign to Agent" button click (`toast.success()`) |
|
|
254
297
|
|
|
255
298
|
---
|
|
256
299
|
|
|
@@ -289,4 +332,4 @@ Build in 4 incremental phases.
|
|
|
289
332
|
|
|
290
333
|
### Phase 4: Agentforce Integration
|
|
291
334
|
|
|
292
|
-
> Add Eva
|
|
335
|
+
> 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