컴포넌트

Field

입력 요소에 레이블과 설명, 오류 메시지를 연결합니다.

설치

pnpm dlx ply-ui add field

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

사용법

Field.Label과 Control을 같은 Root 안에 두면 레이블 관계가 연결됩니다.

required/type 같은 제약과 Error의 match로 오류 메시지를 구분합니다.

구성

구성 요소역할
Root입력의 값, 오류, 레이블 관계를 관리합니다.
Label입력 이름입니다.
Control기본 입력 요소입니다. 같은 Root 안에서 Input을 사용할 수도 있습니다.
Description입력 형식이나 조건을 설명합니다.
Error검증 오류를 표시합니다. match로 오류 조건을 구분합니다.

구현 코드

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

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

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

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

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

function FieldError({
  className,
  ...props
}: ComponentProps<typeof Primitive.Error>) {
  return (
    <Primitive.Error
      {...props}
      className={withClassName("rbx-error", className)}
    />
  );
}

function FieldControl({
  className,
  ...props
}: ComponentProps<typeof Primitive.Control>) {
  return (
    <Primitive.Control
      {...props}
      className={withClassName("rbx-input", className)}
    />
  );
}

// Root/Portal 등 스타일 없는 파트와 제네릭 API는 원본을 그대로 보존합니다.
export const Field = {
  ...Primitive,
  Root: FieldRoot,
  Label: FieldLabel,
  Description: FieldDescription,
  Error: FieldError,
  Control: FieldControl,
};
components/ui/field.css
field.css
/* Field: 공통 구조는 theme.css, 컴포넌트 전용 조정은 아래에 작성합니다. */
.rbx-field {
  display: grid;
  gap: 8px;
  width: 100%;
}

목차