♻️ 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),
|
||||
p: theme.spacing(3),
|
||||
zIndex: 9999,
|
||||
'@media print': {
|
||||
display: 'none',
|
||||
},
|
||||
})}>
|
||||
<Box>
|
||||
<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
|
||||
},
|
||||
'&.Mui-expanded': {
|
||||
bgcolor: 'background.paper', // use summary hover background
|
||||
borderBottom: '1px solid',
|
||||
borderTop: '1px solid',
|
||||
bgcolor: 'background.paper', // use summary hover background
|
||||
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
|
||||
},
|
||||
}}>
|
||||
@@ -48,6 +54,9 @@ const CurriculumItem = (props: CurriculumEntryProps) => {
|
||||
},
|
||||
'& .MuiAccordionSummary-expandIconWrapper.Mui-expanded': {
|
||||
transform: 'rotate(0deg)',
|
||||
'@media print': {
|
||||
transform: 'rotate(-90deg)',
|
||||
},
|
||||
},
|
||||
'& .MuiAccordionSummary-content': {
|
||||
marginLeft: 2,
|
||||
|
||||
@@ -14,7 +14,17 @@ type FooterProps = {
|
||||
const Footer: React.FC<FooterProps> = ({ showCookieConsent = true }) => {
|
||||
const year = new Date().getFullYear()
|
||||
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}>
|
||||
<LinkedInIconLink fontSize="large" href="https://www.linkedin.com/in/m-tartari/" />
|
||||
<GitHubIconLink fontSize="large" href="https://www.github.com/m-tartari/" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
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 { useViewport } from 'components/utils/viewport/index.js'
|
||||
@@ -125,79 +125,91 @@ const Description = (props: Props) => {
|
||||
}
|
||||
}
|
||||
|
||||
const DesktopComponent = React.forwardRef<HTMLSelectElement, Props>((props, ref) => {
|
||||
return (
|
||||
<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',
|
||||
const ProjectSpotlight = React.forwardRef<HTMLSelectElement, Props>((props, ref) => {
|
||||
const { width } = useViewport()
|
||||
|
||||
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 (
|
||||
<Box component="section">
|
||||
<Box
|
||||
ref={ref}
|
||||
component="img"
|
||||
sx={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
maxHeight: '60vh',
|
||||
}}
|
||||
src={props.mobileImage ?? props.image}
|
||||
/>
|
||||
<Box ref={ref}>
|
||||
<Box
|
||||
component="section"
|
||||
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)}`,
|
||||
display: width < theme.breakpoints.values.md ? 'none' : 'inline',
|
||||
'@media print': { display: 'none' },
|
||||
})}>
|
||||
<Typography variant="h4">{props.title}</Typography>
|
||||
{props.caption}
|
||||
<Typography pt={1}>{props.children}</Typography>
|
||||
<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>
|
||||
</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>
|
||||
)
|
||||
})
|
||||
|
||||
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
|
||||
|
||||
@@ -15,22 +15,30 @@ import {
|
||||
Stack,
|
||||
Toolbar,
|
||||
Typography,
|
||||
TypographyProps,
|
||||
styled,
|
||||
useScrollTrigger,
|
||||
useTheme,
|
||||
} from '@mui/material'
|
||||
import MenuIcon from '@mui/icons-material/Menu'
|
||||
|
||||
const AppBarButton = styled(Button<typeof RouterLink>)(({ theme }) => ({
|
||||
textTransform: 'none',
|
||||
color: theme.palette.mode === 'dark' ? 'inherit' : 'text.secondary',
|
||||
':hover': {
|
||||
backgroundColor: 'transparent',
|
||||
...(theme.palette.mode === 'dark' && {
|
||||
const TypographyLink = styled(Typography)(({ theme }) => ({
|
||||
role: 'link',
|
||||
textDecoration: 'none',
|
||||
...(theme.palette.mode === 'dark' && {
|
||||
color: 'inherit',
|
||||
':hover': {
|
||||
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 }) => ({
|
||||
textTransform: 'none',
|
||||
color: 'inherit',
|
||||
@@ -102,6 +110,7 @@ const CustomToolbar: React.FC<CustomToolbarProps> = ({ drawerWidth = 240, window
|
||||
{...props}
|
||||
sx={{
|
||||
backgroundColor: trigger ? 'background.paper' : 'transparent',
|
||||
'@media print': { backgroundColor: 'background.default' },
|
||||
...(theme.palette.mode === 'light' && {
|
||||
backgroundColor: 'hsla(0, 0%, 100%, 0.75)',
|
||||
backdropFilter: 'blur(8px)',
|
||||
@@ -115,6 +124,7 @@ const CustomToolbar: React.FC<CustomToolbarProps> = ({ drawerWidth = 240, window
|
||||
<Toolbar
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
// maxWidth: '100%',
|
||||
// [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"
|
||||
edge="start"
|
||||
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 />
|
||||
</IconButton>
|
||||
<AppBarButton
|
||||
component={RouterLink}
|
||||
|
||||
<AppBarLink
|
||||
to="/"
|
||||
disableRipple
|
||||
sx={theme => ({
|
||||
color: theme.palette.text.primary,
|
||||
[theme.breakpoints.down('md')]: { mx: 'auto' },
|
||||
[theme.breakpoints.up('md')]: { mr: 'auto' },
|
||||
})}>
|
||||
<Typography variant="h6">Michele Tartari</Typography>
|
||||
</AppBarButton>
|
||||
<Stack component="div" direction="row" spacing={2} sx={{ display: { xs: 'none', md: 'flex' } }}>
|
||||
<AppBarButton component={RouterLink} to="/" disableRipple>
|
||||
<Typography variant="h6">Home</Typography>
|
||||
</AppBarButton>
|
||||
<AppBarButton component={RouterLink} to="/projects" disableRipple>
|
||||
<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',
|
||||
}}>
|
||||
Michele Tartari
|
||||
</AppBarLink>
|
||||
<Stack component="div" direction="row" spacing={2} sx={{ display: { xs: 'none', md: 'flex', alignItems: 'center' } }}>
|
||||
<AppBarLink to="/">Home</AppBarLink>
|
||||
<AppBarLink to="/projects">Projects</AppBarLink>
|
||||
<AppBarLink to="/curriculum">Curriculum</AppBarLink>
|
||||
<Button component={RouterLink} to="/contacts" color="primary" variant="contained" sx={{ textTransform: 'none' }}>
|
||||
<Typography variant="h6">Hire me</Typography>
|
||||
</Button>
|
||||
</Stack>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<nav>
|
||||
<Drawer
|
||||
variant="temporary"
|
||||
open={mobileOpen}
|
||||
onClose={handleDrawerToggle}
|
||||
ModalProps={{
|
||||
keepMounted: true, // Better open performance on mobile.
|
||||
}}
|
||||
sx={{
|
||||
display: { xs: 'block', md: 'none' },
|
||||
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
|
||||
}}>
|
||||
{drawer}
|
||||
</Drawer>
|
||||
</nav>
|
||||
<Drawer
|
||||
variant="temporary"
|
||||
open={mobileOpen}
|
||||
onClose={handleDrawerToggle}
|
||||
ModalProps={{
|
||||
keepMounted: true, // Better open performance on mobile.
|
||||
}}
|
||||
sx={{
|
||||
display: { xs: 'block', md: 'none' },
|
||||
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
|
||||
}}>
|
||||
{drawer}
|
||||
</Drawer>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,11 +19,17 @@ const Page: React.FC<PageProps> = ({ title, children, showCookieConsent, ...prop
|
||||
}, [title])
|
||||
|
||||
return (
|
||||
<Box sx={{ flexGrow: 1 }} aria-label="page">
|
||||
<Box
|
||||
aria-label="page"
|
||||
sx={{
|
||||
'@media print': { backgroundColor: 'background.default' },
|
||||
flexGrow: 1,
|
||||
}}>
|
||||
<Toolbar />
|
||||
{title && (
|
||||
<>
|
||||
<Typography
|
||||
id="page-title"
|
||||
variant="h1"
|
||||
aria-label="page-title"
|
||||
textAlign="center"
|
||||
@@ -53,8 +59,8 @@ const Page: React.FC<PageProps> = ({ title, children, showCookieConsent, ...prop
|
||||
</>
|
||||
)}
|
||||
<Container
|
||||
id="page-content"
|
||||
component="main"
|
||||
maxWidth={false}
|
||||
sx={{
|
||||
mt: { xs: 8, md: 12 },
|
||||
mb: 4,
|
||||
|
||||
Reference in New Issue
Block a user