Featuring Design System
Legacy

CoreDropdown

레거시 포지셔닝 드롭다운 컴포넌트. Dropdown으로 마이그레이션을 권장합니다.

개요

마이그레이션 안내 — 이 컴포넌트는 레거시입니다. 신규 프로젝트에서는 Dropdown을 사용하세요.

CoreDropdowntargetRef 기준으로 위치를 계산해 CorePortal에 렌더링하는 플로팅 레이어 컴포넌트입니다.

  • 12가지 placementtop/bottom/left/right × start/center/end 조합
  • autoAdjust — 뷰포트 경계를 감지해 방향·정렬을 자동 보정
  • bgProps — 배경 오버레이로 외부 클릭 시 드롭다운을 닫음
  • OverlayScrollbars — 내부 스크롤을 자체 처리, 문서 스크롤 차단

Usage

기본 사용법

() => {
const [open, setOpen] = React.useState(false);
const ref = React.useRef(null);
return (
  <>
    <CoreButton text="드롭다운 열기" ref={ref} onClick={() => setOpen(!open)} />
    <CoreDropdown
      open={open}
      handler={setOpen}
      placement="bottom-center"
      targetMargin="4px"
      targetRef={ref}
    >
      <div style={{ padding: '12px' }}>드롭다운 내용</div>
    </CoreDropdown>
  </>
);
}

Placement 변형

() => {
const [placement, setPlacement] = React.useState('bottom-center');
const ref = React.useRef(null);
const [open, setOpen] = React.useState(false);
const placements = [
  'top-start','top-center','top-end',
  'bottom-start','bottom-center','bottom-end',
  'left-start','left-center','left-end',
  'right-start','right-center','right-end',
];
return (
  <VStack $css={{ gap: '8px' }}>
    <HStack $css={{ gap: '4px', flexWrap: 'wrap' }}>
      {placements.map((p) => (
        <CoreButton
          key={p}
          text={p}
          buttonType={placement === p ? 'primary' : 'secondary'}
          size="xs"
          onClick={() => { setPlacement(p); setOpen(true); }}
        />
      ))}
    </HStack>
    <CoreButton text="닫기" size="sm" ref={ref} onClick={() => setOpen(false)} />
    <CoreDropdown open={open} handler={setOpen} placement={placement} targetRef={ref} targetMargin="8px">
      <div style={{ padding: '12px', minWidth: '120px' }}>{placement}</div>
    </CoreDropdown>
  </VStack>
);
}

크기와 스크롤

() => {
const [open, setOpen] = React.useState(false);
const ref = React.useRef(null);
return (
  <>
    <CoreButton text="열기" ref={ref} onClick={() => setOpen(!open)} />
    <CoreDropdown
      open={open}
      handler={setOpen}
      placement="bottom-center"
      targetRef={ref}
      width="200px"
      maxHeight="120px"
      padding="8px"
    >
      {Array.from({ length: 10 }, (_, i) => (
        <div key={i} style={{ padding: '4px 8px' }}>항목 {i + 1}</div>
      ))}
    </CoreDropdown>
  </>
);
}

autoAdjust — 자동 위치 보정

() => {
const [open, setOpen] = React.useState(false);
const ref = React.useRef(null);
return (
  <>
    <CoreButton text="autoAdjust 열기" ref={ref} onClick={() => setOpen(!open)} />
    <CoreDropdown
      open={open}
      handler={setOpen}
      placement="bottom-center"
      targetRef={ref}
      autoAdjust
    >
      <div style={{ padding: '12px' }}>뷰포트 경계에 맞춰 자동 조정됩니다</div>
    </CoreDropdown>
  </>
);
}

bgProps — 배경 오버레이

() => {
const [open, setOpen] = React.useState(false);
const ref = React.useRef(null);
return (
  <>
    <CoreButton text="오버레이 열기" ref={ref} onClick={() => setOpen(!open)} />
    <CoreDropdown
      open={open}
      handler={setOpen}
      placement="bottom-center"
      targetRef={ref}
      bgProps
    >
      <div style={{ padding: '16px' }}>배경 클릭 시 닫힙니다</div>
    </CoreDropdown>
  </>
);
}

Props

ComponentPropsWithoutRef<'div'>를 확장한 컴포넌트입니다.

Prop

Type

Placement 타입

Prop

Type

스타일

CoreDropdownCorePortal(#core-dropdown-portal) 안에 렌더링되며, 위치는 런타임 CSS 변수로 제어됩니다.

드롭다운 루트:

  • position: fixed
  • border-radius: radius-100
  • background-color: white
  • box-shadow: elevation-8
  • z-index: 10

OverlayScrollbars 래퍼:

  • padding: spacing-200 (8px, 기본값)
  • overscroll-behavior: none

배경 오버레이 (bgProps):

  • position: fixed, inset: 0
  • z-index: 1 (드롭다운보다 낮음)

런타임 CSS 변수

변수설명기본값
dropdownWidthVar너비targetRef 너비
dropdownHeightVar높이auto
dropdownMaxHeightVar최대 높이unset
dropdownTopVartop 위치unset
dropdownBottomVarbottom 위치unset
dropdownLeftVarleft 위치unset
dropdownRightVarright 위치unset
dropdownPaddingVar내부 paddingspacing-200
dropdownTranslatetransform translatetranslate(0,0)

마이그레이션 가이드

신규 Dropdown 컴포넌트는 Base UI 기반으로 접근성과 애니메이션이 개선됐습니다.

Before / After

// Before — CoreDropdown
const [open, setOpen] = useState(false);
const ref = useRef(null);

<CoreButton ref={ref} text="열기" onClick={() => setOpen(!open)} />
<CoreDropdown
  open={open}
  handler={setOpen}
  placement="bottom-center"
  targetMargin="4px"
  targetRef={ref}
>
  <div>내용</div>
</CoreDropdown>
// After — Select (Dropdown은 visual layer로 직접 사용하지 않고 Select와 조합합니다)
<Select.Root>
	<Select.Trigger size="md">
		<Select.Value placeholder="열기" />
	</Select.Trigger>
	<Select.Positioner side="bottom" align="center" sideOffset={4}>
		<Select.Popup>
			<Select.Item value="item1">항목 1</Select.Item>
			<Select.Item value="item2">항목 2</Select.Item>
		</Select.Popup>
	</Select.Positioner>
</Select.Root>

참고 — 신규 Dropdown은 visual layer 전용 컴포넌트입니다. 독립 드롭다운 UI는 Select compound 패턴을 사용하세요.

변경 사항

CoreDropdownSelect / Dropdown
open / handler (외부 state)Select.Root가 내부 state 관리
targetRefSelect.Trigger가 자동으로 anchor
placement="bottom-center"side="bottom" align="center"
targetMarginsideOffset
autoAdjust기본 활성화 (collisionAvoidance)
bgPropsSelect.Backdrop
width / maxHeight$css prop 또는 CSS