Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement Menubar & Toast component with storybook #24

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

dgd03146
Copy link
Collaborator

Motivation 🤔

  • Implement a Menubar and Toast component to enhance user interface functionality.
  • Ensure both components are accessible and integrated with Storybook for better testing and demonstration.

Key Changes 🔑

  • Designed and implemented the Menubar component with accessibility in mind.
  • Designed and implemented the Toast component, ensuring it is accessible.
  • Integrated both components with Storybook.
  • Added documentation and usage examples for both components in Storybook.
  • Ensured that both components adhere to accessibility standards.
  • Conducted thorough testing to verify the accessibility and functionality of the components.

To Reviews 🙏🏻

  • Review the implementation of the Menubar and Toast components.
  • Check the accessibility features of both components.
  • Verify the integration and documentation in Storybook.
  • Ensure that the components are tested thoroughly and adhere to best practices.

@dgd03146 dgd03146 added the enhancement New feature or request label Jun 14, 2024
@dgd03146 dgd03146 requested a review from ebokyung June 14, 2024 19:53
@dgd03146 dgd03146 self-assigned this Jun 14, 2024
Copy link

@ebokyung ebokyung left a comment

Choose a reason for hiding this comment

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

고생하셨습니다! 코드에서 가독성과 접근성, 성능까지 고려한다는 점이 많이 느껴지는 것 같습니다!!
많이 배워갑니다 ㅎㅎㅎ 👍🏻

parameters: {
layout: 'centered',
},
} satisfies Meta<typeof Menubar>;

Choose a reason for hiding this comment

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

오 satisfies 배워갑니다

Comment on lines +35 to +42
const contextValue = {
selectedMenu,
isOpen,
setIsOpen,
onOpenMenu: () => setIsOpen(true),
onSelectedMenu,
onCloseMenu,
};

Choose a reason for hiding this comment

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

이렇게 해서 넘기니까 가독성이 좋네요 👍🏻

Comment on lines +24 to +26
useEffect(() => {
if (!open) wasKeyboardTriggerOpenRef.current = false;
}, [open]);

Choose a reason for hiding this comment

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

혹시 여기 의존성배열에 있는 open은 어디에서 가져오는 건가요?

Comment on lines +26 to +36
const extractText = useCallback(
(child: ReactNode): string => {
if (typeof child === 'string') {
return child;
}
return '';
},
[selectedMenu],
);

const menuName = extractText(children);

Choose a reason for hiding this comment

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

저는 props.children으로 바로 사용했었는데 😅
이렇게 children를 이용해서 구체적으로 메뉴이름을 추출해서 변수로 사용하는 방법 좋은 것 같습니다 👍🏻👍🏻👍🏻

);

const menuName = extractText(children);
const isActive = selectedMenu === menuName;

Choose a reason for hiding this comment

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

isActive도 명시적이고 좋네요

Comment on lines +29 to +31
triggerId: useId(),
triggerRef,
contentId: useId(),

Choose a reason for hiding this comment

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

trigger와 content에 고유한 id를 부여하는 방법도 좋은 것 같아요 👍🏻

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

radix ui를 참고했는데 useId 사용 하더라구요!

Choose a reason for hiding this comment

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

👍🏻👍🏻👍🏻

Comment on lines +32 to +42
export const ToastProvider = ({ children }: { children: ReactNode }) => {
const [toastList, setToastList] = useState<ToastContent[]>([]);
const value = useMemo(
() => ({ toastList, setToastList }),
[toastList, setToastList],
);

return (
<ToastContext.Provider value={value}>{children}</ToastContext.Provider>
);
};

Choose a reason for hiding this comment

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

shadcn은 최상단에 Provider없이 Toaster(== 거정님 코드에서 ToastContainer)만 사용하길래 어떻게 사용하는지 코드를 살펴봤는데, 아래 코드처럼 아예 전역변수를 사용하는 것 같더라구요. (scope 관련한 코드가 있는 것 같기도한데 파악하지는 못했습니다.)

// useToast.tsx
let memoryState: State = { toasts: [] };
const listeners: Array<(state: State) => void> = [];

const useToast = () => {
  const [state, setState] = useState<State>(memoryState);

  useEffect(() => {
    listeners.push(setState);
    return () => {
      const index = listeners.indexOf(setState);
      if (index > -1) {
        listeners.splice(index, 1);
      }
    };
  }, [state]);

  return {
    ...state, // toasts
    toast,
  };
};
export { useToast, toast };

전역변수를 쓰면 렌더링 사이클에 얽매이지 않아 퍼포먼스 면에서 오버헤드가 적을 수 있지만,
context provider를 쓰는게 1. 명확한 구조이고 2. 전역 변수가 아니라서 예측가능하다는 점에서 협업시에 더 좋은 것 같다고 생각했습니다.

그리고 react-toastify도 provider를 사용하지 않는데, 이를 간략하게 구현한 글이 있어 공유합니다. toast와 toastContainer 사이에 eventManager를 두어 동작하는 방식이고, toastlist는 useToastContainer 내에서 Map으로 관리하더라구요.
https://www.milk717.com/gomterview-3

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

공유 감사합니다!! 한번 찾아보겠습니다!

@dgd03146
Copy link
Collaborator Author

고생하셨습니다! 코드에서 가독성과 접근성, 성능까지 고려한다는 점이 많이 느껴지는 것 같습니다!! 많이 배워갑니다 ㅎㅎㅎ 👍🏻
감사합니다!! ㅎㅎ 근데 뭐가 꼬여서 storybook test에서 오류가 나서 수정해야하네요ㅠㅠ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants