[优化] go 引用调整

This commit is contained in:
ryan
2026-06-06 10:26:20 +08:00
parent ee1110b752
commit 3cfefb4367
552 changed files with 1642 additions and 2185 deletions
@@ -0,0 +1,23 @@
import type {ReactNode} from 'react';
interface EmptyStateProps {
title: string;
description?: string;
children?: ReactNode;
}
export function EmptyState({ title, description, children }: EmptyStateProps) {
return (
<div className="rounded-2xl border border-dashed border-[var(--border-default)] bg-[var(--surface-muted)] px-5 py-6 text-sm">
<p className="text-base font-semibold text-[var(--foreground-primary)]">
{title}
</p>
{description ? (
<p className="mt-2 leading-6 text-[var(--foreground-secondary)]">
{description}
</p>
) : null}
{children ? <div className="mt-4">{children}</div> : null}
</div>
);
}
@@ -0,0 +1,17 @@
interface ErrorStateProps {
title: string;
description: string;
}
export function ErrorState({ title, description }: ErrorStateProps) {
return (
<div className="rounded-2xl border border-[var(--status-danger-border)] bg-[var(--status-danger-soft)] px-5 py-6 text-sm">
<p className="text-base font-semibold text-[var(--status-danger-foreground)]">
{title}
</p>
<p className="mt-2 leading-6 text-[var(--status-danger-foreground)]/80">
{description}
</p>
</div>
);
}
@@ -0,0 +1,31 @@
import {AppCard} from '@/components/ui/app-card';
import {StatusBadge} from '@/components/ui/status-badge';
interface FeaturePlaceholderProps {
title: string;
description: string;
milestones: string[];
}
export function FeaturePlaceholder({
title,
description,
milestones,
}: FeaturePlaceholderProps) {
return (
<AppCard
title={title}
description={description}
action={<StatusBadge label="阶段 1 骨架完成" variant="success" />}
>
<ul className="space-y-3 text-sm leading-6 text-[var(--foreground-secondary)]">
{milestones.map((item) => (
<li key={item} className="flex gap-3">
<span className="mt-2 h-2 w-2 shrink-0 rounded-full bg-[var(--brand-primary)]" />
<span>{item}</span>
</li>
))}
</ul>
</AppCard>
);
}
@@ -0,0 +1,75 @@
'use client';
import {useEffect, useRef} from 'react';
import {toast} from 'sonner';
import {cn} from '@/lib/utils/cn';
type InlineMessageTone = 'info' | 'success' | 'danger';
const toneClasses: Record<InlineMessageTone, string> = {
info: 'border-[var(--status-info-border)] bg-[var(--status-info-soft)] text-[var(--status-info-foreground)]',
success:
'border-[var(--status-success-border)] bg-[var(--status-success-soft)] text-[var(--status-success-foreground)]',
danger:
'border-[var(--status-danger-border)] bg-[var(--status-danger-soft)] text-[var(--status-danger-foreground)]',
};
interface InlineMessageProps {
tone?: InlineMessageTone;
message: string;
className?: string;
onClear?: () => void;
}
export function InlineMessage({
tone = 'info',
message,
className,
onClear,
}: InlineMessageProps) {
const onClearRef = useRef(onClear);
useEffect(() => {
onClearRef.current = onClear;
}, [onClear]);
useEffect(() => {
// Only trigger toast if onClear is provided (dynamic feedback)
if (!onClearRef.current || !message) return;
const options = {
position: 'bottom-right' as const,
};
if (tone === 'success') {
toast.success(message, options);
} else if (tone === 'danger') {
toast.error(message, options);
} else {
toast(message, options);
}
const timer = setTimeout(() => {
onClearRef.current?.();
}, 0);
return () => clearTimeout(timer);
}, [tone, message]);
// If onClear is provided, this is a toast feedback notice, so render nothing inline
if (onClear) {
return null;
}
// Otherwise, render as a static/persistent inline alert banner (original behavior)
return (
<div
className={cn(
'rounded-2xl border px-4 py-3 text-sm leading-6',
toneClasses[tone],
className,
)}
>
{message}
</div>
);
}
@@ -0,0 +1,15 @@
import {cn} from '@/lib/utils/cn';
interface LoadingStateProps {
className?: string;
}
export function LoadingState({ className }: LoadingStateProps) {
return (
<div className={cn('space-y-3', className)}>
<div className="h-4 w-32 animate-pulse rounded bg-[var(--control-background-hover)]" />
<div className="h-24 animate-pulse rounded-2xl bg-[var(--surface-muted)]" />
<div className="h-24 animate-pulse rounded-2xl bg-[var(--surface-muted)]" />
</div>
);
}