Skip to content

사이드바 컴포넌트 개발#27

Merged
jungwon123 merged 3 commits into
mainfrom
feat/sidebar
Feb 8, 2026
Merged

사이드바 컴포넌트 개발#27
jungwon123 merged 3 commits into
mainfrom
feat/sidebar

Conversation

@jungwon123

Copy link
Copy Markdown
Contributor

Summary

사이드바 컴포넌트 입니다.

Issue

  • Closes #

  • 특이사항
    모바일 버전 로고 추가하였습니다.

@jungwon123 jungwon123 added this to the 컴포넌트 milestone Feb 4, 2026
@jungwon123 jungwon123 added the 기능추가 기능개발 및 추가할 때 사용해주세요. label Feb 4, 2026
@github-project-automation github-project-automation Bot moved this to 개발 대기중 in workers Feb 4, 2026
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @jungwon123, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 애플리케이션의 사이드바 기능을 구현하기 위한 포괄적인 컴포넌트 세트를 도입합니다. 데스크톱 및 모바일 환경 모두에서 사용자에게 일관되고 반응형 탐색 경험을 제공하는 것을 목표로 하며, 재사용 가능한 UI 요소들을 통해 향후 확장성을 고려하여 설계되었습니다. 이를 통해 사용자 인터페이스의 전반적인 구조와 접근성이 향상될 것입니다.

Highlights

  • 사이드바 컴포넌트 개발: 데스크톱 환경을 위한 접기/펼치기 기능을 갖춘 Sidebar 컴포넌트와 모바일 환경을 위한 MobileDrawerMobileHeader 컴포넌트가 새로 추가되었습니다.
  • 사이드바 관련 하위 컴포넌트 추가: SidebarAddButton, SidebarButton, SidebarTeamSelect 등 사이드바 내에서 사용될 다양한 UI 요소 컴포넌트들이 개발되었습니다.
  • Storybook 스토리 및 스타일 모듈: 새로 추가된 모든 컴포넌트에 대한 Storybook 스토리가 작성되어 시각적 테스트 및 문서화가 용이하며, 각 컴포넌트별 CSS 모듈이 적용되어 스타일 격리 및 관리가 개선되었습니다.
  • 새로운 SVG 에셋 추가: 모바일 버전 로고를 포함한 logoIcon.svg와 같은 새로운 SVG 이미지 에셋이 추가되었습니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/assets/logos/logoIcon.svg
    • 모바일 헤더에 사용될 새로운 SVG 로고 아이콘이 추가되었습니다.
  • src/components/sidebar/MobileDrawer.stories.tsx
    • MobileDrawer 컴포넌트의 Storybook 스토리가 추가되어 모바일 드로어의 동작과 시각적 요소를 확인할 수 있습니다.
  • src/components/sidebar/MobileDrawer.tsx
    • 모바일 환경을 위한 사이드 드로어 컴포넌트가 추가되었습니다. 오버레이 클릭, X 버튼, ESC 키를 통한 닫기 기능과 포커스 트랩이 구현되어 접근성을 높였습니다.
  • src/components/sidebar/MobileHeader.stories.tsx
    • MobileHeader 컴포넌트의 Storybook 스토리가 추가되어 로그인/로그아웃 상태별 모바일 헤더를 확인할 수 있습니다.
  • src/components/sidebar/MobileHeader.tsx
    • 모바일 환경을 위한 상단 헤더 컴포넌트가 추가되었습니다. 로그인 여부에 따라 로고, 햄버거 메뉴, 프로필 버튼 표시 여부가 달라집니다.
  • src/components/sidebar/Sidebar.stories.tsx
    • Sidebar 컴포넌트의 Storybook 스토리가 추가되어 접기/펼치기 기능과 다양한 슬롯을 통한 콘텐츠 주입 방식을 확인할 수 있습니다.
  • src/components/sidebar/Sidebar.tsx
    • 데스크톱 환경을 위한 사이드바 레이아웃 컨테이너 컴포넌트가 추가되었습니다. 접기/펼치기 기능을 지원하며, 팀 선택, 버튼, 푸터 등 다양한 콘텐츠를 위한 슬롯을 제공합니다.
  • src/components/sidebar/SidebarAddButton.stories.tsx
    • SidebarAddButton 컴포넌트의 Storybook 스토리가 추가되었습니다.
  • src/components/sidebar/SidebarAddButton.tsx
    • 사이드바 내에서 항목을 추가하는 데 사용되는 버튼 컴포넌트가 추가되었습니다.
  • src/components/sidebar/SidebarButton.stories.tsx
    • SidebarButton 컴포넌트의 Storybook 스토리가 추가되어 활성 상태 및 아이콘 전용 모드 등을 확인할 수 있습니다.
  • src/components/sidebar/SidebarButton.tsx
    • 사이드바 내 메뉴 항목으로 사용되는 범용 버튼 컴포넌트가 추가되었습니다. 활성 상태와 아이콘 전용 모드를 지원합니다.
  • src/components/sidebar/SidebarTeamSelect.stories.tsx
    • SidebarTeamSelect 컴포넌트의 Storybook 스토리가 추가되어 선택 상태 및 아이콘 표시를 확인할 수 있습니다.
  • src/components/sidebar/SidebarTeamSelect.tsx
    • 사이드바에서 팀을 선택하는 드롭다운 트리거 버튼 컴포넌트가 추가되었습니다.
  • src/components/sidebar/index.ts
    • 새로 추가된 모든 사이드바 관련 컴포넌트들을 쉽게 임포트할 수 있도록 index.ts 파일에 export 구문이 추가되었습니다.
  • src/components/sidebar/styles/MobileDrawer.module.css
    • MobileDrawer 컴포넌트의 스타일을 정의하는 CSS 모듈이 추가되었습니다.
  • src/components/sidebar/styles/MobileHeader.module.css
    • MobileHeader 컴포넌트의 스타일을 정의하는 CSS 모듈이 추가되었습니다.
  • src/components/sidebar/styles/Sidebar.module.css
    • Sidebar 컴포넌트의 스타일을 정의하는 CSS 모듈이 추가되었습니다.
  • src/components/sidebar/styles/SidebarAddButton.module.css
    • SidebarAddButton 컴포넌트의 스타일을 정의하는 CSS 모듈이 추가되었습니다.
  • src/components/sidebar/styles/SidebarButton.module.css
    • SidebarButton 컴포넌트의 스타일을 정의하는 CSS 모듈이 추가되었습니다.
  • src/components/sidebar/styles/SidebarTeamSelect.module.css
    • SidebarTeamSelect 컴포넌트의 스타일을 정의하는 CSS 모듈이 추가되었습니다.
  • src/components/sidebar/types/types.ts
    • 사이드바 컴포넌트의 props 타입을 정의하는 파일이 추가되었습니다.
