HapplyUI

Logo Upload

A compound component for uploading logos or profile images. Shows a rounded avatar preview with placeholder, title, description, and action buttons. Designed to work with the useFileUpload hook.


Installation

bunx @happlyui/cli@latest add logo-upload

Dependencies

Registry dependencies

These are automatically installed when you add this component.

  • avatar
  • button
  • loader
  • tv
  • happly-ui-utils
  • use-file-upload

Usage

import * as LogoUpload from "@/components/ui/logo-upload"
import * as Button from "@/components/ui/button"
import { useFileUpload } from "@/hooks/use-file-upload"

const upload = useFileUpload({ ... })
const file = upload.files[0]

<LogoUpload.Root>
  <LogoUpload.Preview file={file} placeholderType="company" />
  <LogoUpload.Content>
    <LogoUpload.Title>Business logo</LogoUpload.Title>
    <LogoUpload.Description>
      <p>Supports JPEG or PNG files (max 3MB).</p>
    </LogoUpload.Description>
    <LogoUpload.Actions>
      <Button.Root variant="neutral" mode="stroke" size="xsmall" onClick={upload.openFilePicker}>
        Change
      </Button.Root>
      <input {...upload.getInputProps()} />
    </LogoUpload.Actions>
  </LogoUpload.Content>
</LogoUpload.Root>

Examples

Default (Empty State)

Shows a company placeholder avatar when no file has been uploaded yet.

Loading

Business logo

Supports JPEG or PNG files (max 3MB).

Use a horizontal image (16:9). Best size: 1200 × 675 px.

<LogoUpload.Root>
  <LogoUpload.Preview placeholderType="company" />
  <LogoUpload.Content>
    <LogoUpload.Title>Business logo</LogoUpload.Title>
    <LogoUpload.Description>
      <p>Supports JPEG or PNG files (max 3MB).</p>
      <p>Use a horizontal image (16:9). Best size: 1200 × 675 px.</p>
    </LogoUpload.Description>
    <LogoUpload.Actions>
      <Button.Root variant="neutral" mode="stroke" size="xsmall">Change</Button.Root>
    </LogoUpload.Actions>
  </LogoUpload.Content>
</LogoUpload.Root>

Shows the uploaded image in the avatar preview.

Logo
Loading

Business logo

Supports JPEG or PNG files (max 3MB).

Use a horizontal image (16:9). Best size: 1200 × 675 px.

<LogoUpload.Root>
  <LogoUpload.Preview file={file} />
  <LogoUpload.Content>
    <LogoUpload.Title>Business logo</LogoUpload.Title>
    <LogoUpload.Description>
      <p>Supports JPEG or PNG files (max 3MB).</p>
    </LogoUpload.Description>
    <LogoUpload.Actions>
      <Button.Root variant="neutral" mode="stroke" size="xsmall">Change</Button.Root>
    </LogoUpload.Actions>
  </LogoUpload.Content>
</LogoUpload.Root>

Uploading

While a file is uploading, the preview shows a spinner overlay. When a preview image is available, the image blurs behind the spinner.

Loading

Business logo

Uploading new-logo.png… 45%

Logo
Loading

Business logo

Uploading new-logo.png… 45%

<LogoUpload.Root>
  <LogoUpload.Preview file={uploadingFile} />
  <LogoUpload.Content>
    <LogoUpload.Title>Business logo</LogoUpload.Title>
    <LogoUpload.Description>
      <p>Uploading new-logo.png… 45%</p>
    </LogoUpload.Description>
  </LogoUpload.Content>
</LogoUpload.Root>

Custom Preview

Replace LogoUpload.Preview with any custom element. Since Root is a flex container, drop in your own preview markup.

Loading

Business logo

Supports JPEG or PNG files (max 3MB).

Use a horizontal image (16:9). Best size: 1200 × 675 px.

<LogoUpload.Root>
  <LogoUpload.Preview
    placeholder={<RiBuildingLine className="size-[60px] text-[#B8ACF6]" />}
    avatarClassName="bg-[#EFEBFF] ring-[1.26px] ring-[rgba(14,18,27,0.1)]"
  />
  <LogoUpload.Content>
    <LogoUpload.Title>Business logo</LogoUpload.Title>
    <LogoUpload.Description>
      <p>Supports JPEG or PNG files (max 3MB).</p>
    </LogoUpload.Description>
    <LogoUpload.Actions>
      <Button.Root variant="neutral" mode="stroke" size="xsmall">Change</Button.Root>
    </LogoUpload.Actions>
  </LogoUpload.Content>
