- Desktop: on /chat the main sidebar shows the chat list (search, New chat, items with rename/delete, active highlight) in place of the deck navigation; the separate second column is gone and the chat uses the full width. The expand/collapse chevron sits outside the swappable section and a collapsed rail stays clean (the highlighted Chat row already opens a new chat). Active conversation travels via a tiny store (lib/chat-active) so the sidebar needs no useSearchParams and pages stay static. - Header (phones): history, theme and New chat are now identical chips - same 44px hit area, rounded-2xl, border/surface tokens, size-5 icons, even spacing; the title block truncates cleanly. ThemeToggle gained a 'plain' variant so the header styles it without touching other pages. - ChatIcon redrawn (clean message-circle, no inner lines) and the empty state uses the app's icon-chip pattern (size-12 chip, accent-600/200) instead of the bare oversized glyph; the model chip icon follows. - Also fixed a pre-existing dev-only breakage found while verifying: the tab-bar bounce animated three keyframes with a spring, which framer motion's dev build throws on - breaking client updates in the dev instance (library tab switching, sheet Escape). It now uses a tween. - Dev metadata keeps the Apple icons in both branches. - SW -> freezmo-v35.
59 lines
2.1 KiB
TypeScript
59 lines
2.1 KiB
TypeScript
"use client";
|
|
|
|
import { useRouter } from "next/navigation";
|
|
import { useState, useSyncExternalStore } from "react";
|
|
|
|
import { ChatHistoryList } from "./HistoryPanel";
|
|
import { chatActive } from "@/lib/chat-active";
|
|
import { chatHistoryStore, deleteConversation, renameConversation, saveConversation } from "@/lib/chat-store";
|
|
import { useI18n } from "@/lib/i18n";
|
|
import { showToast } from "@/lib/toast";
|
|
import type { ChatConversation } from "@/lib/schemas";
|
|
|
|
/**
|
|
* Chat history inside the main sidebar: when the Chat section is active the
|
|
* deck navigation is replaced by the chat list (search, new chat, items with
|
|
* rename/delete). Collapsed, it keeps one New-chat icon row.
|
|
*/
|
|
export function SidebarChatSection({ collapsed }: { collapsed: boolean }) {
|
|
const { t } = useI18n();
|
|
const router = useRouter();
|
|
const conversations = useSyncExternalStore(
|
|
chatHistoryStore.subscribe,
|
|
chatHistoryStore.getSnapshot,
|
|
chatHistoryStore.getServerSnapshot,
|
|
);
|
|
const activeId = useSyncExternalStore(chatActive.subscribe, chatActive.getSnapshot, chatActive.getServerSnapshot);
|
|
const [query, setQuery] = useState("");
|
|
|
|
const onDelete = (conversation: ChatConversation) => {
|
|
deleteConversation(conversation.id);
|
|
showToast({
|
|
message: t("chat.deletedChat"),
|
|
actionLabel: t("toast.undo"),
|
|
onAction: () => saveConversation(conversation),
|
|
});
|
|
};
|
|
|
|
// Collapsed, the list needs width — the highlighted Chat row above (and the
|
|
// expand chevron) already cover navigation, so the section renders nothing.
|
|
if (collapsed) return null;
|
|
|
|
return (
|
|
<div className="flex min-h-0 flex-1 flex-col">
|
|
<h2 className="px-2 pb-1 pt-1 text-[11px] font-semibold uppercase tracking-wider text-[var(--text-subtle)]">
|
|
{t("chat.history")}
|
|
</h2>
|
|
<ChatHistoryList
|
|
conversations={conversations}
|
|
currentId={activeId}
|
|
query={query}
|
|
onQueryChange={setQuery}
|
|
onOpen={(id) => router.push(`/chat?c=${id}`)}
|
|
onRename={renameConversation}
|
|
onDelete={onDelete}
|
|
onNew={() => router.push("/chat")}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|