feat(ui): Improve login card design and theme customization

Refactor the `Button` component, add new `LoginCard` component, update `ThemePicker` component, edit global CSS styles to include card background and foreground and style the login page, including the logo and login form.
This commit is contained in:
Maximilian Liebmann 2025-05-21 16:42:48 +02:00 committed by Maximilian Liebmann
parent 9f9c2157f5
commit 4f4e73318a
11 changed files with 122 additions and 29 deletions

View file

@ -15,8 +15,9 @@ const buttonVariants = cva(
'bg-secondary text-text-alt shadow-xs hover:bg-hover-secondary active:bg-active-secondary',
outline:
'border-2 border-primary bg-transparent text-text shadow-xs hover:bg-primary hover:border-neutral-000 hover:border-1.5 hover:text-neutral-000 active:bg-active-primary',
destructive:
/*destructive:
'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
*/
ghost:
'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
link: 'text-text underline-offset-4 hover:underline',

View file

@ -0,0 +1,92 @@
import * as React from 'react';
import { cn } from '@/lib/utils';
function Card({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot='card'
className={cn(
'bg-card flex flex-col gap-6 py-6 shadow-[4px_4px_9px_9px_rgba(0,0,0,0.25)] rounded-[11px]',
className,
)}
{...props}
/>
);
}
function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot='card-header'
className={cn(
'@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',
className,
)}
{...props}
/>
);
}
function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot='card-title'
className={cn('leading-none font-semibold', className)}
{...props}
/>
);
}
function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot='card-description'
className={cn('text-muted-foreground text-sm', className)}
{...props}
/>
);
}
function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot='card-action'
className={cn(
'col-start-2 row-span-2 row-start-1 self-start justify-self-end',
className,
)}
{...props}
/>
);
}
function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot='card-content'
className={cn('px-6', className)}
{...props}
/>
);
}
function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot='card-footer'
className={cn('flex items-center px-6 [.border-t]:pt-6', className)}
{...props}
/>
);
}
export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardAction,
CardDescription,
CardContent,
};

View file

@ -1,4 +1,4 @@
import { Button } from '@/components/ui/button';
import { Button } from '@/components/custom-ui/button';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@ -12,7 +12,7 @@ export function IconButton({
children: React.ReactNode;
} & React.ComponentProps<typeof Button>) {
return (
<Button type='button' variant='default' {...props}>
<Button type='button' variant='secondary' {...props}>
<FontAwesomeIcon icon={icon} className='mr-2' />
{children}
</Button>

View file

@ -1,6 +1,6 @@
import { signIn } from '@/auth';
import LabeledInput from '@/components/labeled-input';
import { Button } from '@/components/ui/button';
import { Button } from '@/components/custom-ui/button';
import { AuthError } from 'next-auth';
import { redirect } from 'next/navigation';

View file

@ -1,4 +1,4 @@
import { Button } from '../ui/button';
import { Button } from '../custom-ui/button';
import Link from 'next/link';
export function RedirectButton({

View file

@ -22,7 +22,6 @@ export default function SSOLogin({
type='submit'
variant='secondary'
icon={faOpenid}
icon={faOpenid}
>
Login with {providerDisplayName}
</IconButton>

View file

@ -4,7 +4,7 @@ import * as React from 'react';
import { Moon, Sun } from 'lucide-react';
import { useTheme } from 'next-themes';
import { Button } from '@/components/ui/button';
import { Button } from '@/components/custom-ui/button';
import {
DropdownMenu,
DropdownMenuContent,