DEV Community

Cover image for How To Make Resume With React
Radzion Chachura
Radzion Chachura

Posted on • Originally published at radzion.com

How To Make Resume With React

Watch on YouTube | 🐙 GitHub | 🎮 Demo

Let's make a resume with React that you can turn into a one-page PDF to find a remote job. If you are curious about advice on how to make a resume for remote work, check out this post.

The container has a fixed width and aspect ratio of an A4 page to print the resume onto a single page. To separate sections of the page, we make the container a flexbox element with a background of a separator color while making children that will take the remaining space a black or white color depending on a selected theme. While printing, we want to remove the border and border-radius and make the content take up the whole space of the page by using media print.

import { defaultBorderRadiusCSS } from "lib/ui/borderRadius"
import styled from "styled-components"

export const ResumeContainer = styled.div`
  width: 880px;
  aspect-ratio: 1 / 1.414;

  display: flex;
  flex-direction: column;
  gap: 2px;
  background: ${({ theme }) => theme.colors.foreground.toCssValue()};
  border: 2px solid ${({ theme }) => theme.colors.foreground.toCssValue()};

  ${defaultBorderRadiusCSS}
  overflow: hidden;

  > * {
    background: ${({ theme }) => theme.colors.background.toCssValue()};
    padding: 20px;
  }

  @media print {
    width: 100%;
    height: 100%;
    border-radius: 0;
    border: none;
  }
`
Enter fullscreen mode Exit fullscreen mode

To get a PDF, we use ReactToPrint, which will convert the content when we press the download button.

We start the resume with a summary that consists of two lines. To separate elements, we use the SeparatedBy component that goes over every child and puts a passed React element between them.

import styled from "styled-components"
import { StickyIconButton } from "lib/ui/buttons/square/StickyIconButton"
import ReactToPrint from "react-to-print"
import { DownloadIcon } from "lib/ui/icons/DonwloadIcon"
import { ReactInstance } from "react"

interface Props {
  renderContent: () => ReactInstance | null
}

const PrintButton = styled(StickyIconButton)`
  @media print {
    display: none;
  }
`

export const PrintResume = ({ renderContent }: Props) => (
  <ReactToPrint
    trigger={() => <PrintButton icon={<DownloadIcon />} />}
    content={renderContent}
  />
)
Enter fullscreen mode Exit fullscreen mode
import { ComponentWithChildrenProps } from "lib/shared/props"
import React, { Fragment } from "react"

import { HStack } from "./Stack"
import { Text } from "./Text"

export const dotSeparator = ""
export const slashSeparator = "/"

interface Props extends ComponentWithChildrenProps {
  separator?: string
  gap?: number
}

export const SeparatedBy = ({ children, separator, gap = 8 }: Props) => {
  const definedChildren = React.Children.toArray(children).filter(
    (child) => child
  )
  return (
    <HStack alignItems="center" gap={gap}>
      {definedChildren.map((child, index) => {
        if (index === definedChildren.length - 1) {
          return child
        }

        return (
          <Fragment key={index}>
            {child}
            <Text color="supporting" as="div">
              {separator}
            </Text>
          </Fragment>
        )
      })}
    </HStack>
  )
}
Enter fullscreen mode Exit fullscreen mode

After that, we continue with lists of experience where the first one shows the most recent work, the second one older job positions, and the last one - side projects.

The JobExperience component receives position, company, start and end dates, and the list of responsibilities with technologies to render a summary of work at a given position. To show a personal project, we use a similar component that doesn't have the start and end dates but receives an achievement, description, and URL. Finally, we include a footer with links to email, Twitter, Github and Telegram.

Top comments (0)