Input File
InputFileは、ファイルをアップロードする際に使用されるコンポーネントです。
<script lang="ts">
import InputFile from '$lib/components/ui/atoms/InputFile.svelte';
let files = $state();
</script>
<InputFile bind:files />
プロパティ
InputFileは、以下のプロパティをサポートしています。
| 名前 | 型 | デフォルト値 | 説明 |
|---|---|---|---|
multiple |
boolean |
false |
ファイルを複数選択できます。 |
disabled |
boolean |
false |
入力を無効化します。操作できません。 |
isError |
boolean |
false |
エラー状態を視覚的に示します。バリデーション用など。 |
インストールの手順
以下のコンポーネントのコードを、使いたいプロジェクトにコピー&ペーストします。
パスは実際のプロジェクトの構成にあわせて更新してください。
atoms/InputFile.svelte
<!--
@component
## 概要
- ファイルを選択するコンポーネントです
## 機能
- ユーザーが一つまたは複数のファイルを端末のストレージから選択することできます
- 複数の場合は multiple 属性が必要です
- 見た目を変更するためのいくつかのスタイル用Propsが追加されています(詳細はPropsセクションを参照)
## Props
- isError: true の場合エラー時のスタイルを適用します
- disabled: 指定するとグレーアウトされ、クリック不可になります
## Usage
```svelte
// 単一
<InputFile bind:files />
// 複数
<InputFile multiple bind:files />
```
-->
<script module lang="ts">
import type { ClassValue, HTMLInputAttributes } from 'svelte/elements';
import { cva, type VariantProps } from 'class-variance-authority';
export const inputFileVariants = cva('w-full px-[0.6875rem] py-2 border border-base-stroke-default rounded-md font-normal text-base-foreground-default text-base-foreground-muted text-sm outline-primary transition-colors file:px-2 file:py-0.25 hover:bg-base-container-accent/90 active:border-base-stroke-default file:font-medium file:text-base-foreground-default placeholder:text-base-foreground-muted focus-visible:outline-[0.125rem] focus-visible:outline-offset-[0.125rem] focus-visible:outline-primary file:mr-1', {
variants: {
/** 操作できるかどうか */
disabled: {
true: ['opacity-50 cursor-not-allowed file:cursor-not-allowed'],
false: ['cursor-pointer file:cursor-pointer'],
},
/** エラーかどうか */
isError: {
true: ['border-destructive'],
false: [],
},
},
defaultVariants: {
disabled: false,
isError: false,
},
});
export type InputFileVariants = VariantProps<typeof inputFileVariants>;
export interface InputFileProps extends InputFileVariants, HTMLInputAttributes {
/** クラス */
class?: ClassValue;
/** 選択したファイル */
files?: FileList;
}
</script>
<script lang="ts">
let { isError = false, class: className, files = $bindable(), ...inputAttributes }: InputFileProps = $props();
let inputFileVariantClass = $derived(inputFileVariants({ disabled: inputAttributes.disabled, class: className, isError }));
</script>
<input class={inputFileVariantClass} type="file" {...inputAttributes} bind:files />
使い方
<script lang="ts">
import InputFile from '$lib/components/ui/atoms/InputFile.svelte';
let files = $state();
</script>
<InputFile bind:files />
サンプル
Default
特に操作が行われていない、デフォルトの状態です。
<script lang="ts">
import InputFile from '$lib/components/ui/atoms/InputFile.svelte';
let files = $state();
</script>
<InputFile bind:files />
Error
入力内容に問題があり、エラーが表示されている状態です。
<script lang="ts">
import InputFile from '$lib/components/ui/atoms/InputFile.svelte';
let files = $state<FileList>();
let isError = $derived(!files?.length);
</script>
<div class="w-full">
<InputFile bind:files {isError} />
{#if isError}
<p class="text-destructive text-sm mt-2">ここにエラーメッセージが入ります。</p>
{/if}
</div>
Disabled
利用不可の状態です。
<script lang="ts">
import InputFile from '$lib/components/ui/atoms/InputFile.svelte';
let files = $state();
</script>
<InputFile disabled bind:files />
Multiple
複数のファイルを選択できる状態です。
<script lang="ts">
import DebugConsole from '$lib/components/ui/atoms/DebugConsole.svelte';
import InputFile from '$lib/components/ui/atoms/InputFile.svelte';
let files = $state<FileList>();
let filenames = $derived(files && Array.from(files).map((file) => file.name));
</script>
<div class="w-full gap-4">
<InputFile class="mb-4" multiple bind:files />
<DebugConsole data={{ filenames }} />
</div>