@flamingo-stack/openframe-frontend-core 0.0.222 → 0.0.223
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/dist/{chunk-AIKPR6BE.js → chunk-4VHWSAQR.js} +6069 -5235
- package/dist/chunk-4VHWSAQR.js.map +1 -0
- package/dist/{chunk-GMNE7P7V.cjs → chunk-4WBVMIKQ.cjs} +26 -26
- package/dist/{chunk-GMNE7P7V.cjs.map → chunk-4WBVMIKQ.cjs.map} +1 -1
- package/dist/{chunk-QYRV6MKX.js → chunk-53EA4QPZ.js} +13 -7
- package/dist/chunk-53EA4QPZ.js.map +1 -0
- package/dist/{chunk-4JOWZLEL.cjs → chunk-7TKYFZ3L.cjs} +7 -7
- package/dist/{chunk-4JOWZLEL.cjs.map → chunk-7TKYFZ3L.cjs.map} +1 -1
- package/dist/{chunk-IZA5WF44.cjs → chunk-ABBU7QOM.cjs} +12 -12
- package/dist/{chunk-IZA5WF44.cjs.map → chunk-ABBU7QOM.cjs.map} +1 -1
- package/dist/{chunk-KM4KK2A6.cjs → chunk-ENDUMC7Z.cjs} +2558 -1724
- package/dist/chunk-ENDUMC7Z.cjs.map +1 -0
- package/dist/{chunk-CCSEXVI4.js → chunk-GYYGA24C.js} +2 -2
- package/dist/{chunk-RMOHKAHA.js → chunk-ISWWP2BH.js} +3 -3
- package/dist/{chunk-QNYH3WUU.cjs → chunk-JUWPBMQM.cjs} +13 -7
- package/dist/chunk-JUWPBMQM.cjs.map +1 -0
- package/dist/{chunk-A2SFHYVF.cjs → chunk-KXLTWANQ.cjs} +10 -10
- package/dist/{chunk-A2SFHYVF.cjs.map → chunk-KXLTWANQ.cjs.map} +1 -1
- package/dist/{chunk-ND24XSVT.js → chunk-TA6Z2AKD.js} +3 -3
- package/dist/chunk-TA6Z2AKD.js.map +1 -0
- package/dist/{chunk-HRIAZQ5D.js → chunk-WOKB6RJ7.js} +3 -3
- package/dist/components/chat/chat-archive-page.d.ts.map +1 -1
- package/dist/components/chat/chat-composer.d.ts.map +1 -1
- package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
- package/dist/components/chat/chat-message-skeleton.d.ts +19 -4
- package/dist/components/chat/chat-message-skeleton.d.ts.map +1 -1
- package/dist/components/chat/chat-panel-header-mobile.d.ts +24 -0
- package/dist/components/chat/chat-panel-header-mobile.d.ts.map +1 -0
- package/dist/components/chat/chat-panel-header.d.ts +6 -0
- package/dist/components/chat/chat-panel-header.d.ts.map +1 -1
- package/dist/components/chat/chat-quick-action-row.d.ts +31 -0
- package/dist/components/chat/chat-quick-action-row.d.ts.map +1 -0
- package/dist/components/chat/embeddable-chat.d.ts +27 -0
- package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
- package/dist/components/chat/entity-cards/dispatch.d.ts +14 -0
- package/dist/components/chat/entity-cards/dispatch.d.ts.map +1 -1
- package/dist/components/chat/entity-cards/github-activity-card.d.ts +10 -1
- package/dist/components/chat/entity-cards/github-activity-card.d.ts.map +1 -1
- package/dist/components/chat/guide-welcome.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts +9 -0
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-slash-commands.d.ts +26 -0
- package/dist/components/chat/hooks/use-slash-commands.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts +12 -1
- package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-unified-chat.d.ts +12 -0
- package/dist/components/chat/hooks/use-unified-chat.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +9 -3
- package/dist/components/chat/index.cjs.map +1 -1
- package/dist/components/chat/index.js +8 -2
- package/dist/components/chat/mingo-chat-history.d.ts +10 -0
- package/dist/components/chat/mingo-chat-history.d.ts.map +1 -1
- package/dist/components/chat/mingo-info-card.d.ts +63 -0
- package/dist/components/chat/mingo-info-card.d.ts.map +1 -0
- package/dist/components/chat/mingo-welcome.d.ts +14 -1
- package/dist/components/chat/mingo-welcome.d.ts.map +1 -1
- package/dist/components/chat/types/chat.types.d.ts +6 -0
- package/dist/components/chat/types/chat.types.d.ts.map +1 -1
- package/dist/components/chat/types/unified-chat-state.types.d.ts +30 -0
- package/dist/components/chat/types/unified-chat-state.types.d.ts.map +1 -1
- package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +4 -4
- package/dist/components/contact/index.js +3 -3
- package/dist/components/features/index.cjs +3 -3
- package/dist/components/features/index.js +2 -2
- package/dist/components/index.cjs +110 -104
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +36 -30
- package/dist/components/index.js.map +1 -1
- package/dist/components/navigation/app-layout-drawer.d.ts +7 -0
- package/dist/components/navigation/app-layout-drawer.d.ts.map +1 -1
- package/dist/components/navigation/index.cjs +3 -3
- package/dist/components/navigation/index.js +2 -2
- package/dist/components/onboarding-guides/index.cjs +26 -26
- package/dist/components/onboarding-guides/index.js +4 -4
- package/dist/components/tickets/index.cjs +67 -67
- package/dist/components/tickets/index.js +5 -5
- package/dist/components/ui/actions-menu.d.ts +9 -0
- package/dist/components/ui/actions-menu.d.ts.map +1 -1
- package/dist/components/ui/dropdown-button.d.ts +2 -2
- package/dist/components/ui/dropdown-button.d.ts.map +1 -1
- package/dist/components/ui/index.cjs +9 -3
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.js +8 -2
- package/dist/components/ui/modal-v2.d.ts.map +1 -1
- package/dist/components/ui/more-actions-menu.d.ts +13 -0
- package/dist/components/ui/more-actions-menu.d.ts.map +1 -1
- package/dist/components/ui/square-avatar.d.ts +4 -0
- package/dist/components/ui/square-avatar.d.ts.map +1 -1
- package/dist/components/ui/textarea.d.ts.map +1 -1
- package/dist/hooks/index.cjs +2 -2
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/ui/use-auto-limit-tags.d.ts +7 -1
- package/dist/hooks/ui/use-auto-limit-tags.d.ts.map +1 -1
- package/dist/index.cjs +9 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +8 -2
- package/package.json +1 -1
- package/src/components/chat/chat-archive-page.tsx +32 -7
- package/src/components/chat/chat-composer.tsx +6 -2
- package/src/components/chat/chat-message-enhanced.tsx +24 -7
- package/src/components/chat/chat-message-list.tsx +1 -1
- package/src/components/chat/chat-message-skeleton.tsx +60 -60
- package/src/components/chat/chat-panel-header-mobile.tsx +94 -0
- package/src/components/chat/chat-panel-header.tsx +78 -50
- package/src/components/chat/chat-quick-action-row.tsx +146 -0
- package/src/components/chat/embeddable-chat.tsx +140 -45
- package/src/components/chat/entity-cards/dispatch.tsx +770 -232
- package/src/components/chat/entity-cards/github-activity-card.tsx +9 -3
- package/src/components/chat/guide-welcome.tsx +11 -8
- package/src/components/chat/hooks/use-nats-chat-adapter.ts +80 -7
- package/src/components/chat/hooks/use-slash-commands.ts +39 -0
- package/src/components/chat/hooks/use-sse-chat-adapter.ts +49 -45
- package/src/components/chat/hooks/use-unified-chat.ts +31 -8
- package/src/components/chat/mingo-chat-history.tsx +118 -36
- package/src/components/chat/mingo-info-card.tsx +214 -0
- package/src/components/chat/mingo-welcome.tsx +89 -36
- package/src/components/chat/types/chat.types.ts +4 -0
- package/src/components/chat/types/unified-chat-state.types.ts +35 -0
- package/src/components/chat/utils/process-historical-messages.ts +8 -0
- package/src/components/content-loading-container.tsx +1 -1
- package/src/components/empty-state.tsx +3 -3
- package/src/components/faq-accordion.tsx +2 -2
- package/src/components/features/changelog-manager.tsx +2 -2
- package/src/components/features/highlight-config-section.tsx +2 -2
- package/src/components/features/og-editor-preview.tsx +3 -3
- package/src/components/features/release-media-manager.tsx +2 -2
- package/src/components/loading/card-skeleton.tsx +3 -3
- package/src/components/loading/device-card-skeleton.tsx +1 -1
- package/src/components/loading/margin-report-skeleton.tsx +2 -2
- package/src/components/loading/organization-card-skeleton.tsx +1 -1
- package/src/components/loading/organization-icon-skeleton.tsx +1 -1
- package/src/components/loading/page-layout-skeleton.tsx +9 -9
- package/src/components/loading/users-grid-skeleton.tsx +2 -2
- package/src/components/logs-list.tsx +1 -1
- package/src/components/media-carousel.tsx +1 -1
- package/src/components/navigation/app-layout-drawer.tsx +70 -6
- package/src/components/open-source-features.tsx +2 -2
- package/src/components/ui/actions-menu.tsx +36 -13
- package/src/components/ui/allowed-domains-input.tsx +3 -3
- package/src/components/ui/cursor-pagination.tsx +1 -1
- package/src/components/ui/dropdown-button.tsx +6 -6
- package/src/components/ui/info-row.tsx +2 -2
- package/src/components/ui/modal-v2.tsx +8 -1
- package/src/components/ui/more-actions-menu.tsx +13 -0
- package/src/components/ui/square-avatar.tsx +6 -1
- package/src/components/ui/tags-input.tsx +1 -1
- package/src/components/ui/textarea.tsx +18 -4
- package/src/components/vendor-icon.tsx +1 -1
- package/src/components/vendor-tag.tsx +1 -1
- package/src/components/why-it-matters.tsx +1 -1
- package/src/hooks/ui/use-auto-limit-tags.ts +22 -8
- package/src/stories/ActionsMenu.stories.tsx +256 -0
- package/src/stories/AppLayoutSidebar.stories.tsx +6 -0
- package/src/stories/Board.stories.tsx +1 -1
- package/src/stories/ChatMingoInfoCards.stories.tsx +748 -0
- package/src/stories/ChatTicketList.stories.tsx +1 -1
- package/src/stories/DataTable.stories.tsx +17 -13
- package/src/stories/EmbeddableChat.stories.tsx +233 -1
- package/src/stories/MingoInfoCard.stories.tsx +193 -0
- package/src/stories/MingoOnboardingCard.stories.tsx +1 -1
- package/src/stories/Modal.stories.tsx +1 -0
- package/src/stories/NotificationDrawer.stories.tsx +14 -3
- package/src/stories/PageActions.stories.tsx +4 -4
- package/src/stories/PageContainer.stories.tsx +5 -5
- package/src/stories/PageLayout.stories.tsx +1 -1
- package/src/stories/TabSelector.stories.tsx +2 -2
- package/src/stories/Tag.stories.tsx +10 -5
- package/src/stories/TicketInfoSection.stories.tsx +23 -11
- package/src/stories/Toaster.stories.tsx +5 -5
- package/src/stories/__fixtures__/chat-card-decorator.tsx +44 -0
- package/dist/chunk-AIKPR6BE.js.map +0 -1
- package/dist/chunk-KM4KK2A6.cjs.map +0 -1
- package/dist/chunk-ND24XSVT.js.map +0 -1
- package/dist/chunk-QNYH3WUU.cjs.map +0 -1
- package/dist/chunk-QYRV6MKX.js.map +0 -1
- package/src/stories/.TicketDescriptionViewer.stories.md +0 -39
- package/src/stories/.TicketKnowledgeBaseList.stories.md +0 -36
- package/src/stories/TicketDescriptionViewer.stories.tsx +0 -70
- package/src/stories/TicketKnowledgeBaseList.stories.tsx +0 -51
- /package/dist/{chunk-CCSEXVI4.js.map → chunk-GYYGA24C.js.map} +0 -0
- /package/dist/{chunk-RMOHKAHA.js.map → chunk-ISWWP2BH.js.map} +0 -0
- /package/dist/{chunk-HRIAZQ5D.js.map → chunk-WOKB6RJ7.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/nextjs-vite";
|
|
2
2
|
import type React from "react";
|
|
3
|
-
import type { ChatTicketItemData } from "../components/chat/chat-ticket-item";
|
|
3
|
+
import type { ChatTicketItemData } from "../components/chat/entity-cards/chat-ticket-item";
|
|
4
4
|
import { ChatTicketList } from "../components/chat/chat-ticket-list";
|
|
5
5
|
|
|
6
6
|
const mockTickets: ChatTicketItemData[] = [
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
import { Button } from '../components/ui/button'
|
|
22
22
|
import { Checkbox } from '../components/ui/checkbox'
|
|
23
23
|
import { Tag } from '../components/ui/tag'
|
|
24
|
-
import {
|
|
24
|
+
import { ActionsMenuDropdown } from '../components/ui/actions-menu'
|
|
25
25
|
import { Chevron02RightIcon } from '../components/icons-v2-generated'
|
|
26
26
|
|
|
27
27
|
/* ──────────────────────────────── sample data ───────────────────────────────── */
|
|
@@ -580,12 +580,14 @@ export const WithActionsColumn: Story = {
|
|
|
580
580
|
data-no-row-click
|
|
581
581
|
className="flex gap-2 items-center justify-end pointer-events-auto"
|
|
582
582
|
>
|
|
583
|
-
<
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
583
|
+
<ActionsMenuDropdown
|
|
584
|
+
groups={[{
|
|
585
|
+
items: [
|
|
586
|
+
{ id: 'ping', label: 'Ping', onClick: () => alert(`Ping ${device.hostname}`) },
|
|
587
|
+
{ id: 'restart', label: 'Restart', onClick: () => alert(`Restart ${device.hostname}`) },
|
|
588
|
+
{ id: 'remove', label: 'Remove', onClick: () => alert(`Remove ${device.hostname}`), danger: true },
|
|
589
|
+
],
|
|
590
|
+
}]}
|
|
589
591
|
/>
|
|
590
592
|
</div>
|
|
591
593
|
)
|
|
@@ -1328,12 +1330,14 @@ export const KitchenSink: Story = {
|
|
|
1328
1330
|
data-no-row-click
|
|
1329
1331
|
className="flex gap-2 items-center justify-end pointer-events-auto"
|
|
1330
1332
|
>
|
|
1331
|
-
<
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1333
|
+
<ActionsMenuDropdown
|
|
1334
|
+
groups={[{
|
|
1335
|
+
items: [
|
|
1336
|
+
{ id: 'ping', label: 'Ping', onClick: () => alert(`Ping ${device.hostname}`) },
|
|
1337
|
+
{ id: 'restart', label: 'Restart', onClick: () => alert(`Restart ${device.hostname}`) },
|
|
1338
|
+
{ id: 'remove', label: 'Remove', onClick: () => alert(`Remove ${device.hostname}`), danger: true },
|
|
1339
|
+
],
|
|
1340
|
+
}]}
|
|
1337
1341
|
/>
|
|
1338
1342
|
</div>
|
|
1339
1343
|
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
|
2
|
+
import { within, userEvent } from 'storybook/test'
|
|
2
3
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
3
4
|
import React, { useMemo } from 'react'
|
|
4
5
|
import {
|
|
@@ -6,9 +7,19 @@ import {
|
|
|
6
7
|
type ChatRuntime,
|
|
7
8
|
} from '../contexts/chat-runtime-context'
|
|
8
9
|
import { EmbeddableChat } from '../components/chat/embeddable-chat'
|
|
9
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
UseNatsChatAdapterConfig,
|
|
12
|
+
FetchDialogsResult,
|
|
13
|
+
FetchDialogMessagesResult,
|
|
14
|
+
} from '../components/chat/hooks/use-nats-chat-adapter'
|
|
10
15
|
import type { SlashCommandSummary } from '../components/chat/hooks/use-slash-commands'
|
|
11
16
|
import type { DialogItem } from '../components/chat/types/component.types'
|
|
17
|
+
import type { MingoQuickAction } from '../components/chat/mingo-welcome'
|
|
18
|
+
import {
|
|
19
|
+
BracketCurlyIcon,
|
|
20
|
+
Rocket01Icon,
|
|
21
|
+
SearchIcon,
|
|
22
|
+
} from '../components/icons-v2-generated'
|
|
12
23
|
|
|
13
24
|
// =============================================================================
|
|
14
25
|
// Stub commands endpoint — module-level constant referenced both by the
|
|
@@ -104,6 +115,42 @@ const SAMPLE_DIALOGS: ReadonlyArray<DialogItem> = [
|
|
|
104
115
|
{ id: 'd8', title: 'SQL Server maintenance plan troubleshooting' },
|
|
105
116
|
]
|
|
106
117
|
|
|
118
|
+
// Caller-provided Mingo quick-action chips — rendered after the built-in
|
|
119
|
+
// "Start Guide Chat" chip in the welcome/returning-user view. `onClick` just
|
|
120
|
+
// logs; the story demonstrates the chip row layout, not the action behaviour.
|
|
121
|
+
const SAMPLE_QUICK_ACTIONS: ReadonlyArray<MingoQuickAction> = [
|
|
122
|
+
{
|
|
123
|
+
id: 'weekly-log-summary',
|
|
124
|
+
label: 'Weekly Log Summary',
|
|
125
|
+
icon: <SearchIcon size={16} />,
|
|
126
|
+
onClick: () => console.log('[story] quick action: weekly log summary'),
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: 'run-script',
|
|
130
|
+
label: 'Run a script',
|
|
131
|
+
icon: <BracketCurlyIcon size={16} />,
|
|
132
|
+
onClick: () => console.log('[story] quick action: run a script'),
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: 'device-health',
|
|
136
|
+
label: 'Device health check',
|
|
137
|
+
icon: <Rocket01Icon size={16} />,
|
|
138
|
+
onClick: () => console.log('[story] quick action: device health check'),
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
id: 'summarize-tickets',
|
|
142
|
+
label: 'Summarize open tickets',
|
|
143
|
+
icon: <SearchIcon size={16} />,
|
|
144
|
+
onClick: () => console.log('[story] quick action: summarize tickets'),
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
id: 'patch-status',
|
|
148
|
+
label: 'Patch status report',
|
|
149
|
+
icon: <BracketCurlyIcon size={16} />,
|
|
150
|
+
onClick: () => console.log('[story] quick action: patch status report'),
|
|
151
|
+
},
|
|
152
|
+
]
|
|
153
|
+
|
|
107
154
|
/** Mingo config whose `fetchDialogs` resolves a single page of history (with
|
|
108
155
|
* timestamps so the list splits into Today / Yesterday) plus working
|
|
109
156
|
* rename/archive callbacks — used by the returning-user story. */
|
|
@@ -149,6 +196,69 @@ function createMockMingoConfigWithDialogs(): UseNatsChatAdapterConfig {
|
|
|
149
196
|
}
|
|
150
197
|
}
|
|
151
198
|
|
|
199
|
+
/**
|
|
200
|
+
* A promise that never settles — keeps whichever adapter loading flag it
|
|
201
|
+
* backs pinned `true`, so the loading UI stays on screen for the story
|
|
202
|
+
* (no fake timers, no flicker to a resolved state).
|
|
203
|
+
*/
|
|
204
|
+
const pending = <T,>(): Promise<T> => new Promise<T>(() => {})
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Chats-loading config — `fetchDialogs` never resolves, so the adapter keeps
|
|
208
|
+
* `isDialogsLoading` true with an empty list. EmbeddableChat reports
|
|
209
|
+
* `dialogsInitialLoading` and the Mingo empty state shows its history
|
|
210
|
+
* skeleton instead of the new/returning-user greeting.
|
|
211
|
+
*/
|
|
212
|
+
function createMockMingoConfigChatsLoading(): UseNatsChatAdapterConfig {
|
|
213
|
+
return {
|
|
214
|
+
...createMockMingoConfig(),
|
|
215
|
+
fetchDialogs: () => pending<FetchDialogsResult>(),
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Chat-loading config — the dialog list resolves normally, but
|
|
221
|
+
* `fetchDialogMessages` never resolves. Paired with the story's `play`
|
|
222
|
+
* (which opens the first dialog), this pins `isMessagesLoading` with no
|
|
223
|
+
* messages yet, so the conversation view shows the message-list skeleton.
|
|
224
|
+
*/
|
|
225
|
+
function createMockMingoConfigChatLoading(): UseNatsChatAdapterConfig {
|
|
226
|
+
return {
|
|
227
|
+
...createMockMingoConfigWithDialogs(),
|
|
228
|
+
fetchDialogMessages: () => pending<FetchDialogMessagesResult>(),
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Chats-error config — `fetchDialogs` rejects, so the adapter flips
|
|
234
|
+
* `dialogsError` true with an empty list. EmbeddableChat reports
|
|
235
|
+
* `dialogsLoadError`, and the Mingo empty state shows its load-error + retry
|
|
236
|
+
* affordance instead of the greeting (distinguishing a backend failure from a
|
|
237
|
+
* genuinely empty list). `reloadDialogs` re-invokes this — the retry path is
|
|
238
|
+
* wired, it just keeps failing against the unavailable mock backend.
|
|
239
|
+
*/
|
|
240
|
+
function createMockMingoConfigChatsError(): UseNatsChatAdapterConfig {
|
|
241
|
+
return {
|
|
242
|
+
...createMockMingoConfig(),
|
|
243
|
+
fetchDialogs: () =>
|
|
244
|
+
Promise.reject(new Error('Story: dialog list backend unavailable')),
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Archive-empty config — a populated dialog list (so the header's archive
|
|
250
|
+
* button is present), but `fetchArchivedDialogs` resolves an empty page. Paired
|
|
251
|
+
* with the story's `play` (which opens the archive page), this renders the
|
|
252
|
+
* archive page's empty state.
|
|
253
|
+
*/
|
|
254
|
+
function createMockMingoConfigArchiveEmpty(): UseNatsChatAdapterConfig {
|
|
255
|
+
return {
|
|
256
|
+
...createMockMingoConfigWithDialogs(),
|
|
257
|
+
fetchArchivedDialogs: () =>
|
|
258
|
+
Promise.resolve({ dialogs: [], nextCursor: null }),
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
152
262
|
// =============================================================================
|
|
153
263
|
// Mocked slash-commands — fed into the empty-state card list (Figma node
|
|
154
264
|
// 7363:205938) via a `window.fetch` override below. Each entry must set
|
|
@@ -452,6 +562,9 @@ export const BothModes: Story = {
|
|
|
452
562
|
* returning-user form: the "New to OpenFrame?" notification is hidden and the
|
|
453
563
|
* "Start Guide Chat" chip drops from the accent yellow to the muted outline
|
|
454
564
|
* style. The dialog list itself renders inline via MingoChatHistory.
|
|
565
|
+
*
|
|
566
|
+
* Caller-provided `quickActions` chips render in the pinned chip row after
|
|
567
|
+
* "Start Guide Chat" — the first is `primary` (accent), the rest `outline`.
|
|
455
568
|
*/
|
|
456
569
|
export const ReturningUser: Story = {
|
|
457
570
|
render: (args) => (
|
|
@@ -464,7 +577,126 @@ export const ReturningUser: Story = {
|
|
|
464
577
|
defaultActiveMode="mingo"
|
|
465
578
|
defaultOpen
|
|
466
579
|
showInternalTrigger={false}
|
|
580
|
+
mingoWelcome={{ quickActions: SAMPLE_QUICK_ACTIONS }}
|
|
467
581
|
/>
|
|
468
582
|
),
|
|
469
583
|
args: {},
|
|
470
584
|
}
|
|
585
|
+
|
|
586
|
+
// =============================================================================
|
|
587
|
+
// 5. Chats loading — dialog list fetch in flight
|
|
588
|
+
// =============================================================================
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Dialog-list loading state. The mock `fetchDialogs` never resolves, so the
|
|
592
|
+
* adapter keeps `isDialogsLoading` true with an empty list. The Mingo empty
|
|
593
|
+
* state renders its history skeleton (instead of the new/returning-user
|
|
594
|
+
* greeting), matching what the panel shows on first open before the chat list
|
|
595
|
+
* lands.
|
|
596
|
+
*/
|
|
597
|
+
export const ChatsLoading: Story = {
|
|
598
|
+
render: (args) => (
|
|
599
|
+
<EmbeddableChat
|
|
600
|
+
{...args}
|
|
601
|
+
modes={{
|
|
602
|
+
mingo: createMockMingoConfigChatsLoading(),
|
|
603
|
+
}}
|
|
604
|
+
defaultActiveMode="mingo"
|
|
605
|
+
defaultOpen
|
|
606
|
+
showInternalTrigger={false}
|
|
607
|
+
/>
|
|
608
|
+
),
|
|
609
|
+
args: {},
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// =============================================================================
|
|
613
|
+
// 6. Chat loading — opening a dialog whose history is in flight
|
|
614
|
+
// =============================================================================
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Single-conversation loading state. The dialog list resolves, but
|
|
618
|
+
* `fetchDialogMessages` never resolves. The `play` step opens the first
|
|
619
|
+
* dialog, so the panel flips to the conversation view and shows the
|
|
620
|
+
* message-list skeleton (`isMessagesLoading` with no messages yet) — the
|
|
621
|
+
* "opening a chat" loading frame before bubbles stream in.
|
|
622
|
+
*/
|
|
623
|
+
export const ChatLoading: Story = {
|
|
624
|
+
render: (args) => (
|
|
625
|
+
<EmbeddableChat
|
|
626
|
+
{...args}
|
|
627
|
+
modes={{
|
|
628
|
+
mingo: createMockMingoConfigChatLoading(),
|
|
629
|
+
}}
|
|
630
|
+
defaultActiveMode="mingo"
|
|
631
|
+
defaultOpen
|
|
632
|
+
showInternalTrigger={false}
|
|
633
|
+
/>
|
|
634
|
+
),
|
|
635
|
+
args: {},
|
|
636
|
+
play: async () => {
|
|
637
|
+
// The drawer portals to <body>, so query the document, not the canvas.
|
|
638
|
+
const body = within(document.body)
|
|
639
|
+
const row = await body.findByText(SAMPLE_DIALOGS[0].title)
|
|
640
|
+
await userEvent.click(row)
|
|
641
|
+
},
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// =============================================================================
|
|
645
|
+
// 7. Chats error — dialog list fetch failed
|
|
646
|
+
// =============================================================================
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Dialog-list error state. The mock `fetchDialogs` rejects, so the adapter
|
|
650
|
+
* sets `dialogsError` with an empty list. EmbeddableChat reports
|
|
651
|
+
* `dialogsLoadError` and the Mingo empty state shows its error message + retry
|
|
652
|
+
* button instead of the greeting — what the panel shows when the chat backend
|
|
653
|
+
* is unreachable. Clicking retry re-runs the (still-failing) fetch.
|
|
654
|
+
*/
|
|
655
|
+
export const ChatsError: Story = {
|
|
656
|
+
render: (args) => (
|
|
657
|
+
<EmbeddableChat
|
|
658
|
+
{...args}
|
|
659
|
+
modes={{
|
|
660
|
+
mingo: createMockMingoConfigChatsError(),
|
|
661
|
+
}}
|
|
662
|
+
defaultActiveMode="mingo"
|
|
663
|
+
defaultOpen
|
|
664
|
+
showInternalTrigger={false}
|
|
665
|
+
/>
|
|
666
|
+
),
|
|
667
|
+
args: {},
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// =============================================================================
|
|
671
|
+
// 8. Archive empty — archive page with no archived chats
|
|
672
|
+
// =============================================================================
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Archive page empty state. The dialog list is populated (so the header's
|
|
676
|
+
* archive button renders), but `fetchArchivedDialogs` resolves an empty page.
|
|
677
|
+
* The `play` step clicks the archive button to open the Chat Archive page,
|
|
678
|
+
* which — with nothing archived — shows its centred empty state (icon + title +
|
|
679
|
+
* hint) rather than the dialog list or skeleton.
|
|
680
|
+
*/
|
|
681
|
+
export const ArchiveEmpty: Story = {
|
|
682
|
+
render: (args) => (
|
|
683
|
+
<EmbeddableChat
|
|
684
|
+
{...args}
|
|
685
|
+
modes={{
|
|
686
|
+
mingo: createMockMingoConfigArchiveEmpty(),
|
|
687
|
+
}}
|
|
688
|
+
defaultActiveMode="mingo"
|
|
689
|
+
defaultOpen
|
|
690
|
+
showInternalTrigger={false}
|
|
691
|
+
/>
|
|
692
|
+
),
|
|
693
|
+
args: {},
|
|
694
|
+
play: async () => {
|
|
695
|
+
// The drawer portals to <body>, so query the document, not the canvas.
|
|
696
|
+
const body = within(document.body)
|
|
697
|
+
const archiveButton = await body.findByRole('button', {
|
|
698
|
+
name: 'Chat archive',
|
|
699
|
+
})
|
|
700
|
+
await userEvent.click(archiveButton)
|
|
701
|
+
},
|
|
702
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
|
2
|
+
import { MingoInfoCard } from '../components/chat/mingo-info-card'
|
|
3
|
+
import { MonitorIcon } from '../components/icons-v2-generated/devices/monitor-icon'
|
|
4
|
+
import { Copy01Icon } from '../components/icons-v2-generated/documents/copy-01-icon'
|
|
5
|
+
import { TrashIcon } from '../components/icons-v2-generated/interface/trash-icon'
|
|
6
|
+
|
|
7
|
+
const AVATAR_SRC = 'https://i.pravatar.cc/80?img=12'
|
|
8
|
+
|
|
9
|
+
const SAMPLE_MENU = [
|
|
10
|
+
{
|
|
11
|
+
items: [
|
|
12
|
+
{
|
|
13
|
+
id: 'copy',
|
|
14
|
+
label: 'Copy link',
|
|
15
|
+
icon: <Copy01Icon size={16} />,
|
|
16
|
+
onClick: () => {
|
|
17
|
+
// eslint-disable-next-line no-console
|
|
18
|
+
console.log('[story] copy link')
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: 'remove',
|
|
23
|
+
label: 'Remove',
|
|
24
|
+
icon: <TrashIcon size={16} />,
|
|
25
|
+
danger: true,
|
|
26
|
+
onClick: () => {
|
|
27
|
+
// eslint-disable-next-line no-console
|
|
28
|
+
console.log('[story] remove')
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
const meta: Meta<typeof MingoInfoCard> = {
|
|
36
|
+
title: 'Chat/MingoInfoCard',
|
|
37
|
+
component: MingoInfoCard,
|
|
38
|
+
parameters: {
|
|
39
|
+
// `fullscreen` (not `centered`): `centered` shrinks the wrapper to the
|
|
40
|
+
// content, so the card's `w-full` resolves against a content-sized box and
|
|
41
|
+
// never stretches. A full-width block container lets the card fill 100% and
|
|
42
|
+
// shrink with the canvas — resize the Storybook viewport to see it reflow.
|
|
43
|
+
layout: 'fullscreen',
|
|
44
|
+
docs: {
|
|
45
|
+
description: {
|
|
46
|
+
component:
|
|
47
|
+
'Figma node `2410:6007`. Horizontal info row: a leading 40px avatar (`imageSrc`) or boxed glyph (`icon`), a title + optional description column, an optional status pill, and a trailing "⋯" overflow menu separated by a vertical divider. Background `ods-card`, border `ods-border`, `rounded-md`. The card is `w-full` — it fills whatever block container it is placed in.',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
argTypes: {
|
|
52
|
+
icon: { control: false },
|
|
53
|
+
menuGroups: { control: false },
|
|
54
|
+
onClick: { control: false },
|
|
55
|
+
},
|
|
56
|
+
decorators: [
|
|
57
|
+
(Story) => (
|
|
58
|
+
<div className="w-full bg-ods-bg p-6">
|
|
59
|
+
<Story />
|
|
60
|
+
</div>
|
|
61
|
+
),
|
|
62
|
+
],
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default meta
|
|
66
|
+
type Story = StoryObj<typeof meta>
|
|
67
|
+
|
|
68
|
+
// =============================================================================
|
|
69
|
+
// The two Figma media variants
|
|
70
|
+
// =============================================================================
|
|
71
|
+
|
|
72
|
+
export const WithImage: Story = {
|
|
73
|
+
args: {
|
|
74
|
+
title: 'Card Title',
|
|
75
|
+
description: 'Card Description',
|
|
76
|
+
imageSrc: AVATAR_SRC,
|
|
77
|
+
imageAlt: 'Acme Corp',
|
|
78
|
+
status: { label: 'Status' },
|
|
79
|
+
menuGroups: SAMPLE_MENU,
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const WithIcon: Story = {
|
|
84
|
+
args: {
|
|
85
|
+
title: 'Card Title',
|
|
86
|
+
description: 'Card Description',
|
|
87
|
+
icon: <MonitorIcon size={24} />,
|
|
88
|
+
status: { label: 'Status' },
|
|
89
|
+
menuGroups: SAMPLE_MENU,
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// =============================================================================
|
|
94
|
+
// Optional-element permutations
|
|
95
|
+
// =============================================================================
|
|
96
|
+
|
|
97
|
+
export const WithoutStatus: Story = {
|
|
98
|
+
args: {
|
|
99
|
+
title: 'Card Title',
|
|
100
|
+
description: 'Card Description',
|
|
101
|
+
icon: <MonitorIcon size={24} />,
|
|
102
|
+
menuGroups: SAMPLE_MENU,
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export const WithoutDescription: Story = {
|
|
107
|
+
args: {
|
|
108
|
+
title: 'Card Title',
|
|
109
|
+
imageSrc: AVATAR_SRC,
|
|
110
|
+
imageAlt: 'Acme Corp',
|
|
111
|
+
status: { label: 'Status' },
|
|
112
|
+
menuGroups: SAMPLE_MENU,
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export const WithoutMenu: Story = {
|
|
117
|
+
args: {
|
|
118
|
+
title: 'Card Title',
|
|
119
|
+
description: 'Card Description',
|
|
120
|
+
icon: <MonitorIcon size={24} />,
|
|
121
|
+
status: { label: 'Status' },
|
|
122
|
+
},
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export const Clickable: Story = {
|
|
126
|
+
args: {
|
|
127
|
+
title: 'Card Title',
|
|
128
|
+
description: 'Click anywhere on the row',
|
|
129
|
+
imageSrc: AVATAR_SRC,
|
|
130
|
+
imageAlt: 'Acme Corp',
|
|
131
|
+
status: { label: 'Online' },
|
|
132
|
+
menuGroups: SAMPLE_MENU,
|
|
133
|
+
onClick: () => {
|
|
134
|
+
// eslint-disable-next-line no-console
|
|
135
|
+
console.log('[story] card clicked')
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export const StatusVariants: Story = {
|
|
141
|
+
parameters: {
|
|
142
|
+
docs: {
|
|
143
|
+
description: {
|
|
144
|
+
story:
|
|
145
|
+
'The `status.variant` maps to the shared `Tag` palette — `success` (default), `warning`, `error`, `grey`.',
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
render: () => (
|
|
150
|
+
<div className="flex flex-col gap-3">
|
|
151
|
+
<MingoInfoCard
|
|
152
|
+
title="Production"
|
|
153
|
+
description="All systems operational"
|
|
154
|
+
icon={<MonitorIcon size={24} />}
|
|
155
|
+
status={{ label: 'Online', variant: 'success' }}
|
|
156
|
+
menuGroups={SAMPLE_MENU}
|
|
157
|
+
/>
|
|
158
|
+
<MingoInfoCard
|
|
159
|
+
title="Staging"
|
|
160
|
+
description="Elevated latency detected"
|
|
161
|
+
icon={<MonitorIcon size={24} />}
|
|
162
|
+
status={{ label: 'Degraded', variant: 'warning' }}
|
|
163
|
+
menuGroups={SAMPLE_MENU}
|
|
164
|
+
/>
|
|
165
|
+
<MingoInfoCard
|
|
166
|
+
title="Legacy host"
|
|
167
|
+
description="Unreachable for 12 minutes"
|
|
168
|
+
icon={<MonitorIcon size={24} />}
|
|
169
|
+
status={{ label: 'Offline', variant: 'error' }}
|
|
170
|
+
menuGroups={SAMPLE_MENU}
|
|
171
|
+
/>
|
|
172
|
+
<MingoInfoCard
|
|
173
|
+
title="Archived host"
|
|
174
|
+
description="Decommissioned last quarter"
|
|
175
|
+
icon={<MonitorIcon size={24} />}
|
|
176
|
+
status={{ label: 'Archived', variant: 'grey' }}
|
|
177
|
+
menuGroups={SAMPLE_MENU}
|
|
178
|
+
/>
|
|
179
|
+
</div>
|
|
180
|
+
),
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export const LongContentTruncates: Story = {
|
|
184
|
+
args: {
|
|
185
|
+
title: 'Some Really Long Card Title That Should Truncate Cleanly Without Wrapping',
|
|
186
|
+
description:
|
|
187
|
+
'An equally long description line that also truncates instead of pushing the status pill and overflow menu off the card',
|
|
188
|
+
imageSrc: AVATAR_SRC,
|
|
189
|
+
imageAlt: 'Acme Corp',
|
|
190
|
+
status: { label: 'Status' },
|
|
191
|
+
menuGroups: SAMPLE_MENU,
|
|
192
|
+
},
|
|
193
|
+
}
|
|
@@ -61,7 +61,7 @@ export const WithoutDescription: Story = {
|
|
|
61
61
|
|
|
62
62
|
export const WithoutSlashCommand: Story = {
|
|
63
63
|
args: {
|
|
64
|
-
icon: <
|
|
64
|
+
icon: <Rocket02Icon size={16} />,
|
|
65
65
|
title: 'Get started',
|
|
66
66
|
description: 'Browse onboarding guides and quick wins',
|
|
67
67
|
},
|
|
@@ -24,6 +24,17 @@ const meta = {
|
|
|
24
24
|
},
|
|
25
25
|
},
|
|
26
26
|
},
|
|
27
|
+
args: {
|
|
28
|
+
notification: {
|
|
29
|
+
id: 'preview',
|
|
30
|
+
variant: 'default',
|
|
31
|
+
title: 'Preview',
|
|
32
|
+
description: 'Preview notification',
|
|
33
|
+
createdAt: 0,
|
|
34
|
+
read: true,
|
|
35
|
+
},
|
|
36
|
+
onComplete: () => {},
|
|
37
|
+
},
|
|
27
38
|
} satisfies Meta<typeof NotificationTile>;
|
|
28
39
|
|
|
29
40
|
export default meta;
|
|
@@ -264,7 +275,7 @@ function PlaygroundControls() {
|
|
|
264
275
|
|
|
265
276
|
<div className="flex flex-wrap gap-2">
|
|
266
277
|
<Button
|
|
267
|
-
variant="
|
|
278
|
+
variant="accent"
|
|
268
279
|
onClick={() =>
|
|
269
280
|
fire('success', 'Device Deployment Complete', 'HP EliteBook deployed to Marketing Dept')
|
|
270
281
|
}
|
|
@@ -280,13 +291,13 @@ function PlaygroundControls() {
|
|
|
280
291
|
Fire error
|
|
281
292
|
</Button>
|
|
282
293
|
<Button
|
|
283
|
-
variant="
|
|
294
|
+
variant="outline"
|
|
284
295
|
onClick={() => fire('warning', 'Tech Required', 'Approval is required to execute the command.')}
|
|
285
296
|
>
|
|
286
297
|
Fire warning
|
|
287
298
|
</Button>
|
|
288
299
|
<Button
|
|
289
|
-
variant="
|
|
300
|
+
variant="transparent"
|
|
290
301
|
onClick={() => fire('info', 'Update available', 'A new agent version is ready to install.')}
|
|
291
302
|
>
|
|
292
303
|
Fire info
|
|
@@ -16,7 +16,7 @@ PageActions component for displaying action buttons in page headers.
|
|
|
16
16
|
**Three variants:**
|
|
17
17
|
1. \`icon-buttons\` - Buttons with icons, collapses to dropdown menu on mobile
|
|
18
18
|
2. \`primary-buttons\` - Primary + outline buttons, fixed to bottom on mobile
|
|
19
|
-
3. \`menu-primary\` -
|
|
19
|
+
3. \`menu-primary\` - ActionsMenuDropdown ("...") + primary button on desktop, all actions expand to fixed bottom bar on mobile
|
|
20
20
|
|
|
21
21
|
Use with \`PageContainer\` headerActions prop for consistent page layouts.
|
|
22
22
|
`,
|
|
@@ -52,7 +52,7 @@ type Story = StoryObj<typeof meta>
|
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
* Icon buttons variant - used for list pages like Scripts.
|
|
55
|
-
* Shows buttons with icons on desktop, collapses to
|
|
55
|
+
* Shows buttons with icons on desktop, collapses to ActionsMenuDropdown on mobile.
|
|
56
56
|
*/
|
|
57
57
|
export const IconButtons: Story = {
|
|
58
58
|
args: {
|
|
@@ -151,7 +151,7 @@ export const SingleIconButton: Story = {
|
|
|
151
151
|
parameters: {
|
|
152
152
|
docs: {
|
|
153
153
|
description: {
|
|
154
|
-
story: 'When there is only one action in icon-buttons variant, it displays as an icon button on mobile instead of collapsing to
|
|
154
|
+
story: 'When there is only one action in icon-buttons variant, it displays as an icon button on mobile instead of collapsing to an ActionsMenuDropdown.',
|
|
155
155
|
},
|
|
156
156
|
},
|
|
157
157
|
},
|
|
@@ -207,7 +207,7 @@ export const WithStates: Story = {
|
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
/**
|
|
210
|
-
* Menu + primary variant - shows
|
|
210
|
+
* Menu + primary variant - shows ActionsMenuDropdown ("...") + primary button on desktop.
|
|
211
211
|
* On mobile all actions expand into a fixed bottom bar.
|
|
212
212
|
*/
|
|
213
213
|
export const MenuPrimary: Story = {
|
|
@@ -85,7 +85,7 @@ export const ListPage: Story = {
|
|
|
85
85
|
title: 'Devices',
|
|
86
86
|
subtitle: '24 devices found',
|
|
87
87
|
actions: [
|
|
88
|
-
{ label: 'Add Device', onClick: () => {}, icon: <Plus className="w-5 h-5" />, variant: '
|
|
88
|
+
{ label: 'Add Device', onClick: () => {}, icon: <Plus className="w-5 h-5" />, variant: 'accent' },
|
|
89
89
|
],
|
|
90
90
|
children: <PlaceholderContent />,
|
|
91
91
|
},
|
|
@@ -101,7 +101,7 @@ export const ListPageMultipleActions: Story = {
|
|
|
101
101
|
subtitle: 'Manage your scripts',
|
|
102
102
|
actions: [
|
|
103
103
|
{ label: 'Edit', onClick: () => {}, icon: <Edit className="w-5 h-5" />, variant: 'outline' },
|
|
104
|
-
{ label: 'Create Script', onClick: () => {}, icon: <Plus className="w-5 h-5" />, variant: '
|
|
104
|
+
{ label: 'Create Script', onClick: () => {}, icon: <Plus className="w-5 h-5" />, variant: 'accent' },
|
|
105
105
|
],
|
|
106
106
|
children: <PlaceholderContent />,
|
|
107
107
|
},
|
|
@@ -133,7 +133,7 @@ export const DetailPageWithActions: Story = {
|
|
|
133
133
|
backButton: { onClick: () => {} },
|
|
134
134
|
actions: [
|
|
135
135
|
{ label: 'Delete', onClick: () => {}, icon: <Trash2 className="w-5 h-5" />, variant: 'outline' },
|
|
136
|
-
{ label: 'Run Script', onClick: () => {}, variant: '
|
|
136
|
+
{ label: 'Run Script', onClick: () => {}, variant: 'accent' },
|
|
137
137
|
],
|
|
138
138
|
children: <PlaceholderContent />,
|
|
139
139
|
},
|
|
@@ -151,7 +151,7 @@ export const FormPage: Story = {
|
|
|
151
151
|
backButton: { label: 'Cancel', onClick: () => {} },
|
|
152
152
|
actions: [
|
|
153
153
|
{ label: 'Save Draft', onClick: () => {}, variant: 'outline' },
|
|
154
|
-
{ label: 'Publish', onClick: () => {}, variant: '
|
|
154
|
+
{ label: 'Publish', onClick: () => {}, variant: 'accent' },
|
|
155
155
|
],
|
|
156
156
|
children: (
|
|
157
157
|
<div className="flex flex-col gap-6">
|
|
@@ -208,7 +208,7 @@ export const WithHeaderActions: Story = {
|
|
|
208
208
|
<Button variant="outline" size="small-legacy">Export</Button>
|
|
209
209
|
),
|
|
210
210
|
actions: [
|
|
211
|
-
{ label: 'Add Device', onClick: () => {}, icon: <Plus className="w-5 h-5" />, variant: '
|
|
211
|
+
{ label: 'Add Device', onClick: () => {}, icon: <Plus className="w-5 h-5" />, variant: 'accent' },
|
|
212
212
|
],
|
|
213
213
|
children: <PlaceholderContent />,
|
|
214
214
|
},
|