@flamingo-stack/openframe-frontend-core 0.0.438-snapshot.20260716203356 → 0.0.438
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-HTVVXVJL.cjs → chunk-2DCP2TIF.cjs} +1490 -1966
- package/dist/chunk-2DCP2TIF.cjs.map +1 -0
- package/dist/{chunk-PBTY7AH5.js → chunk-44HNH57W.js} +4 -4
- package/dist/{chunk-G5FALXNO.js → chunk-5D5SJOLE.js} +4 -4
- package/dist/{chunk-NQQ4NLUT.js → chunk-6ETVJ5ON.js} +6101 -6577
- package/dist/chunk-6ETVJ5ON.js.map +1 -0
- package/dist/{chunk-3WJQL4DN.cjs → chunk-6R5SZPAQ.cjs} +15 -15
- package/dist/{chunk-3WJQL4DN.cjs.map → chunk-6R5SZPAQ.cjs.map} +1 -1
- package/dist/{chunk-P7PISHM5.js → chunk-A25RPWYF.js} +2 -2
- package/dist/{chunk-AUJXLVXA.cjs → chunk-B5SGPIJ4.cjs} +37 -37
- package/dist/{chunk-AUJXLVXA.cjs.map → chunk-B5SGPIJ4.cjs.map} +1 -1
- package/dist/{chunk-VWGF6IFR.cjs → chunk-CMP56RUC.cjs} +62 -62
- package/dist/{chunk-VWGF6IFR.cjs.map → chunk-CMP56RUC.cjs.map} +1 -1
- package/dist/{chunk-F7YVI54P.js → chunk-D5RTZ2WN.js} +4 -4
- package/dist/{chunk-R46QEE3R.cjs → chunk-DTYPYYKD.cjs} +59 -59
- package/dist/{chunk-R46QEE3R.cjs.map → chunk-DTYPYYKD.cjs.map} +1 -1
- package/dist/{chunk-RQQZF6G6.cjs → chunk-H2TQ44VD.cjs} +31 -31
- package/dist/{chunk-RQQZF6G6.cjs.map → chunk-H2TQ44VD.cjs.map} +1 -1
- package/dist/{chunk-7WM77CSW.js → chunk-KBFQF4AV.js} +2 -2
- package/dist/{chunk-2ELBNZJ3.js → chunk-LR6A67KZ.js} +2 -2
- package/dist/{chunk-ZMUFTGL7.cjs → chunk-PCMDRDYX.cjs} +5 -5
- package/dist/{chunk-ZMUFTGL7.cjs.map → chunk-PCMDRDYX.cjs.map} +1 -1
- package/dist/{chunk-WAGTZVQN.js → chunk-POFDZH2C.js} +4 -4
- package/dist/{chunk-EGRZHR7J.js → chunk-RTHOCS3S.js} +2 -2
- package/dist/{chunk-M3LD6DNE.cjs → chunk-SYTL2VIU.cjs} +7 -7
- package/dist/{chunk-M3LD6DNE.cjs.map → chunk-SYTL2VIU.cjs.map} +1 -1
- package/dist/{chunk-WZ6TCAYQ.cjs → chunk-VYG2CJFJ.cjs} +9 -9
- package/dist/{chunk-WZ6TCAYQ.cjs.map → chunk-VYG2CJFJ.cjs.map} +1 -1
- package/dist/{chunk-COMBYYQY.js → chunk-W2PRXXUD.js} +2 -2
- package/dist/{chunk-IAN7GUIV.cjs → chunk-WF7VGEYR.cjs} +26 -26
- package/dist/{chunk-IAN7GUIV.cjs.map → chunk-WF7VGEYR.cjs.map} +1 -1
- package/dist/{chunk-C3FH53AP.cjs → chunk-X66KRL5G.cjs} +11 -11
- package/dist/{chunk-C3FH53AP.cjs.map → chunk-X66KRL5G.cjs.map} +1 -1
- package/dist/{chunk-WPVBTVI3.js → chunk-XFSDFO6U.js} +2 -2
- package/dist/{chunk-M6QGB6DC.cjs → chunk-YKP2F2NC.cjs} +26 -26
- package/dist/{chunk-M6QGB6DC.cjs.map → chunk-YKP2F2NC.cjs.map} +1 -1
- package/dist/{chunk-PEIR7D25.js → chunk-ZEY7A3MP.js} +2 -2
- package/dist/components/case-studies/index.cjs +8 -8
- package/dist/components/case-studies/index.js +2 -2
- package/dist/components/chat/chat-archive-page.d.ts +8 -28
- package/dist/components/chat/chat-archive-page.d.ts.map +1 -1
- package/dist/components/chat/chat-header-icon-button.d.ts +2 -6
- package/dist/components/chat/chat-header-icon-button.d.ts.map +1 -1
- package/dist/components/chat/chat-panel-header.d.ts +9 -19
- package/dist/components/chat/chat-panel-header.d.ts.map +1 -1
- package/dist/components/chat/embeddable-chat.d.ts +6 -15
- package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-chat-dialog-manager.d.ts +0 -2
- package/dist/components/chat/hooks/use-chat-dialog-manager.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +2 -4
- package/dist/components/chat/index.cjs.map +1 -1
- package/dist/components/chat/index.d.ts +0 -2
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +3 -5
- package/dist/components/chat/mingo-chat-history.d.ts +10 -5
- package/dist/components/chat/mingo-chat-history.d.ts.map +1 -1
- package/dist/components/chat/mingo-welcome.d.ts +25 -6
- package/dist/components/chat/mingo-welcome.d.ts.map +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 +128 -130
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +11 -13
- package/dist/components/index.js.map +1 -1
- package/dist/components/navigation/index.cjs +2 -2
- package/dist/components/navigation/index.js +1 -1
- 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 -4
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.js +3 -5
- package/dist/index.cjs +2 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -5
- package/package.json +1 -1
- package/src/components/chat/chat-archive-page.tsx +73 -89
- package/src/components/chat/chat-header-icon-button.tsx +5 -12
- package/src/components/chat/chat-panel-header.tsx +29 -76
- package/src/components/chat/embeddable-chat.tsx +125 -548
- package/src/components/chat/guide-welcome.tsx +4 -4
- package/src/components/chat/hooks/use-chat-dialog-manager.ts +5 -59
- package/src/components/chat/index.ts +0 -2
- package/src/components/chat/mingo-chat-history.tsx +100 -46
- package/src/components/chat/mingo-welcome.tsx +98 -17
- package/src/stories/MingoWelcome.stories.tsx +11 -2
- package/dist/chunk-HTVVXVJL.cjs.map +0 -1
- package/dist/chunk-NQQ4NLUT.js.map +0 -1
- package/dist/components/chat/chat-header-search-field.d.ts +0 -25
- package/dist/components/chat/chat-header-search-field.d.ts.map +0 -1
- package/dist/components/chat/chat-list-empty-state.d.ts +0 -20
- package/dist/components/chat/chat-list-empty-state.d.ts.map +0 -1
- package/dist/components/chat/mingo-history-rail.d.ts +0 -54
- package/dist/components/chat/mingo-history-rail.d.ts.map +0 -1
- package/src/components/chat/chat-header-search-field.tsx +0 -144
- package/src/components/chat/chat-list-empty-state.tsx +0 -44
- package/src/components/chat/mingo-history-rail.tsx +0 -161
- /package/dist/{chunk-PBTY7AH5.js.map → chunk-44HNH57W.js.map} +0 -0
- /package/dist/{chunk-G5FALXNO.js.map → chunk-5D5SJOLE.js.map} +0 -0
- /package/dist/{chunk-P7PISHM5.js.map → chunk-A25RPWYF.js.map} +0 -0
- /package/dist/{chunk-F7YVI54P.js.map → chunk-D5RTZ2WN.js.map} +0 -0
- /package/dist/{chunk-7WM77CSW.js.map → chunk-KBFQF4AV.js.map} +0 -0
- /package/dist/{chunk-2ELBNZJ3.js.map → chunk-LR6A67KZ.js.map} +0 -0
- /package/dist/{chunk-WAGTZVQN.js.map → chunk-POFDZH2C.js.map} +0 -0
- /package/dist/{chunk-EGRZHR7J.js.map → chunk-RTHOCS3S.js.map} +0 -0
- /package/dist/{chunk-COMBYYQY.js.map → chunk-W2PRXXUD.js.map} +0 -0
- /package/dist/{chunk-WPVBTVI3.js.map → chunk-XFSDFO6U.js.map} +0 -0
- /package/dist/{chunk-PEIR7D25.js.map → chunk-ZEY7A3MP.js.map} +0 -0
|
@@ -4,102 +4,75 @@ import * as React from 'react'
|
|
|
4
4
|
import { Chevron02LeftIcon, BoxArchiveIcon } from '../icons-v2-generated'
|
|
5
5
|
import { XmarkIcon } from '../icons-v2-generated/signs-and-symbols/xmark-icon'
|
|
6
6
|
import { ChatHeaderIconButton } from './chat-header-icon-button'
|
|
7
|
+
import { COMPACT_HEADER_BUTTON } from './chat-panel-header'
|
|
7
8
|
import { ChatPanelHeaderMobile } from './chat-panel-header-mobile'
|
|
8
|
-
import { MingoChatHistory
|
|
9
|
-
import { ChatListEmptyState } from './chat-list-empty-state'
|
|
9
|
+
import { MingoChatHistory } from './mingo-chat-history'
|
|
10
10
|
import type { DialogItem } from './types/component.types'
|
|
11
11
|
|
|
12
|
-
interface
|
|
12
|
+
export interface ChatArchivePageProps {
|
|
13
13
|
/** Archived dialogs, grouped (Today / Yesterday / Older) by the list. */
|
|
14
14
|
dialogs: ReadonlyArray<DialogItem>
|
|
15
15
|
/** Open an archived dialog. */
|
|
16
16
|
onSelectDialog: (id: string) => void
|
|
17
|
-
/**
|
|
17
|
+
/** Back chevron — returns to the previous (list) view. */
|
|
18
|
+
onBack: () => void
|
|
19
|
+
/** Close the whole chat panel. */
|
|
20
|
+
onClose: () => void
|
|
21
|
+
/** True while a page is loading (drives the empty/loading copy + spinner). */
|
|
18
22
|
isLoading?: boolean
|
|
19
|
-
/** A first-page load is in flight but the delayed skeleton hasn't appeared
|
|
20
|
-
* yet — keeps the empty state suppressed so it never flashes before the
|
|
21
|
-
* skeleton/data arrives. */
|
|
22
|
-
isFetching?: boolean
|
|
23
23
|
/** Whether another page of archived dialogs remains. */
|
|
24
24
|
hasMore?: boolean
|
|
25
25
|
/** Fetch the next page. */
|
|
26
26
|
onLoadMore?: () => void
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
/** Standalone (default): renders its own back/close header, so BOTH handlers
|
|
30
|
-
* are required. */
|
|
31
|
-
export interface ChatArchivePageStandaloneProps extends ChatArchivePageBaseProps {
|
|
32
|
-
embedded?: false
|
|
33
|
-
/** Back chevron — returns to the previous (list) view. */
|
|
34
|
-
onBack: () => void
|
|
35
|
-
/** Close the whole chat panel. */
|
|
36
|
-
onClose: () => void
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** Embedded (wide split layout): the archive lives in the left rail and the
|
|
40
|
-
* host header already provides the "Chat Archive" back + close controls, so
|
|
41
|
-
* the built-in header — and its handlers — are dropped. */
|
|
42
|
-
export interface ChatArchivePageEmbeddedProps extends ChatArchivePageBaseProps {
|
|
43
|
-
embedded: true
|
|
44
|
-
onBack?: never
|
|
45
|
-
onClose?: never
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export type ChatArchivePageProps =
|
|
49
|
-
| ChatArchivePageStandaloneProps
|
|
50
|
-
| ChatArchivePageEmbeddedProps
|
|
51
|
-
|
|
52
29
|
/**
|
|
53
30
|
* Chat Archive page — Figma node `7361:427312`. Back + title + close header
|
|
54
31
|
* over the date-grouped archived-dialog list (reuses `MingoChatHistory`
|
|
55
|
-
* without the row action menus).
|
|
56
|
-
* the list can slot into the split layout's left rail.
|
|
32
|
+
* without the row action menus).
|
|
57
33
|
*/
|
|
58
|
-
export function ChatArchivePage(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
34
|
+
export function ChatArchivePage({
|
|
35
|
+
dialogs,
|
|
36
|
+
onSelectDialog,
|
|
37
|
+
onBack,
|
|
38
|
+
onClose,
|
|
39
|
+
isLoading = false,
|
|
40
|
+
hasMore = false,
|
|
41
|
+
onLoadMore,
|
|
42
|
+
}: ChatArchivePageProps) {
|
|
67
43
|
return (
|
|
68
44
|
<>
|
|
69
45
|
{/* Mobile (<md): the shared mobile header — back to the list + a ⋯ menu
|
|
70
|
-
(Close only here, since the archive list has no per-chat actions).
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
onBack={props.onBack}
|
|
80
|
-
onClose={props.onClose}
|
|
81
|
-
/>
|
|
82
|
-
)}
|
|
83
|
-
|
|
84
|
-
{/* Desktop (md+): fixed-height bar with full-height divider action cells —
|
|
85
|
-
the back chevron is a leading `ChatHeaderIconButton` cell matching the
|
|
86
|
-
trailing close cell (not a small inline chevron). */}
|
|
87
|
-
{!props.embedded && (
|
|
88
|
-
<div className="hidden md:flex flex-shrink-0 h-14 w-full overflow-hidden border-b border-ods-border bg-ods-card">
|
|
89
|
-
<ChatHeaderIconButton divider="right" onClick={props.onBack} aria-label="Back">
|
|
90
|
-
<Chevron02LeftIcon size={24} />
|
|
91
|
-
</ChatHeaderIconButton>
|
|
92
|
-
<div className="flex flex-1 min-w-0 items-center px-[var(--spacing-system-mf)] py-[var(--spacing-system-sf)]">
|
|
93
|
-
<span className="truncate text-h3 text-ods-text-primary">
|
|
94
|
-
Chat Archive
|
|
95
|
-
</span>
|
|
96
|
-
</div>
|
|
46
|
+
(Close only here, since the archive list has no per-chat actions). */}
|
|
47
|
+
<ChatPanelHeaderMobile
|
|
48
|
+
className="flex md:hidden"
|
|
49
|
+
showBack
|
|
50
|
+
title="Chat Archive"
|
|
51
|
+
backAriaLabel="Back"
|
|
52
|
+
onBack={onBack}
|
|
53
|
+
onClose={onClose}
|
|
54
|
+
/>
|
|
97
55
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
56
|
+
{/* Desktop (md+): fixed-height bar with back + full-height close cell. */}
|
|
57
|
+
<div className="hidden md:flex flex-shrink-0 h-14 w-full overflow-hidden border-b border-ods-border bg-ods-card">
|
|
58
|
+
<div className="flex flex-1 min-w-0 items-center gap-2 px-4 py-3">
|
|
59
|
+
<button
|
|
60
|
+
type="button"
|
|
61
|
+
onClick={onBack}
|
|
62
|
+
aria-label="Back"
|
|
63
|
+
className={`${COMPACT_HEADER_BUTTON} -ml-1`}
|
|
64
|
+
>
|
|
65
|
+
<Chevron02LeftIcon size={20} />
|
|
66
|
+
</button>
|
|
67
|
+
<span className="truncate text-h3 text-ods-text-primary">
|
|
68
|
+
Chat Archive
|
|
69
|
+
</span>
|
|
101
70
|
</div>
|
|
102
|
-
|
|
71
|
+
|
|
72
|
+
<ChatHeaderIconButton onClick={onClose} aria-label="Close">
|
|
73
|
+
<XmarkIcon size={24} />
|
|
74
|
+
</ChatHeaderIconButton>
|
|
75
|
+
</div>
|
|
103
76
|
<div className="flex flex-1 min-h-0 flex-col p-[var(--spacing-system-m)]">
|
|
104
77
|
{dialogs.length > 0 ? (
|
|
105
78
|
<MingoChatHistory
|
|
@@ -110,23 +83,34 @@ export function ChatArchivePage(props: ChatArchivePageProps) {
|
|
|
110
83
|
onLoadMore={onLoadMore}
|
|
111
84
|
/>
|
|
112
85
|
) : isLoading ? (
|
|
113
|
-
// First-load skeleton —
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
86
|
+
// First-load skeleton — `h-12` rows matching the dialog-list layout
|
|
87
|
+
// so results land without a shift (auth → data → empty → content).
|
|
88
|
+
<div className="flex flex-col" aria-hidden>
|
|
89
|
+
{[...Array(6)].map((_, i) => (
|
|
90
|
+
<div
|
|
91
|
+
key={i}
|
|
92
|
+
className="flex h-12 items-center gap-[var(--spacing-system-xsf)] border-b border-ods-border px-[var(--spacing-system-s)] last:border-b-0"
|
|
93
|
+
>
|
|
94
|
+
<div className="h-4 w-full max-w-[60%] animate-pulse rounded bg-ods-bg-secondary" />
|
|
95
|
+
</div>
|
|
96
|
+
))}
|
|
97
|
+
</div>
|
|
122
98
|
) : (
|
|
123
|
-
// Empty state —
|
|
124
|
-
//
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
99
|
+
// Empty state — no archived chats. Centred icon + title + hint,
|
|
100
|
+
// mirroring the panel's other empty surfaces (icon in a muted token,
|
|
101
|
+
// h-scale title, secondary body copy). Pure ODS tokens.
|
|
102
|
+
<div className="flex flex-1 flex-col items-center justify-center gap-[var(--spacing-system-s)] px-[var(--spacing-system-l)] text-center">
|
|
103
|
+
<div className="flex size-14 items-center justify-center rounded-full bg-ods-bg-secondary text-ods-text-secondary">
|
|
104
|
+
<BoxArchiveIcon size={28} />
|
|
105
|
+
</div>
|
|
106
|
+
<div className="flex flex-col gap-[var(--spacing-system-xxs)]">
|
|
107
|
+
<p className="text-h3 text-ods-text-primary">No archived chats</p>
|
|
108
|
+
<p className="max-w-xs text-h5 text-ods-text-secondary">
|
|
109
|
+
Chats you archive will appear here. Archive a chat from its
|
|
110
|
+
actions menu to tuck it away without deleting it.
|
|
111
|
+
</p>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
130
114
|
)}
|
|
131
115
|
</div>
|
|
132
116
|
</>
|
|
@@ -4,17 +4,12 @@ import * as React from 'react'
|
|
|
4
4
|
import { cn } from '../../utils/cn'
|
|
5
5
|
|
|
6
6
|
export interface ChatHeaderIconButtonProps
|
|
7
|
-
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
8
|
-
/** Which side carries the 1px cell divider. Trailing cells (close, ⋯,
|
|
9
|
-
* archive) use the default `'left'`; a leading cell (the back chevron) uses
|
|
10
|
-
* `'right'`; `'none'` drops it. */
|
|
11
|
-
divider?: 'left' | 'right' | 'none'
|
|
12
|
-
}
|
|
7
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
|
|
13
8
|
|
|
14
9
|
/**
|
|
15
10
|
* Square 56×56 icon cell used in the chat panel's top-navigation
|
|
16
|
-
* (archive / restore / close, the `⋯` menu trigger
|
|
17
|
-
*
|
|
11
|
+
* (archive / restore / close, and the `⋯` menu trigger). A left border acts
|
|
12
|
+
* as the 1px divider between cells.
|
|
18
13
|
*
|
|
19
14
|
* On hover only the background changes (`ods-bg-hover`) — the icon keeps its
|
|
20
15
|
* `ods-text-secondary` colour. `forwardRef` + prop spread so it works as a
|
|
@@ -23,14 +18,12 @@ export interface ChatHeaderIconButtonProps
|
|
|
23
18
|
export const ChatHeaderIconButton = React.forwardRef<
|
|
24
19
|
HTMLButtonElement,
|
|
25
20
|
ChatHeaderIconButtonProps
|
|
26
|
-
>(({ className, children, type = 'button',
|
|
21
|
+
>(({ className, children, type = 'button', ...props }, ref) => (
|
|
27
22
|
<button
|
|
28
23
|
ref={ref}
|
|
29
24
|
type={type}
|
|
30
25
|
className={cn(
|
|
31
|
-
'flex size-14 shrink-0 items-center justify-center border-ods-border',
|
|
32
|
-
divider === 'left' && 'border-l',
|
|
33
|
-
divider === 'right' && 'border-r',
|
|
26
|
+
'flex size-14 shrink-0 items-center justify-center border-l border-ods-border',
|
|
34
27
|
'text-ods-text-secondary transition-colors hover:bg-ods-bg-hover',
|
|
35
28
|
'focus:outline-none focus-visible:ring-2 focus-visible:ring-ods-accent',
|
|
36
29
|
className,
|
|
@@ -2,35 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
import { cn } from '../../utils/cn'
|
|
5
|
+
import { Chevron01LeftIcon } from '../icons-v2-generated/arrows/chevron-01-left-icon'
|
|
5
6
|
import {
|
|
6
|
-
Chevron02LeftIcon,
|
|
7
7
|
Ellipsis01Icon,
|
|
8
8
|
ClockHistoryIcon,
|
|
9
9
|
Refresh01LeftIcon,
|
|
10
|
-
SearchIcon,
|
|
11
10
|
} from '../icons-v2-generated'
|
|
12
11
|
import { XmarkIcon } from '../icons-v2-generated/signs-and-symbols/xmark-icon'
|
|
13
12
|
import { ChatHeaderIconButton } from './chat-header-icon-button'
|
|
14
|
-
import { ChatHeaderSearchField } from './chat-header-search-field'
|
|
15
13
|
import { ActionsMenuDropdown, type ActionsMenuItem } from '../ui/actions-menu'
|
|
16
14
|
import { ChatPanelHeaderMobile } from './chat-panel-header-mobile'
|
|
17
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Compact rounded header button used for the desktop back chevron. Borderless
|
|
18
|
+
* square with a hover background. (Mobile uses its own header component —
|
|
19
|
+
* `ChatPanelHeaderMobile`.)
|
|
20
|
+
*/
|
|
21
|
+
export const COMPACT_HEADER_BUTTON =
|
|
22
|
+
'inline-flex shrink-0 items-center justify-center size-8 rounded-md text-ods-text-secondary transition-colors hover:bg-ods-bg-hover hover:text-ods-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-ods-accent'
|
|
23
|
+
|
|
18
24
|
export interface ChatPanelHeaderProps {
|
|
19
25
|
/** Show the back-chevron + bold (h3) title. When false, the static list
|
|
20
26
|
* title (h4) is shown with no back affordance. */
|
|
21
27
|
showBack?: boolean
|
|
22
28
|
/** Title text (next to the back chevron, or the static list title). */
|
|
23
29
|
title: string
|
|
24
|
-
/** Optional sub-line under the title (e.g. the signed-in user's name).
|
|
25
|
-
* Rendered muted (`h6`) beneath the title in every view that has one. */
|
|
26
|
-
subtitle?: React.ReactNode
|
|
27
30
|
/** Accessible label for the back chevron. */
|
|
28
31
|
backAriaLabel?: string
|
|
29
32
|
/** The open conversation is an archived chat (read-only). */
|
|
30
33
|
isArchivedView?: boolean
|
|
31
|
-
/** Back-chevron handler.
|
|
32
|
-
|
|
33
|
-
onBack?: () => void
|
|
34
|
+
/** Back-chevron handler. */
|
|
35
|
+
onBack: () => void
|
|
34
36
|
/** Close the panel. */
|
|
35
37
|
onClose: () => void
|
|
36
38
|
/** Restore/unarchive — renders the refresh button (archived view only). */
|
|
@@ -46,18 +48,6 @@ export interface ChatPanelHeaderProps {
|
|
|
46
48
|
* panel) where the phone-sized full-bleed header (large `text-h2` title) is
|
|
47
49
|
* wrong regardless of viewport. Default false = viewport-responsive. */
|
|
48
50
|
compact?: boolean
|
|
49
|
-
/** Toggle the dialog-list search field — renders a magnifier button (list
|
|
50
|
-
* view only), before the archive clock. */
|
|
51
|
-
onToggleSearch?: () => void
|
|
52
|
-
/** Whether the search field is currently open. When true (and `onSearchChange`
|
|
53
|
-
* is wired) the title area is REPLACED in place by the inline search field
|
|
54
|
-
* and the magnifier toggle is hidden. */
|
|
55
|
-
searchActive?: boolean
|
|
56
|
-
/** Seeds the inline search field when it opens (current search term). */
|
|
57
|
-
searchQuery?: string
|
|
58
|
-
/** Emits the debounced search term from the inline field. Enables the
|
|
59
|
-
* in-header search experience (list view only). */
|
|
60
|
-
onSearchChange?: (query: string) => void
|
|
61
51
|
}
|
|
62
52
|
|
|
63
53
|
/**
|
|
@@ -69,7 +59,6 @@ export interface ChatPanelHeaderProps {
|
|
|
69
59
|
export function ChatPanelHeader({
|
|
70
60
|
showBack = false,
|
|
71
61
|
title,
|
|
72
|
-
subtitle,
|
|
73
62
|
backAriaLabel = 'Back',
|
|
74
63
|
isArchivedView = false,
|
|
75
64
|
onBack,
|
|
@@ -79,13 +68,7 @@ export function ChatPanelHeader({
|
|
|
79
68
|
onArchive,
|
|
80
69
|
onOpenArchive,
|
|
81
70
|
compact = false,
|
|
82
|
-
onToggleSearch,
|
|
83
|
-
searchActive = false,
|
|
84
|
-
searchQuery,
|
|
85
|
-
onSearchChange,
|
|
86
71
|
}: ChatPanelHeaderProps) {
|
|
87
|
-
// Search open (with a wired handler) swaps the title for the inline field.
|
|
88
|
-
const searchInline = searchActive && !!onSearchChange
|
|
89
72
|
// Desktop ⋯ menu (active, non-archived conversation only) — rename / archive.
|
|
90
73
|
const menuItems = [
|
|
91
74
|
onRename && { id: 'rename', label: 'Rename chat', onClick: onRename },
|
|
@@ -102,7 +85,6 @@ export function ChatPanelHeader({
|
|
|
102
85
|
className="flex md:hidden"
|
|
103
86
|
showBack={showBack}
|
|
104
87
|
title={title}
|
|
105
|
-
subtitle={subtitle}
|
|
106
88
|
backAriaLabel={backAriaLabel}
|
|
107
89
|
isArchivedView={isArchivedView}
|
|
108
90
|
onBack={onBack}
|
|
@@ -116,41 +98,24 @@ export function ChatPanelHeader({
|
|
|
116
98
|
|
|
117
99
|
{/* Compact bar: `md+` normally, or ALL widths when `compact`. Fixed-height
|
|
118
100
|
bar with full-height divider action cells. */}
|
|
119
|
-
<div
|
|
120
|
-
className=
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
// Search open — the inline field takes over the title area in place
|
|
138
|
-
// (Figma 116:51217); the magnifier toggle below is hidden.
|
|
139
|
-
<ChatHeaderSearchField
|
|
140
|
-
initialValue={searchQuery}
|
|
141
|
-
onSearchChange={onSearchChange}
|
|
142
|
-
onCollapse={onToggleSearch}
|
|
143
|
-
/>
|
|
144
|
-
) : (
|
|
145
|
-
<div className="flex flex-1 min-w-0 items-center px-[var(--spacing-system-mf)] py-[var(--spacing-system-sf)]">
|
|
146
|
-
<div className="flex min-w-0 flex-col">
|
|
147
|
-
<p className="truncate text-h3 leading-tight text-ods-text-primary">{title}</p>
|
|
148
|
-
{subtitle && (
|
|
149
|
-
<p className="truncate text-h6 leading-tight text-ods-text-secondary">{subtitle}</p>
|
|
150
|
-
)}
|
|
151
|
-
</div>
|
|
152
|
-
</div>
|
|
153
|
-
)}
|
|
101
|
+
<div className={cn('flex-shrink-0 h-14 w-full overflow-hidden border-b border-ods-border bg-ods-card', compact ? 'flex' : 'hidden md:flex')}>
|
|
102
|
+
<div className="flex flex-1 min-w-0 items-center gap-2 px-4 py-3">
|
|
103
|
+
{showBack ? (
|
|
104
|
+
<>
|
|
105
|
+
<button
|
|
106
|
+
type="button"
|
|
107
|
+
onClick={onBack}
|
|
108
|
+
aria-label={backAriaLabel}
|
|
109
|
+
className={`${COMPACT_HEADER_BUTTON} -ml-1`}
|
|
110
|
+
>
|
|
111
|
+
<Chevron01LeftIcon size={20} />
|
|
112
|
+
</button>
|
|
113
|
+
<span className="truncate text-h3 text-ods-text-primary">{title}</span>
|
|
114
|
+
</>
|
|
115
|
+
) : (
|
|
116
|
+
<p className="truncate text-h3 text-ods-text-primary">{title}</p>
|
|
117
|
+
)}
|
|
118
|
+
</div>
|
|
154
119
|
|
|
155
120
|
{/* Restore (refresh) — archived chat header (Figma node 7361:425441). */}
|
|
156
121
|
{isArchivedView && onRestore && (
|
|
@@ -173,18 +138,6 @@ export function ChatPanelHeader({
|
|
|
173
138
|
/>
|
|
174
139
|
)}
|
|
175
140
|
|
|
176
|
-
{/* Dialog search toggle — list view only, before the archive entry.
|
|
177
|
-
Hidden while search is open (the inline field owns the magnifier). */}
|
|
178
|
-
{!showBack && !searchInline && onToggleSearch && (
|
|
179
|
-
<ChatHeaderIconButton
|
|
180
|
-
onClick={onToggleSearch}
|
|
181
|
-
aria-label="Search chats"
|
|
182
|
-
aria-pressed={searchActive}
|
|
183
|
-
>
|
|
184
|
-
<SearchIcon size={24} />
|
|
185
|
-
</ChatHeaderIconButton>
|
|
186
|
-
)}
|
|
187
|
-
|
|
188
141
|
{/* Chat Archive entry (Figma node 7532:225034) — list view only. */}
|
|
189
142
|
{!showBack && onOpenArchive && (
|
|
190
143
|
<ChatHeaderIconButton onClick={onOpenArchive} aria-label="Chat archive">
|