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 { 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 navItems = [
@ -33,13 +38,21 @@ export const Navbar = () => {
return (
<div className="fixed top-1 left-0 right-0 z-60 w-full select-none">
<DesktopNav navItems={navItems} isScrolled={isScrolled} />
<MobileNav navItems={navItems} isScrolled={isScrolled} />
<DesktopNav
navItems={navItems}
isScrolled={isScrolled}
scrolledBgClassName={scrolledBgClassName}
/>
<MobileNav
navItems={navItems}
isScrolled={isScrolled}
scrolledBgClassName={scrolledBgClassName}
/>
</div>
);
};
const DesktopNav = ({ navItems, isScrolled }: any) => {
const DesktopNav = ({ navItems, isScrolled, scrolledBgClassName }: any) => {
const [hovered, setHovered] = useState<number | null>(null);
return (
<motion.div
@ -49,7 +62,8 @@ const DesktopNav = ({ navItems, isScrolled }: any) => {
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",
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"
)}
>
@ -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 navRef = useRef<HTMLDivElement>(null);
@ -133,7 +147,8 @@ const MobileNav = ({ navItems, isScrolled }: any) => {
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",
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"
)}
>

View file

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

View file

@ -24,7 +24,7 @@ interface PublicThreadProps {
export const PublicThread: FC<PublicThreadProps> = ({ footer }) => {
return (
<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={{
["--thread-max-width" as string]: "44rem",
}}
@ -42,7 +42,7 @@ export const PublicThread: FC<PublicThreadProps> = ({ footer }) => {
</ThreadPrimitive.Viewport>
{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}
</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="px-5 pt-5 pb-4">
<p className="text-sm font-semibold text-muted-foreground">Report Cancelled</p>
<p className="text-xs text-muted-foreground mt-0.5">
Report generation was cancelled
</p>
<p className="text-xs text-muted-foreground mt-0.5">Report generation was cancelled</p>
</div>
</div>
);
@ -229,8 +227,7 @@ function ReportCard({
<span className="inline-block h-3 w-24 rounded bg-muted/60 animate-pulse" />
) : (
<>
{metadata.wordCount != null &&
`${metadata.wordCount.toLocaleString()} words`}
{metadata.wordCount != null && `${metadata.wordCount.toLocaleString()} words`}
{metadata.wordCount != null && metadata.versionLabel && (
<Dot className="inline size-4" />
)}
@ -250,8 +247,7 @@ function ReportCard({
className="max-h-[7rem] overflow-hidden [&_*]:!text-[24px]"
style={{
maskImage: "linear-gradient(to bottom, black 50%, transparent 100%)",
WebkitMaskImage:
"linear-gradient(to bottom, black 50%, transparent 100%)",
WebkitMaskImage: "linear-gradient(to bottom, black 50%, transparent 100%)",
}}
>
<PlateEditor