feat(ui): 添加基础 UI 组件
- Avatar: 用户头像组件,支持图片和文字头像 - Toggle: 开关切换组件,用于设置项 - AILogo: AI 助手 Logo 组件,品牌标识
This commit is contained in:
parent
fefacff0d1
commit
ee9dc67708
26
src/components/ui/AILogo.tsx
Normal file
26
src/components/ui/AILogo.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
'use client';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface AILogoProps {
|
||||
size?: number;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function AILogo({ size = 48, className }: AILogoProps) {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 48 48"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={size}
|
||||
height={size}
|
||||
className={cn('text-[var(--color-primary)]', className)}
|
||||
>
|
||||
<path
|
||||
d="M24 4L26.5 18.5L41 16L29.5 24L41 32L26.5 29.5L24 44L21.5 29.5L7 32L18.5 24L7 16L21.5 18.5L24 4Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
31
src/components/ui/Avatar.tsx
Normal file
31
src/components/ui/Avatar.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
'use client';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface AvatarProps {
|
||||
name: string;
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function Avatar({ name, size = 'md', className }: AvatarProps) {
|
||||
const initial = name.charAt(0).toUpperCase();
|
||||
|
||||
const sizeClasses = {
|
||||
sm: 'w-6 h-6 text-xs',
|
||||
md: 'w-8 h-8 text-sm',
|
||||
lg: 'w-10 h-10 text-base',
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center justify-center rounded-full bg-[var(--color-primary)] text-white font-semibold',
|
||||
sizeClasses[size],
|
||||
className
|
||||
)}
|
||||
>
|
||||
{initial}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
32
src/components/ui/Toggle.tsx
Normal file
32
src/components/ui/Toggle.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
'use client';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface ToggleProps {
|
||||
checked: boolean;
|
||||
onChange: (checked: boolean) => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function Toggle({ checked, onChange, className }: ToggleProps) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
role="switch"
|
||||
aria-checked={checked}
|
||||
onClick={() => onChange(!checked)}
|
||||
className={cn(
|
||||
'relative w-11 h-6 rounded-full transition-colors duration-150 ease-in-out',
|
||||
checked ? 'bg-[var(--color-primary)]' : 'bg-[var(--color-border)]',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
'absolute top-0.5 left-0.5 w-5 h-5 bg-white rounded-full shadow-sm transition-transform duration-150 ease-in-out',
|
||||
checked && 'translate-x-5'
|
||||
)}
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user