Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ export interface ChatPanelHeaderMobileProps extends ChatPanelHeaderProps {
* without it the panel cannot be dismissed at all.
*
* Same prop contract as `ChatPanelHeader`; the orchestrator renders this on
* mobile and the desktop bar on `md+`.
* mobile and the desktop bar on `md+`. Pass `compact` to trade the
* full-screen-drawer spacing above for a tighter, vertically-centered row
* (see `compact`'s doc on `ChatPanelHeaderProps`).
*/
export function ChatPanelHeaderMobile({
showBack = false,
Expand All @@ -40,6 +42,7 @@ export function ChatPanelHeaderMobile({
onArchive,
onOpenArchive,
className,
compact = false,
}: ChatPanelHeaderMobileProps) {
// The right-hand ⋯ menu carries the view-dependent actions. Close is not
// listed (the panel is dismissed elsewhere); the trigger is hidden entirely
Expand All @@ -55,11 +58,12 @@ export function ChatPanelHeaderMobile({
<div
className={cn(
'flex-shrink-0 flex flex-col border-b border-ods-border bg-ods-card',
'px-[var(--spacing-system-l)] pb-[var(--spacing-system-l)]',
'px-[var(--spacing-system-l)]',
compact ? 'py-[var(--spacing-system-m)]' : 'pb-[var(--spacing-system-l)]',
className,
)}
>
<div className="flex w-full items-end gap-[var(--spacing-system-sf)]">
<div className={cn('flex w-full gap-[var(--spacing-system-sf)]', compact ? 'items-center' : 'items-end')}>
{showBack && (
<Button
variant="outline"
Expand All @@ -73,8 +77,14 @@ export function ChatPanelHeaderMobile({
)}

{/* Title block — `xl` top padding pushes the title down so the row
bottom-aligns the title, back chevron, and ⋯ menu. */}
<div className="flex flex-1 min-w-0 items-end gap-[var(--spacing-system-m)] pt-[var(--spacing-system-xl)]">
bottom-aligns the title, back chevron, and ⋯ menu. Skipped in
`compact` mode, which centers the row instead (see prop doc). */}
<div
className={cn(
'flex flex-1 min-w-0 gap-[var(--spacing-system-m)]',
compact ? 'items-center' : 'items-end pt-[var(--spacing-system-xl)]',
)}
>
<div className="flex flex-1 min-w-0 flex-col gap-[var(--spacing-system-xs)]">
<p className="min-w-0 truncate text-h2 text-ods-text-primary" title={title}>
{title}
Expand Down
12 changes: 12 additions & 0 deletions openframe-frontend-core/src/components/chat/chat-panel-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ export interface ChatPanelHeaderProps {
onArchive?: () => void
/** Open the Chat Archive page — renders the clock button (list view only). */
onOpenArchive?: () => void
/**
* Compact mobile layout — drops the generous `xl` top padding + bottom-
* anchored title row that assumes a full-screen drawer, in favor of a
* single vertically-centered row (matching the desktop bar's rhythm).
* For hosts that embed the mobile header inside a short, non-full-screen
* container (e.g. a marketing preview) where the full-screen spacing
* reads as broken/misaligned. Desktop bar is unaffected. Defaults to
* `false` (today's full-screen-drawer behavior).
*/
compact?: boolean
}

/**
Expand All @@ -61,6 +71,7 @@ export function ChatPanelHeader({
onRename,
onArchive,
onOpenArchive,
compact = false,
}: ChatPanelHeaderProps) {
// Desktop ⋯ menu (active, non-archived conversation only) — rename / archive.
const menuItems = [
Expand All @@ -83,6 +94,7 @@ export function ChatPanelHeader({
onRename={onRename}
onArchive={onArchive}
onOpenArchive={onOpenArchive}
compact={compact}
/>

{/* Desktop (md+): fixed-height bar with full-height divider action cells. */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1722,6 +1722,12 @@ function EmbeddableChatInner({
: undefined
}
onOpenArchive={fetchArchivedDialogs ? openArchive : undefined}
// Marketing/hero preview embeds are typically a short, non-
// full-screen box — the mobile header's full-screen-drawer
// spacing (generous top padding, bottom-anchored title) reads
// as broken there. Real (non-preview) mobile drawer usage is
// unaffected — `previewMode` is only ever true for mocks.
compact={previewMode}
/>

{/* Guide-mode indicator banner (Figma node 7532:328222) —
Expand Down
2 changes: 2 additions & 0 deletions openframe-frontend-core/src/components/tool-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
MeshcentralLogoGreyIcon,
FleetMdmLogoGreyIcon,
AuthentikLogoGreyIcon,
PowershellLogoGreyIcon,
} from "./icons-v2-generated";

const renderOpenFrameLogo = (_size: number, className?: string) => (
Expand All @@ -27,6 +28,7 @@ const toolIconMap: Record<ToolType, (size: number, className?: string) => React.
[ToolTypeValues.AUTHENTIK]: (size, className) => <AuthentikLogoGreyIcon size={size} className={className} />,
[ToolTypeValues.OSQUERY]: (size, className) => <OsqueryLogoGreyIcon size={size} className={className} />,
[ToolTypeValues.SYSTEM]: () => null,
[ToolTypeValues.POWERSHELL]: (size, className) => <PowershellLogoGreyIcon size={size} className={className} />,
};

export interface ToolIconProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@ const SCRIPTED_MESSAGES: UnifiedChatMessage[] = [
type: 'tool_execution',
data: {
type: 'EXECUTING_TOOL', // → DotsLoader status + collapsed command block
integratedToolType: 'OPENFRAME',
integratedToolType: 'POWERSHELL',
toolFunction: 'run_script',
toolTitle: RUN_SCRIPT_TITLE,
parameters: {},
Expand Down Expand Up @@ -903,10 +903,9 @@ function createScriptedMingoState(): UnifiedChatState {
* frame) with zero backend — no NATS, no fetch, fully static + read-only.
*
* Known deviations from the mock (the shipped component is the source of
* truth): author names render with a trailing ":" ; the command-block icon is
* the OpenFrame mark (the `ToolIcon` registry has no PowerShell glyph); the
* composer placeholder reads "Ask a question…"; and the trailing loader is the
* component's dots+phrase streaming indicator.
* truth): author names render with a trailing ":" ; the composer placeholder
* reads "Ask a question…"; and the trailing loader is the component's
* dots+phrase streaming indicator.
*/
export const ScriptedConversation: Story = {
parameters: { layout: 'fullscreen' },
Expand Down
6 changes: 4 additions & 2 deletions openframe-frontend-core/src/types/tool.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export const ToolTypeValues = {
OPENFRAME_CLIENT: 'OPENFRAME_CLIENT',
OPENFRAME_RMM: 'OPENFRAME_RMM',
OSQUERY: 'OSQUERY',
SYSTEM: 'SYSTEM'
SYSTEM: 'SYSTEM',
POWERSHELL: 'POWERSHELL'
} as const

export type ToolType = (typeof ToolTypeValues)[keyof typeof ToolTypeValues]
Expand All @@ -31,5 +32,6 @@ export const toolLabels: Record<ToolType, string> = {
OPENFRAME_CLIENT: 'OpenFrame Client',
OPENFRAME_RMM: 'RMM',
OSQUERY: 'Osquery',
SYSTEM: 'System'
SYSTEM: 'System',
POWERSHELL: 'PowerShell'
}
5 changes: 5 additions & 0 deletions openframe-frontend-core/src/utils/tool-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ const toolAliasMap: Record<string, ToolType> = {
// System
'SYSTEM': 'SYSTEM',
'system': 'SYSTEM',

// PowerShell
'POWERSHELL': 'POWERSHELL',
'powershell': 'POWERSHELL',
'PowerShell': 'POWERSHELL',
}

/**
Expand Down
Loading