2.0 beta — new releases can include breaking changes. Stable 1.x docs
dimah-s3v2.0.0-beta.0
ComponentsUpload

Avatar Upload

Image button that shows the current picture and uploads a new one.

AvatarUpload shows a stored image and replaces it. A click opens the file picker, and an image dropped on it uploads too. It shows the new image while it uploads, with a progress ring.

Preview

Click or drop an image.

Install

Complete UI Setup first: the stylesheet and one <Toaster />. Then add this component:

import { AvatarUpload } from "@dimah-s3/ui";

Usage

"use client";

import { useUpload } from "@dimah-s3/react";
import { AvatarUpload, UploadToasts } from "@dimah-s3/ui";

export function ProfilePhoto({
  avatarKey,
  saveAvatar,
}: {
  avatarKey: string | null;
  saveAvatar: (key: string) => void;
}) {
  const upload = useUpload({ route: "avatar", accept: ["image/*"] });

  return (
    <>
      <AvatarUpload
        upload={upload}
        route="avatar"
        objectKey={avatarKey}
        label="Change profile photo"
        onChange={(result) => saveAvatar(result.key)}
      />
      <UploadToasts upload={upload} />
    </>
  );
}

onChange runs once for each image that uploads. Store result.key and pass it back as objectKey. Images that uploaded before the avatar mounted are not reported.

Examples

Sizes and shapes

size sets the width and height in pixels. shape="square" rounds the corners instead of the whole image, for logos and covers.

64 px
96 px
Square, for logos

What it shows

  • While an image uploads, and after it succeeds, the picked file's preview.
  • Otherwise objectKey, signed through route with ObjectImage.
  • Without a key, or when the image cannot load, a placeholder icon.

route is the route that signs the GET for objectKey. It is usually the same route the hook uploads to. size sets the width and height in pixels, and shape is circle (the default) or square. The button is disabled while the hook is (useUpload({ disabled: true })).

Accessibility

label is required: it is the button's accessible name. A polite live region announces the upload: "Preparing…", "Uploading…", "Upload complete", the error, or the reason a file was rejected.

Without a provider

AvatarUpload signs the image URL with the API from <S3Provider>. Without a provider, pass the same api to the hook and to the component:

const upload = useUpload({ api, route: "avatar" });

<AvatarUpload
  api={api}
  upload={upload}
  route="avatar"
  objectKey={avatarKey}
  label="Change profile photo"
/>;

Props

import type { AvatarUploadProps } from "@dimah-s3/ui";

Prop

Type

On this page