diff --git a/src/features/about/headline/data/profile.ts b/src/features/about/headline/data/profile.ts index 9f0bb82f..9d362ca3 100644 --- a/src/features/about/headline/data/profile.ts +++ b/src/features/about/headline/data/profile.ts @@ -11,6 +11,7 @@ export const profileLinks: Profile[] = [ label: ProfileLabel.github, href: 'https://github.com/1ilsang', imageSrc: '/assets/logo/github.webp', + imageSrcBlack: 'https://cdn-icons-png.flaticon.com/512/25/25231.png', alt: 'github', }, { diff --git a/src/features/about/headline/models.ts b/src/features/about/headline/models.ts index daa04da7..250247c1 100644 --- a/src/features/about/headline/models.ts +++ b/src/features/about/headline/models.ts @@ -2,6 +2,7 @@ export type Profile = { label: string; href: string; imageSrc: string; + imageSrcBlack?: string; alt: string; }; diff --git a/src/features/about/headline/profile/Container.tsx b/src/features/about/headline/profile/Container.tsx index 48bafab0..459c4091 100644 --- a/src/features/about/headline/profile/Container.tsx +++ b/src/features/about/headline/profile/Container.tsx @@ -3,11 +3,15 @@ import { FunctionComponent } from 'react'; import ProfileLogo from './Logo'; import { profileLinks } from '~/about/headline/data/profile'; +import usePrint from '~/shared/hooks/usePrint'; const ProfileContainer: FunctionComponent = () => { + const { print } = usePrint(); + const title = print ? '이상철' : '!ILSANG'; + return ( <> -
!ILSANG
+
{title}
{profileLinks.map((link) => ( diff --git a/src/features/about/headline/profile/Logo.tsx b/src/features/about/headline/profile/Logo.tsx index b8866503..0028e333 100644 --- a/src/features/about/headline/profile/Logo.tsx +++ b/src/features/about/headline/profile/Logo.tsx @@ -1,21 +1,20 @@ import { FunctionComponent } from 'react'; import classNames from 'classnames'; -import { ProfileLabel } from '../models'; +import { Profile, ProfileLabel } from '../models'; -type ProfileLogoProps = { - href: string; - imageSrc: string; - alt: string; - label?: string; -}; +import usePrint from '~/shared/hooks/usePrint'; + +type ProfileLogoProps = Profile; const ProfileLogo: FunctionComponent = ({ label, href, imageSrc, + imageSrcBlack, alt, }) => { + const { print } = usePrint(); return (
= ({ {label} {alt} diff --git a/src/features/about/introduction/Container.tsx b/src/features/about/introduction/Container.tsx index 0c423726..93e15aca 100644 --- a/src/features/about/introduction/Container.tsx +++ b/src/features/about/introduction/Container.tsx @@ -24,7 +24,7 @@ const IntroductionContainer: FunctionComponent = () => {

웃으면서 일하고 싶습니다. 농담을 즐기고 어떻게 하면 동료를 웃길 수 - 있을지 늘 탐구합니다. + 있을지 늘 탐구하고 있습니다.
영향력 있는 동료가 되고 싶습니다. 성장 자극을 줄 수 있는 동료이고 싶습니다. 맡은 부분에 대한 기술적 책임을 지려고 노력합니다. 기술에 diff --git a/src/features/about/work/card/content/Container.tsx b/src/features/about/work/card/content/Container.tsx index 1f3302e3..fe4a51af 100644 --- a/src/features/about/work/card/content/Container.tsx +++ b/src/features/about/work/card/content/Container.tsx @@ -8,6 +8,7 @@ import ProjectDate from './ProjectDate'; import ProjectDetail from './ProjectDetail'; import ExternalLink from '~/shared/components/ExternalLink'; +import usePrint from '~/shared/hooks/usePrint'; export type CompanyContentProjectProps = Project & { format?: string; @@ -18,14 +19,25 @@ const CompanyContentProject: FunctionComponent = ( ) => { const { name, url, tags, startDate, endDate, format = 'yyyy.MM' } = props; const [open, setOpen] = useState(undefined); + const { print } = usePrint(); const handleDetailClick: MouseEventHandler = () => { setOpen(!open); }; - const openClassName = open === undefined ? 'mh-zero' : open ? 'show' : 'hide'; - const foldState = open ? 'unfold' : 'fold'; - const externalLink = open !== undefined && url && openClassName !== 'hide'; + const openClassName = (() => { + if (print) return 'show'; + if (open === undefined) return 'mh-zero'; + return open ? 'show' : 'hide'; + })(); + const foldState = (() => { + if (print) return 'unfold'; + return open ? 'unfold' : 'fold'; + })(); + const externalLink = (() => { + if (print) return undefined; + return open !== undefined && url && openClassName !== 'hide'; + })(); return (

diff --git a/src/features/about/work/card/content/ProjectDetail.tsx b/src/features/about/work/card/content/ProjectDetail.tsx index c1311206..b1a0de7b 100644 --- a/src/features/about/work/card/content/ProjectDetail.tsx +++ b/src/features/about/work/card/content/ProjectDetail.tsx @@ -2,14 +2,17 @@ import { FunctionComponent, memo } from 'react'; import { Project } from '~/about/work/models'; import DynamicImage from '~/shared/components/DynamicImage'; +import usePrint from '~/shared/hooks/usePrint'; type ProjectDetailProps = Project; const ProjectDetail: FunctionComponent = memo( ({ summary, body, img }) => { + const { print } = usePrint(); + return ( <> - {img && ( + {!print && img && ( void; +type AfterFn = (event: WindowEventMap['afterprint']) => void; + +const usePrint = (beforeFn?: BeforeFn, afterFn?: AfterFn) => { + const [print, setPrint] = useState(false); + + useEffect(() => { + const handleBeforePrint: BeforeFn = (e) => { + beforeFn?.(e); + setPrint(true); + }; + const handleAfterPrint: AfterFn = (e) => { + afterFn?.(e); + setPrint(false); + }; + window.addEventListener('beforeprint', handleBeforePrint); + window.addEventListener('afterprint', handleAfterPrint); + return () => { + window.removeEventListener('beforeprint', handleBeforePrint); + window.removeEventListener('afterprint', handleAfterPrint); + }; + }, []); + + return { print }; +}; + +export default usePrint; diff --git a/src/features/styles/_utils.scss b/src/features/styles/_utils.scss index 51e95ef5..16246a9a 100644 --- a/src/features/styles/_utils.scss +++ b/src/features/styles/_utils.scss @@ -15,8 +15,10 @@ } @mixin mobile { - @media (max-width: $mobile) { - @content; + @media not print { + @media (max-width: $mobile) { + @content; + } } } diff --git a/src/features/styles/_variables.scss b/src/features/styles/_variables.scss index b4305249..928770b3 100644 --- a/src/features/styles/_variables.scss +++ b/src/features/styles/_variables.scss @@ -12,3 +12,4 @@ $dark-color: rgb(100 116 139); $base-color: #425061; $sub-color: #61768f; $min-color: #d9dee5; +$black: #101010; diff --git a/src/features/styles/common.scss b/src/features/styles/common.scss index b3e9ecc0..bb877986 100644 --- a/src/features/styles/common.scss +++ b/src/features/styles/common.scss @@ -95,6 +95,11 @@ $target: #e73c7e; color: $highlight-color; line-height: 1.1; + @media print { + color: $black; + text-decoration: underline; + } + &::after { content: ''; display: block; @@ -127,6 +132,10 @@ $target: #e73c7e; } animation: fade 0.5s forwards; + + @media print { + animation: none; + } } .hide { @@ -144,6 +153,10 @@ $target: #e73c7e; } animation: fade-out 0.25s forwards; + + @media print { + animation: none; + } } .mh-zero { diff --git a/src/features/styles/globals.scss b/src/features/styles/globals.scss index 0c88c946..652da16a 100644 --- a/src/features/styles/globals.scss +++ b/src/features/styles/globals.scss @@ -6,6 +6,14 @@ body { background-color: $background-color; -webkit-font-smoothing: antialiased; color: $deep-light-color; + + @media print { + print-color-adjust: exact; + width: 210mm; + height: 297mm; + background-color: rgb(255 255 255); + color: $black; + } } /* stylelint-disable */ diff --git a/src/features/styles/ui/about/index.scss b/src/features/styles/ui/about/index.scss index 3c4e833f..3a62b4c4 100644 --- a/src/features/styles/ui/about/index.scss +++ b/src/features/styles/ui/about/index.scss @@ -13,6 +13,10 @@ font-weight: bold; font-size: 1.5rem; margin-bottom: 4px; + + @media print { + color: #101010; + } } .about { @@ -22,6 +26,10 @@ &-container { @include root-container; + + @media print { + padding: 5vh 0; + } } &-profile { @@ -51,6 +59,13 @@ font-size: 6rem; letter-spacing: 1px; } + + @media print { + color: #101010; + font-weight: normal; + background: none; + filter: none; + } } .logo-container { @@ -193,6 +208,10 @@ border-bottom: 1px dotted $min-color; margin-bottom: 15px; user-select: none; + + @media print { + border-bottom: 1px dotted $black; + } } .project { @@ -246,6 +265,10 @@ .category { min-width: 120px; color: $min-color; + + @media print { + color: #101010; + } } .link-wrap { @@ -255,6 +278,10 @@ .link { color: #2dd0a8; + @media print { + color: #101010; + } + &:hover { color: $highlight-color; } diff --git a/src/features/styles/ui/about/project.scss b/src/features/styles/ui/about/project.scss index a54cd45c..b3070d34 100644 --- a/src/features/styles/ui/about/project.scss +++ b/src/features/styles/ui/about/project.scss @@ -5,8 +5,17 @@ padding-bottom: 1rem; margin-bottom: 1rem; + @media print { + border-left: 0.24rem solid $black; + border-bottom: 1px dotted $black; + } + .border { border: 1px solid $min-color; + + @media print { + color: $black; + } } .headline { @@ -35,6 +44,10 @@ content: '▶'; margin-right: 0.5rem; color: $sub-color; + + @media print { + color: $black; + } } } @@ -43,6 +56,10 @@ content: '▼'; margin-right: 0.5rem; color: $sub-color; + + @media print { + color: $black; + } } } @@ -51,6 +68,10 @@ font-style: italic; margin-right: 1rem; min-width: 119px; + + @media print { + color: $black; + } } } @@ -64,6 +85,12 @@ padding: 0 5px; margin: 4px 4px 0 0; border-radius: 1px; + + @media print { + background-color: transparent; + border: 1px solid $black; + color: $black; + } } } @@ -97,6 +124,10 @@ .section { margin: 2rem 0 0; + + @media print { + margin: 1rem 0 0; + } } ul { @@ -115,6 +146,11 @@ content: '❑'; margin-right: 0.5rem; color: $min-color; + + @media print { + content: '•'; + color: $black; + } } } } diff --git a/src/features/styles/ui/tag/index.scss b/src/features/styles/ui/tag/index.scss index 3a7a3a71..fe286fdd 100644 --- a/src/features/styles/ui/tag/index.scss +++ b/src/features/styles/ui/tag/index.scss @@ -12,6 +12,10 @@ .hashtag { color: $highlight-color; + + @media print { + color: $black; + } } .hashtag:hover { diff --git a/src/pages/about.tsx b/src/pages/about.tsx index eb69ac4e..a0f070f1 100644 --- a/src/pages/about.tsx +++ b/src/pages/about.tsx @@ -5,8 +5,10 @@ import Footer from '~/shared/components/Footer'; import MetaHeader from '~/shared/components/MetaHeader'; import Navbar from '~/shared/components/nav/Navbar'; import { ImageUrl, MetaDescription, MetaTitle } from '~/shared/constants/blog'; +import usePrint from '~/shared/hooks/usePrint'; const About: NextPage = () => { + const { print } = usePrint(); return ( <> { description={MetaDescription.HOME} />
- + {!print && } -
);