@flamingo-stack/openframe-frontend-core 0.0.416 → 0.0.417-snapshot.20260712015802
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-RQLQOH46.cjs → chunk-5NV3BBFC.cjs} +37 -37
- package/dist/{chunk-RQLQOH46.cjs.map → chunk-5NV3BBFC.cjs.map} +1 -1
- package/dist/{chunk-D4NSPERU.cjs → chunk-6GUJGVPI.cjs} +26 -26
- package/dist/{chunk-D4NSPERU.cjs.map → chunk-6GUJGVPI.cjs.map} +1 -1
- package/dist/{chunk-CQ6MF7KT.js → chunk-7QDHNBLD.js} +4 -4
- package/dist/{chunk-SFZ2BJST.js → chunk-AU53RWCJ.js} +2 -2
- package/dist/{chunk-BIFZRCGN.cjs → chunk-AZGPEBKL.cjs} +31 -31
- package/dist/{chunk-BIFZRCGN.cjs.map → chunk-AZGPEBKL.cjs.map} +1 -1
- package/dist/{chunk-N6T7CDEN.js → chunk-BDXXP46V.js} +1469 -1396
- package/dist/chunk-BDXXP46V.js.map +1 -0
- package/dist/{chunk-FHAMKB5L.js → chunk-BFV2R5OA.js} +2 -2
- package/dist/{chunk-43AKGHDL.js → chunk-C6R2FRK6.js} +4 -4
- package/dist/{chunk-DQMH6NAF.cjs → chunk-CVG5QEWB.cjs} +15 -15
- package/dist/{chunk-DQMH6NAF.cjs.map → chunk-CVG5QEWB.cjs.map} +1 -1
- package/dist/{chunk-4AFA5N5Q.js → chunk-EBMGBZCB.js} +2 -2
- package/dist/{chunk-BGSIZWAK.js → chunk-FRDNZT33.js} +2 -2
- package/dist/{chunk-3F4LKYIK.cjs → chunk-HH6AJLPX.cjs} +7 -7
- package/dist/{chunk-3F4LKYIK.cjs.map → chunk-HH6AJLPX.cjs.map} +1 -1
- package/dist/{chunk-GEUZA4VP.js → chunk-MGFW2QXW.js} +2 -2
- package/dist/{chunk-CRPIHDEI.cjs → chunk-PPU67VJR.cjs} +9 -9
- package/dist/{chunk-CRPIHDEI.cjs.map → chunk-PPU67VJR.cjs.map} +1 -1
- package/dist/{chunk-IVWQIWZI.cjs → chunk-PUKSGYO5.cjs} +5 -5
- package/dist/{chunk-IVWQIWZI.cjs.map → chunk-PUKSGYO5.cjs.map} +1 -1
- package/dist/{chunk-234A5WF2.cjs → chunk-S6J3CLBD.cjs} +26 -26
- package/dist/{chunk-234A5WF2.cjs.map → chunk-S6J3CLBD.cjs.map} +1 -1
- package/dist/{chunk-3OSTXIB6.cjs → chunk-T35MGBXH.cjs} +59 -59
- package/dist/{chunk-3OSTXIB6.cjs.map → chunk-T35MGBXH.cjs.map} +1 -1
- package/dist/{chunk-GIHNDMGI.js → chunk-TLRWCDX6.js} +2 -2
- package/dist/{chunk-S3PO5NOK.cjs → chunk-VXOZXOOR.cjs} +442 -369
- package/dist/chunk-VXOZXOOR.cjs.map +1 -0
- package/dist/{chunk-3RW27WRK.js → chunk-WD3PDTQP.js} +2 -2
- package/dist/{chunk-CQG77HCB.cjs → chunk-XDJXRHGL.cjs} +11 -11
- package/dist/{chunk-CQG77HCB.cjs.map → chunk-XDJXRHGL.cjs.map} +1 -1
- package/dist/{chunk-QMGXJEZ3.cjs → chunk-XLBCOT73.cjs} +62 -62
- package/dist/{chunk-QMGXJEZ3.cjs.map → chunk-XLBCOT73.cjs.map} +1 -1
- package/dist/{chunk-VBJC75FT.js → chunk-ZNQ2QRQF.js} +4 -4
- package/dist/{chunk-QO2JZYIB.js → chunk-ZQTVLFS6.js} +4 -4
- package/dist/components/announcement-bar.d.ts.map +1 -1
- package/dist/components/case-studies/index.cjs +8 -8
- package/dist/components/case-studies/index.js +2 -2
- package/dist/components/chat/chat-panel-header-mobile.d.ts +8 -8
- package/dist/components/chat/chat-panel-header-mobile.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +2 -2
- package/dist/components/chat/index.js +1 -1
- package/dist/components/contact/index.cjs +3 -3
- package/dist/components/contact/index.js +2 -2
- package/dist/components/docs/index.cjs +5 -5
- package/dist/components/docs/index.js +4 -4
- package/dist/components/embeds/index.cjs +3 -3
- package/dist/components/embeds/index.js +2 -2
- package/dist/components/faq/index.cjs +3 -3
- package/dist/components/faq/index.js +2 -2
- package/dist/components/features/index.cjs +2 -2
- package/dist/components/features/index.js +1 -1
- package/dist/components/help-center-pages/index.cjs +20 -20
- package/dist/components/help-center-pages/index.js +11 -11
- package/dist/components/index.cjs +131 -129
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +12 -10
- package/dist/components/index.js.map +1 -1
- package/dist/components/navigation/header.d.ts.map +1 -1
- package/dist/components/navigation/index.cjs +4 -2
- package/dist/components/navigation/index.cjs.map +1 -1
- package/dist/components/navigation/index.d.ts +2 -0
- package/dist/components/navigation/index.d.ts.map +1 -1
- package/dist/components/navigation/index.js +3 -1
- package/dist/components/navigation/mingo-ai-button.d.ts +16 -0
- package/dist/components/navigation/mingo-ai-button.d.ts.map +1 -0
- package/dist/components/onboarding-guides/index.cjs +5 -5
- package/dist/components/onboarding-guides/index.js +4 -4
- package/dist/components/related-content/index.cjs +3 -3
- package/dist/components/related-content/index.js +2 -2
- package/dist/components/tickets/index.cjs +5 -5
- package/dist/components/tickets/index.js +4 -4
- package/dist/components/ui/index.cjs +2 -2
- package/dist/components/ui/index.js +1 -1
- package/dist/index.cjs +4 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -1
- package/dist/types/navigation.d.ts +12 -0
- package/dist/types/navigation.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/announcement-bar.tsx +5 -1
- package/src/components/chat/chat-panel-header-mobile.tsx +21 -8
- package/src/components/chat/embeddable-chat.tsx +13 -0
- package/src/components/navigation/header.tsx +25 -10
- package/src/components/navigation/index.ts +3 -0
- package/src/components/navigation/mingo-ai-button.tsx +96 -0
- package/src/stories/Header.stories.tsx +28 -0
- package/src/stories/MingoAiButton.stories.tsx +46 -0
- package/src/styles/chat-animations.css +66 -0
- package/src/types/navigation.ts +12 -0
- package/dist/chunk-N6T7CDEN.js.map +0 -1
- package/dist/chunk-S3PO5NOK.cjs.map +0 -1
- /package/dist/{chunk-CQ6MF7KT.js.map → chunk-7QDHNBLD.js.map} +0 -0
- /package/dist/{chunk-SFZ2BJST.js.map → chunk-AU53RWCJ.js.map} +0 -0
- /package/dist/{chunk-FHAMKB5L.js.map → chunk-BFV2R5OA.js.map} +0 -0
- /package/dist/{chunk-43AKGHDL.js.map → chunk-C6R2FRK6.js.map} +0 -0
- /package/dist/{chunk-4AFA5N5Q.js.map → chunk-EBMGBZCB.js.map} +0 -0
- /package/dist/{chunk-BGSIZWAK.js.map → chunk-FRDNZT33.js.map} +0 -0
- /package/dist/{chunk-GEUZA4VP.js.map → chunk-MGFW2QXW.js.map} +0 -0
- /package/dist/{chunk-GIHNDMGI.js.map → chunk-TLRWCDX6.js.map} +0 -0
- /package/dist/{chunk-3RW27WRK.js.map → chunk-WD3PDTQP.js.map} +0 -0
- /package/dist/{chunk-VBJC75FT.js.map → chunk-ZNQ2QRQF.js.map} +0 -0
- /package/dist/{chunk-QO2JZYIB.js.map → chunk-ZQTVLFS6.js.map} +0 -0
|
@@ -7,6 +7,7 @@ import { cn } from '../../utils'
|
|
|
7
7
|
import { Button } from '../ui/button'
|
|
8
8
|
import { Menu01Icon } from '../icons-v2-generated'
|
|
9
9
|
import { MOBILE_NAV_PANEL_ID } from './mobile-nav-panel'
|
|
10
|
+
import { MingoAiButton } from './mingo-ai-button'
|
|
10
11
|
|
|
11
12
|
export interface HeaderProps {
|
|
12
13
|
config: HeaderConfig
|
|
@@ -273,9 +274,12 @@ export function Header({ config, platform }: HeaderProps) {
|
|
|
273
274
|
>
|
|
274
275
|
<header
|
|
275
276
|
className={cn(
|
|
276
|
-
|
|
277
|
+
// 72px = unified-header spec height (Figma 4033-90260); the right
|
|
278
|
+
// cluster self-stretches so the Mingo launcher can sit flush.
|
|
279
|
+
"w-full h-[72px] flex items-center justify-between",
|
|
277
280
|
"border-b border-ods-border backdrop-blur-sm",
|
|
278
|
-
"
|
|
281
|
+
"pl-6",
|
|
282
|
+
!config.mingo?.enabled && "pr-6",
|
|
279
283
|
// Background color (configurable via backgroundColor prop)
|
|
280
284
|
config.backgroundColor || "bg-ods-card",
|
|
281
285
|
config.className
|
|
@@ -297,13 +301,13 @@ export function Header({ config, platform }: HeaderProps) {
|
|
|
297
301
|
|
|
298
302
|
{/* Center: Navigation */}
|
|
299
303
|
{config.navigation && config.navigation.items.length > 0 && (
|
|
300
|
-
<nav
|
|
304
|
+
<nav
|
|
301
305
|
className={cn(
|
|
302
|
-
"hidden
|
|
306
|
+
"hidden lg:flex items-center gap-2",
|
|
303
307
|
config.navigation.position === 'center' && "absolute left-1/2 transform -translate-x-1/2",
|
|
304
308
|
config.navigation.position === 'right' && "ml-auto mr-4"
|
|
305
309
|
)}
|
|
306
|
-
role="navigation"
|
|
310
|
+
role="navigation"
|
|
307
311
|
aria-label="Main navigation"
|
|
308
312
|
>
|
|
309
313
|
{config.navigation.items.map(renderNavigationItem)}
|
|
@@ -311,20 +315,27 @@ export function Header({ config, platform }: HeaderProps) {
|
|
|
311
315
|
)}
|
|
312
316
|
|
|
313
317
|
{/* Right: Actions */}
|
|
314
|
-
<div className="flex items-center justify-end gap-
|
|
315
|
-
{/* Desktop Actions
|
|
318
|
+
<div className="flex items-center justify-end gap-3 flex-shrink-0 self-stretch">
|
|
319
|
+
{/* Desktop Actions — banded with the nav/burger breakpoint (lg) so the
|
|
320
|
+
desktop right-cluster and the mobile toggle never co-show. */}
|
|
316
321
|
{config.actions?.right && (
|
|
317
|
-
<div className="hidden
|
|
322
|
+
<div className="hidden lg:flex items-center gap-3">
|
|
318
323
|
{config.actions.right}
|
|
319
324
|
</div>
|
|
320
325
|
)}
|
|
321
326
|
|
|
327
|
+
{config.actions?.persistent && config.actions.persistent.length > 0 && (
|
|
328
|
+
<div className="flex items-center">
|
|
329
|
+
{config.actions.persistent}
|
|
330
|
+
</div>
|
|
331
|
+
)}
|
|
332
|
+
|
|
322
333
|
{/* Mobile Menu Toggle */}
|
|
323
334
|
{config.mobile && config.mobile.enabled && (
|
|
324
335
|
<Button
|
|
325
|
-
variant="
|
|
336
|
+
variant="outline"
|
|
326
337
|
size="icon"
|
|
327
|
-
className="flex
|
|
338
|
+
className="flex lg:hidden"
|
|
328
339
|
onClick={() => {
|
|
329
340
|
config.mobile?.onToggle?.()
|
|
330
341
|
}}
|
|
@@ -336,6 +347,10 @@ export function Header({ config, platform }: HeaderProps) {
|
|
|
336
347
|
leftIcon={config.mobile?.menuIcon || <Menu01Icon />}
|
|
337
348
|
/>
|
|
338
349
|
)}
|
|
350
|
+
|
|
351
|
+
{config.mingo?.enabled && (
|
|
352
|
+
<MingoAiButton source={config.mingo.source} icon={config.mingo.icon} label={config.mingo.label} className={config.mingo.className} />
|
|
353
|
+
)}
|
|
339
354
|
</div>
|
|
340
355
|
</header>
|
|
341
356
|
</div>
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
export { Header } from './header'
|
|
5
5
|
export type { HeaderConfig, HeaderProps } from './header'
|
|
6
6
|
|
|
7
|
+
export { MingoAiButton } from './mingo-ai-button'
|
|
8
|
+
export type { MingoAiButtonProps } from './mingo-ai-button'
|
|
9
|
+
|
|
7
10
|
export { ClientOnlyHeader } from './client-only-header'
|
|
8
11
|
export type { ClientOnlyHeaderProps } from './client-only-header'
|
|
9
12
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { MingoIcon } from '../icons'
|
|
5
|
+
import { cn } from '../../utils'
|
|
6
|
+
|
|
7
|
+
export interface MingoAiButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
8
|
+
source?: string
|
|
9
|
+
/** The platform's Mingo identity glyph — pass the SAME server-configured
|
|
10
|
+
* icon the chat panel renders (host-side: `EntityIcon` fed by the admin
|
|
11
|
+
* `assistantIcon`), so the launcher and the panel can never diverge.
|
|
12
|
+
* Falls back to the packaged Mingo mark when the server has none. */
|
|
13
|
+
icon?: React.ReactNode
|
|
14
|
+
/** The launcher's wordmark + aria-label — pass the server-configured
|
|
15
|
+
* assistant name (same `assistantName` the chat panel shows) so the
|
|
16
|
+
* launcher never hardcodes an identity the admin has renamed. */
|
|
17
|
+
label?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Marketing-header Mingo AI launcher: the flush, full-height button rendered
|
|
22
|
+
* at the far right edge of the public `Header` (`config.mingo`). Stateless:
|
|
23
|
+
* clicking dispatches an `ask-ai:open` CustomEvent (source-filtered) that the
|
|
24
|
+
* mounted `EmbeddableChat` panel listens for.
|
|
25
|
+
*
|
|
26
|
+
* Distinct from `header-mingo-button.tsx` (`HeaderMingoButton`), the
|
|
27
|
+
* dashboard/AppHeader controlled toggle; different surface and contract, do
|
|
28
|
+
* not merge them.
|
|
29
|
+
*
|
|
30
|
+
* Deliberately a raw `<button>` rather than the ui-kit `Button`: it needs
|
|
31
|
+
* full-height flush layout, an absolutely-positioned glow child, and icon-only
|
|
32
|
+
* collapse that `Button` cannot express (same precedent as
|
|
33
|
+
* `header-mingo-button.tsx`).
|
|
34
|
+
*/
|
|
35
|
+
const MINGO_ACCENT = 'var(--ods-flamingo-cyan-base)'
|
|
36
|
+
|
|
37
|
+
export function MingoAiButton({ source, icon, label = 'Mingo AI', className, onClick, ...props }: MingoAiButtonProps) {
|
|
38
|
+
return (
|
|
39
|
+
<button
|
|
40
|
+
{...props}
|
|
41
|
+
type="button"
|
|
42
|
+
aria-label={label}
|
|
43
|
+
onClick={(e) => {
|
|
44
|
+
// Coalesce to '' so a source-less mount still matches EmbeddableChat's
|
|
45
|
+
// own `runtime.source ?? ''` comparison (undefined !== '' would make
|
|
46
|
+
// the panel silently ignore the event).
|
|
47
|
+
window.dispatchEvent(new CustomEvent('ask-ai:open', { detail: { source: source ?? '' } }))
|
|
48
|
+
onClick?.(e)
|
|
49
|
+
}}
|
|
50
|
+
className={cn(
|
|
51
|
+
// `--spacing-system-l` is itself responsive (16px, 24px from 800px):
|
|
52
|
+
// the compact mobile padding keeps the 375px header row
|
|
53
|
+
// (logo + CTA + burger + Mingo) inside one viewport per Figma
|
|
54
|
+
// 3924-35639 (mobile) / 4033-90260 (desktop).
|
|
55
|
+
'group/mingo relative flex h-full items-center border-l border-ods-border bg-transparent px-[var(--spacing-system-l)] transition-colors duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-ods-accent',
|
|
56
|
+
className,
|
|
57
|
+
)}
|
|
58
|
+
>
|
|
59
|
+
{/* Inner box = 1:1 twin of the ui-kit Button geometry the header CTA
|
|
60
|
+
uses (rounded-md, h-10 md:h-12, px m) so the animated ring traces
|
|
61
|
+
EXACTLY where a normal button border would sit. */}
|
|
62
|
+
<span className="relative flex h-10 items-center gap-[var(--spacing-system-s)] rounded-md px-[var(--spacing-system-m)] md:h-12">
|
|
63
|
+
{/* AI edge light (Apple-Intelligence-style): a rotating accent-
|
|
64
|
+
gradient arc clipped to a 3px ring on the Button-shaped outline
|
|
65
|
+
via CSS mask (.mingo-edge-frame) — NO opaque cover, so the
|
|
66
|
+
launcher inherits whatever background sits behind it. Platform-
|
|
67
|
+
tinted via the accent token. */}
|
|
68
|
+
<span aria-hidden="true" className="mingo-edge-frame pointer-events-none absolute inset-0 rounded-md">
|
|
69
|
+
<span className="mingo-edge" />
|
|
70
|
+
</span>
|
|
71
|
+
{/* One-shot light-streak shimmer on hover, clipped to the box. */}
|
|
72
|
+
<span aria-hidden="true" className="pointer-events-none absolute inset-0 overflow-hidden rounded-md">
|
|
73
|
+
<span
|
|
74
|
+
className="mingo-shimmer absolute inset-y-0 left-0 w-1/2"
|
|
75
|
+
style={{ background: 'linear-gradient(105deg, transparent, color-mix(in srgb, var(--ods-system-greys-white) 12%, transparent), transparent)' }}
|
|
76
|
+
/>
|
|
77
|
+
</span>
|
|
78
|
+
{icon ? (
|
|
79
|
+
<span className="relative inline-flex size-6 shrink-0 items-center justify-center">{icon}</span>
|
|
80
|
+
) : (
|
|
81
|
+
<MingoIcon
|
|
82
|
+
color="currentColor"
|
|
83
|
+
eyesColor={MINGO_ACCENT}
|
|
84
|
+
cornerColor={MINGO_ACCENT}
|
|
85
|
+
className="relative h-6 w-6 shrink-0 text-ods-text-primary"
|
|
86
|
+
/>
|
|
87
|
+
)}
|
|
88
|
+
<span className="relative hidden whitespace-nowrap text-h3 font-bold tracking-[-0.36px] text-ods-text-primary md:inline">
|
|
89
|
+
{label}
|
|
90
|
+
</span>
|
|
91
|
+
</span>
|
|
92
|
+
</button>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default MingoAiButton
|
|
@@ -197,3 +197,31 @@ export const FixedHeader: Story = {
|
|
|
197
197
|
} satisfies HeaderConfig,
|
|
198
198
|
},
|
|
199
199
|
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Header with the Mingo AI launcher enabled via `config.mingo`. `MingoAiButton`
|
|
203
|
+
* renders after the mobile toggle, so below `lg` the right cluster reads
|
|
204
|
+
* `Try for Free | hamburger | Mingo AI`; at `lg+` the hamburger is hidden and it
|
|
205
|
+
* collapses to `Try for Free | Mingo AI`, with Mingo full-height and flush to the
|
|
206
|
+
* right edge (its left border acts as the divider). Resize under 800px to see the
|
|
207
|
+
* Mingo label collapse to icon-only. Clicking it dispatches an `ask-ai:open` event.
|
|
208
|
+
*/
|
|
209
|
+
export const WithMingoAi: Story = {
|
|
210
|
+
args: {
|
|
211
|
+
config: {
|
|
212
|
+
logo: { element: flamingoLogo, href: '/' },
|
|
213
|
+
navigation: baseNavigation,
|
|
214
|
+
actions: {
|
|
215
|
+
persistent: [
|
|
216
|
+
<Button key="cta" variant="accent" href="/signup">
|
|
217
|
+
Try for Free
|
|
218
|
+
</Button>,
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
autoHide: false,
|
|
222
|
+
mobile: { enabled: true, onToggle: fn() },
|
|
223
|
+
mingo: { enabled: true, source: 'flamingo' },
|
|
224
|
+
className: 'px-0',
|
|
225
|
+
} satisfies HeaderConfig,
|
|
226
|
+
},
|
|
227
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
|
2
|
+
import { MingoAiButton } from '../components/navigation/mingo-ai-button'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Marketing-header Mingo AI launcher. Full-height and flush inside the 72px
|
|
6
|
+
* unified header: the decorator reproduces that context so the left border
|
|
7
|
+
* divider and traveling accent edge light render as they do in `Header` (`config.mingo`).
|
|
8
|
+
* The "Mingo AI" label hides below `md` (icon-only, see IconOnly).
|
|
9
|
+
*/
|
|
10
|
+
const meta = {
|
|
11
|
+
title: 'Navigation/MingoAiButton',
|
|
12
|
+
component: MingoAiButton,
|
|
13
|
+
parameters: {
|
|
14
|
+
layout: 'centered',
|
|
15
|
+
},
|
|
16
|
+
tags: ['autodocs'],
|
|
17
|
+
argTypes: {
|
|
18
|
+
source: { control: 'text' },
|
|
19
|
+
},
|
|
20
|
+
decorators: [
|
|
21
|
+
(Story) => (
|
|
22
|
+
<div className="flex h-[72px] items-center justify-end border-b border-ods-border bg-ods-card w-[360px]">
|
|
23
|
+
<Story />
|
|
24
|
+
</div>
|
|
25
|
+
),
|
|
26
|
+
],
|
|
27
|
+
} satisfies Meta<typeof MingoAiButton>
|
|
28
|
+
|
|
29
|
+
export default meta
|
|
30
|
+
type Story = StoryObj<typeof meta>
|
|
31
|
+
|
|
32
|
+
export const Default: Story = {
|
|
33
|
+
args: {
|
|
34
|
+
source: 'flamingo',
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Below `md` the wordmark is hidden and only the Mingo icon shows. */
|
|
39
|
+
export const IconOnly: Story = {
|
|
40
|
+
args: {
|
|
41
|
+
source: 'flamingo',
|
|
42
|
+
},
|
|
43
|
+
parameters: {
|
|
44
|
+
viewport: { defaultViewport: 'mobile1' },
|
|
45
|
+
},
|
|
46
|
+
}
|
|
@@ -63,3 +63,69 @@
|
|
|
63
63
|
.mingo-chat-content[data-state="open"] { animation-name: mingo-chat-slide-in-right; }
|
|
64
64
|
.mingo-chat-content[data-state="closed"] { animation-name: mingo-chat-slide-out-right; }
|
|
65
65
|
}
|
|
66
|
+
|
|
67
|
+
/* =============================================================================
|
|
68
|
+
* Mingo AI header button — the 2026 AI edge-light pattern (Apple Intelligence
|
|
69
|
+
* glow-edge / Gemini gradient language): a thin accent-gradient arc TRAVELS
|
|
70
|
+
* around the button's border. No blurry blobs. Transform-only rotation on an
|
|
71
|
+
* oversized conic layer (compositor-friendly); an inset cover reveals only
|
|
72
|
+
* the edge. Reduced motion: rotation stops → a static gradient edge (the
|
|
73
|
+
* colorful state survives, only motion is removed). Hover adds a one-shot
|
|
74
|
+
* light-streak shimmer.
|
|
75
|
+
* ---------------------------------------------------------------------------*/
|
|
76
|
+
@keyframes mingo-edge-spin {
|
|
77
|
+
from { transform: translate(-50%, -50%) rotate(0deg); }
|
|
78
|
+
to { transform: translate(-50%, -50%) rotate(360deg); }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Ring mask: clips the rotating conic layer to a 3px band along the frame's
|
|
82
|
+
rounded outline (padding-box XOR), so the interior stays fully transparent
|
|
83
|
+
and the host background shows through — no opaque cover element. */
|
|
84
|
+
.mingo-edge-frame {
|
|
85
|
+
overflow: hidden;
|
|
86
|
+
padding: 3px;
|
|
87
|
+
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
|
88
|
+
-webkit-mask-composite: xor;
|
|
89
|
+
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
|
90
|
+
mask-composite: exclude;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.mingo-edge {
|
|
94
|
+
position: absolute;
|
|
95
|
+
left: 50%;
|
|
96
|
+
top: 50%;
|
|
97
|
+
width: 300%;
|
|
98
|
+
aspect-ratio: 1;
|
|
99
|
+
transform: translate(-50%, -50%);
|
|
100
|
+
/* Single luminous accent arc with a soft tail — platform-tinted via the
|
|
101
|
+
RAW --color-* accent var (the --ods-* alias does not exist in raw CSS). */
|
|
102
|
+
background: conic-gradient(
|
|
103
|
+
from 0deg,
|
|
104
|
+
transparent 0deg,
|
|
105
|
+
color-mix(in srgb, var(--color-accent-primary) 40%, transparent) 50deg,
|
|
106
|
+
var(--color-accent-primary) 90deg,
|
|
107
|
+
color-mix(in srgb, var(--color-accent-primary) 45%, white) 105deg,
|
|
108
|
+
transparent 160deg
|
|
109
|
+
);
|
|
110
|
+
animation: mingo-edge-spin 4s linear infinite;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@keyframes mingo-shimmer {
|
|
114
|
+
from { transform: translateX(-160%) skewX(-18deg); }
|
|
115
|
+
to { transform: translateX(260%) skewX(-18deg); }
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.mingo-shimmer {
|
|
119
|
+
opacity: 0;
|
|
120
|
+
transform: translateX(-160%) skewX(-18deg);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.group\/mingo:hover .mingo-shimmer {
|
|
124
|
+
opacity: 1;
|
|
125
|
+
animation: mingo-shimmer 0.9s ease-out;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@media (prefers-reduced-motion: reduce) {
|
|
129
|
+
.mingo-edge { animation: none; }
|
|
130
|
+
.group\/mingo:hover .mingo-shimmer { animation: none; opacity: 0; }
|
|
131
|
+
}
|
package/src/types/navigation.ts
CHANGED
|
@@ -36,6 +36,7 @@ export interface HeaderConfig {
|
|
|
36
36
|
actions?: {
|
|
37
37
|
left?: React.ReactNode[]
|
|
38
38
|
right?: React.ReactNode[]
|
|
39
|
+
persistent?: React.ReactNode[]
|
|
39
40
|
}
|
|
40
41
|
mobile?: {
|
|
41
42
|
enabled: boolean
|
|
@@ -44,6 +45,17 @@ export interface HeaderConfig {
|
|
|
44
45
|
onToggle?: () => void
|
|
45
46
|
isOpen?: boolean
|
|
46
47
|
}
|
|
48
|
+
mingo?: {
|
|
49
|
+
enabled?: boolean
|
|
50
|
+
source?: string
|
|
51
|
+
className?: string
|
|
52
|
+
/** Server-configured Mingo identity glyph (same EntityIcon the chat
|
|
53
|
+
* panel renders); omit to use the packaged fallback mark. */
|
|
54
|
+
icon?: React.ReactNode
|
|
55
|
+
/** Server-configured assistant name for the wordmark/aria-label; omit
|
|
56
|
+
* for the default "Mingo AI". */
|
|
57
|
+
label?: string
|
|
58
|
+
}
|
|
47
59
|
className?: string
|
|
48
60
|
style?: React.CSSProperties
|
|
49
61
|
autoHide?: boolean
|