SPB Git

spb/uqo-chat

Public
4.0 KB · 74 lines tsx
1import { useEffect } from 'react';2import { Outlet, useNavigate, useParams } from 'react-router-dom';3import * as RD from '@radix-ui/react-dialog';4import { Menu, PanelRight, Plus } from 'lucide-react';5import { Sidebar } from './sidebar';6import { ArtifactsPanel } from '@/features/conversations/artifacts-panel';7import { SettingsDialog } from '@/features/auth/settings-dialog';8import { Logo } from '@/components/ui/logo';9import { useUI } from '@/stores/ui';10import { useChat } from '@/stores/chat';11import { useAuth } from '@/stores/auth';12import { cn } from '@/lib/cn';1314export function AppShell() {15  const { id } = useParams();16  const nav = useNavigate();17  const { sidebarOpen, setSidebar, panelOpen, setPanel } = useUI();18  const conv = useChat((s) => s.conversations.find((c) => c.id === id));19  const user = useAuth((s) => s.user);2021  useEffect(() => {22    const fs = user?.preferences.font_scale ?? 1;23    document.documentElement.style.setProperty('--font-scale', String(fs));24  }, [user]);2526  return (27    <div className="flex h-[100dvh] w-full overflow-hidden bg-neutral-bg">28      <div className="hidden lg:block shrink-0"><Sidebar /></div>29      <RD.Root open={sidebarOpen} onOpenChange={setSidebar}>30        <RD.Portal>31          <RD.Overlay className="fixed inset-0 z-40 bg-uqo-blue-dark/40 lg:hidden" />32          <RD.Content className="fixed inset-y-0 left-0 z-50 lg:hidden outline-none animate-fadein" aria-describedby={undefined}>33            <RD.Title className="sr-only">Menu</RD.Title>34            <Sidebar onClose={() => setSidebar(false)} />35          </RD.Content>36        </RD.Portal>37      </RD.Root>3839      <main className="relative flex min-w-0 flex-1 flex-col">40        <header className="flex items-center gap-1 border-b border-neutral-line bg-white px-2 sm:px-4 pt-[var(--safe-top)] h-[calc(56px+var(--safe-top))] shrink-0">41          <button onClick={() => setSidebar(true)} className="lg:hidden h-11 w-11 inline-flex items-center justify-center rounded-xl hover:bg-neutral-surface" aria-label="Ouvrir le menu"><Menu size={22} /></button>42          <div className="lg:hidden"><Logo withText={false} /></div>43          <div className="min-w-0 flex-1 px-2">44            <div className="truncate text-sm sm:text-base font-semibold text-uqo-blue-dark">{conv?.title || 'Nouvelle conversation'}</div>45            <div className="truncate text-[11px] text-neutral-muted">{conv ? `${conv.course}` : 'Tuteur IA — IMM1003 · IMM1033'}</div>46          </div>47          <button onClick={() => nav('/')} className="lg:hidden h-11 w-11 inline-flex items-center justify-center rounded-xl hover:bg-neutral-surface" aria-label="Nouvelle conversation"><Plus size={22} /></button>48          {id && (49            <button onClick={() => setPanel(!panelOpen)} className={cn('h-11 w-11 inline-flex items-center justify-center rounded-xl hover:bg-neutral-surface', panelOpen && 'bg-uqo-blue-light text-uqo-blue')} aria-label="Fichiers et sources de la conversation" aria-pressed={panelOpen}><PanelRight size={20} /></button>50          )}51        </header>52        <div className="flex min-h-0 flex-1">53          <div className="relative min-w-0 flex-1"><Outlet /></div>54          {id && panelOpen && (55            <div className="hidden md:block w-[320px] shrink-0 border-l border-neutral-line bg-white"><ArtifactsPanel conversationId={id} /></div>56          )}57        </div>58        {id && panelOpen && (59          <RD.Root open onOpenChange={setPanel}>60            <RD.Portal>61              <RD.Overlay className="fixed inset-0 z-40 bg-uqo-blue-dark/40 md:hidden" />62              <RD.Content className="fixed inset-x-0 bottom-0 z-50 md:hidden max-h-[80dvh] rounded-t-2xl bg-white outline-none" aria-describedby={undefined}>63                <RD.Title className="sr-only">Fichiers et sources</RD.Title>64                <ArtifactsPanel conversationId={id} onClose={() => setPanel(false)} />65              </RD.Content>66            </RD.Portal>67          </RD.Root>68        )}69      </main>70      <SettingsDialog />71    </div>72  );73}74
Files · a783830277be7351834d9f17d071180b013561fa
Menu

Theme