React

Attachment Field

파일을 선택하거나 드래그 앤 드롭으로 업로드할 수 있는 컴포넌트입니다.

Installation

Default

파일 순서 변경이 불필요한 경우 사용할 수 있는 컴포넌트를 포함합니다.

npx @seed-design/cli@latest add ui:attachment-field

Reorderable

드래그 앤 드롭을 통한 파일 순서 변경이 필요한 경우 활용할 수 있는 컴포넌트를 포함합니다. 프로젝트에 dnd-kit 의존성이 추가됩니다.

npx @seed-design/cli@latest add ui:attachment-field-reorderable

Props

AttachmentField

Prop

Type

label?React.ReactNode
indicator?React.ReactNode
description?React.ReactNode
errorMessage?React.ReactNode
showRequiredIndicator?boolean | undefined
inputProps?React.InputHTMLAttributes<HTMLInputElement> | undefined
fieldRef?React.Ref<HTMLDivElement> | undefined
rootProps?React.HTMLAttributes<HTMLDivElement> | undefined
name?string | undefined
acceptedFileEntries?FileEntry[] | undefined
defaultAcceptedFileEntries?FileEntry[] | undefined
onAcceptedFileEntriesChange?((fileEntries: FileEntry[]) => void) | undefined
onFileReject?((rejections: FileRejection[]) => void) | undefined
onFileAccept?((acceptedEntries: FileEntry[], helpers: { updateFileEntryStatus: (id: string, details: FileStatusDetails) => void; }) => void) | undefined

AttachmentInput

Prop

Type

children?((context: UseFileUploadContext) => React.ReactNode) | undefined
onRetry?((fileEntry: FileEntry, helpers: Pick<UseFileUploadReturn, "updateFileEntryStatus">) => void) | undefined

AttachmentDropzone

Prop

Type

children?((context: UseFileUploadContext) => React.ReactNode) | undefined
onRetry?((fileEntry: FileEntry, helpers: Pick<UseFileUploadReturn, "updateFileEntryStatus">) => void) | undefined

AttachmentInputItem

Prop

Type

onRetry?(() => void) | undefined
fileEntryFileEntry

Usage

기본 사용법

AttachmentField 안에 AttachmentInput, AttachmentDropzone, AttachmentInputReorderable, AttachmentDropzoneReorderable 중 하나를 조합하여 사용합니다.

import {
  AttachmentField,
  AttachmentInput,
  AttachmentDropzone,
} from "seed-design/ui/attachment-field";

<AttachmentField>
  <AttachmentInput />
</AttachmentField>;

<AttachmentField>
  <AttachmentDropzone />
</AttachmentField>;
import { AttachmentField } from "seed-design/ui/attachment-field";
import {
  AttachmentInputReorderable,
  AttachmentDropzoneReorderable,
} from "seed-design/ui/attachment-field-reorderable";

<AttachmentField>
  <AttachmentInputReorderable />
</AttachmentField>;

<AttachmentField>
  <AttachmentDropzoneReorderable />
</AttachmentField>;

Item 직접 구성하기

AttachmentInput, AttachmentDropzone, AttachmentInputReorderable, AttachmentDropzoneReorderablechildren을 render prop으로 사용합니다.

acceptedFileEntries을 활용하여 AttachmentInputItem을 직접 렌더링할 수 있습니다. 이때 FileEntry 타입이 제공하는 idkey로 활용하는 것을 권장합니다.

children을 제공하지 않는 경우 자동으로 acceptedFileEntries에 등록된 파일을 AttachmentInputItem으로 렌더링합니다.

import {
  AttachmentField,
  AttachmentInput,
  AttachmentInputItem,
} from "seed-design/ui/attachment-field";

<AttachmentField>
  <AttachmentInput>
    {({ acceptedFileEntries }) =>
      acceptedFileEntries.map((entry) => (
        <AttachmentInputItem key={entry.id} fileEntry={entry} />
      ))
    }
  </AttachmentInput>
</AttachmentField>;

Uploading Files

Trigger

AttachmentInput를 사용하면 trigger(업로드 버튼)가 포함된 레이아웃을 사용할 수 있습니다.

Dropzone

AttachmentDropzone을 사용하면 드래그 앤 드롭 영역이 포함된 레이아웃을 사용할 수 있습니다.

Listening to Accepted File Changes

acceptedFileEntries는 유효성 검사를 마친 파일의 목록입니다. onAcceptedFileEntriesChange 콜백으로 acceptedFileEntries에 등록된 파일 변경 이벤트를 감지할 수 있습니다.

Validating Files

사용자가 선택한 파일이 acceptedFileEntries에 등록되기 전 유효성을 확인할 수 있습니다.

유효하지 않은 파일에 대해 각각 onFileReject 콜백이 실행됩니다. 해당 콜백에서 파일과 에러 코드들을 확인하여 에러 메시지를 표시할 수 있습니다.

Max Files

maxFiles로 업로드 가능한 최대 파일 수를 제한할 수 있습니다. 기본값은 1입니다. 최대 수에 도달한 경우 trigger 및 dropzone이 비활성화됩니다.

업로드 가능한 파일의 수보다 많은 파일을 선택한 경우 업로드 가능한 파일까지 acceptedFileEntries에 등록됩니다. 나머지 파일에 대해서는 각각 onFileReject 콜백이 실행됩니다. 이때 reject된 파일의 에러는 "TOO_MANY_FILES"입니다.

