Skip to main content

File

Overview​

The File component provides a Bulma-styled file input, supporting color, size, boxed/fullwidth/align styles, icons, "has name", and filename display.

It is highly customizable for all file upload UI needs.


Import​

import { File, Icon } from '@allxsmith/bestax-bulma';

Usage​

File is a self-contained Bulma file widget. It detects whether it's already inside a Field and skips rendering its own field wrapper if so. For typical use, pass buttonLabel, iconLeft, and any modifier props (hasName, isBoxed, isFullwidth, isRight, isCentered, color, size) — Bulma doesn't document file inputs in addons or grouped layouts, so the convenience form covers every case. Use label only when you want an additional Bulma <label class="label"> rendered above the widget.

Default​

A basic file input. The buttonLabel prop sets the text on the CTA button, and iconLeft adds an icon for visual context.

<File
  buttonLabel="Choose a file…"
  iconLeft={<Icon name="upload" aria-hidden="true" />}
/>


With Filename Display​

Set hasName to display the selected file name. The fileName prop shows a custom or pre-selected name.

<File
  hasName
  fileName="resume.pdf"
  buttonLabel="Choose a file…"
  iconLeft={<Icon name="upload" aria-hidden="true" />}
/>


CTA on Right​

Combine isRight with hasName to put the CTA button on the right and the filename on the left.

<File
  hasName
  isRight
  fileName="contract.pdf"
  buttonLabel="Choose a file…"
  iconLeft={<Icon name="upload" aria-hidden="true" />}
/>


Full Width​

isFullwidth makes the file input take the full width of its container — pairs well with hasName so the filename area expands.

<File
  hasName
  isFullwidth
  fileName="picture.png"
  buttonLabel="Choose a file…"
  iconLeft={<Icon name="upload" aria-hidden="true" />}
/>


Boxed​

isBoxed stacks the icon over the text into a square box.

<File
  isBoxed
  buttonLabel="Choose a file…"
  iconLeft={<Icon name="upload" aria-hidden="true" />}
/>


Boxed with Name​

Combine isBoxed and hasName for a boxed widget that also shows the filename.

<File
  isBoxed
  hasName
  fileName="holiday.jpg"
  buttonLabel="Choose a file…"
  iconLeft={<Icon name="upload" aria-hidden="true" />}
/>


Colors​

The color prop applies Bulma color modifiers. The four examples below match the combinations Bulma's docs show.

<>
  <File
    color="primary"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    color="info"
    hasName
    fileName="resume.pdf"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    color="warning"
    isBoxed
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="cloud-upload-alt" aria-hidden="true" />}
  />
  <File
    color="danger"
    isBoxed
    hasName
    fileName="resume.pdf"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="cloud-upload-alt" aria-hidden="true" />}
  />
</>


Sizes​

The size prop controls the file input's size.

<>
  <File
    size="small"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    size="medium"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    size="large"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
</>


Sizes with Name​

Combine size with hasName to scale the filename display alongside the button.

<>
  <File
    size="small"
    hasName
    fileName="sample.txt"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    hasName
    fileName="sample.txt"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    size="medium"
    hasName
    fileName="sample.txt"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    size="large"
    hasName
    fileName="sample.txt"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
</>


Sizes with Boxed​

Combine size with isBoxed for boxed file inputs at every size.

<>
  <File
    size="small"
    isBoxed
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    isBoxed
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    size="medium"
    isBoxed
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    size="large"
    isBoxed
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
</>


Sizes with Boxed and Name​

For a boxed file input that also shows the filename, combine isBoxed, hasName, and size.

<>
  <File
    size="small"
    isBoxed
    hasName
    fileName="summary.docx"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    isBoxed
    hasName
    fileName="summary.docx"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    size="medium"
    isBoxed
    hasName
    fileName="summary.docx"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
  <File
    size="large"
    isBoxed
    hasName
    fileName="summary.docx"
    buttonLabel="Choose a file…"
    iconLeft={<Icon name="upload" aria-hidden="true" />}
  />
</>


Alignment: Centered​

isCentered centers the widget within its parent container.

<File
  color="info"
  isCentered
  isBoxed
  hasName
  fileName="centered.pdf"
  buttonLabel="Choose a file…"
  iconLeft={<Icon name="upload" aria-hidden="true" />}
/>


Alignment: Right​

isRight aligns the widget to the right of its parent.

<File
  color="primary"
  isRight
  hasName
  fileName="right.pdf"
  buttonLabel="Choose a file…"
  iconLeft={<Icon name="upload" aria-hidden="true" />}
/>


Context-Aware Rendering​

The File component is context-aware: it detects whether it is already inside a Field and skips rendering its own field wrapper if so. Use label to add a Bulma <label class="label"> above the widget; use buttonLabel to set the CTA text.

note

File renders no Control of its own (it is a self-contained widget). The "With Field and Control Wrappers" example below shows that wrapping File in a Control is harmless but doesn't change its rendering.

Default (with label)​

The simplest usage — label adds a Field label above the widget.

<File
  label="Document"
  buttonLabel="Choose a file…"
  iconLeft={<Icon name="upload" aria-hidden="true" />}
/>


With Field Wrapper​

For manual layout control (e.g., horizontal forms), wrap in Field. The component detects it's inside a Field and skips rendering its own.

