import React from "react"; import { cn } from "~/lib/utils"; import { colors, typography, spacing, borderRadius, shadows, } from "~/lib/design-tokens"; // Button Component with Figma variants interface ButtonProps extends React.ButtonHTMLAttributes { variant?: "primary" | "secondary" | "outline" | "ghost" | "destructive"; size?: "sm" | "md" | "lg"; fullWidth?: boolean; loading?: boolean; leftIcon?: React.ReactNode; rightIcon?: React.ReactNode; } export const Button = React.forwardRef( ( { className, variant = "primary", size = "md", fullWidth = false, loading = false, leftIcon, rightIcon, children, disabled, ...props }, ref, ) => { const baseStyles = "inline-flex items-center justify-center font-medium transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed font-persian"; const variants = { primary: "bg-primary text-primary-foreground hover:bg-primary/90 focus:ring-primary active:bg-primary/80", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/90 focus:ring-secondary active:bg-secondary/80", teal: "bg-teal-500 text-slate-800 hover:bg-teal-600 focus:ring-teal-500 active:bg-teal-700", outline: "border border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground focus:ring-ring", ghost: "text-foreground hover:bg-accent hover:text-accent-foreground focus:ring-ring", destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90 focus:ring-destructive active:bg-destructive/80", }; const sizes = { sm: "h-8 px-3 text-sm rounded-md", md: "h-10 px-4 text-sm rounded-lg", lg: "h-12 px-6 text-base rounded-lg", }; return ( ); }, ); Button.displayName = "Button"; // Input Component interface InputProps extends React.InputHTMLAttributes { label?: string; error?: string; helper?: string; leftIcon?: React.ReactNode; rightIcon?: React.ReactNode; inputSize?: "sm" | "md" | "lg"; } export const Input = React.forwardRef( ( { className, label, error, helper, leftIcon, rightIcon, inputSize = "md", ...props }, ref, ) => { const baseStyles = "w-full border rounded-lg transition-colors duration-200 focus:outline-none focus:ring-2 disabled:opacity-50 disabled:cursor-not-allowed font-persian text-right"; const sizes = { sm: "h-8 px-3 text-sm", md: "h-10 px-3 text-sm", lg: "h-12 px-4 text-base", }; const variants = error ? "border-destructive focus:border-destructive focus:ring-destructive/20" : "border-input focus:border-primary focus:ring-primary/20"; return (
{label && ( )}
{leftIcon && (
{leftIcon}
)} {rightIcon && (
{rightIcon}
)}
{error && (

{error}

)} {helper && !error && (

{helper}

)}
); }, ); Input.displayName = "Input"; // Card Component interface CardProps extends React.HTMLAttributes { variant?: "default" | "bordered" | "shadow" | "elevated"; padding?: "none" | "sm" | "md" | "lg"; } export const Card = React.forwardRef( ( { className, variant = "default", padding = "md", children, ...props }, ref, ) => { const baseStyles = "rounded-lg bg-card"; const variants = { default: "border border-border", bordered: "border-2 border-border", shadow: "shadow-md border border-border", elevated: "shadow-lg border border-border", }; const paddings = { none: "", sm: "p-4", md: "p-6", lg: "p-8", }; return (
{children}
); }, ); Card.displayName = "Card"; // Badge Component interface BadgeProps extends React.HTMLAttributes { variant?: | "default" | "primary" | "secondary" | "success" | "warning" | "error"; size?: "sm" | "md" | "lg"; } export const Badge = React.forwardRef( ( { className, variant = "default", size = "md", children, ...props }, ref, ) => { const baseStyles = "inline-flex items-center font-medium rounded-full font-persian"; const variants = { default: "bg-secondary text-secondary-foreground", primary: "bg-primary/10 text-primary", secondary: "bg-secondary/10 text-secondary", success: "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200", warning: "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200", error: "bg-destructive/10 text-destructive", }; const sizes = { sm: "px-2 py-0.5 text-xs", md: "px-2.5 py-0.5 text-sm", lg: "px-3 py-1 text-sm", }; return ( {children} ); }, ); Badge.displayName = "Badge"; // Avatar Component interface AvatarProps extends React.HTMLAttributes { src?: string; alt?: string; size?: "sm" | "md" | "lg" | "xl"; fallback?: string; } export const Avatar = React.forwardRef( ({ className, src, alt, size = "md", fallback, ...props }, ref) => { const sizes = { sm: "h-8 w-8", md: "h-10 w-10", lg: "h-12 w-12", xl: "h-16 w-16", }; const textSizes = { sm: "text-xs", md: "text-sm", lg: "text-base", xl: "text-lg", }; return (
{src ? ( {alt} ) : ( {fallback} )}
); }, ); Avatar.displayName = "Avatar"; // Loading Spinner Component interface SpinnerProps extends React.HTMLAttributes { size?: "sm" | "md" | "lg"; color?: "primary" | "secondary" | "white"; } export const Spinner = React.forwardRef( ({ className, size = "md", color = "primary", ...props }, ref) => { const sizes = { sm: "h-4 w-4", md: "h-6 w-6", lg: "h-8 w-8", }; const colors = { primary: "text-primary", secondary: "text-secondary", white: "text-white", }; return (
); }, ); Spinner.displayName = "Spinner"; // Progress Bar Component interface ProgressProps extends React.HTMLAttributes { value: number; max?: number; size?: "sm" | "md" | "lg"; variant?: "default" | "success" | "warning" | "error"; showLabel?: boolean; } export const Progress = React.forwardRef( ( { className, value, max = 100, size = "md", variant = "default", showLabel = false, ...props }, ref, ) => { const percentage = Math.min(Math.max((value / max) * 100, 0), 100); const sizes = { sm: "h-1", md: "h-2", lg: "h-3", }; const variants = { default: "bg-primary", success: "bg-green-500", warning: "bg-yellow-500", error: "bg-destructive", }; return (
{showLabel && (
پیشرفت {Math.round(percentage)}%
)}
); }, ); Progress.displayName = "Progress"; // Divider Component interface DividerProps extends React.HTMLAttributes { orientation?: "horizontal" | "vertical"; variant?: "solid" | "dashed" | "dotted"; } export const Divider = React.forwardRef( ( { className, orientation = "horizontal", variant = "solid", ...props }, ref, ) => { const baseStyles = "border-border"; const orientations = { horizontal: "w-full border-t", vertical: "h-full border-l", }; const variants = { solid: "border-solid", dashed: "border-dashed", dotted: "border-dotted", }; return (
); }, ); Divider.displayName = "Divider";