Files
helix-engage/src/components/shared/ai-floating-button.tsx
saridsa2 d0e34fa9dd feat: global AI assistant floating button for supervisors (#578)
- AiFloatingButton: FAB (bottom-right) opens a slide-in drawer with
  the supervisor AI chat panel. Close button collapses drawer, FAB
  reappears. Chat state persists across open/close and page navigation.
- app-shell: mounts FAB for admin users (isAdmin), same pattern as
  CallWidget for agents.
- team-dashboard: removed inline AI panel + toggle button — replaced
  by the global FAB. Dashboard content reclaims the full width.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 10:45:45 +05:30

51 lines
2.5 KiB
TypeScript

import { useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faSparkles, faXmark } from '@fortawesome/pro-duotone-svg-icons';
import { AiChatPanel } from '@/components/call-desk/ai-chat-panel';
import { cx } from '@/utils/cx';
export const AiFloatingButton = () => {
const [open, setOpen] = useState(false);
return (
<>
{/* FAB — bottom right, hidden when drawer is open */}
{!open && (
<button
onClick={() => setOpen(true)}
className="fixed bottom-6 right-6 z-50 flex size-12 items-center justify-center rounded-full bg-brand-solid text-white shadow-lg hover:bg-brand-solid_hover transition duration-100 ease-linear"
title="AI Assistant"
>
<FontAwesomeIcon icon={faSparkles} className="size-5" />
</button>
)}
{/* Drawer — slides in from right */}
<div className={cx(
'fixed top-0 right-0 z-50 h-full bg-primary border-l border-secondary shadow-xl transition-all duration-200 ease-linear flex flex-col',
open ? 'w-[400px]' : 'w-0 overflow-hidden border-l-0',
)}>
{open && (
<>
<div className="flex shrink-0 items-center justify-between border-b border-secondary px-4 py-3">
<div className="flex items-center gap-2">
<FontAwesomeIcon icon={faSparkles} className="size-3.5 text-fg-brand-primary" />
<span className="text-sm font-semibold text-primary">AI Assistant</span>
</div>
<button
onClick={() => setOpen(false)}
className="flex size-7 items-center justify-center rounded-lg text-fg-quaternary hover:text-fg-secondary hover:bg-primary_hover transition duration-100 ease-linear"
>
<FontAwesomeIcon icon={faXmark} className="size-4" />
</button>
</div>
<div className="flex-1 min-h-0 overflow-hidden">
<AiChatPanel callerContext={{ type: 'supervisor' }} />
</div>
</>
)}
</div>
</>
);
};