migration wip
This commit is contained in:
162
components/ui/Badge.tsx
Normal file
162
components/ui/Badge.tsx
Normal file
@@ -0,0 +1,162 @@
|
||||
import React, { forwardRef, ReactNode, HTMLAttributes } from 'react';
|
||||
import { cn } from '../../lib/utils';
|
||||
|
||||
// Badge variants
|
||||
type BadgeVariant = 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' | 'neutral';
|
||||
|
||||
// Badge sizes
|
||||
type BadgeSize = 'sm' | 'md' | 'lg';
|
||||
|
||||
// Badge props interface
|
||||
interface BadgeProps extends HTMLAttributes<HTMLDivElement> {
|
||||
variant?: BadgeVariant;
|
||||
size?: BadgeSize;
|
||||
icon?: ReactNode;
|
||||
iconPosition?: 'left' | 'right';
|
||||
rounded?: boolean;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
// Helper function to get variant styles
|
||||
const getVariantStyles = (variant: BadgeVariant) => {
|
||||
switch (variant) {
|
||||
case 'primary':
|
||||
return 'bg-primary text-white';
|
||||
case 'secondary':
|
||||
return 'bg-secondary text-white';
|
||||
case 'success':
|
||||
return 'bg-success text-white';
|
||||
case 'warning':
|
||||
return 'bg-warning text-gray-900';
|
||||
case 'error':
|
||||
return 'bg-danger text-white';
|
||||
case 'info':
|
||||
return 'bg-info text-white';
|
||||
case 'neutral':
|
||||
return 'bg-gray-200 text-gray-800';
|
||||
default:
|
||||
return 'bg-primary text-white';
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to get size styles
|
||||
const getSizeStyles = (size: BadgeSize) => {
|
||||
switch (size) {
|
||||
case 'sm':
|
||||
return 'text-xs px-2 py-0.5';
|
||||
case 'md':
|
||||
return 'text-sm px-3 py-1';
|
||||
case 'lg':
|
||||
return 'text-base px-4 py-1.5';
|
||||
default:
|
||||
return 'text-sm px-3 py-1';
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to get icon spacing
|
||||
const getIconSpacing = (size: BadgeSize, iconPosition: 'left' | 'right') => {
|
||||
const spacing = {
|
||||
sm: iconPosition === 'left' ? 'mr-1' : 'ml-1',
|
||||
md: iconPosition === 'left' ? 'mr-1.5' : 'ml-1.5',
|
||||
lg: iconPosition === 'left' ? 'mr-2' : 'ml-2',
|
||||
};
|
||||
return spacing[size];
|
||||
};
|
||||
|
||||
// Helper function to get icon size
|
||||
const getIconSize = (size: BadgeSize) => {
|
||||
const sizeClasses = {
|
||||
sm: 'w-3 h-3',
|
||||
md: 'w-4 h-4',
|
||||
lg: 'w-5 h-5',
|
||||
};
|
||||
return sizeClasses[size];
|
||||
};
|
||||
|
||||
// Main Badge Component
|
||||
export const Badge = forwardRef<HTMLDivElement, BadgeProps>(
|
||||
(
|
||||
{
|
||||
variant = 'primary',
|
||||
size = 'md',
|
||||
icon,
|
||||
iconPosition = 'left',
|
||||
rounded = true,
|
||||
className = '',
|
||||
children,
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
// Base styles
|
||||
'inline-flex items-center justify-center font-medium',
|
||||
'transition-all duration-200 ease-in-out',
|
||||
// Variant styles
|
||||
getVariantStyles(variant),
|
||||
// Size styles
|
||||
getSizeStyles(size),
|
||||
// Border radius
|
||||
rounded ? 'rounded-full' : 'rounded-md',
|
||||
// Custom classes
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{/* Icon - Left position */}
|
||||
{icon && iconPosition === 'left' && (
|
||||
<span className={cn('flex items-center justify-center', getIconSpacing(size, 'left'), getIconSize(size))}>
|
||||
{icon}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{/* Badge content */}
|
||||
{children && <span>{children}</span>}
|
||||
|
||||
{/* Icon - Right position */}
|
||||
{icon && iconPosition === 'right' && (
|
||||
<span className={cn('flex items-center justify-center', getIconSpacing(size, 'right'), getIconSize(size))}>
|
||||
{icon}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Badge.displayName = 'Badge';
|
||||
|
||||
// Badge Group Component for multiple badges
|
||||
interface BadgeGroupProps extends HTMLAttributes<HTMLDivElement> {
|
||||
children?: ReactNode;
|
||||
gap?: 'xs' | 'sm' | 'md' | 'lg';
|
||||
}
|
||||
|
||||
export const BadgeGroup = forwardRef<HTMLDivElement, BadgeGroupProps>(
|
||||
({ gap = 'sm', className = '', children, ...props }, ref) => {
|
||||
const gapClasses = {
|
||||
xs: 'gap-1',
|
||||
sm: 'gap-2',
|
||||
md: 'gap-3',
|
||||
lg: 'gap-4',
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn('flex flex-wrap items-center', gapClasses[gap], className)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
BadgeGroup.displayName = 'BadgeGroup';
|
||||
|
||||
// Export types for external use
|
||||
export type { BadgeProps, BadgeVariant, BadgeSize, BadgeGroupProps };
|
||||
Reference in New Issue
Block a user