From bb9c2f30a8f9c4fce550964d131fda0a9bb8473a Mon Sep 17 00:00:00 2001 From: arraysid Date: Tue, 27 May 2025 02:16:02 +0700 Subject: [PATCH] feat: add auth layout --- .../_components/animated-background.tsx | 86 +++++++++++++++++++ apps/landing/src/app/(auth)/layout.tsx | 18 ++++ libs/shadcn-ui/src/atoms/button.tsx | 2 +- libs/shadcn-ui/src/atoms/card.tsx | 82 ++++++++++++++++++ libs/shadcn-ui/src/atoms/index.ts | 1 + 5 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 apps/landing/src/app/(auth)/_components/animated-background.tsx create mode 100644 apps/landing/src/app/(auth)/layout.tsx create mode 100644 libs/shadcn-ui/src/atoms/card.tsx diff --git a/apps/landing/src/app/(auth)/_components/animated-background.tsx b/apps/landing/src/app/(auth)/_components/animated-background.tsx new file mode 100644 index 0000000..60b146c --- /dev/null +++ b/apps/landing/src/app/(auth)/_components/animated-background.tsx @@ -0,0 +1,86 @@ +'use client'; + +import { motion } from 'framer-motion'; +import { useEffect, useMemo, useState } from 'react'; +import { + SiCplusplus, + SiCss3, + SiGo, + SiHtml5, + SiJavascript, + SiPhp, + SiPython, + SiRuby, + SiRust, + SiSwift, + SiTypescript, +} from 'react-icons/si'; + +export function AnimatedBackground() { + const [isClient, setIsClient] = useState(false); + + useEffect(() => { + setIsClient(true); + }, []); + + const iconColorMap = useMemo( + () => [ + { Icon: SiJavascript, color: '#F7DF1E' }, + { Icon: SiTypescript, color: '#3178C6' }, + { Icon: SiPython, color: '#3776AB' }, + { Icon: SiCplusplus, color: '#00599C' }, + { Icon: SiRuby, color: '#CC342D' }, + { Icon: SiSwift, color: '#F05138' }, + { Icon: SiRust, color: '#000000' }, + { Icon: SiGo, color: '#00ADD8' }, + { Icon: SiPhp, color: '#777BB4' }, + { Icon: SiHtml5, color: '#E34F26' }, + { Icon: SiCss3, color: '#1572B6' }, + ], + [] + ); + + const getRandom = (min: number, max: number) => + Math.random() * (max - min) + min; + + const floatingIcons = useMemo(() => { + if (!isClient) return []; + + return Array.from({ length: 40 }).map((_, i) => { + const { Icon, color } = iconColorMap[i % iconColorMap.length]; + return ( + + + + ); + }); + }, [isClient, iconColorMap]); + + if (!isClient) return null; + + return ( +
{floatingIcons}
+ ); +} diff --git a/apps/landing/src/app/(auth)/layout.tsx b/apps/landing/src/app/(auth)/layout.tsx new file mode 100644 index 0000000..50fb487 --- /dev/null +++ b/apps/landing/src/app/(auth)/layout.tsx @@ -0,0 +1,18 @@ +import { Card } from '@components'; +import { ReactNode } from 'react'; +import { AnimatedBackground } from './_components/animated-background'; + +export default function Layout({ children }: { children: ReactNode }) { + return ( +
+ +
+ +
+
{children}
+
+
+
+
+ ); +} diff --git a/libs/shadcn-ui/src/atoms/button.tsx b/libs/shadcn-ui/src/atoms/button.tsx index d8c89fc..80237ef 100644 --- a/libs/shadcn-ui/src/atoms/button.tsx +++ b/libs/shadcn-ui/src/atoms/button.tsx @@ -3,7 +3,7 @@ import { Slot } from '@radix-ui/react-slot'; import { cva, type VariantProps } from 'class-variance-authority'; import * as React from 'react'; -import { cn } from '../lib/cn'; +import { cn } from '../lib'; const buttonVariants = cva( 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', diff --git a/libs/shadcn-ui/src/atoms/card.tsx b/libs/shadcn-ui/src/atoms/card.tsx new file mode 100644 index 0000000..78e70ea --- /dev/null +++ b/libs/shadcn-ui/src/atoms/card.tsx @@ -0,0 +1,82 @@ +import * as React from 'react'; +import { cn } from '../lib'; + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +Card.displayName = 'Card'; + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardHeader.displayName = 'CardHeader'; + +const CardTitle = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardTitle.displayName = 'CardTitle'; + +const CardDescription = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardDescription.displayName = 'CardDescription'; + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardContent.displayName = 'CardContent'; + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardFooter.displayName = 'CardFooter'; + +export { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +}; diff --git a/libs/shadcn-ui/src/atoms/index.ts b/libs/shadcn-ui/src/atoms/index.ts index e54f955..d79f6cd 100644 --- a/libs/shadcn-ui/src/atoms/index.ts +++ b/libs/shadcn-ui/src/atoms/index.ts @@ -1,2 +1,3 @@ export * from './button'; +export * from './card'; export * from './icons';