@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
|
@@ -0,0 +1,748 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
|
2
|
+
import type { ReactNode } from 'react'
|
|
3
|
+
import { MingoInfoCard } from '../components/chat/mingo-info-card'
|
|
4
|
+
import { ChatColumnDecorator, makeAnchorProps } from './__fixtures__/chat-card-decorator'
|
|
5
|
+
import { MingoIcon } from '../components/icons'
|
|
6
|
+
import { EyeIcon } from '../components/icons-v2-generated/interface/eye-icon'
|
|
7
|
+
import { ArrowRightUpIcon } from '../components/icons-v2-generated/arrows/arrow-right-up-icon'
|
|
8
|
+
import { TagIcon } from '../components/icons-v2-generated/shopping/tag-icon'
|
|
9
|
+
import { CodingCommitIcon } from '../components/icons-v2-generated/coding/coding-commit-icon'
|
|
10
|
+
import { CodingPullRequestIcon } from '../components/icons-v2-generated/coding/coding-pull-request-icon'
|
|
11
|
+
import { CodeIcon } from '../components/icons-v2-generated/coding/code-icon'
|
|
12
|
+
import { SlackLogoGreyIcon } from '../components/icons-v2-generated/brand-logos/slack-logo-grey-icon'
|
|
13
|
+
import { FileContentIcon } from '../components/icons-v2-generated/documents/file-content-icon'
|
|
14
|
+
import { ChartBar01VerIcon } from '../components/icons-v2-generated/charts/chart-bar-01-ver-icon'
|
|
15
|
+
import { ChartPieIcon } from '../components/icons-v2-generated/charts/chart-pie-icon'
|
|
16
|
+
import { MoneyBillDollarIcon } from '../components/icons-v2-generated/finance/money-bill-dollar-icon'
|
|
17
|
+
import { BankIcon } from '../components/icons-v2-generated/finance/bank-icon'
|
|
18
|
+
import { CoinsExchangeCurrencyIcon } from '../components/icons-v2-generated/finance/coins-exchange-currency-icon'
|
|
19
|
+
import { NewspaperIcon } from '../components/icons-v2-generated/documents/newspaper-icon'
|
|
20
|
+
import { TrophyIcon } from '../components/icons-v2-generated/sport/trophy-icon'
|
|
21
|
+
import { MicrophoneIcon } from '../components/icons-v2-generated/household/microphone-icon'
|
|
22
|
+
import { Rocket02Icon } from '../components/icons-v2-generated/vehicles-and-delivery/rocket-02-icon'
|
|
23
|
+
import { TruckFastIcon } from '../components/icons-v2-generated/vehicles-and-delivery/truck-fast-icon'
|
|
24
|
+
import { PresentationBarIcon } from '../components/icons-v2-generated/charts/presentation-bar-icon'
|
|
25
|
+
import { PresentationLineIcon } from '../components/icons-v2-generated/charts/presentation-line-icon'
|
|
26
|
+
import { CalendarIcon } from '../components/icons-v2-generated/date-and-time/calendar-icon'
|
|
27
|
+
import { CompassIcon } from '../components/icons-v2-generated/map-and-travel/compass-icon'
|
|
28
|
+
import { MapIcon } from '../components/icons-v2-generated/map-and-travel/map-icon'
|
|
29
|
+
import { CheckSquareIcon } from '../components/icons-v2-generated/signs-and-symbols/check-square-icon'
|
|
30
|
+
import { Megaphone01Icon } from '../components/icons-v2-generated/shopping/megaphone-01-icon'
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Chat entity-cards re-skinned with `MingoInfoCard`.
|
|
34
|
+
*
|
|
35
|
+
* As each `[card://type:id]` registry entry in `entity-cards/dispatch.tsx` is
|
|
36
|
+
* migrated to render a `MingoInfoCard`, its variants are mirrored here so the
|
|
37
|
+
* compact in-chat appearance can be reviewed in isolation — same column width
|
|
38
|
+
* and background the dispatch renders into, without booting the chat runtime.
|
|
39
|
+
*
|
|
40
|
+
* Each `render` reproduces the registry's field mapping for that card type
|
|
41
|
+
* (icon, status pill, description, "⋯" menu). Anchor clicks are neutralized via
|
|
42
|
+
* `makeAnchorProps` so the Storybook iframe doesn't navigate away.
|
|
43
|
+
*/
|
|
44
|
+
const meta: Meta<typeof MingoInfoCard> = {
|
|
45
|
+
title: 'Chat/ChatMingoInfoCards',
|
|
46
|
+
component: MingoInfoCard,
|
|
47
|
+
parameters: {
|
|
48
|
+
layout: 'fullscreen',
|
|
49
|
+
docs: {
|
|
50
|
+
description: {
|
|
51
|
+
component:
|
|
52
|
+
'In-chat entity cards rendered through `MingoInfoCard`. One section per migrated `CHAT_CARD_REGISTRY` type — mirrors the icon / status / description / menu mapping from `entity-cards/dispatch.tsx`.',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
decorators: [
|
|
57
|
+
(Story) => (
|
|
58
|
+
<ChatColumnDecorator>
|
|
59
|
+
<Story />
|
|
60
|
+
</ChatColumnDecorator>
|
|
61
|
+
),
|
|
62
|
+
],
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default meta
|
|
66
|
+
type Story = StoryObj<typeof meta>
|
|
67
|
+
|
|
68
|
+
/** Shared "⋯" overflow menu (Figma `7740:55075`): "Ask Mingo" (Mingo logo)
|
|
69
|
+
* followed by "Open Details" (eye) with a trailing ↗ open-in-new-tab side
|
|
70
|
+
* button. */
|
|
71
|
+
const openMenu = (
|
|
72
|
+
href: string,
|
|
73
|
+
openDetails?: { label: string; icon: ReactNode },
|
|
74
|
+
) => [
|
|
75
|
+
{
|
|
76
|
+
items: [
|
|
77
|
+
{
|
|
78
|
+
id: 'discuss',
|
|
79
|
+
label: 'Ask Mingo',
|
|
80
|
+
icon: (
|
|
81
|
+
<MingoIcon
|
|
82
|
+
className="size-5"
|
|
83
|
+
color="white"
|
|
84
|
+
eyesColor="var(--ods-flamingo-cyan-base)"
|
|
85
|
+
cornerColor="var(--ods-flamingo-cyan-base)"
|
|
86
|
+
/>
|
|
87
|
+
),
|
|
88
|
+
onClick: () => {
|
|
89
|
+
// eslint-disable-next-line no-console
|
|
90
|
+
console.log('[story] ask mingo', href)
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: 'open-details',
|
|
95
|
+
label: openDetails?.label ?? 'Open Details',
|
|
96
|
+
icon: openDetails?.icon ?? <EyeIcon size={20} />,
|
|
97
|
+
onClick: () => {
|
|
98
|
+
// eslint-disable-next-line no-console
|
|
99
|
+
console.log('[story] open details', href)
|
|
100
|
+
},
|
|
101
|
+
iconAction: {
|
|
102
|
+
icon: <ArrowRightUpIcon size={20} />,
|
|
103
|
+
'aria-label': 'Open in new tab',
|
|
104
|
+
onClick: () => {
|
|
105
|
+
// eslint-disable-next-line no-console
|
|
106
|
+
console.log('[story] open in new tab', href)
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
// =============================================================================
|
|
115
|
+
// HubSpot ticket — icon: HubSpot grey logo · status: ticket state · desc: preview
|
|
116
|
+
// =============================================================================
|
|
117
|
+
|
|
118
|
+
export const HubspotTicket: Story = {
|
|
119
|
+
parameters: {
|
|
120
|
+
docs: {
|
|
121
|
+
description: {
|
|
122
|
+
story:
|
|
123
|
+
'Registry types `hubspot_ticket` / `_anon` / `_self`. Status pill maps the ticket state (Closed → green, Open → amber, other → grey); description is the ticket preview.',
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
render: () => {
|
|
128
|
+
const HREF = 'https://app.hubspot.com/contacts/0/ticket/123'
|
|
129
|
+
return (
|
|
130
|
+
<div className="flex flex-col gap-3">
|
|
131
|
+
<MingoInfoCard
|
|
132
|
+
title="Login page returns 500 after SSO redirect"
|
|
133
|
+
description="Customer cannot sign in via Google SSO since this morning…"
|
|
134
|
+
icon={<TagIcon size={24} />}
|
|
135
|
+
status={{ label: 'Open', variant: 'warning' }}
|
|
136
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
137
|
+
menuGroups={openMenu(HREF, {
|
|
138
|
+
label: 'Open Ticket Details',
|
|
139
|
+
icon: <TagIcon size={20} />,
|
|
140
|
+
})}
|
|
141
|
+
menuAriaLabel="Ticket actions"
|
|
142
|
+
/>
|
|
143
|
+
<MingoInfoCard
|
|
144
|
+
title="Export to CSV missing last column"
|
|
145
|
+
description="Resolved — shipped in 2.14.1, customer confirmed the fix."
|
|
146
|
+
icon={<TagIcon size={24} />}
|
|
147
|
+
status={{ label: 'Closed', variant: 'success' }}
|
|
148
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
149
|
+
menuGroups={openMenu(HREF, {
|
|
150
|
+
label: 'Open Ticket Details',
|
|
151
|
+
icon: <TagIcon size={20} />,
|
|
152
|
+
})}
|
|
153
|
+
menuAriaLabel="Ticket actions"
|
|
154
|
+
/>
|
|
155
|
+
<MingoInfoCard
|
|
156
|
+
title="Waiting on customer logs for the sync failure"
|
|
157
|
+
description="Pending — asked for the agent log bundle from the affected host."
|
|
158
|
+
icon={<TagIcon size={24} />}
|
|
159
|
+
status={{ label: 'Waiting on us', variant: 'grey' }}
|
|
160
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
161
|
+
menuGroups={openMenu(HREF, {
|
|
162
|
+
label: 'Open Ticket Details',
|
|
163
|
+
icon: <TagIcon size={20} />,
|
|
164
|
+
})}
|
|
165
|
+
menuAriaLabel="Ticket actions"
|
|
166
|
+
/>
|
|
167
|
+
<MingoInfoCard
|
|
168
|
+
title="Ticket with no preview text and no status set at all"
|
|
169
|
+
icon={<TagIcon size={24} />}
|
|
170
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
171
|
+
menuGroups={openMenu(HREF, {
|
|
172
|
+
label: 'Open Ticket Details',
|
|
173
|
+
icon: <TagIcon size={20} />,
|
|
174
|
+
})}
|
|
175
|
+
menuAriaLabel="Ticket actions"
|
|
176
|
+
/>
|
|
177
|
+
</div>
|
|
178
|
+
)
|
|
179
|
+
},
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// =============================================================================
|
|
183
|
+
// GitHub activity — icon per kind · status: review state or activity type ·
|
|
184
|
+
// description: "<id> · <date>"
|
|
185
|
+
// =============================================================================
|
|
186
|
+
|
|
187
|
+
export const GithubActivity: Story = {
|
|
188
|
+
parameters: {
|
|
189
|
+
docs: {
|
|
190
|
+
description: {
|
|
191
|
+
story:
|
|
192
|
+
'Registry types `github_commit` / `github_pull_request` / `github_pr_review` (+ `_public`). Icon differs per kind (commit / pull-request / code); the pill shows the PR review state (Approved → green, Changes → red, Comment → grey) or, for commits/PRs, the neutral activity type.',
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
render: () => {
|
|
197
|
+
const HREF = 'https://github.com/flamingo/openframe/commit/a1b2c3d'
|
|
198
|
+
return (
|
|
199
|
+
<div className="flex flex-col gap-3">
|
|
200
|
+
<MingoInfoCard
|
|
201
|
+
title="fix(auth): guard SSO redirect against null session"
|
|
202
|
+
description="a1b2c3d · May 28, 2026"
|
|
203
|
+
icon={<CodingCommitIcon size={24} />}
|
|
204
|
+
status={{ label: 'Commit', variant: 'grey' }}
|
|
205
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
206
|
+
menuGroups={openMenu(HREF)}
|
|
207
|
+
menuAriaLabel="Activity actions"
|
|
208
|
+
/>
|
|
209
|
+
<MingoInfoCard
|
|
210
|
+
title="Add device bulk-actions to the fleet table"
|
|
211
|
+
description="#482 · May 27, 2026"
|
|
212
|
+
icon={<CodingPullRequestIcon size={24} />}
|
|
213
|
+
status={{ label: 'PR', variant: 'grey' }}
|
|
214
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
215
|
+
menuGroups={openMenu(HREF)}
|
|
216
|
+
menuAriaLabel="Activity actions"
|
|
217
|
+
/>
|
|
218
|
+
<MingoInfoCard
|
|
219
|
+
title="Pavlo Shylo"
|
|
220
|
+
description="#482 · May 27, 2026"
|
|
221
|
+
icon={<CodeIcon size={24} />}
|
|
222
|
+
status={{ label: 'Approved', variant: 'success' }}
|
|
223
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
224
|
+
menuGroups={openMenu(HREF)}
|
|
225
|
+
menuAriaLabel="Activity actions"
|
|
226
|
+
/>
|
|
227
|
+
<MingoInfoCard
|
|
228
|
+
title="Alex Rivera"
|
|
229
|
+
description="#479 · May 26, 2026"
|
|
230
|
+
icon={<CodeIcon size={24} />}
|
|
231
|
+
status={{ label: 'Changes', variant: 'error' }}
|
|
232
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
233
|
+
menuGroups={openMenu(HREF)}
|
|
234
|
+
menuAriaLabel="Activity actions"
|
|
235
|
+
/>
|
|
236
|
+
<MingoInfoCard
|
|
237
|
+
title="Sam Lee"
|
|
238
|
+
description="#477 · May 25, 2026"
|
|
239
|
+
icon={<CodeIcon size={24} />}
|
|
240
|
+
status={{ label: 'Comment', variant: 'grey' }}
|
|
241
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
242
|
+
menuGroups={openMenu(HREF)}
|
|
243
|
+
menuAriaLabel="Activity actions"
|
|
244
|
+
/>
|
|
245
|
+
</div>
|
|
246
|
+
)
|
|
247
|
+
},
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// =============================================================================
|
|
251
|
+
// Slack message — icon: Slack grey logo · no pill · description: message text
|
|
252
|
+
// =============================================================================
|
|
253
|
+
|
|
254
|
+
export const SlackMessage: Story = {
|
|
255
|
+
parameters: {
|
|
256
|
+
docs: {
|
|
257
|
+
description: {
|
|
258
|
+
story:
|
|
259
|
+
'Registry type `slack_message`. No status pill (Slack has no status); the channel is appended to the author title ("Author · #channel"), and the description is the message preview text.',
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
render: () => {
|
|
264
|
+
const HREF = 'https://flamingo.slack.com/archives/C12345/p1700000000'
|
|
265
|
+
return (
|
|
266
|
+
<div className="flex flex-col gap-3">
|
|
267
|
+
<MingoInfoCard
|
|
268
|
+
title="Pavlo Shylo · #deploys"
|
|
269
|
+
description="Heads up — the staging deploy is going out in 10 minutes, hold any merges to main."
|
|
270
|
+
icon={<SlackLogoGreyIcon size={24} />}
|
|
271
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
272
|
+
menuGroups={openMenu(HREF)}
|
|
273
|
+
menuAriaLabel="Message actions"
|
|
274
|
+
/>
|
|
275
|
+
<MingoInfoCard
|
|
276
|
+
title="Alex Rivera · #incidents"
|
|
277
|
+
description="Found the root cause of the sync failure — it's the token refresh race. PR incoming."
|
|
278
|
+
icon={<SlackLogoGreyIcon size={24} />}
|
|
279
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
280
|
+
menuGroups={openMenu(HREF)}
|
|
281
|
+
menuAriaLabel="Message actions"
|
|
282
|
+
/>
|
|
283
|
+
<MingoInfoCard
|
|
284
|
+
title="Sam Lee · #general"
|
|
285
|
+
icon={<SlackLogoGreyIcon size={24} />}
|
|
286
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
287
|
+
menuGroups={openMenu(HREF)}
|
|
288
|
+
menuAriaLabel="Message actions"
|
|
289
|
+
/>
|
|
290
|
+
</div>
|
|
291
|
+
)
|
|
292
|
+
},
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// =============================================================================
|
|
296
|
+
// Data-room doc / markdown — icon: FileContent · status: source badge ·
|
|
297
|
+
// description: preview
|
|
298
|
+
// =============================================================================
|
|
299
|
+
|
|
300
|
+
export const DataRoomDoc: Story = {
|
|
301
|
+
parameters: {
|
|
302
|
+
docs: {
|
|
303
|
+
description: {
|
|
304
|
+
story:
|
|
305
|
+
'Registry types `data_room_doc` / `markdown`. Status pill is the provenance label (the source-repo label, or a neutral "Document" when unknown); the description is the content preview.',
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
render: () => {
|
|
310
|
+
const HREF = 'https://hub.flamingo.cx/docs/openframe/getting-started'
|
|
311
|
+
return (
|
|
312
|
+
<div className="flex flex-col gap-3">
|
|
313
|
+
<MingoInfoCard
|
|
314
|
+
title="Getting started with OpenFrame"
|
|
315
|
+
description="Install the agent, connect your first device, and open the fleet view."
|
|
316
|
+
icon={<FileContentIcon size={24} />}
|
|
317
|
+
status={{ label: 'OpenFrame Docs', variant: 'grey' }}
|
|
318
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
319
|
+
menuGroups={openMenu(HREF)}
|
|
320
|
+
menuAriaLabel="Document actions"
|
|
321
|
+
/>
|
|
322
|
+
<MingoInfoCard
|
|
323
|
+
title="Series A — financial model (Q1 2026)"
|
|
324
|
+
description="Revenue, burn, and runway projections for the upcoming raise."
|
|
325
|
+
icon={<FileContentIcon size={24} />}
|
|
326
|
+
status={{ label: 'Data room', variant: 'grey' }}
|
|
327
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
328
|
+
menuGroups={openMenu(HREF)}
|
|
329
|
+
menuAriaLabel="Document actions"
|
|
330
|
+
/>
|
|
331
|
+
<MingoInfoCard
|
|
332
|
+
title="Unlabeled doc — source repo unknown, falls back to Document"
|
|
333
|
+
description="Neutral provenance so unknown content can't be mislabeled."
|
|
334
|
+
icon={<FileContentIcon size={24} />}
|
|
335
|
+
status={{ label: 'Document', variant: 'grey' }}
|
|
336
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
337
|
+
menuGroups={openMenu(HREF)}
|
|
338
|
+
menuAriaLabel="Document actions"
|
|
339
|
+
/>
|
|
340
|
+
</div>
|
|
341
|
+
)
|
|
342
|
+
},
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// =============================================================================
|
|
346
|
+
// Financial — distinct icon per type · no pill · description: subtitle
|
|
347
|
+
// =============================================================================
|
|
348
|
+
|
|
349
|
+
export const Financial: Story = {
|
|
350
|
+
parameters: {
|
|
351
|
+
docs: {
|
|
352
|
+
description: {
|
|
353
|
+
story:
|
|
354
|
+
'Registry types `financial_kpi` / `cap_table` / `profit_loss` / `balance_sheet` / `cash_flow`. No status pill — the per-type icon carries the type signal (chart / pie / money / bank / exchange); the description is the subtitle.',
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
render: () => {
|
|
359
|
+
const HREF = 'https://hub.flamingo.cx/data-room/financials'
|
|
360
|
+
return (
|
|
361
|
+
<div className="flex flex-col gap-3">
|
|
362
|
+
<MingoInfoCard
|
|
363
|
+
title="Net revenue retention"
|
|
364
|
+
description="TTM · 118%"
|
|
365
|
+
icon={<ChartBar01VerIcon size={24} />}
|
|
366
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
367
|
+
menuGroups={openMenu(HREF)}
|
|
368
|
+
menuAriaLabel="Document actions"
|
|
369
|
+
/>
|
|
370
|
+
<MingoInfoCard
|
|
371
|
+
title="Cap table — Series A"
|
|
372
|
+
description="Post-money · $42M"
|
|
373
|
+
icon={<ChartPieIcon size={24} />}
|
|
374
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
375
|
+
menuGroups={openMenu(HREF)}
|
|
376
|
+
menuAriaLabel="Document actions"
|
|
377
|
+
/>
|
|
378
|
+
<MingoInfoCard
|
|
379
|
+
title="Profit & loss"
|
|
380
|
+
description="Q1 2026"
|
|
381
|
+
icon={<MoneyBillDollarIcon size={24} />}
|
|
382
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
383
|
+
menuGroups={openMenu(HREF)}
|
|
384
|
+
menuAriaLabel="Document actions"
|
|
385
|
+
/>
|
|
386
|
+
<MingoInfoCard
|
|
387
|
+
title="Balance sheet"
|
|
388
|
+
description="As of Mar 31, 2026"
|
|
389
|
+
icon={<BankIcon size={24} />}
|
|
390
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
391
|
+
menuGroups={openMenu(HREF)}
|
|
392
|
+
menuAriaLabel="Document actions"
|
|
393
|
+
/>
|
|
394
|
+
<MingoInfoCard
|
|
395
|
+
title="Cash flow statement"
|
|
396
|
+
description="Q1 2026 · burn $1.1M/mo"
|
|
397
|
+
icon={<CoinsExchangeCurrencyIcon size={24} />}
|
|
398
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
399
|
+
menuGroups={openMenu(HREF)}
|
|
400
|
+
menuAriaLabel="Document actions"
|
|
401
|
+
/>
|
|
402
|
+
</div>
|
|
403
|
+
)
|
|
404
|
+
},
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// =============================================================================
|
|
408
|
+
// Blog post — media: cover image (newspaper-icon fallback) · pill: category ·
|
|
409
|
+
// description: summary
|
|
410
|
+
// =============================================================================
|
|
411
|
+
|
|
412
|
+
export const BlogPost: Story = {
|
|
413
|
+
parameters: {
|
|
414
|
+
docs: {
|
|
415
|
+
description: {
|
|
416
|
+
story:
|
|
417
|
+
'Registry type `blog_post` (fetch mode). Media is the cover `featured_image` (OG placeholder, then a newspaper glyph as fallbacks); the pill is the first category; the description is the post summary.',
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
render: () => {
|
|
422
|
+
const HREF = 'https://openmsp.com/blog/rmm-buyers-guide'
|
|
423
|
+
return (
|
|
424
|
+
<div className="flex flex-col gap-3">
|
|
425
|
+
<MingoInfoCard
|
|
426
|
+
title="The 2026 RMM buyer's guide"
|
|
427
|
+
description="What to look for when choosing a remote monitoring and management platform."
|
|
428
|
+
imageSrc="https://picsum.photos/seed/rmm/80"
|
|
429
|
+
imageAlt="The 2026 RMM buyer's guide"
|
|
430
|
+
icon={<NewspaperIcon size={24} />}
|
|
431
|
+
status={{ label: 'Guides', variant: 'grey' }}
|
|
432
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
433
|
+
menuGroups={openMenu(HREF)}
|
|
434
|
+
menuAriaLabel="Article actions"
|
|
435
|
+
/>
|
|
436
|
+
<MingoInfoCard
|
|
437
|
+
title="Post with no cover image — falls back to the newspaper icon"
|
|
438
|
+
description="When featured_image and the OG placeholder are both missing."
|
|
439
|
+
icon={<NewspaperIcon size={24} />}
|
|
440
|
+
status={{ label: 'News', variant: 'grey' }}
|
|
441
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
442
|
+
menuGroups={openMenu(HREF)}
|
|
443
|
+
menuAriaLabel="Article actions"
|
|
444
|
+
/>
|
|
445
|
+
<MingoInfoCard
|
|
446
|
+
title="How we built the Mingo chat: streaming, citations and inline cards"
|
|
447
|
+
description="A deep-dive into the unified chat runtime that powers Guide and Mingo modes…"
|
|
448
|
+
imageSrc="https://picsum.photos/seed/videopost/80"
|
|
449
|
+
imageAlt="How we built the Mingo chat"
|
|
450
|
+
icon={<NewspaperIcon size={24} />}
|
|
451
|
+
status={{ label: 'Video', variant: 'primary' }}
|
|
452
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
453
|
+
menuGroups={openMenu(HREF)}
|
|
454
|
+
menuAriaLabel="Article actions"
|
|
455
|
+
/>
|
|
456
|
+
</div>
|
|
457
|
+
)
|
|
458
|
+
},
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// =============================================================================
|
|
462
|
+
// Case study — trophy fallback icon · "Case study" pill · cover image
|
|
463
|
+
// =============================================================================
|
|
464
|
+
|
|
465
|
+
export const CaseStudy: Story = {
|
|
466
|
+
render: () => {
|
|
467
|
+
const HREF = 'https://openmsp.com/case-studies/acme-it'
|
|
468
|
+
return (
|
|
469
|
+
<div className="flex flex-col gap-3">
|
|
470
|
+
<MingoInfoCard
|
|
471
|
+
title="How Acme IT cut ticket volume by 40%"
|
|
472
|
+
description="Acme IT · Jordan Blake"
|
|
473
|
+
imageSrc="https://picsum.photos/seed/acme/80"
|
|
474
|
+
imageAlt="How Acme IT cut ticket volume by 40%"
|
|
475
|
+
icon={<TrophyIcon size={24} />}
|
|
476
|
+
status={{ label: 'Case study', variant: 'grey' }}
|
|
477
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
478
|
+
menuGroups={openMenu(HREF)}
|
|
479
|
+
menuAriaLabel="Case study actions"
|
|
480
|
+
/>
|
|
481
|
+
<MingoInfoCard
|
|
482
|
+
title="Case study without a cover — trophy icon fallback"
|
|
483
|
+
description="NorthStar MSP"
|
|
484
|
+
icon={<TrophyIcon size={24} />}
|
|
485
|
+
status={{ label: 'Case study', variant: 'grey' }}
|
|
486
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
487
|
+
menuGroups={openMenu(HREF)}
|
|
488
|
+
menuAriaLabel="Case study actions"
|
|
489
|
+
/>
|
|
490
|
+
</div>
|
|
491
|
+
)
|
|
492
|
+
},
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// =============================================================================
|
|
496
|
+
// Customer interview — microphone fallback · "Interview" pill
|
|
497
|
+
// =============================================================================
|
|
498
|
+
|
|
499
|
+
export const CustomerInterview: Story = {
|
|
500
|
+
render: () => {
|
|
501
|
+
const HREF = 'https://openmsp.com/interviews/jamie-fox'
|
|
502
|
+
return (
|
|
503
|
+
<div className="flex flex-col gap-3">
|
|
504
|
+
<MingoInfoCard
|
|
505
|
+
title="Scaling an MSP from 5 to 50 technicians"
|
|
506
|
+
description="Jamie Fox · BrightLayer"
|
|
507
|
+
imageSrc="https://picsum.photos/seed/interview/80"
|
|
508
|
+
imageAlt="Scaling an MSP from 5 to 50 technicians"
|
|
509
|
+
icon={<MicrophoneIcon size={24} />}
|
|
510
|
+
status={{ label: 'Interview', variant: 'grey' }}
|
|
511
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
512
|
+
menuGroups={openMenu(HREF)}
|
|
513
|
+
menuAriaLabel="Interview actions"
|
|
514
|
+
/>
|
|
515
|
+
</div>
|
|
516
|
+
)
|
|
517
|
+
},
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// =============================================================================
|
|
521
|
+
// Product release — rocket fallback · version pill · description: summary/date
|
|
522
|
+
// =============================================================================
|
|
523
|
+
|
|
524
|
+
export const ProductRelease: Story = {
|
|
525
|
+
render: () => {
|
|
526
|
+
const HREF = 'https://openframe.org/releases/2-14-0'
|
|
527
|
+
return (
|
|
528
|
+
<div className="flex flex-col gap-3">
|
|
529
|
+
<MingoInfoCard
|
|
530
|
+
title="OpenFrame 2.14"
|
|
531
|
+
description="Bulk device actions, faster fleet table, SSO hardening."
|
|
532
|
+
imageSrc="https://picsum.photos/seed/release/80"
|
|
533
|
+
imageAlt="OpenFrame 2.14"
|
|
534
|
+
icon={<Rocket02Icon size={24} />}
|
|
535
|
+
status={{ label: 'v2.14', variant: 'grey' }}
|
|
536
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
537
|
+
menuGroups={openMenu(HREF)}
|
|
538
|
+
menuAriaLabel="Release actions"
|
|
539
|
+
/>
|
|
540
|
+
<MingoInfoCard
|
|
541
|
+
title="OpenFrame 2.13.2 — patch release"
|
|
542
|
+
description="May 12, 2026"
|
|
543
|
+
icon={<Rocket02Icon size={24} />}
|
|
544
|
+
status={{ label: 'v2.13.2', variant: 'grey' }}
|
|
545
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
546
|
+
menuGroups={openMenu(HREF)}
|
|
547
|
+
menuAriaLabel="Release actions"
|
|
548
|
+
/>
|
|
549
|
+
</div>
|
|
550
|
+
)
|
|
551
|
+
},
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// =============================================================================
|
|
555
|
+
// Programs — podcast / webinar / event, distinct icon + type pill
|
|
556
|
+
// =============================================================================
|
|
557
|
+
|
|
558
|
+
export const Programs: Story = {
|
|
559
|
+
render: () => {
|
|
560
|
+
const HREF = 'https://openmsp.com/podcasts/ep-42'
|
|
561
|
+
return (
|
|
562
|
+
<div className="flex flex-col gap-3">
|
|
563
|
+
<MingoInfoCard
|
|
564
|
+
title="Ep. 42 — The economics of co-managed IT"
|
|
565
|
+
description="May 28, 2026 · 42 min"
|
|
566
|
+
imageSrc="https://picsum.photos/seed/podcast/80"
|
|
567
|
+
imageAlt="Ep. 42 — The economics of co-managed IT"
|
|
568
|
+
icon={<MicrophoneIcon size={24} />}
|
|
569
|
+
status={{ label: 'Podcast', variant: 'grey' }}
|
|
570
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
571
|
+
menuGroups={openMenu(HREF)}
|
|
572
|
+
menuAriaLabel="Podcast actions"
|
|
573
|
+
/>
|
|
574
|
+
<MingoInfoCard
|
|
575
|
+
title="Live: securing the MSP supply chain"
|
|
576
|
+
description="Jun 4, 2026 · 11:00 AM PT · 1h"
|
|
577
|
+
icon={<PresentationBarIcon size={24} />}
|
|
578
|
+
status={{ label: 'Webinar', variant: 'grey' }}
|
|
579
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
580
|
+
menuGroups={openMenu(HREF)}
|
|
581
|
+
menuAriaLabel="Webinar actions"
|
|
582
|
+
/>
|
|
583
|
+
<MingoInfoCard
|
|
584
|
+
title="OpenMSP meetup — Austin"
|
|
585
|
+
description="Jun 18, 2026 · Austin, TX"
|
|
586
|
+
icon={<CalendarIcon size={24} />}
|
|
587
|
+
status={{ label: 'Event', variant: 'grey' }}
|
|
588
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
589
|
+
menuGroups={openMenu(HREF)}
|
|
590
|
+
menuAriaLabel="Event actions"
|
|
591
|
+
/>
|
|
592
|
+
</div>
|
|
593
|
+
)
|
|
594
|
+
},
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// =============================================================================
|
|
598
|
+
// Investor update — presentation fallback · "Investor update" pill
|
|
599
|
+
// =============================================================================
|
|
600
|
+
|
|
601
|
+
export const InvestorUpdate: Story = {
|
|
602
|
+
render: () => {
|
|
603
|
+
const HREF = 'https://hub.flamingo.cx/investor-updates/2026-q1'
|
|
604
|
+
return (
|
|
605
|
+
<div className="flex flex-col gap-3">
|
|
606
|
+
<MingoInfoCard
|
|
607
|
+
title="Q1 2026 investor update"
|
|
608
|
+
description="118% NRR, $42M post-money, 14 months runway."
|
|
609
|
+
imageSrc="https://picsum.photos/seed/investor/80"
|
|
610
|
+
imageAlt="Q1 2026 investor update"
|
|
611
|
+
icon={<PresentationLineIcon size={24} />}
|
|
612
|
+
status={{ label: 'Investor update', variant: 'grey' }}
|
|
613
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
614
|
+
menuGroups={openMenu(HREF)}
|
|
615
|
+
menuAriaLabel="Update actions"
|
|
616
|
+
/>
|
|
617
|
+
<MingoInfoCard
|
|
618
|
+
title="Update #7"
|
|
619
|
+
description="Title-less row falls back to the update number."
|
|
620
|
+
icon={<PresentationLineIcon size={24} />}
|
|
621
|
+
status={{ label: 'Investor update', variant: 'grey' }}
|
|
622
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
623
|
+
menuGroups={openMenu(HREF)}
|
|
624
|
+
menuAriaLabel="Update actions"
|
|
625
|
+
/>
|
|
626
|
+
</div>
|
|
627
|
+
)
|
|
628
|
+
},
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// =============================================================================
|
|
632
|
+
// Onboarding guide — compass fallback · "Guide" pill
|
|
633
|
+
// =============================================================================
|
|
634
|
+
|
|
635
|
+
export const OnboardingGuide: Story = {
|
|
636
|
+
render: () => {
|
|
637
|
+
const HREF = 'https://hub.flamingo.cx/guides/first-device'
|
|
638
|
+
return (
|
|
639
|
+
<div className="flex flex-col gap-3">
|
|
640
|
+
<MingoInfoCard
|
|
641
|
+
title="Connect your first device"
|
|
642
|
+
description="A five-minute walkthrough from install to live telemetry."
|
|
643
|
+
imageSrc="https://picsum.photos/seed/guide/80"
|
|
644
|
+
imageAlt="Connect your first device"
|
|
645
|
+
icon={<CompassIcon size={24} />}
|
|
646
|
+
status={{ label: 'Guide', variant: 'grey' }}
|
|
647
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
648
|
+
menuGroups={openMenu(HREF)}
|
|
649
|
+
menuAriaLabel="Guide actions"
|
|
650
|
+
/>
|
|
651
|
+
</div>
|
|
652
|
+
)
|
|
653
|
+
},
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// =============================================================================
|
|
657
|
+
// Roadmap / delivery / task — per-type icon · coloured status pill · no image
|
|
658
|
+
// =============================================================================
|
|
659
|
+
|
|
660
|
+
export const Roadmap: Story = {
|
|
661
|
+
parameters: {
|
|
662
|
+
docs: {
|
|
663
|
+
description: {
|
|
664
|
+
story:
|
|
665
|
+
'Registry types `roadmap_item` / `delivery_item` / `internal_task`. Icon priority mirrors RoadmapCard: server integration logo (`item.icon`, shown contained) → task-type glyph → per-type default (map / truck / check-square). The status pill is coloured via the shared `getStatusColorScheme` mapping (done → green, in-progress → amber, blocked → red, other → grey).',
|
|
666
|
+
},
|
|
667
|
+
},
|
|
668
|
+
},
|
|
669
|
+
render: () => {
|
|
670
|
+
const HREF = 'https://hub.flamingo.cx/roadmap/RM-128'
|
|
671
|
+
return (
|
|
672
|
+
<div className="flex flex-col gap-3">
|
|
673
|
+
<MingoInfoCard
|
|
674
|
+
title="Per-tenant audit log export"
|
|
675
|
+
description="Server integration logo (e.g. ClickUp) shown contained in the box."
|
|
676
|
+
icon={
|
|
677
|
+
<img
|
|
678
|
+
src="https://picsum.photos/seed/clickuplogo/48"
|
|
679
|
+
alt=""
|
|
680
|
+
className="size-6 object-contain"
|
|
681
|
+
/>
|
|
682
|
+
}
|
|
683
|
+
status={{ label: 'In Progress', variant: 'warning' }}
|
|
684
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
685
|
+
menuGroups={openMenu(HREF)}
|
|
686
|
+
menuAriaLabel="Roadmap actions"
|
|
687
|
+
/>
|
|
688
|
+
<MingoInfoCard
|
|
689
|
+
title="Roadmap item with no logo — per-type default glyph"
|
|
690
|
+
description="Falls back to the map glyph when there's no server icon."
|
|
691
|
+
icon={<MapIcon size={24} />}
|
|
692
|
+
status={{ label: 'Planned', variant: 'grey' }}
|
|
693
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
694
|
+
menuGroups={openMenu(HREF)}
|
|
695
|
+
menuAriaLabel="Roadmap actions"
|
|
696
|
+
/>
|
|
697
|
+
<MingoInfoCard
|
|
698
|
+
title="Ship bulk device tagging"
|
|
699
|
+
description="Tag and filter devices in bulk from the fleet table."
|
|
700
|
+
icon={<TruckFastIcon size={24} />}
|
|
701
|
+
status={{ label: 'Done', variant: 'success' }}
|
|
702
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
703
|
+
menuGroups={openMenu(HREF)}
|
|
704
|
+
menuAriaLabel="Roadmap actions"
|
|
705
|
+
/>
|
|
706
|
+
<MingoInfoCard
|
|
707
|
+
title="Investigate flaky NATS reconnect"
|
|
708
|
+
description="Reconnect storm under network partition — needs a repro."
|
|
709
|
+
icon={<CheckSquareIcon size={24} />}
|
|
710
|
+
status={{ label: 'Blocked', variant: 'error' }}
|
|
711
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
712
|
+
menuGroups={openMenu(HREF)}
|
|
713
|
+
menuAriaLabel="Roadmap actions"
|
|
714
|
+
/>
|
|
715
|
+
</div>
|
|
716
|
+
)
|
|
717
|
+
},
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// =============================================================================
|
|
721
|
+
// Marketing campaign — megaphone icon · coloured status pill
|
|
722
|
+
// =============================================================================
|
|
723
|
+
|
|
724
|
+
export const MarketingCampaign: Story = {
|
|
725
|
+
render: () => {
|
|
726
|
+
const HREF = 'https://hub.flamingo.cx/admin/campaigns/c-91'
|
|
727
|
+
return (
|
|
728
|
+
<div className="flex flex-col gap-3">
|
|
729
|
+
<MingoInfoCard
|
|
730
|
+
title="Spring RMM migration push"
|
|
731
|
+
description="Apr 1, 2026 · 3 goals · Marketing campaign"
|
|
732
|
+
icon={<Megaphone01Icon size={24} />}
|
|
733
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
734
|
+
menuGroups={openMenu(HREF)}
|
|
735
|
+
menuAriaLabel="Campaign actions"
|
|
736
|
+
/>
|
|
737
|
+
<MingoInfoCard
|
|
738
|
+
title="Webinar promo — supply chain security"
|
|
739
|
+
description="May 20, 2026 · 1 goal · Marketing campaign"
|
|
740
|
+
icon={<Megaphone01Icon size={24} />}
|
|
741
|
+
anchorProps={makeAnchorProps(HREF)}
|
|
742
|
+
menuGroups={openMenu(HREF)}
|
|
743
|
+
menuAriaLabel="Campaign actions"
|
|
744
|
+
/>
|
|
745
|
+
</div>
|
|
746
|
+
)
|
|
747
|
+
},
|
|
748
|
+
}
|