</LogoUpload.Root>

User Avatar Upload

Use placeholderType="user" for profile photo uploads.

Loading

Profile photo

Supports JPEG or PNG files (max 3MB).

Use a square image. Best size: 400 × 400 px.

<LogoUpload.Root>
  <LogoUpload.Preview placeholderType="user" />
  <LogoUpload.Content>
    <LogoUpload.Title>Profile photo</LogoUpload.Title>
    <LogoUpload.Description>
      <p>Supports JPEG or PNG files (max 3MB).</p>
    </LogoUpload.Description>
    <LogoUpload.Actions>
      <Button.Root variant="neutral" mode="stroke" size="xsmall">Change</Button.Root>
    </LogoUpload.Actions>
  </LogoUpload.Content>
</LogoUpload.Root>

Composed

Use LogoUpload.Item for a single-prop composed version that handles the full layout.

Loading

Business logo

Supports JPEG or PNG files (max 3MB).

Use a horizontal image (16:9). Best size: 1200 × 675 px.

<LogoUpload.Item
  label="Business logo"
  description={
    <>
      <p>Supports JPEG or PNG files (max 3MB).</p>
      <p>Use a horizontal image (16:9). Best size: 1200 × 675 px.</p>
    </>
  }
  onButtonClick={upload.openFilePicker}
/>

The composed version showing an uploaded image.

Logo
Loading

Business logo

Supports JPEG or PNG files (max 3MB).

Use a horizontal image (16:9). Best size: 1200 × 675 px.

<LogoUpload.Item
  file={upload.files[0]}
  label="Business logo"
  description={<p>Supports JPEG or PNG files (max 3MB).</p>}
  onButtonClick={upload.openFilePicker}
/>

With FormField

Wrap LogoUpload.Item inside FormField.Root for label, hint, and error support.

Loading

Upload a logo

Supports JPEG or PNG files (max 3MB).

Use a horizontal image (16:9). Best size: 1200 × 675 px.

Used on your public profile and invoices.
Loading

Upload a logo

Supports JPEG or PNG files (max 3MB).

<FormField.Root label="Business logo" hint="Used on your public profile and invoices.">
  <LogoUpload.Item
    label="Upload a logo"
    description={<p>Supports JPEG or PNG files (max 3MB).</p>}
    onButtonClick={upload.openFilePicker}
  />
</FormField.Root>

API Reference

LogoUpload.Root

The outer container with border and padding.

PropTypeDefaultDescription

LogoUpload.Preview

Renders a rounded avatar showing the uploaded image or a placeholder icon.

PropTypeDefaultDescription
fileUploadFile-The file state from useFileUpload. Shows preview/url when available, otherwise shows placeholder.
placeholderType'user' | 'company''company'The placeholder icon type when no image is available.
avatarColor'gray' | 'yellow' | 'blue' | 'sky' | 'purple' | 'red' | 'primary''gray'The background color of the placeholder avatar.

LogoUpload.Content

Wraps the title, description, and actions.

PropTypeDefaultDescription

LogoUpload.Title

The heading text (e.g. "Business logo").

PropTypeDefaultDescription

LogoUpload.Description

Container for description paragraphs (file requirements, size hints).

PropTypeDefaultDescription

LogoUpload.Actions

Container for action buttons (Change, Retry, etc.).

PropTypeDefaultDescription

LogoUpload.Item

Composed preset that renders the full logo upload layout from props.

PropTypeDefaultDescription
fileUploadFile-The file state from useFileUpload. Shows uploaded image when available.
labelstring-The title text (e.g. "Business logo").
descriptionReactNode-Description content rendered below the title.
placeholderType'user' | 'company''company'The placeholder icon type when no image is available.
avatarColor'gray' | 'yellow' | 'blue' | 'sky' | 'purple' | 'red' | 'primary''gray'The background color of the placeholder avatar.
buttonLabelstring'Change'Label for the action button.
onButtonClick() => void-Click handler for the action button (typically upload.openFilePicker).

Previous
File Upload