Files
baya-monorepo/client/src/components/common/AppLoading/AppLoading.tsx
T
2026-07-17 17:10:39 +03:30

37 lines
1.3 KiB
TypeScript

'use client'
import { FunctionComponent } from 'react';
import { keyframes } from '@emotion/react';
import Stack, { StackProps } from '@mui/material/Stack';
import AppIcon from '../AppIcon';
export type AppLoadingProps = StackProps;
const breathe = keyframes`
0%, 100% { opacity: 0.55; transform: scale(0.92); }
50% { opacity: 1; transform: scale(1); }
`;
/**
* The branded full-page loading splash — the Balinyaar mark with a subtle breathing motion, respecting
* `prefers-reduced-motion` (the animation only applies under the `no-preference` media query; a
* reduced-motion user sees a static, still-legible mark). Reserved for **true full-page waits** (the auth
* splash, a payment-gateway return, a route-level `Suspense` fallback) — inline/list loading should reach
* for a shaped skeleton (a co-located `<X.Skeleton />` twin) instead, never a bare spinner.
* @component AppLoading
*/
const AppLoading: FunctionComponent<AppLoadingProps> = ({ sx, ...rest }) => (
<Stack role="status" sx={{ my: 4, alignItems: 'center', justifyContent: 'center', ...sx }} {...rest}>
<Stack
sx={{
'@media (prefers-reduced-motion: no-preference)': {
animation: `${breathe} 1.6s ease-in-out infinite`,
},
}}
>
<AppIcon icon="logo" size={48} color="var(--bal-primary)" />
</Stack>
</Stack>
);
export default AppLoading;