♻️ refactor(print): make print-friendly pages
affected by mui/material-ui#46434
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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,79 +125,91 @@ const Description = (props: Props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const DesktopComponent = React.forwardRef<HTMLSelectElement, Props>((props, ref) => {
|
const ProjectSpotlight = React.forwardRef<HTMLSelectElement, Props>((props, ref) => {
|
||||||
return (
|
const { width } = useViewport()
|
||||||
<section ref={ref}>
|
|
||||||
<ParallaxProvider>
|
|
||||||
<ParallaxBanner
|
|
||||||
layers={[
|
|
||||||
{
|
|
||||||
// translateY: [0, 30],
|
|
||||||
// scale: [1, 0.5, 'easeOutCubic'],
|
|
||||||
// shouldAlwaysCompleteAnimation: true,
|
|
||||||
image: props.image,
|
|
||||||
expanded: false,
|
|
||||||
speed: -20,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
style={{
|
|
||||||
// width: '150%',
|
|
||||||
// marginLeft: '-25%',
|
|
||||||
minHeight: '100vh',
|
|
||||||
position: 'relative',
|
|
||||||
|
|
||||||
height: '100vh',
|
|
||||||
overflow: 'hidden',
|
|
||||||
}}>
|
|
||||||
<Description {...props} />
|
|
||||||
{props.scrollTarget && (
|
|
||||||
<IconButton
|
|
||||||
size="large"
|
|
||||||
onClick={() => (props.scrollTarget as React.RefObject<HTMLSelectElement | null>).current?.scrollIntoView()}
|
|
||||||
sx={{ position: 'absolute', p: 1, bottom: 2, left: '50%', transform: 'translate(-50%, 0)' }}>
|
|
||||||
<ExpandMore fontSize="large" />
|
|
||||||
</IconButton>
|
|
||||||
)}
|
|
||||||
</ParallaxBanner>
|
|
||||||
</ParallaxProvider>
|
|
||||||
</section>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const MobileComponent = React.forwardRef<HTMLSelectElement, Props>((props, ref) => {
|
|
||||||
return (
|
return (
|
||||||
<Box component="section">
|
<Box ref={ref}>
|
||||||
<Box
|
|
||||||
ref={ref}
|
|
||||||
component="img"
|
|
||||||
sx={{
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
maxHeight: '60vh',
|
|
||||||
}}
|
|
||||||
src={props.mobileImage ?? props.image}
|
|
||||||
/>
|
|
||||||
<Box
|
<Box
|
||||||
|
component="section"
|
||||||
sx={theme => ({
|
sx={theme => ({
|
||||||
mt: theme.spacing(-1.05),
|
display: width < theme.breakpoints.values.md ? 'none' : 'inline',
|
||||||
borderTopStyle: 'solid',
|
'@media print': { display: 'none' },
|
||||||
borderTopWidth: theme.spacing(0.5),
|
|
||||||
borderTopColor: theme.palette.primary.main,
|
|
||||||
p: `${theme.spacing(7)} ${theme.spacing(5)} ${theme.spacing(5.5)} ${theme.spacing(5)}`,
|
|
||||||
})}>
|
})}>
|
||||||
<Typography variant="h4">{props.title}</Typography>
|
<ParallaxProvider>
|
||||||
{props.caption}
|
<ParallaxBanner
|
||||||
<Typography pt={1}>{props.children}</Typography>
|
layers={[
|
||||||
|
{
|
||||||
|
// translateY: [0, 30],
|
||||||
|
// scale: [1, 0.5, 'easeOutCubic'],
|
||||||
|
// shouldAlwaysCompleteAnimation: true,
|
||||||
|
image: props.image,
|
||||||
|
expanded: false,
|
||||||
|
speed: -20,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
style={{
|
||||||
|
// width: '150%',
|
||||||
|
// marginLeft: '-25%',
|
||||||
|
minHeight: '100vh',
|
||||||
|
position: 'relative',
|
||||||
|
|
||||||
|
height: '100vh',
|
||||||
|
overflow: 'hidden',
|
||||||
|
}}>
|
||||||
|
<Description {...props} />
|
||||||
|
{props.scrollTarget && (
|
||||||
|
<IconButton
|
||||||
|
size="large"
|
||||||
|
onClick={() => (props.scrollTarget as React.RefObject<HTMLSelectElement | null>).current?.scrollIntoView()}
|
||||||
|
sx={{ position: 'absolute', p: 1, bottom: 2, left: '50%', transform: 'translate(-50%, 0)' }}>
|
||||||
|
<ExpandMore fontSize="large" />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
</ParallaxBanner>
|
||||||
|
</ParallaxProvider>
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
component="section"
|
||||||
|
sx={theme => ({
|
||||||
|
display: width >= theme.breakpoints.values.md ? 'none' : 'inline',
|
||||||
|
'@media print': {
|
||||||
|
display: 'inline',
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
})}>
|
||||||
|
<Box
|
||||||
|
component="img"
|
||||||
|
sx={{
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
maxHeight: '60vh',
|
||||||
|
'@media print': {
|
||||||
|
maxHeight: '100%',
|
||||||
|
'-webkit-print-color-adjust': 'exact !important',
|
||||||
|
'print-color-adjust': 'exact !important',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
src={props.mobileImage ?? props.image}
|
||||||
|
/>
|
||||||
|
<Box
|
||||||
|
sx={theme => ({
|
||||||
|
mt: theme.spacing(-1.05),
|
||||||
|
borderTopStyle: 'solid',
|
||||||
|
borderTopWidth: theme.spacing(0.5),
|
||||||
|
borderTopColor: theme.palette.primary.main,
|
||||||
|
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>
|
||||||
|
{props.caption}
|
||||||
|
<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
|
||||||
|
|||||||
@@ -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': {
|
...(theme.palette.mode === 'dark' && {
|
||||||
backgroundColor: 'transparent',
|
color: 'inherit',
|
||||||
...(theme.palette.mode === 'dark' && {
|
':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,58 +133,47 @@ 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}
|
onClose={handleDrawerToggle}
|
||||||
onClose={handleDrawerToggle}
|
ModalProps={{
|
||||||
ModalProps={{
|
keepMounted: true, // Better open performance on mobile.
|
||||||
keepMounted: true, // Better open performance on mobile.
|
}}
|
||||||
}}
|
sx={{
|
||||||
sx={{
|
display: { xs: 'block', md: 'none' },
|
||||||
display: { xs: 'block', md: 'none' },
|
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
|
||||||
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
|
}}>
|
||||||
}}>
|
{drawer}
|
||||||
{drawer}
|
</Drawer>
|
||||||
</Drawer>
|
|
||||||
</nav>
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user