Files
wehub-resource-sync e30e75b5d4
Changesets / Create Version PR (push) Has been cancelled
Deploy Shadcn Registry / Deploy Production (push) Has been cancelled
Template Metrics / LOC + Bundle Size (push) Has been cancelled
Code Quality / Oxlint + Oxfmt (push) Has been cancelled
Code Quality / Template Sync (push) Has been cancelled
Code Quality / Build Changed Packages (push) Has been cancelled
Code Quality / Test Changed Packages (push) Has been cancelled
Deploy Expo Example / Deploy Production (push) Has been cancelled
Deploy Ink Example / Deploy Production (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.12) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:40:13 +08:00

71 lines
1.8 KiB
TypeScript

"use client";
import { useEffect, useState, type ReactNode } from "react";
import { createPortal } from "react-dom";
import { LayoutGrid, Plus } from "lucide-react";
import { Button } from "@/components/ui/button";
import type { XuluxStoredThread } from "../runtime/types";
import { XuluxHistoryMenu } from "./XuluxHistoryMenu";
function HeaderPortal({ children }: { children: ReactNode }) {
const [container, setContainer] = useState<HTMLElement | null>(null);
useEffect(() => {
setContainer(
document.querySelector<HTMLElement>("[data-sub-project-header-portal]"),
);
}, []);
if (!container) return null;
return createPortal(children, container);
}
export function XuluxHeaderActions({
visible,
showChatActions,
onNewChat,
onShowTemplates,
onRestoreThread,
}: {
visible: boolean;
showChatActions: boolean;
onNewChat: () => void;
onShowTemplates: () => void;
onRestoreThread: (thread: XuluxStoredThread) => void;
}) {
if (!visible) return null;
return (
<HeaderPortal>
<XuluxHistoryMenu
onNewChat={onNewChat}
onRestoreThread={onRestoreThread}
/>
{showChatActions && (
<>
<Button
type="button"
variant="outline"
size="sm"
className="h-7 gap-1.5 px-2.5 text-xs"
onClick={onShowTemplates}
>
<LayoutGrid className="size-3.5" />
<span className="hidden md:inline">Templates</span>
</Button>
<Button
type="button"
variant="outline"
size="sm"
className="h-7 gap-1.5 px-2.5 text-xs"
onClick={onNewChat}
>
<Plus className="size-3.5" />
<span className="hidden md:inline">New</span>
</Button>
</>
)}
</HeaderPortal>
);
}