- 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.
29 lines
808 B
TypeScript
29 lines
808 B
TypeScript
"use client";
|
|
|
|
/**
|
|
* Which conversation the chat screen is currently showing, for surfaces
|
|
* outside the chat route (the sidebar list highlights it). A tiny external
|
|
* store instead of reading `?c=` from the URL, because the sidebar renders on
|
|
* every page and `useSearchParams` there would force pages dynamic.
|
|
*/
|
|
|
|
let active: string | null = null;
|
|
const listeners = new Set<() => void>();
|
|
|
|
export const chatActive = {
|
|
set(id: string | null): void {
|
|
if (active === id) return;
|
|
active = id;
|
|
listeners.forEach((listener) => listener());
|
|
},
|
|
subscribe(listener: () => void): () => void {
|
|
listeners.add(listener);
|
|
return () => listeners.delete(listener);
|
|
},
|
|
getSnapshot(): string | null {
|
|
return active;
|
|
},
|
|
getServerSnapshot(): string | null {
|
|
return null;
|
|
},
|
|
};
|