FileInput
FileInput (파일 입력)
FileInput 컴포넌트는 사용자로부터 파일을 입력받는 컴포넌트예요. Input과 Input.Wrapper 컴포넌트의 기능과 모든 input 요소 props를 지원해요.
출처: 문서
본문
FileInput 컴포넌트는 Input과 Input.Wrapper 컴포넌트의 기능과 모든 input 요소 props를 지원해요. FileInput 문서는 컴포넌트가 지원하는 모든 기능을 담고 있지 않아요. 사용 가능한 모든 기능은 Input 문서를 참고해요.
import { FileInput } from '@mantine/core';
function Demo() {
return (
<FileInput
label="Input label"
description="Input description"
placeholder="Input placeholder"
/>
);
}
로딩 상태 (Loading state)
loading prop을 설정하면 로딩 인디케이터를 표시해요. 기본적으로 로더는 input 오른쪽에 표시돼요. loadingPosition prop을 'left'나 'right'로 바꿔 위치를 조절할 수 있어요. API 호출, 검색, 검증 같은 비동기 작업에 유용해요.
import { FileInput } from '@mantine/core';
function Demo() {
return <FileInput placeholder="Upload file" loading />;
}
제어 사용 (Controlled)
multiple이 false일 때:
import { useState } from 'react';
import { FileInput } from '@mantine/core';
function Demo() {
const [value, setValue] = useState<File | null>(null);
return <FileInput value={value} onChange={setValue} />;
}
multiple이 true일 때:
import { useState } from 'react';
import { FileInput } from '@mantine/core';
function Demo() {
const [value, setValue] = useState<File[]>([]);
return <FileInput multiple value={value} onChange={setValue} />;
}
비제어 사용 (Uncontrolled)
FileInput은 네이티브 input[type="file"]처럼 비제어 폼에서도 사용할 수 있어요. 폼 제출 시 FormData 객체에 파일 입력 값을 포함하려면 name 속성을 설정해요. 비제어 폼에서 초기 값을 제어하려면 defaultValue prop을 사용해요.
FormData와 함께 비제어 FileInput을 사용하는 예시:
import { FileInput } from '@mantine/core';
function Demo() {
return (
<form
onSubmit={(event) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const files = formData.getAll('file');
console.log('File input value:', files);
}}
>
<FileInput label="Upload your file" name="file" />
<button type="submit">Submit</button>
</form>
);
}
여러 파일 (Multiple)
multiple을 설정하면 사용자가 두 개 이상의 파일을 선택할 수 있어요.
import { FileInput } from '@mantine/core';
function Demo() {
return <FileInput label="Upload files" placeholder="Upload files" multiple />;
}
Accept
accept prop으로 특정 mime 타입으로 파일 선택을 제한할 수 있어요.
import { FileInput } from '@mantine/core';
function Demo() {
return (
<FileInput accept="image/png,image/jpeg" label="Upload files" placeholder="Upload files" />
);
}
지우기 가능 (Clearable)
clearable prop을 설정하면 파일이 선택되었을 때 input 오른쪽 섹션에 지우기 버튼이 표시돼요. 커스텀 right section을 정의하면 지우기 버튼이 렌더링되지 않는다는 점을 참고해요.
import { FileInput } from '@mantine/core';
function Demo() {
return <FileInput clearable label="Upload files" placeholder="Upload files" />;
}
지우기 섹션 모드 (Clear section mode)
clearSectionMode prop은 지우기 버튼과 rightSection이 어떻게 렌더링되는지 결정해요.
'both'(기본) – 지우기 버튼과rightSection을 모두 렌더링해요'rightSection'– 사용자가 제공한rightSection만 렌더링하고 지우기 버튼은 무시해요'clear'– 지우기 버튼만 렌더링하고rightSection은 무시해요
import { CaretDownIcon } from '@phosphor-icons/react';
import { FileInput, Stack } from '@mantine/core';
function Demo() {
return (
<Stack>
<FileInput
label="clearSectionMode='both' (default)"
placeholder="Pick file"
clearable
rightSection={<CaretDownIcon size={16} />}
clearSectionMode="both"
/>
<FileInput
label="clearSectionMode='rightSection'"
placeholder="Pick file"
clearable
rightSection={<CaretDownIcon size={16} />}
clearSectionMode="rightSection"
/>
<FileInput
label="clearSectionMode='clear'"
placeholder="Pick file"
clearable
rightSection={<CaretDownIcon size={16} />}
clearSectionMode="clear"
/>
</Stack>
);
}
커스텀 값 컴포넌트
valueComponent prop으로 선택된 파일이 어떻게 표시되는지 커스터마이즈할 수 있어요.
import { FileInput, FileInputProps, Pill } from '@mantine/core';
const ValueComponent: FileInputProps['valueComponent'] = ({ value }) => {
if (value === null) {
return null;
}
if (Array.isArray(value)) {
return (
<Pill.Group>
{value.map((file, index) => (
<Pill key={index}>{file.name}</Pill>
))}
</Pill.Group>
);
}
return <Pill>{value.name}</Pill>;
};
function Demo() {
return (
<FileInput
label="Upload files"
placeholder="Upload files"
multiple
valueComponent={ValueComponent}
/>
);
}
오류 상태 (Error state)
error prop으로 오류 메시지를 표시할 수 있어요.
import { FileInput } from '@mantine/core';
function Demo() {
return (
<>
<FileInput label="Boolean error" placeholder="Boolean error" error />
<FileInput
mt="md"
label="With error message"
placeholder="With error message"
error="Invalid name"
/>
</>
);
}
성공 상태 (Success state)
success prop으로 성공 메시지를 표시할 수 있어요.
import { FileInput } from '@mantine/core';
function Demo() {
return <FileInput label="Upload file" success="File is valid" />;
}
비활성 상태 (Disabled state)
import { FileInput } from '@mantine/core';
function Demo() {
return <FileInput disabled label="Disabled input" placeholder="Disabled input" />;
}
왼쪽·오른쪽 섹션 (Left and right sections)
FileInput은 leftSection과 rightSection prop을 지원해요. 이 섹션들은 input wrapper 안에 절대 위치(absolute positioning)로 렌더링돼요. 아이콘이나 다른 요소를 표시하는 데 사용할 수 있어요.
섹션 스타일과 콘텐츠를 제어하는 props:
rightSection/leftSection– input의 해당 쪽에 렌더링할 React 노드rightSectionWidth/leftSectionWidth– right section의 너비와 input 해당 쪽의 패딩을 제어해요. 기본적으로 컴포넌트sizeprop으로 제어돼요.rightSectionPointerEvents/leftSectionPointerEvents– 섹션의pointer-events속성을 제어해요. 상호작용하지 않는 요소를 렌더링하려면none으로 설정해 클릭이 input을 통과하게 해요.
import { FileInput } from '@mantine/core';
import { FileTextIcon } from '@phosphor-icons/react';
function Demo() {
const icon = <FileTextIcon size={18} />;
return (
<>
<FileInput
leftSection={icon}
label="Attach your CV"
placeholder="Your CV"
leftSectionPointerEvents="none"
/>
<FileInput
rightSection={icon}
label="Attach your CV"
placeholder="Your CV"
rightSectionPointerEvents="none"
mt="md"
/>
</>
);
}
Styles API
FileInput은 Styles API를 지원해요. classNames prop으로 내부 요소에 스타일을 추가할 수 있어요.
주요 선택자는 다음과 같아요.
wrapper– Input의 루트 요소input– input 요소section– 왼쪽·오른쪽 섹션bottomSection– input border 아래쪽에 렌더링되는 하단 섹션 요소root– 루트 요소label– 라벨 요소required– 라벨 안에 렌더링되는 필수 별표 요소description– 설명 요소error– 오류 요소success– 성공 요소placeholder– 플레이스홀더 텍스트
요소 ref 가져오기
import { useRef } from 'react';
import { FileInput } from '@mantine/core';
function Demo() {
const ref = useRef<HTMLButtonElement>(null);
return <FileInput ref={ref} />;
}
접근성 (Accessibility)
FileInput을 label prop 없이 사용하면 스크린 리더가 제대로 인지하지 못해요.
import { FileInput } from '@mantine/core';
// Inaccessible input – screen reader will not announce it properly
function Demo() {
return <FileInput />;
}
aria-label을 설정하면 input을 접근 가능하게 만들 수 있어요. 이 경우 라벨은 보이지 않지만 스크린 리더가 읽어줘요.
import { FileInput } from '@mantine/core';
// Accessible input – it has aria-label
function Demo() {
return <FileInput aria-label="My input" />;
}
label prop이 설정되면 input은 접근 가능하며 aria-label을 설정할 필요가 없어요.
import { FileInput } from '@mantine/core';
// Accessible input – it has associated label element
function Demo() {
return <FileInput label="My input" />;
}
FileInputProps 타입
FileInputProps 타입은 단일 타입 인자를 받는 제네릭 인터페이스예요. 인자는 multiple 값이에요.
import type { FileInputProps } from '@mantine/core';
type SingleInputProps = FileInputProps<false>;
type MultipleInputProps = FileInputProps<true>;
더 알아보기 (Learn more)
- Input — 입력 컴포넌트 기반 문서
- FileButton — 파일 선택 버튼 컴포넌트
- Pill — 파일 이름 표시용 pill 컴포넌트