녕후킴

9월 1주차

0 views

📌 styled 컴포넌트를 이용해서 스타일 상속받기

style을 상속받아야 하는 상황은 다음 두가지가 존재한다.

  1. 스타일 속성이 고정되어 있고, 내용물만 바뀌는 경우
  2. 일부 스타일 속성만 고정되어 있고, 스타일 속성이 추가되며 내용물도 바뀌는 경우

1번은 다음 네이버 메일함의 아이콘 리스트가 좋은 예시가 될수 있다.

example1

내용물은 다르지만, 아이콘들은 사이즈나 색깔에 있어서 공통의 스타일을 갖고 있다.(흰색이 적용된 메일함 아이콘은 우선은 논의에서 제외하자) 이때 styled component에서 제공하는 ‘as’ prop이 매우 유용하다. as를 활용하는 방법은 아래와 같다.

import { styled } from 'styled-component'
import { Mail, Calendar, Cloud } from 'icon-library'

const ButtonOfMail = ({ buttonType, isSelected }) => {
  const buttonTypeToIcon = {
    mail: <Mail />,
    calendar: <Calendar />,
    cloud: <Cloud />,
  }

  return (
    <Button>
      <IconButton as={buttonTypeToIcon(buttonType)} isSelected />
    </Button>
  )
}

const IconButton = styled('template')(({ isSelected }) => ({
  fontSize: '1rem',
  color: isSelected ? 'white' : 'dark',
}))

2번은 ContentEditable을 사용하는 경우를 예로 들수 있다. 특정 요소를 contentEditable로 만들었을 때, 이 요소가 기본적으로 갖게되는 스타일 속성이 사라지고, placeholder를 기본적으로 보여주기를 바랬다. 어떤 요소를 contentEidtable로 만들었을 때, 기본적으로 아래 스타일 속성이 적용되었으면 했다.

'&:empty:before': {
    content: 'attr(placeholder)',
    display: 'block',
    fontSize: '1rem',
    color: 'red'
  },
  '&:focus': {
    outline: 'none'
  }

이를 위해서 CommonStyles라는 파일 내에 기본적으로 스타일이 적용되어 있는 컴포넌트들을 만들었다.

import { styled } from '@mui/material'

export const ContentEditable = styled('div')(({ theme }) => ({
  '&:empty:before': {
    content: 'attr(placeholder)',
    display: 'block',
    fontSize: '1rem',
    color: theme.palette.custom.grey3,
  },
  '&:focus': {
    outline: 'none',
  },
}))

contentEditable 요소가 필요한 곳에서는 다음과 같이 사용할 수 있다.

const ReportContentEditable = styled(ContentEditable)(() => ({
  width: '100%',
  height: '40vh',
  padding: '0.3rem',
  margin: '1rem 0',
  fontSize: '1rem',
  border: '1px solid',
  borderRadius: '6px',
  overflowY: 'scroll',
}))