diff --git a/.github/workflows/merged_backend.yml b/.github/workflows/merged_backend.yml.disabled
similarity index 100%
rename from .github/workflows/merged_backend.yml
rename to .github/workflows/merged_backend.yml.disabled
diff --git a/frontend/app/components/Banner/index.tsx b/frontend/app/components/Banner/index.tsx
new file mode 100644
index 0000000..b62f0dd
--- /dev/null
+++ b/frontend/app/components/Banner/index.tsx
@@ -0,0 +1,14 @@
+import { Banner, BannerClose, BannerTitle } from "@/components/ui/banner";
+
+interface BannerComponentInterface {
+ title: string;
+}
+
+export default function BannerComponent({ title }: BannerComponentInterface) {
+ return (
+
+ {title}
+
+
+ );
+}
diff --git a/frontend/app/components/Header/bannerAlert.tsx b/frontend/app/components/Header/bannerAlert.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/app/components/Header/index.tsx b/frontend/app/components/Header/index.tsx
index 4749896..23530ea 100644
--- a/frontend/app/components/Header/index.tsx
+++ b/frontend/app/components/Header/index.tsx
@@ -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";
@@ -11,12 +12,18 @@ export default function Header() {
const { authData } = useAuthStatus();
return (
-
- {pathname !== "/" && }
-
-
+ <>
+
+
+ {pathname !== "/" && }
+
+
+ >
);
}
diff --git a/frontend/app/components/ui/banner.tsx b/frontend/app/components/ui/banner.tsx
new file mode 100644
index 0000000..61b3d68
--- /dev/null
+++ b/frontend/app/components/ui/banner.tsx
@@ -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({
+ show: true,
+ setShow: () => {},
+});
+
+export type BannerProps = HTMLAttributes & {
+ 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 (
+
+
+ {children}
+
+
+ );
+};
+
+export type BannerIconProps = HTMLAttributes & {
+ icon: LucideIcon;
+};
+
+export const BannerIcon = ({
+ icon: Icon,
+ className,
+ ...props
+}: BannerIconProps) => (
+
+
+
+);
+
+export type BannerTitleProps = HTMLAttributes;
+
+export const BannerTitle = ({ className, ...props }: BannerTitleProps) => (
+
+);
+
+export type BannerActionProps = ComponentProps;
+
+export const BannerAction = ({
+ variant = "ghost",
+ size = "sm",
+ className,
+ ...props
+}: BannerActionProps) => (
+
+);
+
+export type BannerCloseProps = ComponentProps;
+
+export const BannerClose = ({
+ variant = "transparent",
+ size = "icon",
+ onClick,
+ className,
+ ...props
+}: BannerCloseProps) => {
+ const { setShow } = useContext(BannerContext);
+
+ const handleClick: MouseEventHandler = (e) => {
+ setShow(false);
+ onClick?.(e);
+ };
+
+ return (
+
+ );
+};
diff --git a/frontend/app/components/ui/button.tsx b/frontend/app/components/ui/button.tsx
index 04e6e88..fa3dedc 100644
--- a/frontend/app/components/ui/button.tsx
+++ b/frontend/app/components/ui/button.tsx
@@ -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",
diff --git a/frontend/bun.lockb b/frontend/bun.lockb
index 0f1202f..76f83d5 100755
Binary files a/frontend/bun.lockb and b/frontend/bun.lockb differ
diff --git a/frontend/package.json b/frontend/package.json
index a8d7442..28827c1 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -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",
@@ -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",