🚸 feat: redesign AI toolbar with two-zone layout and HoverCard shortcuts popover

- Split composer into AI zone (primary accent) and data actions zone (neutral)
- Move Attach/Generate to labeled footer bar below textarea (left/right aligned)
- Add info icon with HoverCard (hover preview) + Popover (pinned click) showing identical keyboard shortcuts content using shadcn HoverCard to fix theme inconsistency vs Tooltip
- Expose imperative triggerRef on ImagePicker for keyboard shortcut access
- Wire TooltipProvider in root layout; install shadcn kbd and hover-card
- Unauthenticated state shows locked CTA with real sign-in button weight
- Add behavioral contract tests for footer bar, info trigger, and zone layout
This commit is contained in:
2026-04-08 13:08:36 -04:00
parent 650d1d5f95
commit 722c0f0f7d
8 changed files with 881 additions and 151 deletions

View File

@@ -7,6 +7,7 @@ import { ThemeProvider } from "next-themes";
import { ModeToggle } from "@/components/mode-toggle";
import SignIn from "@/components/sign-in";
import { Toaster } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
const geistSans = Geist({
subsets: ["latin", "cyrillic"],
@@ -34,12 +35,13 @@ export default function RootLayout({
<body
className={`${geistSans.variable} ${geistMono.variable} font-sans antialiased min-h-screen flex flex-col`}
>
<ThemeProvider
attribute="class"
defaultTheme="dark"
enableSystem
disableTransitionOnChange
>
<ThemeProvider
attribute="class"
defaultTheme="dark"
enableSystem
disableTransitionOnChange
>
<TooltipProvider delayDuration={300}>
<header className="sticky top-0 z-50 glass-strong">
<div className="max-w-4xl mx-auto flex items-center justify-between px-4 sm:px-6 h-14">
<Link
@@ -60,14 +62,15 @@ export default function RootLayout({
{children}
</div>
</main>
<Toaster
closeButton
richColors
toastOptions={{
className: "glass-strong",
}}
/>
</ThemeProvider>
<Toaster
closeButton
richColors
toastOptions={{
className: "glass-strong",
}}
/>
</TooltipProvider>
</ThemeProvider>
</body>
</html>
);