From 11c6aa8c556bdd3997062bd260d1f5fd55d31219 Mon Sep 17 00:00:00 2001 From: jbatte47 Date: Tue, 10 Mar 2026 23:26:43 -0500 Subject: [PATCH] feat(components): add card component Fixes #17 --- src/components/Card.tsx | 44 +++++++++++++++++++++++++++++++++++++++++ src/components/index.ts | 1 + 2 files changed, 45 insertions(+) create mode 100644 src/components/Card.tsx diff --git a/src/components/Card.tsx b/src/components/Card.tsx new file mode 100644 index 0000000..0e0e0bf --- /dev/null +++ b/src/components/Card.tsx @@ -0,0 +1,44 @@ +import { forwardRef, type HTMLAttributes } from 'react'; + +type CardVariant = 'default' | 'glass' | 'outlined'; + +export type CardProps = HTMLAttributes & { + /** Visual style variant */ + variant?: CardVariant; + /** Enable hover lift effect */ + interactive?: boolean; + /** Additional CSS classes */ + className?: string; +}; + +const variantClasses: Record = { + default: 'bg-bg-surface-raised border border-border-subtle shadow-elevation-raised', + glass: ['bg-bg-surface-default/[0.03] border border-border-subtle/50', 'backdrop-blur-xl'].join( + ' ', + ), + outlined: 'bg-transparent border border-border-subtle', +}; + +export const Card = forwardRef( + ({ variant = 'default', interactive = false, className = '', children, ...props }, ref) => { + const classes = [ + 'rounded-2xl p-6', + 'transition-all duration-250 ease-out', + variantClasses[variant], + interactive + ? 'hover:-translate-y-1 hover:shadow-elevation-overlay hover:border-border-strong cursor-pointer' + : '', + className, + ] + .filter(Boolean) + .join(' '); + + return ( +
+ {children} +
+ ); + }, +); + +Card.displayName = 'Card'; diff --git a/src/components/index.ts b/src/components/index.ts index a27ea27..2962ee0 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,3 +1,4 @@ export { Button, type ButtonProps } from './Button'; export { Badge, type BadgeProps } from './Badge'; export { Text, type TextProps } from './Text'; +export { Card, type CardProps } from './Card';