Skip to content
TopClass UI

File upload

A drop zone that is a real file input, so it works and posts before any script runs. Picked files show as a list.

client - size not measured yet

File upload

client - size not measured yet

A drop zone that is a real file input, so it works and posts before any script runs. Picked files show as a list.

Install

Try it

maxFiles
maxSize
invalid
visibleRows

The code

file-upload.tsx
import { FileUpload } from 'topclassui/file-upload'

<div className="grid gap-1.5">
  <label htmlFor="file-upload-playground" className="text-sm font-medium text-body">Attachment</label>
  <FileUpload id="file-upload-playground" name="attachment" accept=".png,.jpg,.jpeg,.pdf">
    PNG, JPG or PDF
  </FileUpload>
</div>

maxSize is in bytes and checked in the browser only: check it again in the action.

Every state

2 states
Drop files hereBrowseA file is required
    Drop files hereBrowseUploads are closed

      Import from the package

      topclassui/file-upload
      import { FileUpload } from 'topclassui/file-upload'

      Install once:npm i topclassui@beta zod

      Examples

      • The children are the hint inside the zone, such as "PDF or PNG, up to 5 MB", and they describe the input.
      • maxFiles (1 to 100, default 1) alone decides whether the input takes several files at once; with 1 a new file replaces the old one.
      • maxSize refuses a larger file as too large; each refusal is read out, and a refused file is never sent.
      • An input cannot set its form's encType: a form with a string action needs multipart/form-data, or it sends only the file names.
      • The list adds up across picks and drops and shows visibleRows rows before it scrolls. onValueChange hears the kept files after each change.
      basic
      Drop files hereBrowsePNG, JPG or PDF, up to 10 MB
        multiple
        Drop files hereBrowsePDF or PNG, up to 5 files
          in-field
          Drop files hereBrowseDrop them here, 5 MB each
            PDF or PNG, up to 5 files
            form
            Drop files hereBrowseUp to 5 files
              In Arabic, right to left
              أفلت الملفات هناتصفّحPDF أو PNG، حتى 5 ملفات

                Props

                The props of FileUpload
                PropTypeDefaultLimitsDescription
                aria-labelstring--The name read out when no visible label names the control.
                aria-labelledbystring--The id of the visible text that names the control.
                idstring--The id a <label htmlFor> points at.
                childrenReactNode--The hint inside the zone, such as "PDF or PNG, up to 5 MB": it describes the input; a link in it takes its own click.
                classNamestring--On the root, merged last.
                invalidbooleanfalse-Marks the files as wrong: sets aria-invalid on the input, and the line of the zone turns to danger and thickens.
                maxFilesinteger, min 1, max 1001min 1, max 100How many files the list keeps, clamped to 1 to 100; above 1 the input takes several at once.
                maxSizeinteger, min 1, max 1073741824010737418240min 1, max 10737418240The largest file accepted, in bytes, clamped to 1 to 10 GiB; checked in the browser only.
                onValueChange((files: readonly File[]) => void)--The accepted files after each pick, drop or remove. Client-only.
                refRef<HTMLDivElement>--The root element, a <div>.
                styleCSSProperties--On the root.
                visibleRowsnumber, min 1, max 207min 1, max 20Rows the list shows before it scrolls, clamped; left out, the --tc-list-rows knob applies.

                Keyboard and accessibility

                The keyboard of FileUpload
                KeysWhat it does
                TabReaches the file input, and the zone draws the focus ring; then each remove button.
                EnterSpaceOpen the file picker; on a remove button, remove that file.
                • A name is required: id for a <label htmlFor>, or aria-label, or aria-labelledby.
                • Each file has a remove button named after it, such as "Remove brief.pdf"; after a remove the focus goes to the next file, else the previous one, else the input.
                • A drag of files marks the zone with a solid primary line; under forced colours the line is Highlight. invalid turns it to danger.

                Right to left

                The zone centres, the rows mirror, and each file name takes its own direction. Sizes are written in the reader's digits.

                Server and client

                A client component: it renders on the server and hydrates in the browser.

                Files: index.tsx, client.tsx.

                On the chip: client - size not measured yet.