refactor: migrate frontend from shadcn/Tailwind to Mantine v9

Reescribe todos los componentes UI para usar Mantine v9 en lugar de shadcn/Tailwind.
Elimina cn(), CVA, components.json, theme_provider custom y globals.css con Tailwind.
Añade 25+ componentes nuevos (AppShell, AuthForm, DatePickerInput, Dropzone, etc.)
y MantineProvider como wrapper estándar del sistema de temas.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-06 23:46:44 +02:00
parent 4b2bb6998a
commit 97a3c84625
163 changed files with 6008 additions and 6310 deletions
+64 -45
View File
@@ -1,23 +1,6 @@
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '../core/cn'
import { Progress, Box } from "@mantine/core"
const progressBarVariants = cva(
'relative w-full overflow-hidden rounded-full bg-muted',
{
variants: {
size: { sm: 'h-1', md: 'h-2', lg: 'h-3' },
color: {
primary: '[&_.progress-fill]:bg-primary',
success: '[&_.progress-fill]:bg-emerald-500',
warning: '[&_.progress-fill]:bg-amber-500',
destructive: '[&_.progress-fill]:bg-destructive',
},
},
defaultVariants: { size: 'md', color: 'primary' },
}
)
export interface ProgressBarProps extends VariantProps<typeof progressBarVariants> {
export interface ProgressBarProps {
value: number
max?: number
buffer?: number
@@ -25,44 +8,80 @@ export interface ProgressBarProps extends VariantProps<typeof progressBarVariant
animated?: boolean
indeterminate?: boolean
label?: string
size?: "sm" | "md" | "lg"
color?: "primary" | "success" | "warning" | "destructive"
className?: string
}
const colorMap: Record<NonNullable<ProgressBarProps["color"]>, string> = {
primary: "blue",
success: "green",
warning: "yellow",
destructive: "red",
}
const sizeMap: Record<NonNullable<ProgressBarProps["size"]>, number> = {
sm: 4,
md: 8,
lg: 12,
}
export function ProgressBar({
value, max = 100, buffer, showValue = false, animated = false,
indeterminate = false, size = 'md', color = 'primary', label, className,
value,
max = 100,
buffer,
showValue = false,
animated = false,
indeterminate = false,
size = "md",
color = "primary",
label,
className,
}: ProgressBarProps) {
const percentage = Math.min(100, Math.max(0, (value / max) * 100))
const bufferPercentage = buffer ? Math.min(100, Math.max(0, (buffer / max) * 100)) : undefined
const mantineColor = colorMap[color]
const mantineSize = sizeMap[size]
if (bufferPercentage !== undefined) {
return (
<Box data-slot="progress-bar" pos="relative" className={className}>
<Progress.Root size={mantineSize} aria-label={label}>
<Progress.Section value={bufferPercentage} color={mantineColor} style={{ opacity: 0.3 }} />
</Progress.Root>
<Box pos="absolute" top={0} left={0} right={0}>
<Progress.Root size={mantineSize} bg="transparent" aria-label={label}>
<Progress.Section
value={indeterminate ? 100 : percentage}
color={mantineColor}
animated={animated || indeterminate}
>
{showValue && !indeterminate && (
<Progress.Label>{Math.round(percentage)}%</Progress.Label>
)}
</Progress.Section>
</Progress.Root>
</Box>
</Box>
)
}
return (
<div
<Progress.Root
data-slot="progress-bar"
role="progressbar"
aria-valuenow={indeterminate ? undefined : value}
aria-valuemin={0}
aria-valuemax={max}
size={mantineSize}
aria-label={label}
className={cn(progressBarVariants({ size, color }), className)}
className={className}
>
{bufferPercentage !== undefined && (
<div className="progress-buffer absolute inset-0 bg-current opacity-20 transition-all duration-300" style={{ width: `${bufferPercentage}%` }} />
)}
<div
className={cn(
'progress-fill h-full transition-all duration-300',
animated && 'bg-[length:1rem_1rem] bg-[linear-gradient(45deg,rgba(255,255,255,.15)_25%,transparent_25%,transparent_50%,rgba(255,255,255,.15)_50%,rgba(255,255,255,.15)_75%,transparent_75%,transparent)] animate-[progress-stripes_1s_linear_infinite]',
indeterminate && 'w-1/3 animate-[progress-indeterminate_1.5s_ease-in-out_infinite]'
<Progress.Section
value={indeterminate ? 100 : percentage}
color={mantineColor}
animated={animated || indeterminate}
>
{showValue && !indeterminate && (
<Progress.Label>{Math.round(percentage)}%</Progress.Label>
)}
style={indeterminate ? undefined : { width: `${percentage}%` }}
/>
{showValue && !indeterminate && (
<span className="absolute inset-0 flex items-center justify-center text-[10px] font-medium text-foreground mix-blend-difference">
{Math.round(percentage)}%
</span>
)}
</div>
</Progress.Section>
</Progress.Root>
)
}
export { progressBarVariants }