diff --git a/src/components/patterns/EmptyState.tsx b/src/components/patterns/EmptyState.tsx
new file mode 100644
index 0000000..4d9352d
--- /dev/null
+++ b/src/components/patterns/EmptyState.tsx
@@ -0,0 +1,23 @@
+import { type ReactElement, type ReactNode } from "react";
+import { cn } from "@/lib/utils";
+
+interface EmptyStateProps {
+ icon?: ReactElement;
+ title: string;
+ description?: string;
+ action?: ReactNode;
+ className?: string;
+}
+
+export function EmptyState({ icon, title, description, action, className }: EmptyStateProps) {
+ return (
+
+ {icon &&
{icon}
}
+
{title}
+ {description && (
+
{description}
+ )}
+ {action &&
{action}
}
+
+ );
+}
diff --git a/src/components/patterns/FieldRow.tsx b/src/components/patterns/FieldRow.tsx
new file mode 100644
index 0000000..fee697a
--- /dev/null
+++ b/src/components/patterns/FieldRow.tsx
@@ -0,0 +1,28 @@
+import { type ReactNode } from "react";
+import { cn } from "@/lib/utils";
+
+interface FieldRowProps {
+ label: string;
+ description?: string;
+ children: ReactNode;
+ separator?: boolean;
+ className?: string;
+}
+
+export function FieldRow({ label, description, children, separator, className }: FieldRowProps) {
+ return (
+
+
+
{label}
+ {description && (
+
{description}
+ )}
+
+
{children}
+
+ );
+}
diff --git a/src/components/patterns/IconAction.tsx b/src/components/patterns/IconAction.tsx
new file mode 100644
index 0000000..78b8c72
--- /dev/null
+++ b/src/components/patterns/IconAction.tsx
@@ -0,0 +1,40 @@
+import { type ReactElement, forwardRef, type ComponentPropsWithoutRef } from "react";
+import { cn } from "@/lib/utils";
+import { Button } from "@/components/ui/button";
+import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
+
+interface IconActionProps extends Omit, "variant" | "size" | "children"> {
+ icon: ReactElement;
+ tooltip?: string;
+ size?: "sm" | "md";
+}
+
+export const IconAction = forwardRef(
+ function IconAction({ icon, tooltip, size = "md", className, ...props }, ref) {
+ const button = (
+
+ );
+
+ if (tooltip) {
+ return (
+
+ {button}
+ {tooltip}
+
+ );
+ }
+
+ return button;
+ }
+);
diff --git a/src/components/patterns/SectionPage.tsx b/src/components/patterns/SectionPage.tsx
new file mode 100644
index 0000000..b3b32a9
--- /dev/null
+++ b/src/components/patterns/SectionPage.tsx
@@ -0,0 +1,22 @@
+import { type ReactNode } from "react";
+import { cn } from "@/lib/utils";
+
+const maxWidthMap = {
+ sm: "max-w-xl",
+ md: "max-w-2xl",
+ lg: "max-w-3xl",
+} as const;
+
+interface SectionPageProps {
+ children: ReactNode;
+ maxWidth?: "sm" | "md" | "lg";
+ className?: string;
+}
+
+export function SectionPage({ children, maxWidth = "lg", className }: SectionPageProps) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/components/patterns/SettingsCard.tsx b/src/components/patterns/SettingsCard.tsx
new file mode 100644
index 0000000..e3cf1fb
--- /dev/null
+++ b/src/components/patterns/SettingsCard.tsx
@@ -0,0 +1,23 @@
+import { type ReactNode } from "react";
+import { cn } from "@/lib/utils";
+
+interface SettingsCardProps {
+ title?: string;
+ description?: string;
+ children: ReactNode;
+ className?: string;
+}
+
+export function SettingsCard({ title, description, children, className }: SettingsCardProps) {
+ return (
+
+ {(title || description) && (
+
+ {title &&
{title}
}
+ {description &&
{description}
}
+
+ )}
+ {children}
+
+ );
+}
diff --git a/src/components/patterns/StatusBanner.tsx b/src/components/patterns/StatusBanner.tsx
new file mode 100644
index 0000000..3550492
--- /dev/null
+++ b/src/components/patterns/StatusBanner.tsx
@@ -0,0 +1,29 @@
+import { type ReactElement, type ReactNode } from "react";
+import { cn } from "@/lib/utils";
+
+const variantStyles = {
+ success: "bg-green-500/10 text-green-600 dark:text-green-400",
+ warning: "bg-orange-500/10 text-orange-600 dark:text-orange-400",
+ error: "bg-red-500/10 text-red-600 dark:text-red-400",
+ info: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
+} as const;
+
+interface StatusBannerProps {
+ variant: "success" | "warning" | "error" | "info";
+ icon?: ReactElement;
+ children: ReactNode;
+ className?: string;
+}
+
+export function StatusBanner({ variant, icon, children, className }: StatusBannerProps) {
+ return (
+
+ {icon &&
{icon}
}
+
{children}
+
+ );
+}
diff --git a/src/components/patterns/index.ts b/src/components/patterns/index.ts
new file mode 100644
index 0000000..a1f31e2
--- /dev/null
+++ b/src/components/patterns/index.ts
@@ -0,0 +1,6 @@
+export { SettingsCard } from "./SettingsCard";
+export { FieldRow } from "./FieldRow";
+export { SectionPage } from "./SectionPage";
+export { StatusBanner } from "./StatusBanner";
+export { EmptyState } from "./EmptyState";
+export { IconAction } from "./IconAction";