번개 모임 웹 어플리케이션 - 버튼, 메인 네비게이션 리팩토링 (img 태그 관련)

선정·2023년 5월 10일
0

새로고침 할 때마다 잠깐동안 <MainNavigation> 컴포넌트의 레이아웃이 변경됐다가 돌아오는 현상이 있었는데, 자세히 보니 이미지가 뒤늦게 불러와지고 있었다. 그래서 이미지 소스를 가져오기 전에도 레이아웃을 유지하기 위해 <img> 태그의 부모 요소로 <div> 태그를 추가해 width 속성을 추가했다. 이를 위해 <Button> 컴포넌트와 <MainNavigation> 컴포넌트를 수정했다.



버튼 컴포넌트 리팩토링

<Button> 컴포넌트에는 2개의 props가 더 추가됐다.

  • iconWidth : img 태그를 감싸는 div 요소에 적용될 width
  • iconWithText : 이미지 + 텍스트 조합의 버튼, 하위 태그 클래스(.icon-with-text)로 적용하던 속성을 props로 변경함

src/components/ui/Button.js

import styled, { css } from "styled-components";

const colorStyles = css`
  ${({ theme, background, color }) => {
    const selectedBg = theme.palette[background];
    const selectedColor = theme.palette[color];
    return css`
      background: ${selectedBg};
      color: ${selectedColor};
    `;
  }}
`;

const sizes = {
  large: {
    height: "3rem",
    fontSize: "1.25rem"
  },
  medium: {
    height: "2.875rem",
    fontSize: "1rem"
  },
  small: {
    height: "1.75rem",
    fontSize: "0.875rem"
  }
};

const sizeStyles = css`
  ${({ size }) => css`
    height: ${sizes[size].height};
    font-size: ${sizes[size].fontSize};
  `}
`;

const fullWidthStyle = css`
  ${({ fullWidth }) =>
    fullWidth &&
    css`
      width: 100%;
      justify-content: center;
    `}
`;

const StyledButton = styled.button`
  display: inline-flex;
  align-items: center;
  font-weight: ${({ theme }) => theme.fontWeight.semiBold};
  outline: none;
  border: none;
  border-radius: 5px;
  ${({ radius }) =>
    radius === "bottom" &&
    css`
      border-top-left-radius: 0px;
      border-top-right-radius: 0px;
    `}

  padding-right: 0.875rem;
  padding-left: 0.875rem;
  ${({ marginTop }) =>
    marginTop &&
    css`
      margin-top: ${marginTop};
    `}

  ${colorStyles}

  ${sizeStyles}

  ${({ outline }) =>
    outline &&
    css`
      border: 1px solid black;
    `}

  ${({ noPadding }) =>
    noPadding &&
    css`
      padding: 0rem;
    `}

  ${fullWidthStyle}

  > div:first-child {
    display: flex;
    ${({ iconWidth }) =>
      iconWidth &&
      css`
        width: ${iconWidth};
      `}

    ${({ iconWithText }) =>
      iconWithText &&
      css`
        margin-right: 6px;
      `}
  }
`;

function Button({
  children,
  background,
  color,
  size = "medium",
  outline,
  noPadding,
  fullWidth,
  marginTop,
  radius,
  iconWidth,
  iconWithText
}) {
  return (
    <StyledButton
      background={background}
      color={color}
      size={size}
      outline={outline}
      noPadding={noPadding}
      fullWidth={fullWidth}
      marginTop={marginTop}
      radius={radius}
      iconWidth={iconWidth}
      iconWithText={iconWithText}
    >
      {children}
    </StyledButton>
  );
}

export default Button;


메인 네비게이션 컴포넌트 리팩토링

어플리케이션 로고 등을 가져오기 위해 사용되는 <img> 태그를 <div> 태그로 감싸고 width를 지정해줬다.


수정 후

import styled, { css } from "styled-components";

import Button from "./UI/Button";

const Header = styled.header`
  position: sticky;
  top: 0;
  width: 100%;
  height: 72px;
  display: flex;
  align-items: center;
  padding-right: 1.5rem;
  padding-left: 1.5rem;
  border-bottom: 1px solid black;
  background: white;

  > .ddip-logo {
    width: 94px;
    display: flex;
  }

  > .search-box {
    height: 46px;
    flex-grow: 1;
    display: flex;
    align-items: center;
    padding-right: 0.875rem;
    padding-left: 0.875rem;
    margin-right: 1.5rem;
    margin-left: 1.5rem;
    border: 1px solid black;
    border-radius: 5px;
    font-size: 0.875rem;

    > .search-icon {
      width: 14px;
      margin-right: 6px;
    }
  }

  > .right-buttons {
    display: flex;
    > .auth-buttons {
      display: flex;
      align-items: center;
      margin-left: 16px;

      > .user-icon {
        width: 46px;
        display: flex;
      }

      > hr {
        width: 1px;
        height: 12px;
        margin: 8px;
      }
    }
  }

  ${({ logoOnly }) =>
    logoOnly &&
    css`
      justify-content: center;
      background: inherit;
    `}

  ${({ noSearchBox }) =>
    noSearchBox &&
    css`
      justify-content: space-between;
    `}
`;

function MainNavigation({ logoOnly, noSearchBox, loggedIn }) {
  if (logoOnly) {
    return (
      <Header logoOnly={logoOnly}>
        <div className="ddip-logo">
          <img className="logo" src="/images/logo.svg" alt="ddip-logo" />
        </div>
      </Header>
    );
  }

  return (
    <Header noSearchBox={noSearchBox}>
      <div className="ddip-logo">
        <img src="/images/logo.svg" alt="ddip-logo" />
      </div>
      {!noSearchBox && (
        <div className="search-box">
          <div className="search-icon">
            <img src="/images/search.svg" alt="search" />
          </div>
          <span>어떤 번개를 찾으시나요?</span>
        </div>
      )}
      <div className="right-buttons">
        <Button
          background="mainViolet"
          color="white"
          iconWidth="16px"
          iconWithText
        >
          <div>
            <img src="/images/thunder.svg" alt="thunder" />
          </div>
          <span>번개 만들기</span>
        </Button>
        <div className="auth-buttons">
          {loggedIn ? (
            <div className="user-icon">
              <img src="/images/user.svg" alt="user" />
            </div>
          ) : (
            <>
              <Button noPadding>회원가입</Button>
              <hr />
              <Button noPadding>로그인</Button>
            </>
          )}
        </div>
      </div>
    </Header>
  );
}

export default MainNavigation;
profile
starter

0개의 댓글