컴포넌트

Autocomplete

텍스트 입력에 추천 항목을 표시합니다.

설치

pnpm dlx ply-ui add autocomplete

공통 설치 설정을 먼저 적용합니다.

사용법

items가 추천 후보입니다. 선택을 강제해야 한다면 Combobox 사용을 검토합니다.

Input의 aria-label과 Empty의 빈 결과 문구를 앱에 맞게 바꾸세요.

구성

구성 요소역할
Root추천 항목과 입력 문자열을 관리합니다.
Input직접 텍스트를 입력하는 영역입니다.
Trigger / Clear추천 목록을 열거나 입력을 지웁니다.
Portal / Positioner / Popup추천 목록의 위치와 표면을 구성합니다.
List / Item추천 목록과 입력할 후보입니다.
Empty추천 결과가 없을 때 표시합니다.
Group / GroupLabel추천 항목의 그룹과 이름입니다.

입력값 제어

valueonValueChange로 입력 문자열을 관리합니다. 추천에 없는 문자열도 유지됩니다.

구현 코드

components/ui/autocomplete.tsx
autocomplete.tsx
"use client";

import type { ComponentProps } from "react";
import { Autocomplete as Primitive } from "@base-ui/react/autocomplete";
import { withClassName } from "../../lib/cx";
import "./autocomplete.css";

// 동작과 접근성은 Base UI가 담당합니다. 이 파일은 스타일 연결만 담당합니다.
function AutocompleteInput({
  className,
  ...props
}: ComponentProps<typeof Primitive.Input>) {
  return (
    <Primitive.Input
      {...props}
      className={withClassName("rbx-input", className)}
    />
  );
}

function AutocompleteTrigger({
  className,
  ...props
}: ComponentProps<typeof Primitive.Trigger>) {
  return (
    <Primitive.Trigger
      {...props}
      className={withClassName("rbx-button", className)}
    />
  );
}

function AutocompletePopup({
  className,
  ...props
}: ComponentProps<typeof Primitive.Popup>) {
  return (
    <Primitive.Popup
      {...props}
      className={withClassName("rbx-popup", className)}
    />
  );
}

function AutocompletePositioner({
  className,
  ...props
}: ComponentProps<typeof Primitive.Positioner>) {
  return (
    <Primitive.Positioner
      {...props}
      className={withClassName("rbx-positioner", className)}
    />
  );
}

function AutocompleteItem({
  className,
  ...props
}: ComponentProps<typeof Primitive.Item>) {
  return (
    <Primitive.Item
      {...props}
      className={withClassName("rbx-option", className)}
    />
  );
}

function AutocompleteEmpty({
  className,
  ...props
}: ComponentProps<typeof Primitive.Empty>) {
  return (
    <Primitive.Empty
      {...props}
      className={withClassName("rbx-description", className)}
    />
  );
}

function AutocompleteGroupLabel({
  className,
  ...props
}: ComponentProps<typeof Primitive.GroupLabel>) {
  return (
    <Primitive.GroupLabel
      {...props}
      className={withClassName("rbx-group-label", className)}
    />
  );
}

function AutocompleteClear({
  className,
  ...props
}: ComponentProps<typeof Primitive.Clear>) {
  return (
    <Primitive.Clear
      {...props}
      className={withClassName("rbx-icon-button", className)}
    />
  );
}

// Root/Portal 등 스타일 없는 파트와 제네릭 API는 원본을 그대로 보존합니다.
export const Autocomplete = {
  ...Primitive,
  Input: AutocompleteInput,
  Trigger: AutocompleteTrigger,
  Popup: AutocompletePopup,
  Positioner: AutocompletePositioner,
  Item: AutocompleteItem,
  Empty: AutocompleteEmpty,
  GroupLabel: AutocompleteGroupLabel,
  Clear: AutocompleteClear,
};
components/ui/autocomplete.css
autocomplete.css
@import "./button.css";
/* Autocomplete uses shared input and popup styles in theme.css. */

목차