Invalid File Type

accept로 업로드 가능한 파일의 종류를 제한할 수 있습니다.

MIME type(image/png, image/*) 또는 확장자(.png, .jpg, .jpeg) 형식을 지정할 수 있으며, string[]을 전달하는 경우 각 string ,로 join합니다.

<input type="file">에 등록되는 accept 속성을 통해 사용자가 선택할 수 있는 파일의 종류를 제한하는 것은 브라우저 UI에서만 동작하는 편의 기능입니다. 따라서 사용자는 브라우저 파일 선택 다이얼로그의 모든 파일 보기와 같은 기능을 통해 제한된 종류의 파일도 선택할 수 있습니다. 이렇게 선택된 파일의 경우 "INVALID_TYPE" 에러와 함께 onFileReject 콜백이 실행됩니다.

파일 종류 검증이 필요한 경우 해당 검증은 서버에서도 수행되어야 합니다.

File Size

minFileSize, maxFileSize prop을 활용할 수 있습니다.

  • 사용자가 선택한 파일이 minFileSize보다 작은 경우 "FILE_TOO_SMALL" 에러와 함께 onFileReject 콜백이 실행됩니다.
  • 사용자가 선택한 파일이 maxFileSize보다 큰 경우 "FILE_TOO_LARGE" 에러와 함께 onFileReject 콜백이 실행됩니다.

Custom Validation

validate prop으로 각 파일에 대한 유효성 검사를 직접 추가할 수 있습니다. 커스텀 에러 코드를 반환하여 onFileReject에서 에러 종류별로 메시지를 분기할 수 있습니다.

Managing File Status

acceptedFileEntries의 각 항목은 pending, uploading, success, error의 status를 가질 수 있습니다. 새로 추가되는 항목의 status 기본값은 pending입니다.

파일 선택 직후 외부 업로드 API와 연동하는 경우, 사용자에게 각 파일 항목의 업로딩 상태를 보여줄 수 있습니다. onFileAccept 콜백에서 새로 추가된 파일을 받고, 함께 제공되는 updateFileEntryStatus 헬퍼를 사용하여 항목의 status를 업데이트합니다.

  • uploading: ProgressCircle이 표시됩니다.
    • progress를 설정하여 업로드 진행률을 표시할 수 있습니다.
    • progress를 지정하지 않는 경우 indeterminate 상태로 표시됩니다.
  • error: 재시도 버튼이 표시됩니다.
    • 클릭 시 AttachmentInputItem에 지정한 onRetry 콜백이 실행됩니다.

유효성 검증에 성공한 파일 항목은 status와 관계없이 acceptedFileEntries에 유지되므로, 네이티브 form 제출 시 포함됩니다.

Reordering Files

AttachmentInputReorderable 또는 AttachmentDropzoneReorderable을 사용하면 드래그로 파일의 순서를 변경할 수 있습니다.

두 컴포넌트는 dnd-kit 의존성 분리를 위해 별도 snippet ui:attachment-field-reorderable로 제공됩니다.

Context를 통해 reorderFileEntry가 제공되므로, 필요한 경우 원하는 드래그 앤 드롭 동작을 직접 구현하거나, 이미 프로젝트에서 사용 중인 드래그 앤 드롭 라이브러리와 연동하여 사용할 수 있습니다.

Examples

Showing Thumbnails

파일 이름 및 크기 대신 이미지 미리보기를 표시하려면 accept"image/*", ["image/png", "image/jpeg"] 등으로 설정하여 사용자가 이미지 파일만 선택할 수 있도록 제한합니다.

"image/heic" 등 일부 이미지 형식은 브라우저에 따라 이미지 미리보기가 표시되지 않을 수 있습니다.

Disabled

disabled prop으로 trigger 및 dropzone을 비활성화하여 신규 파일 선택을 차단하고, <input type="file">disabled 처리하여 폼 제출 시 값이 전송되지 않도록 합니다.

Read Only

readOnly prop으로 첨부된 파일을 읽기 전용 상태로 표시할 수 있습니다. trigger, dropzone, 파일 제거 버튼, 순서 변경 모두 비활성화되지만 <input type="file">의 값은 유지되어 form 제출 시 함께 전송됩니다.

Controlled

acceptedFileEntriesonAcceptedFileEntriesChange를 사용하여 외부에서 파일 목록을 제어할 수 있습니다.

Custom Inset

--seed-attachment-input-extend-x CSS 변수를 사용하여 스크롤되는 아이템 목록이 레이아웃 바깥으로 빠져나오도록 구성할 수 있습니다.

Field Integration

label, description, errorMessage 등의 Field 관련 prop을 사용할 수 있습니다.

Form (Uncontrolled)

acceptedFileEntries에 등록된 파일이 <input type="file">files로 동기화되므로 <form>name prop을 사용하여 formData에 포함시킬 수 있습니다.

React Hook Form

Customizing Items

Snippet이 제공하는 기본 아이템 구성 외에 추가적인 커스터마이징이 필요한 경우, @seed-design/react에서 제공하는 AttachmentInput.ItemBadge 등의 요소를 활용하여 직접 아이템을 구성할 수 있습니다.

아래 예시에서는 AttachmentInput.ItemBadge를 사용하여 첫 번째 이미지에 "대표사진" 배지를 표시합니다.

Last updated on

On this page