fix: clean up chat UI layout and align theme to neutral white
- Replace beige background with clean neutral white (matches Grok aesthetic) - Remove hardcoded hex colors in thread.tsx - use CSS variables throughout - Remove scroll-to-bottom button that showed incorrectly after auto-send - Chat container now integrates visually with the page instead of floating Made-with: Cursor
This commit is contained in:
@@ -44,44 +44,38 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--radius: 0.625rem;
|
--radius: 0.5rem;
|
||||||
/* Vib'n warm beige background from logo */
|
--background: oklch(0.985 0 0);
|
||||||
--background: oklch(0.96 0.015 80);
|
--foreground: oklch(0.09 0 0);
|
||||||
--foreground: oklch(0.25 0.02 230);
|
--card: oklch(1 0 0);
|
||||||
/* Slightly warmer white for cards */
|
--card-foreground: oklch(0.09 0 0);
|
||||||
--card: oklch(0.99 0.01 80);
|
--popover: oklch(1 0 0);
|
||||||
--card-foreground: oklch(0.25 0.02 230);
|
--popover-foreground: oklch(0.09 0 0);
|
||||||
--popover: oklch(0.99 0.01 80);
|
--primary: oklch(0.09 0 0);
|
||||||
--popover-foreground: oklch(0.25 0.02 230);
|
--primary-foreground: oklch(0.985 0 0);
|
||||||
/* Vib'n dark blue from logo text */
|
--secondary: oklch(0.94 0 0);
|
||||||
--primary: oklch(0.35 0.08 230);
|
--secondary-foreground: oklch(0.09 0 0);
|
||||||
--primary-foreground: oklch(0.99 0 0);
|
--muted: oklch(0.94 0 0);
|
||||||
--secondary: oklch(0.92 0.015 80);
|
--muted-foreground: oklch(0.50 0 0);
|
||||||
--secondary-foreground: oklch(0.35 0.08 230);
|
--accent: oklch(0.94 0 0);
|
||||||
--muted: oklch(0.92 0.015 80);
|
--accent-foreground: oklch(0.09 0 0);
|
||||||
--muted-foreground: oklch(0.50 0.02 230);
|
|
||||||
--accent: oklch(0.92 0.015 80);
|
|
||||||
--accent-foreground: oklch(0.35 0.08 230);
|
|
||||||
--destructive: oklch(0.577 0.245 27.325);
|
--destructive: oklch(0.577 0.245 27.325);
|
||||||
/* Softer borders on warm background */
|
--border: oklch(0.88 0 0);
|
||||||
--border: oklch(0.88 0.015 80);
|
--input: oklch(0.88 0 0);
|
||||||
--input: oklch(0.88 0.015 80);
|
--ring: oklch(0.70 0 0);
|
||||||
--ring: oklch(0.60 0.08 230);
|
--chart-1: oklch(0.70 0.15 60);
|
||||||
/* Vib'n brand colors for charts */
|
--chart-2: oklch(0.70 0.12 210);
|
||||||
--chart-1: oklch(0.70 0.15 60); /* Orange */
|
--chart-3: oklch(0.55 0.10 220);
|
||||||
--chart-2: oklch(0.70 0.12 210); /* Light blue */
|
--chart-4: oklch(0.40 0.08 230);
|
||||||
--chart-3: oklch(0.55 0.10 220); /* Medium blue */
|
--chart-5: oklch(0.75 0.15 70);
|
||||||
--chart-4: oklch(0.40 0.08 230); /* Dark blue */
|
--sidebar: oklch(0.985 0 0);
|
||||||
--chart-5: oklch(0.75 0.15 70); /* Yellow */
|
--sidebar-foreground: oklch(0.09 0 0);
|
||||||
/* Sidebar with warm tint */
|
--sidebar-primary: oklch(0.09 0 0);
|
||||||
--sidebar: oklch(0.98 0.01 80);
|
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-foreground: oklch(0.30 0.02 230);
|
--sidebar-accent: oklch(0.94 0 0);
|
||||||
--sidebar-primary: oklch(0.35 0.08 230);
|
--sidebar-accent-foreground: oklch(0.09 0 0);
|
||||||
--sidebar-primary-foreground: oklch(0.99 0 0);
|
--sidebar-border: oklch(0.88 0 0);
|
||||||
--sidebar-accent: oklch(0.92 0.015 80);
|
--sidebar-ring: oklch(0.70 0 0);
|
||||||
--sidebar-accent-foreground: oklch(0.35 0.08 230);
|
|
||||||
--sidebar-border: oklch(0.88 0.015 80);
|
|
||||||
--sidebar-ring: oklch(0.60 0.08 230);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
|
|||||||
@@ -91,14 +91,14 @@ function AtlasChatInner({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col rounded-2xl overflow-hidden bg-[#fdfdfd] dark:bg-[#141414] ring-1 ring-[#e5e5e5] dark:ring-[#2a2a2a]" style={{ height: "600px" }}>
|
<div className="flex flex-col rounded-2xl overflow-hidden bg-card ring-1 ring-border" style={{ height: "600px" }}>
|
||||||
{/* Minimal header bar */}
|
{/* Minimal header bar */}
|
||||||
<div className="flex items-center justify-end px-4 py-2.5 shrink-0 border-b border-[#e5e5e5] dark:border-[#2a2a2a]">
|
<div className="flex items-center justify-end px-4 py-2.5 shrink-0 border-b border-border">
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={handleReset}
|
onClick={handleReset}
|
||||||
className="h-7 w-7 p-0 text-[#9a9a9a] dark:text-[#6b6b6b] hover:text-[#0d0d0d] dark:hover:text-white"
|
className="h-7 w-7 p-0 text-muted-foreground hover:text-foreground"
|
||||||
title="Start over"
|
title="Start over"
|
||||||
>
|
>
|
||||||
<RotateCcw className="w-3.5 h-3.5" />
|
<RotateCcw className="w-3.5 h-3.5" />
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {
|
|||||||
ThreadPrimitive,
|
ThreadPrimitive,
|
||||||
} from "@assistant-ui/react";
|
} from "@assistant-ui/react";
|
||||||
import {
|
import {
|
||||||
ArrowDownIcon,
|
|
||||||
ArrowUpIcon,
|
ArrowUpIcon,
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
ChevronLeftIcon,
|
ChevronLeftIcon,
|
||||||
@@ -26,7 +25,7 @@ import { MarkdownText } from "./markdown-text";
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export const Thread: FC = () => (
|
export const Thread: FC = () => (
|
||||||
<ThreadPrimitive.Root className="flex flex-col h-full bg-[#fdfdfd] dark:bg-[#141414] px-4">
|
<ThreadPrimitive.Root className="flex flex-col h-full px-4">
|
||||||
|
|
||||||
{/* Empty state: centered welcome + composer */}
|
{/* Empty state: centered welcome + composer */}
|
||||||
<ThreadPrimitive.Empty>
|
<ThreadPrimitive.Empty>
|
||||||
@@ -35,8 +34,8 @@ export const Thread: FC = () => (
|
|||||||
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-violet-500 to-indigo-600 flex items-center justify-center text-white font-bold text-base shadow-sm">
|
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-violet-500 to-indigo-600 flex items-center justify-center text-white font-bold text-base shadow-sm">
|
||||||
A
|
A
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm font-medium text-[#0d0d0d] dark:text-white">Atlas</p>
|
<p className="text-sm font-medium text-foreground">Atlas</p>
|
||||||
<p className="text-xs text-[#9a9a9a] dark:text-[#6b6b6b] max-w-xs">
|
<p className="text-xs text-muted-foreground max-w-xs">
|
||||||
Your product strategist. Let's define what you're building.
|
Your product strategist. Let's define what you're building.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -56,51 +55,33 @@ export const Thread: FC = () => (
|
|||||||
/>
|
/>
|
||||||
</ThreadPrimitive.Viewport>
|
</ThreadPrimitive.Viewport>
|
||||||
|
|
||||||
{/* Scroll to bottom */}
|
<Composer />
|
||||||
<div className="relative">
|
|
||||||
<ThreadScrollToBottom />
|
|
||||||
<Composer />
|
|
||||||
</div>
|
|
||||||
</ThreadPrimitive.Root>
|
</ThreadPrimitive.Root>
|
||||||
);
|
);
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Scroll to bottom
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const ThreadScrollToBottom: FC = () => (
|
|
||||||
<ThreadPrimitive.ScrollToBottom asChild>
|
|
||||||
<button className="absolute -top-10 right-4 flex h-8 w-8 items-center justify-center rounded-full bg-[#0d0d0d] dark:bg-white text-white dark:text-[#0d0d0d] shadow hover:opacity-80 transition-opacity">
|
|
||||||
<ArrowDownIcon className="h-3.5 w-3.5" />
|
|
||||||
</button>
|
|
||||||
</ThreadPrimitive.ScrollToBottom>
|
|
||||||
);
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Composer — Grok pill style with inverted send button
|
// Composer — Grok pill style with inverted send button
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
const Composer: FC = () => (
|
const Composer: FC = () => (
|
||||||
<ComposerPrimitive.Root className="group/composer mx-auto w-full max-w-2xl mb-3">
|
<ComposerPrimitive.Root className="group/composer mx-auto w-full max-w-2xl mb-3">
|
||||||
<div className="flex items-end gap-2 rounded-[26px] bg-[#f8f8f8] dark:bg-[#212121] ring-1 ring-[#e5e5e5] dark:ring-[#2a2a2a] px-4 py-3 transition-shadow focus-within:ring-[#c5c5c5] dark:focus-within:ring-[#3a3a3a]">
|
<div className="flex items-end gap-2 rounded-[26px] bg-muted ring-1 ring-border px-4 py-3 transition-shadow focus-within:ring-ring/50">
|
||||||
<ComposerPrimitive.Input
|
<ComposerPrimitive.Input
|
||||||
placeholder="What do you want to build?"
|
placeholder="What do you want to build?"
|
||||||
rows={1}
|
rows={1}
|
||||||
autoFocus
|
autoFocus
|
||||||
className="flex-1 resize-none bg-transparent text-[#0d0d0d] dark:text-white placeholder:text-[#9a9a9a] dark:placeholder:text-[#6b6b6b] text-sm leading-relaxed outline-none min-h-[24px] max-h-[120px]"
|
className="flex-1 resize-none bg-transparent text-foreground placeholder:text-muted-foreground text-sm leading-relaxed outline-none min-h-[24px] max-h-[120px]"
|
||||||
/>
|
/>
|
||||||
{/* Send button (hidden while running) */}
|
|
||||||
<ThreadPrimitive.If running={false}>
|
<ThreadPrimitive.If running={false}>
|
||||||
<ComposerPrimitive.Send asChild>
|
<ComposerPrimitive.Send asChild>
|
||||||
<button className="h-8 w-8 rounded-full bg-[#0d0d0d] dark:bg-white text-white dark:text-[#0d0d0d] flex items-center justify-center shrink-0 hover:opacity-80 transition-opacity disabled:opacity-30 disabled:cursor-not-allowed">
|
<button className="h-8 w-8 rounded-full bg-foreground text-background flex items-center justify-center shrink-0 hover:opacity-80 transition-opacity disabled:opacity-30 disabled:cursor-not-allowed">
|
||||||
<ArrowUpIcon className="h-3.5 w-3.5" />
|
<ArrowUpIcon className="h-3.5 w-3.5" />
|
||||||
</button>
|
</button>
|
||||||
</ComposerPrimitive.Send>
|
</ComposerPrimitive.Send>
|
||||||
</ThreadPrimitive.If>
|
</ThreadPrimitive.If>
|
||||||
{/* Cancel button (shown while running) */}
|
|
||||||
<ThreadPrimitive.If running>
|
<ThreadPrimitive.If running>
|
||||||
<ComposerPrimitive.Cancel asChild>
|
<ComposerPrimitive.Cancel asChild>
|
||||||
<button className="h-8 w-8 rounded-full bg-[#0d0d0d] dark:bg-white text-white dark:text-[#0d0d0d] flex items-center justify-center shrink-0 hover:opacity-80 transition-opacity">
|
<button className="h-8 w-8 rounded-full bg-foreground text-background flex items-center justify-center shrink-0 hover:opacity-80 transition-opacity">
|
||||||
<SquareIcon className="h-3 w-3 fill-current" />
|
<SquareIcon className="h-3 w-3 fill-current" />
|
||||||
</button>
|
</button>
|
||||||
</ComposerPrimitive.Cancel>
|
</ComposerPrimitive.Cancel>
|
||||||
@@ -115,7 +96,7 @@ const Composer: FC = () => (
|
|||||||
|
|
||||||
const FollowupSuggestion: FC<{ suggestion: { prompt: string } }> = ({ suggestion }) => (
|
const FollowupSuggestion: FC<{ suggestion: { prompt: string } }> = ({ suggestion }) => (
|
||||||
<ThreadPrimitive.Suggestion prompt={suggestion.prompt} send asChild>
|
<ThreadPrimitive.Suggestion prompt={suggestion.prompt} send asChild>
|
||||||
<button className="text-xs px-3 py-1.5 rounded-full ring-1 ring-[#e5e5e5] dark:ring-[#2a2a2a] text-[#9a9a9a] dark:text-[#6b6b6b] hover:ring-[#c5c5c5] dark:hover:ring-[#3a3a3a] hover:text-[#0d0d0d] dark:hover:text-white transition-all">
|
<button className="text-xs px-3 py-1.5 rounded-full ring-1 ring-border text-muted-foreground hover:ring-ring/50 hover:text-foreground transition-all">
|
||||||
{suggestion.prompt}
|
{suggestion.prompt}
|
||||||
</button>
|
</button>
|
||||||
</ThreadPrimitive.Suggestion>
|
</ThreadPrimitive.Suggestion>
|
||||||
@@ -135,7 +116,7 @@ const UserMessage: FC = () => (
|
|||||||
);
|
);
|
||||||
|
|
||||||
const UserText: FC<{ text: string }> = ({ text }) => (
|
const UserText: FC<{ text: string }> = ({ text }) => (
|
||||||
<div className="bg-[#0d0d0d] dark:bg-white text-white dark:text-[#0d0d0d] rounded-[20px] rounded-tr-[6px] px-4 py-2.5 text-sm leading-relaxed whitespace-pre-wrap">
|
<div className="bg-foreground text-background rounded-[20px] rounded-tr-[6px] px-4 py-2.5 text-sm leading-relaxed whitespace-pre-wrap">
|
||||||
{text}
|
{text}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -147,7 +128,7 @@ const UserActionBar: FC = () => (
|
|||||||
className="flex items-center gap-1 mt-1 justify-end opacity-0 group-hover:opacity-100 transition-opacity"
|
className="flex items-center gap-1 mt-1 justify-end opacity-0 group-hover:opacity-100 transition-opacity"
|
||||||
>
|
>
|
||||||
<ActionBarPrimitive.Edit asChild>
|
<ActionBarPrimitive.Edit asChild>
|
||||||
<button className="text-[10px] text-[#9a9a9a] dark:text-[#6b6b6b] hover:text-[#0d0d0d] dark:hover:text-white px-1.5 py-0.5 rounded transition-colors">
|
<button className="text-[10px] text-muted-foreground hover:text-foreground px-1.5 py-0.5 rounded transition-colors">
|
||||||
Edit
|
Edit
|
||||||
</button>
|
</button>
|
||||||
</ActionBarPrimitive.Edit>
|
</ActionBarPrimitive.Edit>
|
||||||
@@ -184,7 +165,7 @@ const AssistantActionBar: FC = () => (
|
|||||||
className="flex items-center gap-2 mt-1.5 opacity-0 group-hover:opacity-100 transition-opacity"
|
className="flex items-center gap-2 mt-1.5 opacity-0 group-hover:opacity-100 transition-opacity"
|
||||||
>
|
>
|
||||||
<ActionBarPrimitive.Copy asChild>
|
<ActionBarPrimitive.Copy asChild>
|
||||||
<button className="flex items-center gap-1 text-[10px] text-[#9a9a9a] dark:text-[#6b6b6b] hover:text-[#0d0d0d] dark:hover:text-white px-1.5 py-0.5 rounded transition-colors">
|
<button className="flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground px-1.5 py-0.5 rounded transition-colors">
|
||||||
<MessagePrimitive.If copied>
|
<MessagePrimitive.If copied>
|
||||||
<CheckIcon className="h-2.5 w-2.5" />
|
<CheckIcon className="h-2.5 w-2.5" />
|
||||||
Copied
|
Copied
|
||||||
@@ -196,7 +177,7 @@ const AssistantActionBar: FC = () => (
|
|||||||
</button>
|
</button>
|
||||||
</ActionBarPrimitive.Copy>
|
</ActionBarPrimitive.Copy>
|
||||||
<ActionBarPrimitive.Reload asChild>
|
<ActionBarPrimitive.Reload asChild>
|
||||||
<button className="flex items-center gap-1 text-[10px] text-[#9a9a9a] dark:text-[#6b6b6b] hover:text-[#0d0d0d] dark:hover:text-white px-1.5 py-0.5 rounded transition-colors">
|
<button className="flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground px-1.5 py-0.5 rounded transition-colors">
|
||||||
<RefreshCwIcon className="h-2.5 w-2.5" />
|
<RefreshCwIcon className="h-2.5 w-2.5" />
|
||||||
Retry
|
Retry
|
||||||
</button>
|
</button>
|
||||||
@@ -214,15 +195,15 @@ const BranchPicker: FC = () => (
|
|||||||
className="flex items-center gap-1 mt-1 opacity-0 group-hover:opacity-100 transition-opacity"
|
className="flex items-center gap-1 mt-1 opacity-0 group-hover:opacity-100 transition-opacity"
|
||||||
>
|
>
|
||||||
<BranchPickerPrimitive.Previous asChild>
|
<BranchPickerPrimitive.Previous asChild>
|
||||||
<button className="text-[#9a9a9a] dark:text-[#6b6b6b] hover:text-[#0d0d0d] dark:hover:text-white transition-colors">
|
<button className="text-muted-foreground hover:text-foreground transition-colors">
|
||||||
<ChevronLeftIcon className="h-3 w-3" />
|
<ChevronLeftIcon className="h-3 w-3" />
|
||||||
</button>
|
</button>
|
||||||
</BranchPickerPrimitive.Previous>
|
</BranchPickerPrimitive.Previous>
|
||||||
<span className="text-[10px] text-[#9a9a9a] dark:text-[#6b6b6b]">
|
<span className="text-[10px] text-muted-foreground">
|
||||||
<BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
|
<BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
|
||||||
</span>
|
</span>
|
||||||
<BranchPickerPrimitive.Next asChild>
|
<BranchPickerPrimitive.Next asChild>
|
||||||
<button className="text-[#9a9a9a] dark:text-[#6b6b6b] hover:text-[#0d0d0d] dark:hover:text-white transition-colors">
|
<button className="text-muted-foreground hover:text-foreground transition-colors">
|
||||||
<ChevronRightIcon className="h-3 w-3" />
|
<ChevronRightIcon className="h-3 w-3" />
|
||||||
</button>
|
</button>
|
||||||
</BranchPickerPrimitive.Next>
|
</BranchPickerPrimitive.Next>
|
||||||
|
|||||||
Reference in New Issue
Block a user