unsloth/studio/frontend/src/features/onboarding/components/wizard-layout.tsx
Shine1i 94296f91a1 style: improve layout consistency and responsiveness across components
- Adjusted padding, spacing, and grid configurations for better alignment and scaling across screen sizes.
- Enhanced mobile responsiveness by updating flex and grid layouts, ensuring optimal display on smaller devices.
- Tuned container dimensions and card styling to maintain design consistency.
2026-02-17 21:27:02 +01:00

95 lines
3.1 KiB
TypeScript

import { Card } from "@/components/ui/card";
import { useNavigate } from "@tanstack/react-router";
import { motion } from "motion/react";
import { Suspense, lazy, useEffect, useRef, useState } from "react";
import type { ConfettiRef } from "@/components/ui/confetti";
import { STEPS } from "@/config/training";
import { isOnboardingDone, markOnboardingDone } from "@/features/auth";
import { useTrainingConfigStore } from "@/features/training";
import { SplashScreen } from "./splash-screen";
import { WizardContent } from "./wizard-content";
import { WizardFooter } from "./wizard-footer";
import { WizardSidebar } from "./wizard-sidebar";
const Confetti = lazy(() =>
import("@/components/ui/confetti").then((m) => ({ default: m.Confetti })),
);
export function WizardLayout() {
const navigate = useNavigate();
const [showSplash, setShowSplash] = useState(true);
const currentStep = useTrainingConfigStore((s) => s.currentStep);
const confettiRef = useRef<ConfettiRef>(null);
const hasFiredRef = useRef(false);
const isFinalStep = currentStep === STEPS.length;
useEffect(() => {
if (isOnboardingDone()) {
navigate({ to: "/studio" });
}
}, [navigate]);
useEffect(() => {
if (isFinalStep && !hasFiredRef.current) {
hasFiredRef.current = true;
confettiRef.current?.fire({
particleCount: 80,
angle: 60,
spread: 55,
origin: { x: 0, y: 0.6 },
colors: ["#34b482", "#26ccff", "#a25afd", "#88ff5a"],
});
confettiRef.current?.fire({
particleCount: 80,
angle: 120,
spread: 55,
origin: { x: 1, y: 0.6 },
colors: ["#34b482", "#26ccff", "#a25afd", "#88ff5a"],
});
}
if (!isFinalStep) {
hasFiredRef.current = false;
}
}, [isFinalStep]);
return (
<div className="relative min-h-screen flex items-center justify-center overflow-hidden bg-gradient-to-br from-primary/5 via-background to-primary/3 p-4 sm:p-6 md:p-8">
{showSplash && (
<SplashScreen
onStartOnboarding={() => setShowSplash(false)}
onGoToStudio={() => {
markOnboardingDone();
navigate({ to: "/studio" });
}}
/>
)}
<Suspense fallback={null}>
<Confetti
ref={confettiRef}
manualstart={true}
className="pointer-events-none fixed inset-0 z-50 size-full"
/>
</Suspense>
{!showSplash && (
<motion.div
className="w-full max-w-5xl"
initial={{ opacity: 0, scale: 0.98, y: 10 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
transition={{
duration: 0.4,
ease: [0.165, 0.84, 0.44, 1],
}}
>
<Card className="relative z-10 w-full !gap-0 !m-0 !p-0 flex min-h-[560px] flex-col overflow-hidden shadow-border ring-1 ring-border md:min-h-[620px] md:flex-row lg:h-[660px]">
<WizardSidebar />
<div className="flex-1 flex flex-col">
<WizardContent />
<WizardFooter />
</div>
</Card>
</motion.div>
)}
</div>
);
}