[Next.js] 포트폴리오 웹 페이지 제작기 - 2. 기초 레이아웃

olwooz·2023년 2월 7일
1

기본적인 셋팅은 얼추 끝났으니 이제 레이아웃을 만들어주려고 한다.
페이지 윗부분에는 헤더 Navbar, 그리고 페이지 아래에는 고정된 아이콘 바를 만들어주고 싶다.

1. 헤더

보통 헤더 Navbar를 보면 왼쪽은 로고, 오른쪽은 메뉴가 위치한다.
flexjustify-between을 사용해서 좌, 우 간격을 벌렸다.
헤더 주변에는 임시로 border를 넣어서 사이즈를 파악하기 쉽게 만들었다.

코드

// components/Header/Header.tsx

import HeaderButton from './HeaderButton';

const Header = () => {
  return (
    <div className="flex justify-between border-2 border-dashed border-gray-400 px-16 py-8">
      <div>LOGO</div>
      <div>
        <HeaderButton text="menu 1" />
        <HeaderButton text="menu 2" />
        <HeaderButton text="menu 3" />
      </div>
    </div>
  );
};

export default Header;
// components/Header/HeaderButton.tsx

interface Props {
  text: string;
}

const HeaderButton = ({ text }: Props) => {
  return <button className="px-4">{text}</button>;
};

export default HeaderButton;

결과

2. 아이콘 바

수직 형태의 작은 아이콘 바를 양 옆에 배치해서 왼쪽에는 라이트/다크 모드 전환과 언어 전환 버튼, 오른쪽에는 깃허브, 블로그 등 링크 버튼을 놓고 싶었다.

코드

// components/IconBar/IconBar.tsx

import IconButton from './IconButton';
import VerticalLine from './VerticalLine';

type Direction = 'left' | 'right';

interface Props {
  direction: Direction;
  icons: string[];
}

const IconBar = ({ direction, icons }: Props) => {
  const placement = direction === 'left' ? 'left-16 right-auto' : 'left-auto right-16';
  return (
    <div className={`w-40px fixed bottom-0 ${placement}`}>
      <div className="m-0 flex list-none flex-col items-center p-0">
        {icons.map((icon, i) => (
          <IconButton key={i} name={icon} />
        ))}
        <VerticalLine />
      </div>
    </div>
  );
};

export default IconBar;

아이콘들은 Icon 폴더에 잘 모아놨다. svg를 사용했기 때문에 컴포넌트를 하나하나 만들어줬는데, 그냥 그림 파일로 만들어서 파라미터로 경로를 넣어주면 코드가 더 간결해질 것 같긴 하다.

// components/IconBar/IconButton.tsx

import GitHubIcon from '../Icons/github';
import LightDarkIcon from '../Icons/light-dark';
import VelogIcon from '../Icons/velog';

interface Props {
  name: string;
}

function getIcon(name: string) {
  switch (name) {
    case 'light-dark':
      return <LightDarkIcon />;
    case 'github':
      return <GitHubIcon />;
    case 'velog':
      return <VelogIcon />;
  }
}

const IconButton = ({ name }: Props) => {
  const icon = getIcon(name);

  return <button className="mb-2 px-4">{icon}</button>;
};

export default IconButton;
// components/IconBar/VerticalLine.tsx
const VerticalLine = () => {
  return <div className="my-0 mx-auto h-[90px] w-[1px] bg-gray-600"></div>;
};

export default VerticalLine;

결과

내일은 메인 콘텐츠 레이아웃을 잡아줘야겠다.

0개의 댓글