Files
duty-teller/webapp-next/src/components/states/ErrorState.tsx
Nikolay Tatarinov 07e22079ee feat: enhance CSS and components for Telegram Mini App performance
- Updated CSS to utilize viewport variables for safe area insets and stable height, improving layout consistency across devices.
- Introduced haptic feedback triggers in various components to enhance user interaction, mimicking native Telegram behavior.
- Added functionality to detect Android performance class, minimizing animations on low-performance devices for better user experience.
- Refactored components to incorporate new CSS classes for content safety and improved responsiveness.
2026-03-04 19:19:14 +03:00

80 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Error state: warning icon, message, and optional Retry button.
* Ported from webapp/js/ui.js showError and states.css .error.
*/
"use client";
import { useTranslation } from "@/i18n/use-translation";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { triggerHapticLight } from "@/lib/telegram-haptic";
export interface ErrorStateProps {
/** Error message to display. If not provided, uses generic i18n message. */
message?: string | null;
/** Optional retry callback; when provided, a Retry button is shown. */
onRetry?: (() => void) | null;
/** Optional class for the container. */
className?: string;
}
/** Warning triangle icon 24×24 for error state. */
function ErrorIcon({ className }: { className?: string }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className={cn("shrink-0 text-error", className)}
aria-hidden
>
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" />
<line x1="12" y1="9" x2="12" y2="13" />
<line x1="12" y1="17" x2="12.01" y2="17" />
</svg>
);
}
/**
* Displays an error message with optional Retry button.
*/
export function ErrorState({ message, onRetry, className }: ErrorStateProps) {
const { t } = useTranslation();
const displayMessage =
message && String(message).trim() ? message : t("error_generic");
return (
<div
className={cn(
"flex flex-col items-center gap-3 rounded-xl bg-surface py-5 px-4 my-3 text-center text-error transition-opacity duration-200",
className
)}
role="alert"
>
<ErrorIcon />
<p className="m-0 text-sm font-medium">{displayMessage}</p>
{typeof onRetry === "function" && (
<Button
type="button"
variant="default"
size="sm"
className="mt-1 bg-primary text-primary-foreground hover:opacity-90 focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2"
onClick={() => {
triggerHapticLight();
onRetry();
}}
>
{t("error.retry")}
</Button>
)}
</div>
);
}