nili/ui
All components

FileUpload

Overview
22 exports9 variant axes42 props3 files
import { FileFormatIcon, FileUploadArea, FileUploadCard, ImageUpload, ImageUploadShape } from '@nili/ui';

This is the library’s own overview page, rendered live. Switch the language or the theme in the header and it follows.

Upload Area

The drop target. onFiles receives a File array whether they were dropped or chosen from the dialogue, so there is one code path to handle. It is a real input underneath, so keyboard and screen-reader users get the picker too.

import { FileUploadArea } from "@nili/ui"

export function Example() {
  return (
    <FileUploadArea
      multiple
      accept="image/*,application/pdf"
      label="Upload files"
      title="Choose a file or drag it here"
      description="PNG, JPG or PDF, up to 10 MB."
      onFiles={(files) => upload(files)}
    />
  )
}

Upload Area states

invalid for a rejected file — wrong type, too large — and disabled while a quota is exhausted or a form is submitting.

default
invalid
disabled
import { FileUploadArea } from "@nili/ui"

export function Example() {
  return (
    <>
      <FileUploadArea label="Upload" onFiles={onFiles} />
      <FileUploadArea label="Upload" invalid onFiles={onFiles} />
      <FileUploadArea label="Upload" disabled onFiles={onFiles} />
    </>
  )
}

File Card

One uploaded file: its format icon, name, size and state. progress drives the bar; onRetry appears with an error, onRemove with anything. Both need a label, since the buttons are icons.

annual-report.pdf2.4 MB
brand-photo.png840 KB
archive.zip18 MBFile is larger than 10 MB.
import { FileUploadCard } from "@nili/ui"

export function Example() {
  return (
    <>
      <FileUploadCard
        fileName="annual-report.pdf"
        fileSize="2.4 MB"
        status="progress"
        progress={62}
        onRemove={cancel}
        removeLabel="Cancel upload"
      />

      <FileUploadCard
        fileName="photo.png"
        fileSize="840 KB"
        status="success"
        onRemove={remove}
        removeLabel="Remove file"
      />

      <FileUploadCard
        fileName="archive.zip"
        fileSize="18 MB"
        status="error"
        errorMessage="File is larger than 10 MB."
        onRetry={retry}
        retryLabel="Try again"
        onRemove={remove}
        removeLabel="Remove file"
      />
    </>
  )
}

File Format Icon

The glyph is derived from the file name, so a list of mixed uploads colours itself. Override it with color when the extension is not the thing you want to signal.

md
pdf
xlsx
pptx
docx
png
mp4
zip
json
xs
pdf
xlsx
pptx
docx
png
mp4
zip
json
import { FileFormatIcon } from "@nili/ui"

export function Example() {
  return (
    <>
      <FileFormatIcon fileName="report.pdf" />
      <FileFormatIcon fileName="sheet.xlsx" />
      <FileFormatIcon fileName="photo.png" size="xs" />
      <FileFormatIcon fileName="anything.bin" color="purple" />
    </>
  )
}

Image Upload

The preview-first variant, for an avatar, a company mark or a cover. shape sets the frame and the crop the preview implies; alignment puts the controls under the image or beside it.

shapes
avatar
company
square
4:3
16:9
horizontal, with a hint and actions
JPG or PNG, at least 256×256.
import { ImageUpload, Button } from "@nili/ui"

export function Example() {
  return (
    <>
      <ImageUpload
        shape="avatar"
        label="Profile photo"
        hint="JPG or PNG, at least 256×256."
        onFiles={(files) => upload(files[0])}
        actions={<Button size="xs" appearance="stroke">Choose file</Button>}
      />

      <ImageUpload shape="16:9" alignment="horizontal" label="Cover" onFiles={onFiles} />
    </>
  )
}