Skip to main content
/
/
/
/
Single file upload

Single file upload

Handling events

You can use the onInput event on <FileInputArea> to handle selected file. The file available in the event are reset every time you select a new file.

The example below shows how we can utilize this event to extract the file name, and set a loading state.

<FileInputArea onInput={(e) => { const files = e.currentTarget.files; if (!files || !files.length) return; setFileName(files[0].name); setUploadState("loading"); //Handle post... }} disabled={uploadState === "loading"} />
<FileInputArea onInput={(e) => { const files = e.currentTarget.files; if (!files || !files.length) return; setFileName(files[0].name); setUploadState("loading"); //Handle post... }} disabled={uploadState === "loading"} />

Before Uploading

This is the default state of <FileInputArea>, with some recommended content.

<FileInputArea aria-label="Upload file"> <Icon icon={faArrowUpFromBracket} className="bfc-base-2" style={{ marginBottom: 8 }} /> <div> Drag & drop file or{" "} <span className="bf-neutral-link-text">click to upload</span> </div> <div className="bfc-base-2">.csv file, less than 10 MB</div> </FileInputArea>
<FileInputArea aria-label="Upload file"> <Icon icon={faArrowUpFromBracket} className="bfc-base-2" style={{ marginBottom: 8 }} /> <div> Drag & drop file or{" "} <span className="bf-neutral-link-text">click to upload</span> </div> <div className="bfc-base-2">.csv file, less than 10 MB</div> </FileInputArea>
Drag & drop file or click to upload
.csv file, less than 10 MB

Loading

While your file is uploading, you can render content appropriate for the loading state. While uploading it can make sense to keep the <FileInputArea> disabled.

<FileInputArea disabled> <Icon.Spinner style={{ marginBottom: 8 }} /> <div>Uploading...</div> <div className="bfc-base-2">filename.jpg</div> </FileInputArea>
<FileInputArea disabled> <Icon.Spinner style={{ marginBottom: 8 }} /> <div>Uploading...</div> <div className="bfc-base-2">filename.jpg</div> </FileInputArea>
Uploading...
filename.jpg

Upload failed

If the upload failed, you can use the state="alert" prop to give the <FileInputArea> a red border.

<FileInputArea state="alert"> <Icon icon={faExclamationCircle} className="bfc-alert" style={{ marginBottom: 8 }} /> <div className="bfc-alert">Could not upload</div> <div className="bf-neutral-link-text">Try again</div> </FileInputArea>
<FileInputArea state="alert"> <Icon icon={faExclamationCircle} className="bfc-alert" style={{ marginBottom: 8 }} /> <div className="bfc-alert">Could not upload</div> <div className="bf-neutral-link-text">Try again</div> </FileInputArea>
Could not upload

Upload successful

<FileInputArea> <Icon icon={faCheck} className="bfc-success" style={{ marginBottom: 8 }} /> <div> <strong>test.pdf</strong> sucessfully uploaded </div> <div className="bfc-base-2"> Drag and drop or <span className="bf-neutral-link-text">click</span> to remove and upload new file </div> </FileInputArea>
<FileInputArea> <Icon icon={faCheck} className="bfc-success" style={{ marginBottom: 8 }} /> <div> <strong>test.pdf</strong> sucessfully uploaded </div> <div className="bfc-base-2"> Drag and drop or <span className="bf-neutral-link-text">click</span> to remove and upload new file </div> </FileInputArea>
test.pdf sucessfully uploaded
Drag and drop or click to remove and upload new file

Interactive demo

This simulation lets you select a file, fakes uploading for 1s with a 50% chance to fake fail.

Drag & drop file or click to upload
.csv file, less than 10 MB

Sandbox

import { useState } from "react";
import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclamationCircle";
import { faCheck } from "@fortawesome/free-solid-svg-icons/faCheck";
import { faArrowUpFromBracket } from "@fortawesome/free-solid-svg-icons/faArrowUpFromBracket";

import FileInputArea from "@intility/bifrost-react/FileInputArea";
import Icon from "@intility/bifrost-react/Icon";

type InputState = "default" | "loading" | "failed" | "success";

const defaultContent = (
  <>
    <Icon
      icon={faArrowUpFromBracket}
      className="bfc-base-2"
      style={{ marginBottom: 8 }}
    />
    <div>
      Drag & drop file or{" "}
      <span className="bf-neutral-link-text">click to upload</span>
    </div>
    <div className="bfc-base-2">.csv file, less than 10 MB</div>
  </>
);

const LoadingContent = ({ fileName = "" }) => (
  <>
    <Icon.Spinner style={{ marginBottom: 8 }} />
    <div>Uploading...</div>
    <div className="bfc-base-2">{fileName}</div>
  </>
);

const failedContent = (
  <>
    <Icon
      icon={faExclamationCircle}
      className="bfc-alert"
      style={{ marginBottom: 8 }}
    />
    <div className="bfc-alert">Could not upload</div>
    <div className="bf-neutral-link-text">Try again</div>
  </>
);

const SucessContent = ({ fileName = "" }) => (
  <>
    <Icon icon={faCheck} className="bfc-success" style={{ marginBottom: 8 }} />
    <div>
      <strong>{fileName}</strong> sucessfully uploaded
    </div>
    <div className="bfc-base-2">
      Drag and drop or <span className="bf-neutral-link-text">click</span> to
      remove and upload new file
    </div>
  </>
);

export default function SingleFileUpload() {
  const [uploadState, setUploadState] = useState<InputState>("default");
  const [fileName, setFileName] = useState<string>("");

  const handleFileUpload = (e: React.FormEvent<HTMLInputElement>) => {
    const files = e.currentTarget.files;
    if (!files || !files.length) return;

    setFileName(files[0].name);

    setUploadState("loading");

    // Simulate a file upload
    setTimeout(() => {
      setUploadState(Math.random() > 0.5 ? "success" : "failed");
    }, 1000);
  };

  return (
    <FileInputArea
      disabled={uploadState === "loading"}
      onInput={handleFileUpload}
      state={uploadState === "failed" ? "alert" : "default"}
    >
      {uploadState === "default" && defaultContent}
      {uploadState === "loading" && <LoadingContent fileName={fileName} />}
      {uploadState === "failed" && failedContent}
      {uploadState === "success" && <SucessContent fileName={fileName} />}
    </FileInputArea>
  );
}