7/28 로그인/로그아웃페이지 CSS, 네비게이션 바 반응형 구현

낄낄박사·2024년 7월 29일

Gotcha

목록 보기
10/22

오늘 고민한 것, 적용한 것들 정리

TailwindCSS 반응형 디자인 기본

  • TailwindCSS에서 sm, md, lg, xl, 2xl 등 브레이크포인트 사용 방법
  • width나 height의 min, max 설정 할때 너무 헷갈렸음.
  • 기본적으로 데스크탑 사이즈로 CSS적용후 작은 화면에 적용할 CSS 코드를 넣음.
    - 화면이 작아지면, sm이하의 사이즈가 되면 SearchBar의 input과 border가 없어지고 아이콘만 남게 하는 것이 목표였는데, 문제는 640~768px까지에서는 의도한대로 되다가 640px 아래로 가면 다시 border와 input이 생기는 것임..
    ==> 해결: 기본적으로 적용될 CSS코드를 작은 화면에 맞춰서 작성함.!

화면 크기에 따라 컴포넌트 표시/숨김

  • hidden, block, inline, sm:block, md:hidden 등 유틸리티 클래스 사용
  • 특정 화면 크기 이하 또는 이상에서 요소를 숨기거나 표시하는 방법
    ==> sm이하에서는 검색아이콘만 보이고 md이상부터 인풋창을 표시하고 보더를 적용 하기 위해서 input에 hidden처리, border는 기본적으로 적용안함. 그리고 input에 md:block, Searchbar Div에 md:border 적용.
import SearchIcon from "./icons/SearchIcon";

export default function SearchBar() {
  return (
    <div className="flex justify-center items-center p-3 rounded-3xl transition-all duration-500 sm:w-10 md:w-[300px] md:border">
      <button className="text-xl ">
        <SearchIcon />
      </button>
      <input
        type="text"
        className="outline-none w-full hidden md:block md:ml-2"
      />
    </div>
  );
}

CSS 트랜지션을 통한 애니메이션 효과

  • transition, transition-all, duration-500 등 클래스 사용
  • 요소의 크기, 위치, 불투명도 등을 부드럽게 변화시키기 => 화면크기 조정시 서치바가 부드럽게 조정됨

화면 크기에 따라 input 창의 표시/숨김

  • sm:hidden, md:block 등 반응형 유틸리티 클래스 사용
  • 작은 화면에서 input 창을 숨기고, 큰 화면에서 표시하기
  • NavMenu와 UserMenu를 분리하여 NavBar 컴포넌트 가독성 높임
  • NavMenu는 navItems배열을 컴포넌트 외부에 만들어서 map을 사용하여 ul 구성

특정 화면 크기 이하에서 아이콘 표시

  • 알림 부분을 NotificationIcon 컴포넌트로 변경
  • 로그인과 로그아웃도 아이콘으로 변경: AuthIcon 컴포넌트를 만들어 로그인/로그아웃 아이콘을 조건부로 렌더링
  • hidden sm:block과 block sm:hidden을 사용하여 반응형 아이콘 표시

햄버거 메뉴 및 하단 내비게이션 바

  • 작은 화면에서 네브바 우측 UserMenu의 반응형 디자인 고민
  • 알림, 로그인,로그아웃 등을 아이콘으로 바꾸어도 메뉴가 다닥다닥 붙어서 UI가 깔끔하지 못함
  • Logo를 제외한 나머지 메뉴는 햄버거에 집어넣음
  • NavMenu + UserMenu 다 넣고나니 용도가 뒤섞인 것같은 느낌이 듦
    ==> 햄버거 제거하고 sm이하 사이즈에서 네비게이션바가 하단에 배치되도록 변경함
"use client";
import { RiHomeFill } from "@react-icons/all-files/ri/RiHomeFill";
import { RiSearchLine } from "@react-icons/all-files/ri/RiSearchLine";
import { RiUserLine } from "@react-icons/all-files/ri/RiUserLine";
import { RiNotificationLine } from "@react-icons/all-files/ri/RiNotificationLine";
import { useState } from "react";
import Link from "next/link";
import { useSession } from "next-auth/react";

export default function BottomNavBar() {
  const [activeTab, setActiveTab] = useState("home");
  const { data: session } = useSession();
  const user = session?.user;

  return (
    <div className="fixed inset-x-0 bottom-0 border-t bg-white text-gray-400 flex justify-around items-center py-2 z-50 sm:hidden">
      <Link href="/">
        <button
          onClick={() => setActiveTab("home")}
          className={activeTab === "home" ? "text-black" : ""}
        >
          <RiHomeFill className="h-6 w-6" />
          <span className="text-xs"></span>
        </button>
      </Link>
      <Link href="/search">
        <button
          onClick={() => setActiveTab("search")}
          className={activeTab === "search" ? "text-black" : ""}
        >
          <RiSearchLine className="h-6 w-6" />
          <span className="text-xs">검색</span>
        </button>
      </Link>
      <Link href="/notification">
        <button
          onClick={() => setActiveTab("notification")}
          className={activeTab === "notification" ? "text-black" : ""}
        >
          <RiNotificationLine className="h-6 w-6" />
          <span className="text-xs">알림</span>
        </button>
      </Link>
      <Link href={`/user/${user?.id}`}>
        <button
          onClick={() => setActiveTab("profile")}
          className={`${
            activeTab === "profile" ? "text-black" : ""
          } flex flex-col items-center`}
        >
          <RiUserLine className="h-6 w-6" />
          <span className="text-xs">마이</span>
        </button>
      </Link>
    </div>
  );
}

로그인 페이지 - onChange 핸들러

  • 인라인으로 작성한 onChange 핸들러를 여러 입력폼을 관리할 수 있는 onChange핸들러로 변경
  • 상태를 email,password 따로 만들지않고 formData객체로 관리
  const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.target;
    setFormData((prev) => ({
      ...prev,
      [name]: value,
    }));
    setErrorMessage("");
  };

텍스트 양 옆으로 지나가는 수평선

  • 텍스트 가운데를 지나가는 수평선을 CSS로 구현: br태그 사용
      <div className="flex w-full items-center justify-center my-4">
        <hr className="border-t  border-gray-300 flex-grow" />
        <span className="mx-4 text-gray-500">OR</span>
        <hr className="border-t border-gray-300 flex-grow" />
      </div>


0개의 댓글