Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions frontend/app/components/Banner/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Banner, BannerClose, BannerTitle } from "@/components/ui/banner";

interface BannerComponentInterface {
title: string;
}

export default function BannerComponent({ title }: BannerComponentInterface) {
return (
<Banner>
<BannerTitle>{title}</BannerTitle>
<BannerClose />
</Banner>
);
}
Empty file.
21 changes: 14 additions & 7 deletions frontend/app/components/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import LoginX from "@/components/Authentication/LoginX";
import BackButton from "@/components/BackButton";
import BannerComponent from "@/components/Banner";
import { AppearanceToggle } from "@/components/ui/appearance-toggle";
import { useAuthStatus } from "@/hooks/use-auth-status";
import { usePathname } from "next/navigation";
Expand All @@ -11,12 +12,18 @@ export default function Header() {
const { authData } = useAuthStatus();

return (
<header className="flex flex-row items-center justify-between px-4 py-6 md:px-6">
<div>{pathname !== "/" && <BackButton />}</div>
<div className="flex items-center gap-2">
<LoginX name={authData?.name ?? ""} />
<AppearanceToggle />
</div>
</header>
<>
<BannerComponent
title="⚠️&nbsp; Notice: AWS resources have been spun down. The backend is
Copy link

Copilot AI Aug 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The HTML entity &nbsp; should not be used in JSX text content. Use a regular space or consider using CSS for spacing control.

Suggested change
title="⚠️&nbsp; Notice: AWS resources have been spun down. The backend is
title="⚠️ Notice: AWS resources have been spun down. The backend is

Copilot uses AI. Check for mistakes.
currently not running."
Comment on lines +17 to +18
Copy link

Copilot AI Aug 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The title prop spans multiple lines but appears to be missing the closing quote and continuation. This will cause a syntax error.

Suggested change
title="⚠️&nbsp; Notice: AWS resources have been spun down. The backend is
currently not running."
title={`⚠️&nbsp; Notice: AWS resources have been spun down. The backend is
currently not running.`}

Copilot uses AI. Check for mistakes.
/>
<header className="flex flex-row items-center justify-between px-4 py-6 md:px-6">
<div>{pathname !== "/" && <BackButton />}</div>
<div className="flex items-center gap-2">
<LoginX name={authData?.name ?? ""} />
<AppearanceToggle />
</div>
</header>
</>
);
}
139 changes: 139 additions & 0 deletions frontend/app/components/ui/banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
"use client";

import { Button } from "@/components/ui/button";
import { cn } from "@/lib/constants/utils";
import { useControllableState } from "@radix-ui/react-use-controllable-state";
import { type LucideIcon, XIcon } from "lucide-react";
import {
type ComponentProps,
createContext,
type HTMLAttributes,
type MouseEventHandler,
useContext,
} from "react";

type BannerContextProps = {
show: boolean;
setShow: (show: boolean) => void;
};

export const BannerContext = createContext<BannerContextProps>({
show: true,
setShow: () => {},
});

export type BannerProps = HTMLAttributes<HTMLDivElement> & {
visible?: boolean;
defaultVisible?: boolean;
onClose?: () => void;
inset?: boolean;
};

export const Banner = ({
children,
visible,
defaultVisible = true,
onClose,
className,
inset = false,
...props
}: BannerProps) => {
const [show, setShow] = useControllableState({
defaultProp: defaultVisible,
prop: visible,
onChange: onClose,
});

if (!show) {
return null;
}

return (
<BannerContext.Provider value={{ show, setShow }}>
<div
className={cn(
"flex w-full items-center justify-between gap-2 bg-orange-400 px-4 py-1 text-white",
inset && "rounded-lg",
className,
)}
{...props}
>
{children}
</div>
</BannerContext.Provider>
);
};

export type BannerIconProps = HTMLAttributes<HTMLDivElement> & {
icon: LucideIcon;
};

export const BannerIcon = ({
icon: Icon,
className,
...props
}: BannerIconProps) => (
<div
className={cn(
"rounded-full border border-background/20 bg-background/10 p-1 shadow-sm",
className,
)}
{...props}
>
<Icon size={16} />
</div>
);

export type BannerTitleProps = HTMLAttributes<HTMLParagraphElement>;

export const BannerTitle = ({ className, ...props }: BannerTitleProps) => (
<p className={cn("flex-1 text-sm", className)} {...props} />
);

export type BannerActionProps = ComponentProps<typeof Button>;

export const BannerAction = ({
variant = "ghost",
size = "sm",
className,
...props
}: BannerActionProps) => (
<Button
className={cn("shrink-0 bg-transparent", className)}
size={size}
variant={variant}
{...props}
/>
);

export type BannerCloseProps = ComponentProps<typeof Button>;

export const BannerClose = ({
variant = "transparent",
size = "icon",
onClick,
className,
...props
}: BannerCloseProps) => {
const { setShow } = useContext(BannerContext);

const handleClick: MouseEventHandler<HTMLButtonElement> = (e) => {
setShow(false);
onClick?.(e);
};

return (
<Button
className={cn(
"shrink-0 bg-transparent hover:bg-background/10 hover:text-background",
className,
)}
onClick={handleClick}
size={size}
variant={variant}
{...props}
>
<XIcon size={18} color="white" />
</Button>
);
};
1 change: 1 addition & 0 deletions frontend/app/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const buttonVariants = cva(
ghost:
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
link: "text-primary underline-offset-4 hover:underline",
transparent: "bg-transparent hover:bg-transparent hover:text-inherit",
},
size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3",
Expand Down
Binary file modified frontend/bun.lockb
Binary file not shown.
5 changes: 3 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"@radix-ui/react-label": "^2.1.6",
"@radix-ui/react-popover": "^1.1.13",
"@radix-ui/react-select": "^2.2.4",
"@radix-ui/react-slot": "^1.2.2",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-use-controllable-state": "^1.2.2",
"@tanstack/react-query": "^5.75.5",
"axios": "^1.9.0",
"class-variance-authority": "^0.7.1",
Expand All @@ -26,7 +27,7 @@
"dompurify": "^3.2.6",
"framer-motion": "^12.12.1",
"install": "^0.13.0",
"lucide-react": "^0.508.0",
"lucide-react": "^0.535.0",
"next": "15.3.2",
"next-themes": "^0.4.6",
"postcss": "^8.5.3",
Expand Down