website refactor

This commit is contained in:
2026-01-18 18:27:39 +01:00
parent 067502a4c6
commit c35682cae5
36 changed files with 47 additions and 108 deletions

View File

@@ -0,0 +1,59 @@
import { Button } from '@/ui/Button';
import { Stack } from '@/ui/primitives/Stack';
interface OnboardingCTAProps {
onBack?: () => void;
onNext?: () => void;
nextLabel?: string;
backLabel?: string;
isLastStep?: boolean;
canNext?: boolean;
isLoading?: boolean;
type?: 'button' | 'submit';
}
export function OnboardingCTA({
onBack,
onNext,
nextLabel = 'Continue',
backLabel = 'Back',
isLastStep = false,
canNext = true,
isLoading = false,
type = 'button',
}: OnboardingCTAProps) {
return (
<Stack direction="row" justify="between" mt={8} gap={4}>
{onBack ? (
<Button
type="button"
variant="secondary"
onClick={onBack}
disabled={isLoading}
className="px-8"
>
{backLabel}
</Button>
) : (
<div />
)}
<Button
type={type}
variant="primary"
onClick={onNext}
disabled={isLoading || !canNext}
className="px-8 min-w-[140px]"
>
{isLoading ? (
<Stack direction="row" gap={2} align="center">
<span className="animate-spin"></span>
<span>Processing...</span>
</Stack>
) : (
isLastStep ? 'Complete Setup' : nextLabel
)}
</Button>
</Stack>
);
}

View File

@@ -0,0 +1,5 @@
export function OnboardingCardAccent() {
return (
<div className="absolute top-0 right-0 w-40 h-40 bg-gradient-to-bl from-primary-blue/10 to-transparent rounded-bl-full" />
);
}

View File

@@ -0,0 +1,11 @@
interface OnboardingContainerProps {
children: React.ReactNode;
}
export function OnboardingContainer({ children }: OnboardingContainerProps) {
return (
<div className="max-w-3xl mx-auto px-4 py-10">
{children}
</div>
);
}

View File

@@ -0,0 +1,25 @@
import { Box } from '../../ui/primitives/Box';
import { Text } from '../../ui/Text';
interface OnboardingErrorProps {
message: string;
}
export function OnboardingError({ message }: OnboardingErrorProps) {
return (
<Box
mt={6}
display="flex"
alignItems="start"
gap={3}
p={4}
rounded="xl"
bg="bg-red-500/10"
border
borderColor="border-red-500/30"
>
<Text color="text-red-400" flexShrink={0} mt={0.5}></Text>
<Text size="sm" color="text-red-400">{message}</Text>
</Box>
);
}

View File

@@ -0,0 +1,15 @@
import { FormEvent, ReactNode } from 'react';
import { Box } from '../../ui/primitives/Box';
interface OnboardingFormProps {
children: ReactNode;
onSubmit: (e: FormEvent) => void;
}
export function OnboardingForm({ children, onSubmit }: OnboardingFormProps) {
return (
<Box as="form" onSubmit={onSubmit} position="relative">
{children}
</Box>
);
}

View File

@@ -0,0 +1,17 @@
interface OnboardingHeaderProps {
title: string;
subtitle: string;
emoji: string;
}
export function OnboardingHeader({ title, subtitle, emoji }: OnboardingHeaderProps) {
return (
<div className="text-center mb-8">
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-primary-blue/20 to-purple-600/10 border border-primary-blue/30 mx-auto mb-4">
<span className="text-2xl">{emoji}</span>
</div>
<h1 className="text-4xl font-bold mb-2">{title}</h1>
<p className="text-gray-400">{subtitle}</p>
</div>
);
}

View File

@@ -0,0 +1,7 @@
export function OnboardingHelpText() {
return (
<p className="text-center text-xs text-gray-500 mt-6">
Your avatar will be AI-generated based on your photo and chosen suit color
</p>
);
}

View File

@@ -0,0 +1,58 @@
import { Button } from '@/ui/Button';
interface OnboardingNavigationProps {
onBack: () => void;
onNext?: () => void;
isLastStep: boolean;
canSubmit: boolean;
loading: boolean;
}
export function OnboardingNavigation({ onBack, onNext, isLastStep, canSubmit, loading }: OnboardingNavigationProps) {
return (
<div className="mt-8 flex items-center justify-between">
<Button
type="button"
variant="secondary"
onClick={onBack}
disabled={loading}
className="flex items-center gap-2"
>
<span></span>
Back
</Button>
{!isLastStep ? (
<Button
type="button"
variant="primary"
onClick={onNext}
disabled={loading}
className="flex items-center gap-2"
>
Continue
<span></span>
</Button>
) : (
<Button
type="submit"
variant="primary"
disabled={loading || !canSubmit}
className="flex items-center gap-2"
>
{loading ? (
<>
<span className="animate-spin"></span>
Creating Profile...
</>
) : (
<>
<span></span>
Complete Setup
</>
)}
</Button>
)}
</div>
);
}

View File

@@ -0,0 +1,22 @@
import { Stack } from '@/ui/primitives/Stack';
import { Text } from '@/ui/Text';
interface OnboardingStepHeaderProps {
title: string;
description?: string;
}
export function OnboardingStepHeader({ title, description }: OnboardingStepHeaderProps) {
return (
<Stack gap={1} mb={6}>
<Text size="2xl" color="text-white" weight="bold" className="tracking-tight" block>
{title}
</Text>
{description && (
<Text size="sm" color="text-gray-400" block>
{description}
</Text>
)}
</Stack>
);
}