Files
duty-teller/webapp-next/src/components/states/FullScreenStateShell.tsx
Nikolay Tatarinov 43cd3bbd7d refactor: improve layout structure and consistency across components
- Refactored layout structure in multiple components to enhance consistency and maintainability by introducing outer and inner wrapper classes.
- Updated the `MonthNavHeader` component for shared month navigation functionality, improving code reuse.
- Adjusted padding and margin properties in various components to ensure a cohesive design and better responsiveness.
- Removed unnecessary padding from certain elements to streamline the layout and improve visual clarity.
2026-03-06 17:19:31 +03:00

55 lines
1.7 KiB
TypeScript

/**
* Shared full-screen state layout for fallback screens (access denied, not-found, error).
* Uses content-safe, app tokens, and consistent spacing so all fallback screens look like the same app.
*/
"use client";
export interface FullScreenStateShellProps {
/** Main heading (e.g. "Access denied", "Page not found"). */
title: React.ReactNode;
/** Optional description or message below the title. */
description?: React.ReactNode;
/** Optional extra content (e.g. server detail, secondary text). */
children?: React.ReactNode;
/** Primary action (Button or Link). */
primaryAction: React.ReactNode;
/** Wrapper role. Default "alert" for error/denied states. */
role?: "alert" | "status";
/** Optional extra class names for the wrapper. */
className?: string;
}
const OUTER_CLASS =
"content-safe flex min-h-[var(--tg-viewport-stable-height,100vh)] flex-col items-center justify-center gap-4 bg-background text-foreground";
const INNER_CLASS = "mx-auto w-full max-w-[var(--max-width-app)] px-3 flex flex-col items-center gap-4";
/**
* Full-screen centered shell with title, optional description, and primary action.
* Use for access denied, not-found, and in-app error boundary screens.
*/
export function FullScreenStateShell({
title,
description,
children,
primaryAction,
role = "alert",
className,
}: FullScreenStateShellProps) {
return (
<div
className={className ? `${OUTER_CLASS} ${className}` : OUTER_CLASS}
role={role}
>
<div className={INNER_CLASS}>
<h1 className="text-xl font-semibold">{title}</h1>
{description != null && (
<p className="text-center text-muted-foreground">{description}</p>
)}
{children}
{primaryAction}
</div>
</div>
);
}