Files
app/src/admin/ui/PageHeader.tsx
BOHA decadd895e fix(ui): stack detail-page header action buttons one-per-row on mobile
Detail-page headers put their action buttons in a flex row with
flexWrap:"wrap", so on a phone the 2-4 buttons (Potvrzení / Zahájit
realizaci / Smazat, etc.) wrapped into a ragged grid.

New shared `headerActionsSx` (ui/PageHeader): on xs it's a full-width
column (each button its own full-width row); from sm up it's the usual
right-aligned wrapping row — desktop unchanged. A StatusChip kept in the
same group stays its natural size (alignSelf) instead of stretching.

Applied to PageHeader's own actions slot and every detail-page header
action group: Order/Offer/Invoice (both views)/Project + the Warehouse
Receipt/Issue/Item/Inventory detail headers.

Verified in Chrome at 430px on OrderDetail: the group is flexDirection
column with all three buttons at the same x, full-width, stacked. tsc -b
--noEmit, npm run build, vitest 152/152 clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 21:44:22 +02:00

64 lines
1.9 KiB
TypeScript

import type { ReactNode } from "react";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import type { SxProps, Theme } from "@mui/material/styles";
export interface PageHeaderProps {
title: string;
subtitle?: string;
actions?: ReactNode;
}
/**
* Shared sx for a header action-button group. On mobile each button gets its
* own full-width row (column + stretch); from `sm` up it's the usual right-
* aligned wrapping row. Use on the Box that wraps the header's action Buttons
* (page headers + detail-page headers) so the mobile layout is identical
* everywhere — no more buttons wrapping into a ragged grid on phones.
*/
export const headerActionsSx: SxProps<Theme> = {
display: "flex",
flexDirection: { xs: "column", sm: "row" },
alignItems: { xs: "stretch", sm: "center" },
justifyContent: { sm: "flex-end" },
flexWrap: { sm: "wrap" },
gap: 1,
width: { xs: "100%", sm: "auto" },
// Some detail-page headers keep a StatusChip in this same group — keep it at
// its natural size on mobile instead of stretching it into a full-width bar.
"& > .MuiChip-root": { alignSelf: { xs: "flex-start", sm: "auto" } },
};
/**
* Standard page header: title (+ optional subtitle) on the left,
* action controls on the right. No framer-motion — pages add their own entrance.
*/
export default function PageHeader({
title,
subtitle,
actions,
}: PageHeaderProps) {
return (
<Box
sx={{
display: "flex",
alignItems: "flex-start",
justifyContent: "space-between",
flexWrap: "wrap",
gap: 2,
mb: 3,
}}
>
<Box>
<Typography variant="h4">{title}</Typography>
{subtitle && (
<Typography variant="body2" color="text.secondary" sx={{ mt: 0.5 }}>
{subtitle}
</Typography>
)}
</Box>
{actions && <Box sx={headerActionsSx}>{actions}</Box>}
</Box>
);
}