ADD new frontend

This commit is contained in:
Urtzi Alfaro
2025-08-28 10:41:04 +02:00
parent 9c247a5f99
commit 0fd273cfce
492 changed files with 114979 additions and 1632 deletions

View File

@@ -0,0 +1,237 @@
import React, { forwardRef, HTMLAttributes } from 'react';
import { clsx } from 'clsx';
export interface CardProps extends HTMLAttributes<HTMLDivElement> {
variant?: 'elevated' | 'outlined' | 'filled' | 'ghost';
padding?: 'none' | 'sm' | 'md' | 'lg' | 'xl';
rounded?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
shadow?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
hoverable?: boolean;
interactive?: boolean;
}
export interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {
padding?: 'none' | 'sm' | 'md' | 'lg' | 'xl';
divider?: boolean;
}
export interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {
padding?: 'none' | 'sm' | 'md' | 'lg' | 'xl';
}
export interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {
padding?: 'none' | 'sm' | 'md' | 'lg' | 'xl';
divider?: boolean;
justify?: 'start' | 'end' | 'center' | 'between' | 'around' | 'evenly';
}
const Card = forwardRef<HTMLDivElement, CardProps>(({
variant = 'elevated',
padding = 'md',
rounded = 'md',
shadow = 'md',
hoverable = false,
interactive = false,
className,
children,
...props
}, ref) => {
const baseClasses = [
'relative',
'transition-all duration-200 ease-in-out',
'bg-[var(--bg-primary)]',
];
const variantClasses = {
elevated: [
'border border-[var(--border-primary)]',
],
outlined: [
'border-2 border-[var(--border-primary)]',
'bg-transparent',
],
filled: [
'bg-[var(--bg-secondary)]',
'border border-transparent',
],
ghost: [
'bg-transparent',
'border border-transparent',
],
};
const paddingClasses = {
none: '',
sm: 'p-3',
md: 'p-4',
lg: 'p-6',
xl: 'p-8',
};
const roundedClasses = {
none: 'rounded-none',
sm: 'rounded-sm',
md: 'rounded-lg',
lg: 'rounded-xl',
xl: 'rounded-2xl',
full: 'rounded-full',
};
const shadowClasses = {
none: '',
sm: 'shadow-sm',
md: 'shadow-md',
lg: 'shadow-lg',
xl: 'shadow-xl',
'2xl': 'shadow-2xl',
};
const interactiveClasses = {
hoverable: 'hover:shadow-lg hover:-translate-y-1',
interactive: 'cursor-pointer hover:shadow-lg hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)]/20 focus:ring-offset-2',
};
const classes = clsx(
baseClasses,
variantClasses[variant],
paddingClasses[padding],
roundedClasses[rounded],
shadowClasses[shadow],
{
[interactiveClasses.hoverable]: hoverable && !interactive,
[interactiveClasses.interactive]: interactive,
},
className
);
const Component = interactive ? 'button' : 'div';
return (
<Component
ref={ref}
className={classes}
{...props}
>
{children}
</Component>
);
});
const CardHeader = forwardRef<HTMLDivElement, CardHeaderProps>(({
padding = 'md',
divider = true,
className,
children,
...props
}, ref) => {
const paddingClasses = {
none: '',
sm: 'p-3',
md: 'p-4',
lg: 'p-6',
xl: 'p-8',
};
const classes = clsx(
'flex items-center justify-between',
paddingClasses[padding],
{
'border-b border-[var(--border-primary)]': divider,
},
className
);
return (
<div
ref={ref}
className={classes}
{...props}
>
{children}
</div>
);
});
const CardBody = forwardRef<HTMLDivElement, CardBodyProps>(({
padding = 'md',
className,
children,
...props
}, ref) => {
const paddingClasses = {
none: '',
sm: 'p-3',
md: 'p-4',
lg: 'p-6',
xl: 'p-8',
};
const classes = clsx(
paddingClasses[padding],
className
);
return (
<div
ref={ref}
className={classes}
{...props}
>
{children}
</div>
);
});
const CardFooter = forwardRef<HTMLDivElement, CardFooterProps>(({
padding = 'md',
divider = true,
justify = 'end',
className,
children,
...props
}, ref) => {
const paddingClasses = {
none: '',
sm: 'p-3',
md: 'p-4',
lg: 'p-6',
xl: 'p-8',
};
const justifyClasses = {
start: 'justify-start',
end: 'justify-end',
center: 'justify-center',
between: 'justify-between',
around: 'justify-around',
evenly: 'justify-evenly',
};
const classes = clsx(
'flex items-center gap-3',
paddingClasses[padding],
justifyClasses[justify],
{
'border-t border-[var(--border-primary)]': divider,
},
className
);
return (
<div
ref={ref}
className={classes}
{...props}
>
{children}
</div>
);
});
Card.displayName = 'Card';
CardHeader.displayName = 'CardHeader';
CardBody.displayName = 'CardBody';
CardFooter.displayName = 'CardFooter';
export default Card;
export { CardHeader, CardBody, CardFooter };

View File

@@ -0,0 +1,3 @@
export { default } from './Card';
export { default as Card, CardHeader, CardBody, CardFooter } from './Card';
export type { CardProps, CardHeaderProps, CardBodyProps, CardFooterProps } from './Card';