refactor: enhance Navbar component to accept custom background class for scrolled state; update PublicChatView and PublicThread styles for consistency

This commit is contained in:
Anish Sarkar 2026-03-21 22:16:48 +05:30
parent b6be92e394
commit 6f82a8ff9c
4 changed files with 33 additions and 20 deletions

View file

@ -9,7 +9,12 @@ import { Logo } from "@/components/Logo";
import { ThemeTogglerComponent } from "@/components/theme/theme-toggle"; import { ThemeTogglerComponent } from "@/components/theme/theme-toggle";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
export const Navbar = () => { interface NavbarProps {
/** Override the scrolled-state background classes (desktop & mobile). */
scrolledBgClassName?: string;
}
export const Navbar = ({ scrolledBgClassName }: NavbarProps = {}) => {
const [isScrolled, setIsScrolled] = useState(false); const [isScrolled, setIsScrolled] = useState(false);
const navItems = [ const navItems = [
@ -33,13 +38,21 @@ export const Navbar = () => {
return ( return (
<div className="fixed top-1 left-0 right-0 z-60 w-full select-none"> <div className="fixed top-1 left-0 right-0 z-60 w-full select-none">
<DesktopNav navItems={navItems} isScrolled={isScrolled} /> <DesktopNav
<MobileNav navItems={navItems} isScrolled={isScrolled} /> navItems={navItems}
isScrolled={isScrolled}
scrolledBgClassName={scrolledBgClassName}
/>
<MobileNav
navItems={navItems}
isScrolled={isScrolled}
scrolledBgClassName={scrolledBgClassName}
/>
</div> </div>
); );
}; };
const DesktopNav = ({ navItems, isScrolled }: any) => { const DesktopNav = ({ navItems, isScrolled, scrolledBgClassName }: any) => {
const [hovered, setHovered] = useState<number | null>(null); const [hovered, setHovered] = useState<number | null>(null);
return ( return (
<motion.div <motion.div
@ -49,7 +62,8 @@ const DesktopNav = ({ navItems, isScrolled }: any) => {
className={cn( className={cn(
"mx-auto hidden w-full max-w-7xl flex-row items-center justify-between self-start rounded-full px-4 py-2 lg:flex transition-all duration-300", "mx-auto hidden w-full max-w-7xl flex-row items-center justify-between self-start rounded-full px-4 py-2 lg:flex transition-all duration-300",
isScrolled isScrolled
? "bg-white/80 backdrop-blur-md border border-white/20 shadow-lg dark:bg-neutral-950/80 dark:border-neutral-800/50" ? (scrolledBgClassName ??
"bg-white/80 backdrop-blur-md border border-white/20 shadow-lg dark:bg-neutral-950/80 dark:border-neutral-800/50")
: "bg-transparent border border-transparent" : "bg-transparent border border-transparent"
)} )}
> >
@ -104,7 +118,7 @@ const DesktopNav = ({ navItems, isScrolled }: any) => {
); );
}; };
const MobileNav = ({ navItems, isScrolled }: any) => { const MobileNav = ({ navItems, isScrolled, scrolledBgClassName }: any) => {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const navRef = useRef<HTMLDivElement>(null); const navRef = useRef<HTMLDivElement>(null);
@ -133,7 +147,8 @@ const MobileNav = ({ navItems, isScrolled }: any) => {
className={cn( className={cn(
"relative mx-auto flex w-full max-w-[calc(100vw-2rem)] flex-col items-center justify-between px-4 py-2 lg:hidden transition-all duration-300", "relative mx-auto flex w-full max-w-[calc(100vw-2rem)] flex-col items-center justify-between px-4 py-2 lg:hidden transition-all duration-300",
isScrolled isScrolled
? "bg-white/80 backdrop-blur-md border border-white/20 shadow-lg dark:bg-neutral-950/80 dark:border-neutral-800/50" ? (scrolledBgClassName ??
"bg-white/80 backdrop-blur-md border border-white/20 shadow-lg dark:bg-neutral-950/80 dark:border-neutral-800/50")
: "bg-transparent border border-transparent" : "bg-transparent border border-transparent"
)} )}
> >

View file

@ -23,10 +23,12 @@ export function PublicChatView({ shareToken }: PublicChatViewProps) {
const { data, isLoading, error } = usePublicChat(shareToken); const { data, isLoading, error } = usePublicChat(shareToken);
const runtime = usePublicChatRuntime({ data }); const runtime = usePublicChatRuntime({ data });
const navbarScrolledBg = "bg-main-panel/80 backdrop-blur-md border border-border/30 shadow-lg";
if (isLoading) { if (isLoading) {
return ( return (
<main className="min-h-screen bg-linear-to-b from-gray-50 to-gray-100 text-gray-900 dark:from-black dark:to-gray-900 dark:text-white overflow-x-hidden"> <main className="min-h-screen bg-main-panel text-foreground overflow-x-hidden">
<Navbar /> <Navbar scrolledBgClassName={navbarScrolledBg} />
<div className="flex h-screen items-center justify-center"> <div className="flex h-screen items-center justify-center">
<Spinner size="lg" className="text-muted-foreground" /> <Spinner size="lg" className="text-muted-foreground" />
</div> </div>
@ -39,8 +41,8 @@ export function PublicChatView({ shareToken }: PublicChatViewProps) {
} }
return ( return (
<main className="min-h-screen bg-linear-to-b from-gray-50 to-gray-100 text-gray-900 dark:from-black dark:to-gray-900 dark:text-white overflow-x-hidden"> <main className="min-h-screen bg-main-panel text-foreground overflow-x-hidden">
<Navbar /> <Navbar scrolledBgClassName={navbarScrolledBg} />
<AssistantRuntimeProvider runtime={runtime}> <AssistantRuntimeProvider runtime={runtime}>
{/* Tool UIs for rendering tool results */} {/* Tool UIs for rendering tool results */}
<GeneratePodcastToolUI /> <GeneratePodcastToolUI />

View file

@ -24,7 +24,7 @@ interface PublicThreadProps {
export const PublicThread: FC<PublicThreadProps> = ({ footer }) => { export const PublicThread: FC<PublicThreadProps> = ({ footer }) => {
return ( return (
<ThreadPrimitive.Root <ThreadPrimitive.Root
className="aui-root aui-thread-root @container flex h-full min-h-0 flex-col bg-background" className="aui-root aui-thread-root @container flex h-full min-h-0 flex-col bg-main-panel"
style={{ style={{
["--thread-max-width" as string]: "44rem", ["--thread-max-width" as string]: "44rem",
}} }}
@ -42,7 +42,7 @@ export const PublicThread: FC<PublicThreadProps> = ({ footer }) => {
</ThreadPrimitive.Viewport> </ThreadPrimitive.Viewport>
{footer && ( {footer && (
<div className="sticky bottom-0 z-20 border-t bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60"> <div className="sticky bottom-0 z-20 border-t bg-main-panel/95 backdrop-blur supports-backdrop-filter:bg-main-panel/60">
{footer} {footer}
</div> </div>
)} )}

View file

@ -106,9 +106,7 @@ function ReportCancelledState() {
<div className="my-4 max-w-lg overflow-hidden rounded-2xl border bg-muted/30 select-none"> <div className="my-4 max-w-lg overflow-hidden rounded-2xl border bg-muted/30 select-none">
<div className="px-5 pt-5 pb-4"> <div className="px-5 pt-5 pb-4">
<p className="text-sm font-semibold text-muted-foreground">Report Cancelled</p> <p className="text-sm font-semibold text-muted-foreground">Report Cancelled</p>
<p className="text-xs text-muted-foreground mt-0.5"> <p className="text-xs text-muted-foreground mt-0.5">Report generation was cancelled</p>
Report generation was cancelled
</p>
</div> </div>
</div> </div>
); );
@ -229,8 +227,7 @@ function ReportCard({
<span className="inline-block h-3 w-24 rounded bg-muted/60 animate-pulse" /> <span className="inline-block h-3 w-24 rounded bg-muted/60 animate-pulse" />
) : ( ) : (
<> <>
{metadata.wordCount != null && {metadata.wordCount != null && `${metadata.wordCount.toLocaleString()} words`}
`${metadata.wordCount.toLocaleString()} words`}
{metadata.wordCount != null && metadata.versionLabel && ( {metadata.wordCount != null && metadata.versionLabel && (
<Dot className="inline size-4" /> <Dot className="inline size-4" />
)} )}
@ -250,8 +247,7 @@ function ReportCard({
className="max-h-[7rem] overflow-hidden [&_*]:!text-[24px]" className="max-h-[7rem] overflow-hidden [&_*]:!text-[24px]"
style={{ style={{
maskImage: "linear-gradient(to bottom, black 50%, transparent 100%)", maskImage: "linear-gradient(to bottom, black 50%, transparent 100%)",
WebkitMaskImage: WebkitMaskImage: "linear-gradient(to bottom, black 50%, transparent 100%)",
"linear-gradient(to bottom, black 50%, transparent 100%)",
}} }}
> >
<PlateEditor <PlateEditor