Activity
  • 이 PR에는 아직 사람의 활동이 없습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

이 PR은 데스크탑 및 모바일 환경을 위한 사이드바 관련 컴포넌트들을 추가합니다. 전반적으로 컴포넌트 구조가 잘 잡혀있고, Storybook을 통한 문서화도 훌륭합니다. 몇 가지 개선점을 제안했습니다. MobileDrawer 컴포넌트에서 useEffect의 의존성 관련 잠재적 성능 문제를 개선하는 방안과, Sidebar 컴포넌트에서 prop 렌더링 로직의 일관성을 높이는 방안을 포함했습니다.

Comment on lines +30 to +62
useEffect(() => {
if (!isOpen || !drawerRef.current) return;

focusableRef.current = Array.from(
drawerRef.current.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),
);

const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
onClose();
return;
}

if (e.key !== 'Tab') return;

const items = focusableRef.current;
if (items.length === 0) return;

const first = items[0];
const last = items[items.length - 1];

if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
};

document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}, [isOpen, onClose]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

현재 useEffect 훅이 onClose 함수에 의존하고 있습니다. 만약 부모 컴포넌트에서 onClose prop을 useCallback으로 감싸지 않으면, 부모가 리렌더링될 때마다 새로운 함수가 생성되어 이 useEffect가 불필요하게 재실행될 수 있습니다. 이는 성능 저하의 원인이 될 수 있습니다.

이러한 문제를 방지하고 컴포넌트의 안정성을 높이기 위해, onClose 함수를 ref에 저장하여 사용하는 것을 고려해볼 수 있습니다. 이렇게 하면 useEffectisOpen 상태가 변경될 때만 실행되면서도 항상 최신의 onClose 함수를 호출할 수 있습니다.

export default function MobileDrawer({ isOpen, children, onClose }: MobileDrawerProps) {
  const drawerRef = useRef<HTMLElement>(null);
  const focusableRef = useRef<HTMLElement[]>([]);
  const onCloseRef = useRef(onClose);

  useEffect(() => {
    onCloseRef.current = onClose;
  }, [onClose]);

  useEffect(() => {
    if (!isOpen || !drawerRef.current) return;

    focusableRef.current = Array.from(
      drawerRef.current.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),
    );

    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        onCloseRef.current();
        return;
      }

      if (e.key !== 'Tab') return;

      const items = focusableRef.current;
      if (items.length === 0) return;

      const first = items[0];
      const last = items[items.length - 1];

      if (e.shiftKey && document.activeElement === first) {
        e.preventDefault();
        last.focus();
      } else if (!e.shiftKey && document.activeElement === last) {
        e.preventDefault();
        first.focus();
      }
    };

    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [isOpen]); // onClose 제거

  // ... 나머지 코드
}

</div>
<div className={styles.content}>
{teamSelect && (typeof teamSelect === 'function' ? teamSelect(isCollapsed) : teamSelect)}
{typeof children === 'function' ? children(isCollapsed) : children}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

가독성과 유지보수성 향상을 위해 다른 슬롯 prop들(teamSelect, addButton)과 일관된 렌더링 패턴을 사용하는 것이 좋습니다. children prop을 렌더링하기 전에 존재 여부를 확인하는 로직을 추가하는 것을 제안합니다.

Suggested change
{typeof children === 'function' ? children(isCollapsed) : children}
{children && (typeof children === 'function' ? children(isCollapsed) : children)}

@jungwon123 jungwon123 merged commit 166d94b into main Feb 8, 2026
1 check passed
@github-project-automation github-project-automation Bot moved this from 개발 대기중 to 개발 완료 in workers Feb 8, 2026
@jungwon123 jungwon123 deleted the feat/sidebar branch February 20, 2026 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

기능추가 기능개발 및 추가할 때 사용해주세요.

Projects

Status: 개발 완료

Development

Successfully merging this pull request may close these issues.

4 participants