← Back to all how-tos

Create a brick

Use the File component

Let editors upload a file and render a download link using the React Bricks File component.

Estimated time: 4 minRaw Markdown

What you'll build

In this how-to, you'll create a CatalogDownload brick using the React Bricks <File> component.

This is useful when editors need to upload downloadable assets like:

  • PDFs
  • catalogs
  • brochures
  • documents
  • short videos

At the end, editors will be able to upload a file in the admin, and your brick will render a download link on the page.

Create a new brick

Create a new CatalogDownload.tsx file and start with this code:

import { File, types } from 'react-bricks/rsc'
 
interface CatalogDownloadProps {
  file: types.IFileSource
}
 
const CatalogDownload: types.Brick<CatalogDownloadProps> = ({ file }) => {
  return (
    <div>
      <File
        propName="file"
        source={file}
        allowedExtensions={['.pdf']}
        renderBlock={(file) => {
          return file ? (
            <a
              href={file.url}
              className="flex h-full items-center font-semibold"
            >
              Download "{file.name}" <small>({file.size.toFixed(2)} MB)</small>
            </a>
          ) : (
            <div className="flex h-full items-center font-semibold">
              No catalogs yet.
            </div>
          )
        }}
      />
    </div>
  )
}
 
CatalogDownload.schema = {
  name: 'catalog-download',
  label: 'Catalog Download',
}
 
export default CatalogDownload

If you're using Next.js App Router, import File from react-bricks/rsc. If you're using Astro, import it from react-bricks/astro.

Add the file prop

The component interface uses:

file: types.IFileSource

types.IFileSource is the React Bricks type for a visually editable file field.

This prop will contain the uploaded file data.

Use the <File> component

Inside the brick, we render:

<File
  propName="file"
  source={file}
  allowedExtensions={['.pdf']}
  renderBlock={(file) => {
    return file ? (
      <a href={file.url} className="flex h-full items-center font-semibold">
        Download "{file.name}" <small>({file.size.toFixed(2)} MB)</small>
      </a>
    ) : (
      <div className="flex h-full items-center font-semibold">
        No catalogs yet.
      </div>
    )
  }}
/>

Here is what the main props do:

  • propName="file" binds the field to the file prop
  • source={file} passes the current file value
  • allowedExtensions={['.pdf']} limits uploads to PDF files
  • renderBlock defines how the uploaded file should be rendered

How renderBlock works

The renderBlock function receives the uploaded file as its argument.

If a file is available, you can use its data to render custom UI.

In this example we use:

  • file.url for the download link
  • file.name for the file name
  • file.size for the size in MB

That is why the code checks:

file ? (...) : (...)

When a file exists, we render a download link. When there is no file yet, we render a placeholder message.

Why allowedExtensions is useful

allowedExtensions helps restrict the kinds of files editors can upload.

For example:

  • ['.pdf'] only allows PDF files
  • ['.pdf', '.docx'] would allow both PDFs and Word documents

This is useful when the brick is meant for a very specific file type.

Final code

Your full CatalogDownload.tsx file should look like this:

import { File, types } from 'react-bricks/rsc'
 
interface CatalogDownloadProps {
  file: types.IFileSource
}
 
const CatalogDownload: types.Brick<CatalogDownloadProps> = ({ file }) => {
  return (
    <div>
      <File
        propName="file"
        source={file}
        allowedExtensions={['.pdf']}
        renderBlock={(file) => {
          return file ? (
            <a
              href={file.url}
              className="flex h-full items-center font-semibold"
            >
              Download "{file.name}" <small>({file.size.toFixed(2)} MB)</small>
            </a>
          ) : (
            <div className="flex h-full items-center font-semibold">
              No catalogs yet.
            </div>
          )
        }}
      />
    </div>
  )
}
 
CatalogDownload.schema = {
  name: 'catalog-download',
  label: 'Catalog Download',
}
 
export default CatalogDownload

Default files

If you want, you can also provide a default file using getDefaultProps in the schema.

That can be useful if you already have a standard catalog or document you want new brick instances to start with.

Docs reference

File component