feat(ui): 增强电池看板状态表达

This commit is contained in:
2026-05-12 00:07:15 +08:00
parent 5d9aa660d8
commit 38943f239f
5 changed files with 255 additions and 122 deletions
+99
View File
@@ -0,0 +1,99 @@
import type { ComponentPropsWithoutRef, ReactNode } from 'react'
type Variant = 'default' | 'muted' | 'success' | 'warning' | 'danger' | 'info'
function cn(...classes: Array<string | false | null | undefined>) {
return classes.filter(Boolean).join(' ')
}
const variantClass: Record<Variant, string> = {
default: 'border-white/10 bg-white/[0.04] text-zinc-100',
muted: 'border-white/10 bg-zinc-900/70 text-zinc-400',
success: 'border-emerald-400/20 bg-emerald-400/10 text-emerald-300',
warning: 'border-amber-400/20 bg-amber-400/10 text-amber-300',
danger: 'border-red-400/20 bg-red-400/10 text-red-300',
info: 'border-teal-400/20 bg-teal-400/10 text-teal-300',
}
export function Badge({
className,
variant = 'default',
children,
...props
}: ComponentPropsWithoutRef<'span'> & { variant?: Variant }) {
return (
<span
className={cn(
'inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs font-medium leading-none',
variantClass[variant],
className,
)}
{...props}
>
{children}
</span>
)
}
export function Card({ className, children, ...props }: ComponentPropsWithoutRef<'div'>) {
return (
<div
className={cn('rounded-2xl border border-white/[0.08] bg-zinc-950/60 shadow-2xl shadow-black/20', className)}
{...props}
>
{children}
</div>
)
}
export function Button({ className, children, ...props }: ComponentPropsWithoutRef<'button'>) {
return (
<button
className={cn(
'inline-flex items-center justify-center gap-2 rounded-lg border border-white/10 bg-white/[0.05] px-4 py-2 text-sm font-medium text-zinc-100 transition-colors hover:border-white/20 hover:bg-white/[0.09] disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-white/[0.05]',
className,
)}
{...props}
>
{children}
</button>
)
}
export function Input({ className, ...props }: ComponentPropsWithoutRef<'input'>) {
return (
<input
className={cn(
'h-10 w-full rounded-lg border border-white/10 bg-zinc-950/80 px-3 py-2 text-sm text-zinc-100 placeholder:text-zinc-600 outline-none transition-colors focus:border-teal-400/60 focus:ring-2 focus:ring-teal-400/10',
className,
)}
{...props}
/>
)
}
export function Select({ className, children, ...props }: ComponentPropsWithoutRef<'select'>) {
return (
<select
className={cn(
'h-10 rounded-lg border border-white/10 bg-zinc-950/95 px-3 py-2 text-sm text-zinc-100 outline-none transition-colors [color-scheme:dark] focus:border-teal-400/60 focus:ring-2 focus:ring-teal-400/10',
className,
)}
{...props}
>
{children}
</select>
)
}
export function SectionTitle({ icon, title, description }: { icon?: ReactNode; title: string; description?: string }) {
return (
<div className="flex items-start gap-3">
{icon && <div className="mt-0.5 rounded-lg border border-white/10 bg-white/[0.04] p-2 text-teal-300">{icon}</div>}
<div>
<h3 className="text-lg font-medium text-white">{title}</h3>
{description && <p className="mt-1 text-sm text-zinc-400">{description}</p>}
</div>
</div>
)
}