feat(mui): PageEnter kit primitive (consistent staggered page entrance) + adopt in WarehouseSuppliers
Each top-level child rises+fades in, staggered (0.4s, ease-out), so every page enters the same way and nothing appears instantly; honors prefers-reduced-motion. Replaces ad-hoc per-page motion.div entrance wrappers. One component → the look is tunable in one place. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
@@ -24,6 +23,7 @@ import {
|
||||
TextField,
|
||||
StatusChip,
|
||||
PageHeader,
|
||||
PageEnter,
|
||||
FilterBar,
|
||||
EmptyState,
|
||||
LoadingState,
|
||||
@@ -344,22 +344,16 @@ export default function WarehouseSuppliers() {
|
||||
];
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.25 }}
|
||||
>
|
||||
<PageHeader
|
||||
title="Dodavatelé"
|
||||
subtitle={subtitle}
|
||||
actions={
|
||||
<Button startIcon={PlusIcon} onClick={openCreateModal}>
|
||||
Přidat dodavatele
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</motion.div>
|
||||
<PageEnter>
|
||||
<PageHeader
|
||||
title="Dodavatelé"
|
||||
subtitle={subtitle}
|
||||
actions={
|
||||
<Button startIcon={PlusIcon} onClick={openCreateModal}>
|
||||
Přidat dodavatele
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
||||
<FilterBar>
|
||||
<Box sx={{ flex: "1 1 320px" }}>
|
||||
@@ -525,6 +519,6 @@ export default function WarehouseSuppliers() {
|
||||
confirmVariant="danger"
|
||||
loading={deleteMutation.isPending}
|
||||
/>
|
||||
</Box>
|
||||
</PageEnter>
|
||||
);
|
||||
}
|
||||
|
||||
51
src/admin/ui/PageEnter.tsx
Normal file
51
src/admin/ui/PageEnter.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import { Children, isValidElement, type ReactNode } from "react";
|
||||
import { motion, useReducedMotion, type Variants } from "framer-motion";
|
||||
import Box from "@mui/material/Box";
|
||||
import type { SxProps, Theme } from "@mui/material/styles";
|
||||
|
||||
const MotionBox = motion(Box);
|
||||
|
||||
const container: Variants = {
|
||||
hidden: {},
|
||||
show: { transition: { staggerChildren: 0.05, delayChildren: 0.03 } },
|
||||
};
|
||||
|
||||
const itemVariant: Variants = {
|
||||
hidden: { opacity: 0, y: 12 },
|
||||
show: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: { duration: 0.4, ease: [0.16, 1, 0.3, 1] },
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Consistent page entrance. Use as a page's OUTERMOST wrapper (in place of the
|
||||
* page's root `<Box>`): each top-level child rises + fades in, staggered, so the
|
||||
* whole page comes in the same way everywhere — no element appears instantly.
|
||||
* Wrapping each child in a block `motion.div` is layout-safe for the vertical
|
||||
* section stacks our pages use (header → filters → card/table); nested grids/
|
||||
* flex inside a section are untouched. Honors prefers-reduced-motion.
|
||||
*/
|
||||
export default function PageEnter({
|
||||
children,
|
||||
sx,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
sx?: SxProps<Theme>;
|
||||
}) {
|
||||
const reduce = useReducedMotion();
|
||||
if (reduce) return <Box sx={sx}>{children}</Box>;
|
||||
|
||||
return (
|
||||
<MotionBox variants={container} initial="hidden" animate="show" sx={sx}>
|
||||
{Children.map(children, (child) =>
|
||||
isValidElement(child) ? (
|
||||
<motion.div variants={itemVariant}>{child}</motion.div>
|
||||
) : (
|
||||
child
|
||||
),
|
||||
)}
|
||||
</MotionBox>
|
||||
);
|
||||
}
|
||||
@@ -28,3 +28,4 @@ export { default as FileUpload } from "./FileUpload";
|
||||
export { default as ProgressBar } from "./ProgressBar";
|
||||
export type { ProgressColor } from "./ProgressBar";
|
||||
export { default as ThemeToggle } from "./ThemeToggle";
|
||||
export { default as PageEnter } from "./PageEnter";
|
||||
|
||||
Reference in New Issue
Block a user