♻️ refactor(print): make print-friendly pages

affected by mui/material-ui#46434
This commit is contained in:
2025-07-03 09:51:07 +02:00
parent cfa31a99a3
commit 76575ead15
6 changed files with 157 additions and 118 deletions
@@ -62,6 +62,9 @@ const CookieConsent = () => {
mb: theme.spacing(1), mb: theme.spacing(1),
p: theme.spacing(3), p: theme.spacing(3),
zIndex: 9999, zIndex: 9999,
'@media print': {
display: 'none',
},
})}> })}>
<Box> <Box>
<SectionSubheader id="cookie-consent-dialog-title" component="h2" variant="h6"> <SectionSubheader id="cookie-consent-dialog-title" component="h2" variant="h6">
@@ -32,10 +32,16 @@ const CurriculumItem = (props: CurriculumEntryProps) => {
// '& .MuiAccordionSummary-expandIconWrapper .MuiSvgIcon-root': { color: 'primary.dark' }, // use summary hover icon color // '& .MuiAccordionSummary-expandIconWrapper .MuiSvgIcon-root': { color: 'primary.dark' }, // use summary hover icon color
}, },
'&.Mui-expanded': { '&.Mui-expanded': {
bgcolor: 'background.paper', // use summary hover background
borderBottom: '1px solid', borderBottom: '1px solid',
borderTop: '1px solid', borderTop: '1px solid',
bgcolor: 'background.paper', // use summary hover background
elevation: 1, elevation: 1,
'@media print': {
bgcolor: 'background.default',
borderBottom: 0,
borderTop: 0,
elevation: 0,
},
// '& .MuiAccordionSummary-expandIconWrapper .MuiSvgIcon-root': { color: 'primary.dark' }, // use summary hover icon color // '& .MuiAccordionSummary-expandIconWrapper .MuiSvgIcon-root': { color: 'primary.dark' }, // use summary hover icon color
}, },
}}> }}>
@@ -48,6 +54,9 @@ const CurriculumItem = (props: CurriculumEntryProps) => {
}, },
'& .MuiAccordionSummary-expandIconWrapper.Mui-expanded': { '& .MuiAccordionSummary-expandIconWrapper.Mui-expanded': {
transform: 'rotate(0deg)', transform: 'rotate(0deg)',
'@media print': {
transform: 'rotate(-90deg)',
},
}, },
'& .MuiAccordionSummary-content': { '& .MuiAccordionSummary-content': {
marginLeft: 2, marginLeft: 2,
+11 -1
View File
@@ -14,7 +14,17 @@ type FooterProps = {
const Footer: React.FC<FooterProps> = ({ showCookieConsent = true }) => { const Footer: React.FC<FooterProps> = ({ showCookieConsent = true }) => {
const year = new Date().getFullYear() const year = new Date().getFullYear()
return ( return (
<Box sx={{ bgcolor: 'background.paper', p: 6, display: 'flex', alignItems: 'center', flexDirection: 'column' }} component="footer"> <Box
id="footer"
component="footer"
sx={{
bgcolor: 'background.paper',
py: 6,
display: 'flex',
alignItems: 'center',
flexDirection: 'column',
'@media print': { py: 3 },
}}>
<Stack direction="row" gap={2}> <Stack direction="row" gap={2}>
<LinkedInIconLink fontSize="large" href="https://www.linkedin.com/in/m-tartari/" /> <LinkedInIconLink fontSize="large" href="https://www.linkedin.com/in/m-tartari/" />
<GitHubIconLink fontSize="large" href="https://www.github.com/m-tartari/" /> <GitHubIconLink fontSize="large" href="https://www.github.com/m-tartari/" />
@@ -1,6 +1,6 @@
import React from 'react' import React from 'react'
import { ParallaxBanner, ParallaxProvider } from 'react-scroll-parallax' import { ParallaxBanner, ParallaxProvider } from 'react-scroll-parallax'
import { Box, Grid, IconButton, Typography, useTheme } from '@mui/material' import { Box, Grid, IconButton, Typography } from '@mui/material'
import { ExpandMore } from '@mui/icons-material' import { ExpandMore } from '@mui/icons-material'
import { useViewport } from 'components/utils/viewport/index.js' import { useViewport } from 'components/utils/viewport/index.js'
@@ -125,9 +125,17 @@ const Description = (props: Props) => {
} }
} }
const DesktopComponent = React.forwardRef<HTMLSelectElement, Props>((props, ref) => { const ProjectSpotlight = React.forwardRef<HTMLSelectElement, Props>((props, ref) => {
const { width } = useViewport()
return ( return (
<section ref={ref}> <Box ref={ref}>
<Box
component="section"
sx={theme => ({
display: width < theme.breakpoints.values.md ? 'none' : 'inline',
'@media print': { display: 'none' },
})}>
<ParallaxProvider> <ParallaxProvider>
<ParallaxBanner <ParallaxBanner
layers={[ layers={[
@@ -160,20 +168,27 @@ const DesktopComponent = React.forwardRef<HTMLSelectElement, Props>((props, ref)
)} )}
</ParallaxBanner> </ParallaxBanner>
</ParallaxProvider> </ParallaxProvider>
</section> </Box>
) <Box
}) component="section"
sx={theme => ({
const MobileComponent = React.forwardRef<HTMLSelectElement, Props>((props, ref) => { display: width >= theme.breakpoints.values.md ? 'none' : 'inline',
return ( '@media print': {
<Box component="section"> display: 'inline',
height: '100%',
},
})}>
<Box <Box
ref={ref}
component="img" component="img"
sx={{ sx={{
width: '100%', width: '100%',
height: '100%', height: '100%',
maxHeight: '60vh', maxHeight: '60vh',
'@media print': {
maxHeight: '100%',
'-webkit-print-color-adjust': 'exact !important',
'print-color-adjust': 'exact !important',
},
}} }}
src={props.mobileImage ?? props.image} src={props.mobileImage ?? props.image}
/> />
@@ -184,20 +199,17 @@ const MobileComponent = React.forwardRef<HTMLSelectElement, Props>((props, ref)
borderTopWidth: theme.spacing(0.5), borderTopWidth: theme.spacing(0.5),
borderTopColor: theme.palette.primary.main, borderTopColor: theme.palette.primary.main,
p: `${theme.spacing(7)} ${theme.spacing(5)} ${theme.spacing(5.5)} ${theme.spacing(5)}`, p: `${theme.spacing(7)} ${theme.spacing(5)} ${theme.spacing(5.5)} ${theme.spacing(5)}`,
'@media print': {
backgroundColor: 'background.default',
},
})}> })}>
<Typography variant="h4">{props.title}</Typography> <Typography variant="h4">{props.title}</Typography>
{props.caption} {props.caption}
<Typography pt={1}>{props.children}</Typography> <Typography pt={1}>{props.children}</Typography>
</Box> </Box>
</Box> </Box>
</Box>
) )
}) })
const ProjectSpotlight = React.forwardRef<HTMLSelectElement, Props>((props, ref) => {
const { width } = useViewport()
const theme = useTheme()
return width < theme.breakpoints.values.md ? <MobileComponent {...props} ref={ref} /> : <DesktopComponent {...props} ref={ref} />
})
export default ProjectSpotlight export default ProjectSpotlight
+32 -33
View File
@@ -15,22 +15,30 @@ import {
Stack, Stack,
Toolbar, Toolbar,
Typography, Typography,
TypographyProps,
styled, styled,
useScrollTrigger, useScrollTrigger,
useTheme, useTheme,
} from '@mui/material' } from '@mui/material'
import MenuIcon from '@mui/icons-material/Menu' import MenuIcon from '@mui/icons-material/Menu'
const AppBarButton = styled(Button<typeof RouterLink>)(({ theme }) => ({ const TypographyLink = styled(Typography)(({ theme }) => ({
textTransform: 'none', role: 'link',
color: theme.palette.mode === 'dark' ? 'inherit' : 'text.secondary', textDecoration: 'none',
':hover': {
backgroundColor: 'transparent',
...(theme.palette.mode === 'dark' && { ...(theme.palette.mode === 'dark' && {
color: 'inherit',
':hover': {
color: theme.palette.primary.main, color: theme.palette.primary.main,
}),
}, },
}),
...(theme.palette.mode === 'light' && {
color: theme.palette.text.primary,
':hover': {
color: theme.palette.primary.dark,
},
}),
})) }))
const AppBarLink = (props: TypographyProps & { to: string }) => <TypographyLink component={RouterLink} variant="h6" {...props} />
const DrawerButton = styled(ListItemButton<typeof RouterLink>)(({ theme }) => ({ const DrawerButton = styled(ListItemButton<typeof RouterLink>)(({ theme }) => ({
textTransform: 'none', textTransform: 'none',
color: 'inherit', color: 'inherit',
@@ -102,6 +110,7 @@ const CustomToolbar: React.FC<CustomToolbarProps> = ({ drawerWidth = 240, window
{...props} {...props}
sx={{ sx={{
backgroundColor: trigger ? 'background.paper' : 'transparent', backgroundColor: trigger ? 'background.paper' : 'transparent',
'@media print': { backgroundColor: 'background.default' },
...(theme.palette.mode === 'light' && { ...(theme.palette.mode === 'light' && {
backgroundColor: 'hsla(0, 0%, 100%, 0.75)', backgroundColor: 'hsla(0, 0%, 100%, 0.75)',
backdropFilter: 'blur(8px)', backdropFilter: 'blur(8px)',
@@ -115,6 +124,7 @@ const CustomToolbar: React.FC<CustomToolbarProps> = ({ drawerWidth = 240, window
<Toolbar <Toolbar
sx={{ sx={{
display: 'flex', display: 'flex',
alignItems: 'center',
// maxWidth: '100%', // maxWidth: '100%',
// [theme.breakpoints.up('md')]: { width: theme => theme.breakpoints.values.lg, mx: 'auto' }, // [theme.breakpoints.up('md')]: { width: theme => theme.breakpoints.values.lg, mx: 'auto' },
}}> }}>
@@ -123,44 +133,34 @@ const CustomToolbar: React.FC<CustomToolbarProps> = ({ drawerWidth = 240, window
aria-label="open drawer" aria-label="open drawer"
edge="start" edge="start"
onClick={handleDrawerToggle} onClick={handleDrawerToggle}
sx={{ mr: 2, display: { md: 'none' }, position: 'absolute', backgroundColor: 'primary' }}> sx={{
mr: 2,
display: { md: 'none' },
position: 'absolute',
backgroundColor: 'primary',
'@media print': { display: 'none' },
}}>
<MenuIcon /> <MenuIcon />
</IconButton> </IconButton>
<AppBarButton
component={RouterLink} <AppBarLink
to="/" to="/"
disableRipple
sx={theme => ({ sx={theme => ({
color: theme.palette.text.primary,
[theme.breakpoints.down('md')]: { mx: 'auto' }, [theme.breakpoints.down('md')]: { mx: 'auto' },
[theme.breakpoints.up('md')]: { mr: 'auto' }, [theme.breakpoints.up('md')]: { mr: 'auto' },
})}> })}>
<Typography variant="h6">Michele Tartari</Typography> Michele Tartari
</AppBarButton> </AppBarLink>
<Stack component="div" direction="row" spacing={2} sx={{ display: { xs: 'none', md: 'flex' } }}> <Stack component="div" direction="row" spacing={2} sx={{ display: { xs: 'none', md: 'flex', alignItems: 'center' } }}>
<AppBarButton component={RouterLink} to="/" disableRipple> <AppBarLink to="/">Home</AppBarLink>
<Typography variant="h6">Home</Typography> <AppBarLink to="/projects">Projects</AppBarLink>
</AppBarButton> <AppBarLink to="/curriculum">Curriculum</AppBarLink>
<AppBarButton component={RouterLink} to="/projects" disableRipple> <Button component={RouterLink} to="/contacts" color="primary" variant="contained" sx={{ textTransform: 'none' }}>
<Typography variant="h6">Projects</Typography>
</AppBarButton>
<AppBarButton component={RouterLink} to="/curriculum" disableRipple>
<Typography variant="h6">Curriculum</Typography>
</AppBarButton>
<Button
component={RouterLink}
to="/contacts"
color="primary"
variant="contained"
sx={{
textTransform: 'none',
}}>
<Typography variant="h6">Hire me</Typography> <Typography variant="h6">Hire me</Typography>
</Button> </Button>
</Stack> </Stack>
</Toolbar> </Toolbar>
</AppBar> </AppBar>
<nav>
<Drawer <Drawer
variant="temporary" variant="temporary"
open={mobileOpen} open={mobileOpen}
@@ -174,7 +174,6 @@ const CustomToolbar: React.FC<CustomToolbarProps> = ({ drawerWidth = 240, window
}}> }}>
{drawer} {drawer}
</Drawer> </Drawer>
</nav>
</> </>
) )
} }
+8 -2
View File
@@ -19,11 +19,17 @@ const Page: React.FC<PageProps> = ({ title, children, showCookieConsent, ...prop
}, [title]) }, [title])
return ( return (
<Box sx={{ flexGrow: 1 }} aria-label="page"> <Box
aria-label="page"
sx={{
'@media print': { backgroundColor: 'background.default' },
flexGrow: 1,
}}>
<Toolbar /> <Toolbar />
{title && ( {title && (
<> <>
<Typography <Typography
id="page-title"
variant="h1" variant="h1"
aria-label="page-title" aria-label="page-title"
textAlign="center" textAlign="center"
@@ -53,8 +59,8 @@ const Page: React.FC<PageProps> = ({ title, children, showCookieConsent, ...prop
</> </>
)} )}
<Container <Container
id="page-content"
component="main" component="main"
maxWidth={false}
sx={{ sx={{
mt: { xs: 8, md: 12 }, mt: { xs: 8, md: 12 },
mb: 4, mb: 4,