92 lines
2.5 KiB
TypeScript
92 lines
2.5 KiB
TypeScript
import type { ReactNode } from "react";
|
|
|
|
interface EmptyStateProps {
|
|
icon?: string;
|
|
title: string;
|
|
description?: string;
|
|
action?: ReactNode;
|
|
}
|
|
|
|
export function EmptyState({ icon = "📭", title, description, action }: EmptyStateProps) {
|
|
return (
|
|
<div
|
|
style={{
|
|
padding: "3rem 2rem",
|
|
textAlign: "center",
|
|
background: "var(--secondary-alt-bg)",
|
|
borderRadius: "16px",
|
|
border: "1px dashed var(--border-color)",
|
|
color: "var(--text-muted)"
|
|
}}
|
|
>
|
|
<div style={{ fontSize: "3rem", marginBottom: "1rem" }}>{icon}</div>
|
|
<h3 style={{ margin: "0 0 0.5rem 0", color: "var(--text-color)" }}>{title}</h3>
|
|
{description && <p style={{ margin: "0 0 1.5rem 0", fontSize: "0.95rem" }}>{description}</p>}
|
|
{action}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function LoadingState({ message = "Loading..." }: { message?: string }) {
|
|
return (
|
|
<div
|
|
style={{
|
|
padding: "3rem 2rem",
|
|
textAlign: "center"
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
width: "40px",
|
|
height: "40px",
|
|
border: "4px solid rgba(255, 255, 255, 0.2)",
|
|
borderTopColor: "currentColor",
|
|
borderRadius: "50%",
|
|
animation: "spin 0.8s linear infinite",
|
|
margin: "0 auto 1rem"
|
|
}}
|
|
></div>
|
|
<p style={{ color: "var(--text-muted)", margin: 0 }}>{message}</p>
|
|
<style>{`
|
|
@keyframes spin {
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
`}</style>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function ErrorState({ message, onRetry }: { message: string, onRetry?: () => void }) {
|
|
return (
|
|
<div
|
|
style={{
|
|
padding: "3rem 2rem",
|
|
textAlign: "center",
|
|
background: "rgba(244, 67, 54, 0.1)",
|
|
borderRadius: "16px",
|
|
border: "1px solid rgba(244, 67, 54, 0.3)"
|
|
}}
|
|
>
|
|
<div style={{ fontSize: "3rem", marginBottom: "1rem" }}>⚠️</div>
|
|
<h3 style={{ margin: "0 0 0.5rem 0", color: "var(--text-color)" }}>Something went wrong</h3>
|
|
<p style={{ margin: "0 0 1.5rem 0", color: "var(--text-muted)", fontSize: "0.95rem" }}>{message}</p>
|
|
{onRetry && (
|
|
<button
|
|
onClick={onRetry}
|
|
style={{
|
|
background: "var(--accent-color)",
|
|
border: "none",
|
|
padding: "0.75rem 1.5rem",
|
|
borderRadius: "8px",
|
|
color: "white",
|
|
fontWeight: 600,
|
|
cursor: "pointer"
|
|
}}
|
|
>
|
|
🔄 Try Again
|
|
</button>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|