fix: deduplicate actions, promote ViewToggle tab bar, standardize naming
Remove duplicate Update/Close actions from chat toolbars (FlowPilotPage, CockpitPage) — session lifecycle actions now live only in headers. Redesign ViewToggle as a persistent tab bar with bottom-border active indicator and ARIA attributes. Standardize all action naming: Resolve (emerald), Update (blue), Close (rose), Pause (muted). Fix IncidentHeader Resolve from orange to emerald. Delete unused FlowPilotActionBar component (227 lines). Update ConcludeSessionModal copy to use forward-facing action verbs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useEffect } from 'react'
|
||||
import { Sparkles, Send, Loader2, Flag, MessageSquare, Paperclip, Terminal, X, RotateCcw, ImagePlus, ListChecks, FileText } from 'lucide-react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Sparkles, Send, Loader2, MessageSquare, Paperclip, Terminal, X, RotateCcw, ImagePlus, ListChecks, CheckCircle2, FileText, MoreHorizontal, Pause } from 'lucide-react'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { PageMeta } from '@/components/common/PageMeta'
|
||||
import { aiSessionsApi } from '@/api/aiSessions'
|
||||
@@ -13,6 +13,7 @@ import { useAssistantSession } from '@/hooks/useAssistantSession'
|
||||
|
||||
export default function FlowPilotPage() {
|
||||
const session = useAssistantSession()
|
||||
const [showOverflow, setShowOverflow] = useState(false)
|
||||
|
||||
// Handle prefill from dashboard / command palette
|
||||
useEffect(() => {
|
||||
@@ -112,12 +113,9 @@ export default function FlowPilotPage() {
|
||||
className="flex items-center gap-2 rounded-lg px-3 py-2 text-sm text-muted-foreground hover:text-foreground hover:bg-[var(--color-bg-elevated)] transition-colors"
|
||||
>
|
||||
<MessageSquare size={16} />
|
||||
Chats
|
||||
Cases
|
||||
</button>
|
||||
<div className="flex-1" />
|
||||
{session.activeChatId && (
|
||||
<ViewToggle currentView="flowpilot" sessionId={session.activeChatId} />
|
||||
)}
|
||||
<button
|
||||
onClick={session.handleNewChat}
|
||||
className="rounded-lg px-3 py-2 text-sm font-medium text-primary hover:bg-primary/10 transition-colors"
|
||||
@@ -126,36 +124,65 @@ export default function FlowPilotPage() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* View tab bar — persistent when a session is active */}
|
||||
{session.activeChatId && (
|
||||
<ViewToggle currentView="flowpilot" sessionId={session.activeChatId} />
|
||||
)}
|
||||
|
||||
{session.activeChatId ? (
|
||||
<>
|
||||
{/* Desktop view toggle + action bar */}
|
||||
<div className="hidden sm:flex items-center justify-between px-4 py-1.5 border-b border-border/50">
|
||||
<div className="flex items-center gap-1.5">
|
||||
{session.messages.length >= 2 && (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => session.setShowStatusUpdate(true)}
|
||||
disabled={session.loading}
|
||||
className="flex items-center gap-1.5 bg-blue-500/10 border border-blue-500/20 rounded-lg px-3 py-1 text-xs font-medium text-blue-400 hover:bg-blue-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
|
||||
>
|
||||
<FileText size={13} />
|
||||
Update
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => session.setShowConclude(true)}
|
||||
disabled={session.loading}
|
||||
className="flex items-center gap-1.5 bg-amber-500/10 border border-amber-500/20 rounded-lg px-3 py-1 text-xs font-medium text-amber-400 hover:bg-amber-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
|
||||
>
|
||||
<Flag size={13} />
|
||||
Conclude
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
{/* Action bar — Resolve, Update, overflow (Pause/Close) */}
|
||||
{session.messages.length >= 2 && (
|
||||
<div className="hidden sm:flex items-center gap-1.5 px-4 py-1.5 border-b border-border/50">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => session.setShowConclude(true)}
|
||||
disabled={session.loading}
|
||||
className="flex items-center gap-1.5 rounded-lg bg-emerald-500/10 border border-emerald-500/20 px-3 py-1.5 text-xs font-medium text-emerald-400 hover:bg-emerald-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
|
||||
>
|
||||
<CheckCircle2 size={13} />
|
||||
Resolve
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => session.setShowStatusUpdate(true)}
|
||||
disabled={session.loading}
|
||||
className="flex items-center gap-1.5 bg-blue-500/10 border border-blue-500/20 rounded-lg px-3 py-1.5 text-xs font-medium text-blue-400 hover:bg-blue-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
|
||||
>
|
||||
<FileText size={13} />
|
||||
Update
|
||||
</button>
|
||||
<div className="relative">
|
||||
<button
|
||||
onClick={() => setShowOverflow(!showOverflow)}
|
||||
className="flex items-center justify-center rounded-lg px-2 py-1.5 text-muted-foreground hover:text-foreground hover:bg-[rgba(255,255,255,0.06)] transition-colors"
|
||||
>
|
||||
<MoreHorizontal size={16} />
|
||||
</button>
|
||||
{showOverflow && (
|
||||
<>
|
||||
<div className="fixed inset-0 z-40" onClick={() => setShowOverflow(false)} />
|
||||
<div className="absolute right-0 top-full mt-1 z-50 w-40 rounded-lg border border-border bg-card py-1 shadow-lg">
|
||||
<button
|
||||
onClick={() => { setShowOverflow(false); /* pause not wired on chat sessions yet */ }}
|
||||
className="flex w-full items-center gap-2 px-3 py-2 text-xs text-muted-foreground hover:text-foreground hover:bg-[rgba(255,255,255,0.06)] transition-colors"
|
||||
>
|
||||
<Pause size={13} />
|
||||
Pause
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { setShowOverflow(false); session.setShowConclude(true) }}
|
||||
className="flex w-full items-center gap-2 px-3 py-2 text-xs text-muted-foreground hover:text-rose-400 hover:bg-rose-500/10 transition-colors"
|
||||
>
|
||||
<X size={13} />
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<ViewToggle currentView="flowpilot" sessionId={session.activeChatId} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Messages */}
|
||||
<div className="flex-1 overflow-y-auto px-4 sm:px-6 py-4 space-y-4">
|
||||
@@ -297,18 +324,6 @@ export default function FlowPilotPage() {
|
||||
<span className="hidden sm:inline">Paste Logs</span>
|
||||
</button>
|
||||
)}
|
||||
{session.messages.length >= 2 && (
|
||||
<>
|
||||
<button type="button" onClick={() => session.setShowStatusUpdate(true)} disabled={session.loading} className="flex items-center gap-1.5 rounded-lg px-2 py-1.5 text-xs text-muted-foreground hover:text-blue-400 hover:bg-blue-500/10 transition-colors disabled:opacity-40" title="Share status update">
|
||||
<FileText size={14} />
|
||||
<span className="hidden sm:inline">Update</span>
|
||||
</button>
|
||||
<button type="button" onClick={() => session.setShowConclude(true)} disabled={session.loading} className="flex items-center gap-1.5 rounded-lg px-2 py-1.5 text-xs text-muted-foreground hover:text-amber-400 hover:bg-amber-400/10 transition-colors disabled:opacity-40" title="Conclude session">
|
||||
<Flag size={14} />
|
||||
<span className="hidden sm:inline">Conclude</span>
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
{!session.showTaskLane && (session.activeQuestions.length > 0 || session.activeActions.length > 0) && (
|
||||
<button
|
||||
type="button"
|
||||
@@ -368,7 +383,7 @@ export default function FlowPilotPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Conclude Session Modal */}
|
||||
{/* Close Case Modal */}
|
||||
<ConcludeSessionModal
|
||||
isOpen={session.showConclude}
|
||||
onClose={() => session.setShowConclude(false)}
|
||||
|
||||
Reference in New Issue
Block a user