20250302_114113.png

Shadcn의 드롭다운(Dropdown)은 특정 동작이나 기능 등을 Popover 형태로 표시하는 컴포넌트다. 드롭다운 메뉴 아이템(DropdownMenuItem)을 클릭했을 때 다이얼로그(혹은 AlertDialog)를 띄우려는 의도로 메뉴 아이템의 자식으로 다이얼로그를 추가할 수 있다. 하지만 이렇게 작성하면 다이얼로그가 제대로 열리지 않는다.

<DropdownMenu>
  <DropdownMenuTrigger>메뉴 열기</DropdownMenuTrigger>
  <DropdownMenuContent>
    <DropdownMenuGroup>
      <DropdownMenuItem>
        <Dialog>{/* ... */}</Dialog>
      </DropdownMenuItem>
    </DropdownMenuGroup>
  </DropdownMenuContent>
</DropdownMenu>;

Radix의 메뉴 아이템은 클릭했을 때 드롭다운이 자동으로 닫히도록 설계되어 있다. 때문에 다이얼로그를 띄우는 메뉴 아이템을 클릭하면, 드롭다운이 닫히는 기본 동작에 의해 다이얼로그가 열리지마자 닫히는 문제가 발생한다.

위 문제로 StackOverFlow를 찾아보면 DropdownMenuItem 컴포넌트 onSelect 이벤트의 기본 동작을 방지하거나(preventDefault 호출), 다이얼로그 트리거/콘텐츠의 onClick 이벤트 전파를 막는 방법 등이 나온다.

하지만 이 방법들은 다이얼로그를 닫았을 때 aria-hidden 접근성 경고가 발생하고, 다이얼로그 푸터(Footer)에 있는 버튼을 키보드로 제어할 수 없게 된다.

다이얼로그를 닫았을 때 표시되는 접근성 경고

다이얼로그를 닫았을 때 표시되는 접근성 경고

자세하진 않지만 Shadcn 공식문서 - Dialog 페이지를 보면 DropdownMenu, Dialog 컴포넌트를 함께 사용하는 방법이 안내되어 있다. 정리해보면 다음과 같다.

  1. DropdownMenuDialog 컴포넌트로 감싼다
  2. DropdownMenuItemDialogTrigger 컴포넌트로 감싼 후 asChild 속성을 지정한다.
  3. DropdownMenu 컴포넌트 바깥 영역에 DialogContent를 배치한다.
<Dialog>
  <DropdownMenu>
    <DropdownMenuTrigger>메뉴 열기</DropdownMenuTrigger>
    <DropdownMenuContent>
      <DropdownMenuGroup>
        <DialogTrigger asChild>
          <DropdownMenuItem>{/* ... */}</DropdownMenuItem>
        </DialogTrigger>
      </DropdownMenuGroup>
    </DropdownMenuContent>
  </DropdownMenu>
  <DialogContent>{/* ... */}</DialogContent>
</Dialog>

Combobox, ContextMenu 등 컴포넌트에서 다이얼로그를 사용할 때도 위와 동일한 방식으로 작성하면 된다.

<Dialog>
  <Popover>
    <PopoverTrigger asChild>{/* ... */}</PopoverTrigger>
    <PopoverContent>
      <Command>
        <CommandInput />
        <CommandList>
          <CommandEmpty>{/* ... */}</CommandEmpty>
          <CommandGroup>
            {boardList.map(({ id, title }) => (
              <CommandItem value={id}>{title}</CommandItem>
            ))}
          </CommandGroup>
        </CommandList>
        <DialogTrigger asChild>{/* ... */}</DialogTrigger>
      </Command>
    </PopoverContent>
  </Popover>
  <DialogContent>{/* ... */}</DialogContent>
</Dialog>