[Framer Motion]Toss Category motion Clone

서론


토스 홈페이지에는 생각보다 많은 디테일이 숨어있는데 (작은 것 하나에도 motion이 들어감) 프론트를 처음했을 때는 어떻게 만들지..? 라는 생각을 자주 했었다.
요즘 공부하다보니 나도 할 수 있겠는데? 라는 생각이 들어 따라 만들어본 모션이다.

토스의 프론트 채용공고에 보면 기술스택에 Framer motion이 있는데 이 라이브러리를 활용해보았다.

Motion

framer motion v5.0.0부터 지원하는 하단 바 모션을 활용했다.
https://codesandbox.io/s/framer-motion-5-shared-layout-animations-snxgv?from-embed

CRA 프로젝트에서 framer motion v5가 실행이 되지 않는 이슈가 있었는데 github를 열심히 찾아 해결했다.(이 부분은 따로 정리하겠다)

코드


AdminTopMenu.tsx

type Props = {
  tabs: { label: string; route: string }[];
  setSelectedCategory: (selectedCategory: string) => void;
  selectedCategory: string;
};
const AdminTopMenu = ({
  tabs,
  setSelectedCategory,
  selectedCategory,
}: Props) => {
  const navigate = useNavigate();
  return (
    <>
      <nav>
        <StyledUl>
          {tabs.map((item) => (
            <>
              <StyledLi
                key={item.label}
                className={item.label === selectedCategory ? 'selected' : ''}
                onClick={() => {
                  setSelectedCategory(item.label);
                  navigate('/admin/' + item.route);
                }}
              >
                //이 부분이 background를 담당한다.
                <StyledLabel>{item.label}</StyledLabel>
                {item.label === selectedCategory ? (
                  <motion.div className="underline" layoutId="underline" />
                ) : null} 
              </StyledLi>
            </>
          ))}
        </StyledUl>
      </nav>
    </>
  );
};

AdminTopMenu.css

.underline {
    position: absolute;
    bottom: -1px;
    left: 0;
    right: 0;
    height: 40px;
    z-index: -1;
    background: #f3f4f6;
    border-radius: 10px;
}
.selected{
    color: black;
    font-weight: bold;
}

styled.ts

import styled from 'styled-components';

export const StyledUl = styled.ul`
  display: flex;
  padding-left: 0;
  justify-content: flex-start;
`;
export const StyledLi = styled.li`
  background: transparent;
  cursor: pointer;
  height: 24px;
  padding: 24px 10px;
  margin: 0px 20px;
  padding-bottom: 7px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  user-select: none;
  font-size: 17px;

  @media (max-width: 500px) {
    font-size: 15px;
    margin: 0px 15px;
  }
`;

좋은 웹페이지 즐겨찾기