function example() {
  return (
    <Field horizontal label="Document">
      <Field.Body>
        <Field>
          <File
            buttonLabel="Choose a file…"
            iconLeft={<Icon name="upload" aria-hidden="true" />}
          />
        </Field>
      </Field.Body>
    </Field>
  );
}


With Field and Control Wrappers​

For full manual composition, wrap in both Field and Control. The outer Field is detected and File's own Field wrapper is skipped.

function example() {
  return (
    <Field horizontal label="Document">
      <Field.Body>
        <Field>
          <Control iconLeftName="paperclip">
            <File
              buttonLabel="Choose a file…"
              iconLeft={<Icon name="upload" aria-hidden="true" />}
            />
          </Control>
        </Field>
      </Field.Body>
    </Field>
  );
}

Inside a Control with no Field around it, File renders no Field of its own either, unless you give it label, message, horizontal or fieldClassName. Those need a Field, so with any of them it keeps its own Field inside the Control and warns in development. Wrap the Control in a Field, as above, and set the label, horizontal and class name on that Field instead.


Accessibility​

  • The root is a <div class="file"> with a nested <label> and <input type="file">.
  • The label is always clickable.
  • When File renders its own Field (that is, outside an existing one), the Field-level label prop is automatically associated with the file input via htmlFor, so the input then has two labels (the Field label plus the wrapping CTA label); assistive technology reads both. An explicit labelProps.htmlFor overrides the association and no id is generated.
  • Add aria-label to the <input> for accessibility if your label is not plain text.


Additional Resources​


Props​

PropTypeDefaultDescription
labelReact.ReactNode—Field label. Automatically associated with the file input via htmlFor — uses your id when provided, otherwise a generated one. The input then has two labels (this one plus the wrapping file-label); assistive tech reads both. Dropped inside an outer Field (label that Field yourself).
labelPropsReact.LabelHTMLAttributes<HTMLLabelElement> & { [key: string]: unknown; }—Props for the label element. An explicit htmlFor here overrides the automatic association (no id is generated then).
color'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger' | 'black' | 'dark' | 'light' | 'white'—Bulma color modifier for the file input.
size'small' | 'medium' | 'large'—Size modifier for the file input.
isBoxedbooleanfalseBoxed file input.
isFullwidthbooleanfalseWhether the file input expands to full width.
isFullWidthbooleanfalseDeprecated. Use isFullwidth instead — isFullwidth wins if both are set. Whether the file input expands to full width.
isRightbooleanfalsePosition the CTA on the right (with hasName).
isCenteredbooleanfalseCenter the file input within its container.
hasNamebooleanfalseShow a file name indicator.
buttonLabelReact.ReactNode—Text on the file CTA button (defaults to "Choose a file…").
iconLeftReact.ReactNode—Left icon element. It renders inside the <label> that names the file input, beside buttonLabel, so pass an Icon with aria-hidden (<Icon name="upload" aria-hidden="true" />); otherwise its default aria-label="icon" becomes part of the input's accessible name.
iconRightReact.ReactNode—Right icon element. Sits inside the same <label> as iconLeft, so the same applies: give an Icon here aria-hidden, or "icon" joins the input's accessible name.
classNamestring—Additional CSS classes to apply.
inputClassNamestring—Additional CSS classes for the <input>.
fileNamestring—File name to display.
labelSize'small' | 'normal' | 'medium' | 'large'—Size for the label (used in horizontal layouts).
horizontalbooleanfalseHorizontal field layout.
messageReact.ReactNode—Help/validation message below the input.
messageColor'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger'—Bulma color for the message.
fieldClassNamestring—Additional CSS classes for the Field wrapper.
refReact.Ref<HTMLInputElement>—Forwarded to the underlying element.
...All standard <input> attributes and Bulma helper props—See Helper Props

CSS & Sass Variables​

File registers these variables on its own .file element. Override them there (or via className) — a value set on an ancestor is only inherited, and loses to the component-level declaration. See Theme.

CSS VariableSass VariableDefault
--bulma-file-radius$file-radiusvar(--bulma-radius)
--bulma-file-name-border-color$file-name-border-colorvar(--bulma-border)
--bulma-file-name-border-style$file-name-border-stylesolid
--bulma-file-name-border-width$file-name-border-width1px 1px 1px 0
--bulma-file-name-max-width$file-name-max-width16em
--bulma-file-h$file-hvar(--bulma-scheme-h)
--bulma-file-s$file-svar(--bulma-scheme-s)
--bulma-file-background-l$file-background-lvar(--bulma-scheme-main-ter-l)
--bulma-file-background-l-delta$file-background-l-delta0%
--bulma-file-hover-background-l-delta$file-hover-background-l-delta-5%
--bulma-file-active-background-l-delta$file-active-background-l-delta-10%
--bulma-file-border-l$file-border-lvar(--bulma-border-l)
--bulma-file-border-l-delta$file-border-l-delta0%
--bulma-file-hover-border-l-delta$file-hover-border-l-delta-10%
--bulma-file-active-border-l-delta$file-active-border-l-delta-20%
--bulma-file-cta-color-l$file-cta-color-lvar(--bulma-text-strong-l)
--bulma-file-name-color-l$file-name-color-lvar(--bulma-text-strong-l)
--bulma-file-color-l-delta$file-color-l-delta0%
--bulma-file-hover-color-l-delta$file-hover-color-l-delta-5%
--bulma-file-active-color-l-delta$file-active-color-l-delta-10%