Skip to content

Inputs

FileUpload

Drag and drop zone for selecting files, with type and size validation.

<script>
  import { FileUpload } from "@codeatlasdev/ui";
  let files = $state([]);
</script>

<FileUpload bind:files multiple accept="image/*" maxSize={10 * 1024 * 1024} />

The drop zone is a keyboard-operable control: Enter or Space opens the file picker. Files larger than maxSize are rejected with a per-file error message. In multiple mode new picks are appended to files, otherwise they replace it. The component never uploads: send files to your API yourself.

Native input attributes (name, capture, data-*…) are spread on the <input type="file">, and bind:ref gives you that input. To open the picker from a button elsewhere, keep the component instance with bind:this and call open() (a no-op while disabled). For apps that upload on pick and draw their own progress, set list={false}: onchange receives only the files just picked, nothing is kept in files, and the built-in list is not rendered.

#020

Basic

Multiple files with a size limit and the selected count.

Drop files here or click to browse PNG, JPG, PDF up to 10 MB

Reference #020 · Pick in the gallery

Code
svelte
<script lang="ts">
  import { FileUpload } from '@codeatlasdev/ui';

  let files = $state<File[]>([]);
</script>

<div class="wrap">
  <FileUpload
    bind:files
    multiple
    hint="PNG, JPG, PDF up to 10 MB"
    maxSize={10 * 1024 * 1024}
  />
  {#if files.length > 0}
    <p class="out">{files.length} file{files.length > 1 ? 's' : ''} selected</p>
  {/if}
</div>

<style>
  .wrap {
    width: 100%;
    max-width: 480px;
  }

  .out {
    margin: var(--ca-space-2) 0 0;
    font-size: var(--ca-font-size-body2);
    color: var(--ca-text-secondary);
  }
</style>
#021

Images only and disabled

Drop images here PNG, JPG, GIF, WebP
Upload unavailable

Reference #021 · Pick in the gallery

Code
svelte
<script lang="ts">
  import { FileUpload } from '@codeatlasdev/ui';
</script>

<div class="wrap">
  <FileUpload accept="image/*" label="Drop images here" hint="PNG, JPG, GIF, WebP" />
  <FileUpload disabled label="Upload unavailable" />
</div>

<style>
  .wrap {
    display: flex;
    flex-direction: column;
    gap: var(--ca-space-4);
    width: 100%;
    max-width: 480px;
  }
</style>
#388

External trigger, no list

list={false} plus an Add files button that calls open().

Attachments

Drop files here or click to browse

Reference #388 · Pick in the gallery

Code
svelte
<script lang="ts">
  import { Button, FileUpload } from '@codeatlasdev/ui';

  let upload = $state<ReturnType<typeof FileUpload> | null>(null);
  let names = $state<string[]>([]);

  function onpick(picked: File[]) {
    names = [...names, ...picked.map((f) => f.name)];
  }
</script>

<div class="wrap">
  <div class="head">
    <h3 class="title">Attachments</h3>
    <Button size="sm" onclick={() => upload?.open()}>Add files</Button>
  </div>
  <FileUpload bind:this={upload} list={false} multiple onchange={onpick} data-testid="attachments-input" />
  {#if names.length > 0}
    <ul class="list">
      {#each names as name, i (i)}
        <li>{name}</li>
      {/each}
    </ul>
  {/if}
</div>

<style>
  .wrap {
    width: 100%;
    max-width: 480px;
  }

  .head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ca-space-3);
    margin-block-end: var(--ca-space-2);
  }

  .title {
    margin: 0;
    font-size: var(--ca-font-size-h6);
  }

  .list {
    margin: var(--ca-space-2) 0 0;
    padding-inline-start: var(--ca-space-5);
    font-size: var(--ca-font-size-body2);
    color: var(--ca-text-secondary);
  }
</style>

Props

PropTypeDefaultDescription
filesFile[][]Bindable list of selected files.
acceptstring–Accepted types, for example "image/*,.pdf". Shown as the hint when hint is not set.
multiplebooleanfalseAllows selecting multiple files.
maxSizenumber–Maximum file size in bytes. Larger files are rejected with an error.
labelstring'Drop files here or click to browse' (localized)Drop zone text and accessible name.
hintstring–Helper text below the label.
listbooleantrueShows the built-in file list. `false` makes a plain picker: `onchange` gets only the newly picked files and `files` is not kept.
refHTMLInputElement | null–Bindable native file input.
disabledbooleanfalseDisables the upload.
classstring–Extra classes on the root.
onchange(files: File[]) => void–Called when the file list changes.
childrenSnippet–Custom content inside the drop zone.