Create src/components/patterns/ with 6 pure-presentation components that abstract repeated layout patterns from settings/bridge pages: - SettingsCard: rounded card with optional title/description - FieldRow: label+description left, control right, optional separator - SectionPage: max-width page container with consistent spacing - StatusBanner: success/warning/error/info inline status messages - EmptyState: centered empty state with icon, title, description, action - IconAction: ghost icon button with optional tooltip wrapper All components are zero-side-effect, only import from React and @/lib/utils (plus ui/button and ui/tooltip for IconAction). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
41 lines
1.1 KiB
TypeScript
41 lines
1.1 KiB
TypeScript
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<ComponentPropsWithoutRef<typeof Button>, "variant" | "size" | "children"> {
|
|
icon: ReactElement;
|
|
tooltip?: string;
|
|
size?: "sm" | "md";
|
|
}
|
|
|
|
export const IconAction = forwardRef<HTMLButtonElement, IconActionProps>(
|
|
function IconAction({ icon, tooltip, size = "md", className, ...props }, ref) {
|
|
const button = (
|
|
<Button
|
|
ref={ref}
|
|
variant="ghost"
|
|
size="icon"
|
|
className={cn(
|
|
size === "sm" ? "h-7 w-7" : "h-8 w-8",
|
|
className
|
|
)}
|
|
{...props}
|
|
>
|
|
{icon}
|
|
</Button>
|
|
);
|
|
|
|
if (tooltip) {
|
|
return (
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>{button}</TooltipTrigger>
|
|
<TooltipContent>{tooltip}</TooltipContent>
|
|
</Tooltip>
|
|
);
|
|
}
|
|
|
|
return button;
|
|
}
|
|
);
|