Specialized inputs

AppLogoPicker

A circular avatar/logo upload — an image ring with a hover overlay and a loading state.

<app-logo-picker name="logo" overlay-label="Update photo" />

<app-logo-picker> is the round upload for an identity image — a workspace logo, a company avatar, a profile picture. It shows a circular ring with the current image (or a placeholder) and a hover overlay that invites an update. It's the picker you use in a settings header, not in a form list.

Its look comes entirely from the shared @webority/theme, so the Razor <app-logo-picker> and the React <AppLogoPicker> render identically on every Webority surface. Never hand-roll a raw <input type="file">.

Playground

Every meaningful attribute, live. Each change re-renders the real tag helper on the server, so the markup underneath is the exact call that produced the ring above it.

<app-logo-picker name="pgLogo" fallback="WS" />

The upload ring

With no image, the ring shows a placeholder. Hover reveals the update overlay; picking a validated file replaces the image.

Placeholder → picked image
The ring shows the current image, or a placeholder when there is none; a successful pick is validated before it replaces the image.
Show code
<app-logo-picker name="workspaceLogo" overlay-label="Upload workspace logo" />
Validation is built inLike the other pickers, the ring validates type and size before it reports the choice — a rejected file raises a toast and never reaches the handler. You can also drag & drop a file straight onto the ring. The picker is for setting an image; to display an existing avatar without uploading, use AppAvatar.

Removing an image

Every freshly-picked image gets a × on the ring to undo it — no attribute needed. For a pre-existing (server) image, add removable so its × shows at load and clears the value.

Clearable ring
Show code
<app-logo-picker name="logo" value="/img.png" removable="true" />

Variants

Two placeholder styles for the empty state. initials (default) shows the letters you pass as fallback; avatar shows the standard avatar disc — a person icon when no initials are given. Both upload an image the same way.

initials · avatar
Show code
<app-logo-picker variant="initials" fallback="WS" />
<app-logo-picker variant="avatar" fallback="WS" />
<app-logo-picker variant="avatar" />   <!-- no fallback → person icon -->

Sizes

size takes a preset (sm · md · lg) or an exact diameter in pixels. Whatever you pass, the whole control — ring, initials font, overlay and placeholder icon — scales from it.

sm · md · lg
Show code
<app-logo-picker size="sm" />
<app-logo-picker size="md" />
<app-logo-picker size="lg" />
Exact pixel sizes
Pass a number to size the ring in px — everything scales, including the initials font.
Show code
<app-logo-picker size="56" />
<app-logo-picker size="96" />
<app-logo-picker size="140" />

Shapes

A logo is not always round. Choose circle (default), rounded or square to match the brand mark.

circle · rounded · square
Show code
<app-logo-picker shape="circle" />
<app-logo-picker shape="rounded" />
<app-logo-picker shape="square" />

Label, hint & error

The ring can be a labelled form field — add a label (with required), hint text, and an inline error, just like the other inputs.

A labelled, required picker with an error
PNG or JPG, at least 200×200px.
Please upload a logo.
Show code
<app-logo-picker label="Company logo" required="true" hint="PNG or JPG, at least 200×200px." />
<app-logo-picker label="Company logo" required="true" error="Please upload a logo." />

Inline (profile row)

layout="inline" lays the ring on the left with a title/subtitle/hint column beside it — the account-settings avatar row: name, role, and the allowed-files line on one line.

Avatar + name + role + hint
Pass title (bold) and subtitle (muted) for the identity block; hint sits under them as the allowed-files line.
Ishita Jindal
Admin
Allowed *.jpeg, *.jpg, *.png · Square image, max 5 MB
Show code
<app-logo-picker layout="inline" fallback="IJ" title="Ishita Jindal" subtitle="Admin"
                 hint="Allowed *.jpeg, *.jpg, *.png · Square image, max 5 MB" />
title & subtitle apply to the identity layoutsThey render in the meta column, so they only apply when layout="inline" or layout="profile". In the default stacked layout the ring stands alone with the hint below it.

Profile (vertical)

layout="profile" is the vertical form of the same identity block — ring on top, with the title/subtitle/hint centred beneath it. An account card or a directory tile.

Centred identity card
Same title/subtitle/hint props as inline, stacked and centred under the ring.
Ishita Jindal
Admin
Allowed *.jpeg, *.jpg, *.png · Square image, max 5 MB
Show code
<app-logo-picker layout="profile" fallback="IJ" title="Ishita Jindal" subtitle="Admin"
                 hint="Allowed *.jpeg, *.jpg, *.png · Square image, max 5 MB" />

Overlay label

The hover overlay text is yours to set — “Update photo” by default, but “Change logo” or “Upload avatar” read better in the right context.

A custom overlay
Show code
<app-logo-picker name="companyLogo" overlay-label="Change logo" overlay-icon="upload" aria-label="Change company logo" />

Loading & disabled

While a pick is uploading, use loading — the ring shows a spinner and the control is blocked. Use disabled for a read-only picker, which dims the ring and drops the overlay.

Uploading vs disabled
loading shows a spinner and blocks interaction; disabled is a static, dimmed, non-interactive ring.
Show code
<app-logo-picker loading="true" />
<app-logo-picker disabled="true" />

When to use

Use it when

  • An identity image is being set — a workspace logo, a company avatar, a profile picture.
  • The upload lives in a header or settings panel, shown as a round ring.
  • You want a hover-to-change overlay plus a loading state while the file uploads.

Reach for something else when

  • A single, rectangular image where the preview should be large. → AppFilePicker
  • A file attached to a record where the name/size matters. → AppFileAttachment
  • You only need to display an avatar, not upload one. → AppAvatar
  • You hand-roll a raw <input type="file"> with a circular mask. → AppLogoPicker

Best practices

Do
Set an overlay label that names the thing — "Change logo" — so the hover affordance says exactly what happens.
Don't
A generic "Click" overlay tells the user how to interact but not what the action does.
Do
Give the control a clear accessible name so screen readers announce the upload action, not just “button”.
Don't
A vague accessible name gives assistive tech nothing specific to announce for the control.

Every option

The whole surface of the component, one cell per value.

variant — with and without fallback

variant="initials" fallback="WS"
variant="avatar" fallback="WS"
variant="avatar" (no fallback → person icon)

size — presets and an exact px

size="sm"
size="md"
size="lg"
size="72" — exact pixel diameter

shape — every value

shape="circle"
shape="rounded"
shape="square"

state

(default)
loading="true"
disabled="true"
value (removable="false") — no × shown
value removable="true" — × shown
required="true" error="…"
Please upload a logo.

overlay — icon and label

overlay-icon="image"
overlay-icon="camera"
overlay-icon="upload"

Attributes

AttributeTypeDefaultDescription
namestring—Form field name for the posted file input.
valuestring—Current image URL; when empty the placeholder ring is shown.
acceptstringimage/png,image/jpeg,image/webpAccepted MIME types for the file input.
overlay-labelstringUpdate photoText shown in the hover overlay; also the button’s accessible name.
removableboolfalseShow the × for a pre-existing value image at load (a just-picked image is always removable). React onRemove.
loadingboolfalseShows a spinner in the ring and blocks interaction while the pick uploads.
disabledboolfalseStatic, dimmed, non-interactive ring (read-only).
variantinitials | avatarinitialsPlaceholder style — initials text, or a standard avatar disc (person icon when no initials).
sizesm | md | lg | <px>mdRing diameter — a preset or an exact px value (e.g. size="96"); the whole control scales from it.
shapecircle | rounded | squarecircleRing shape for non-round logos.
layoutstacked | inline | profilestackedstacked = ring with hint below; inline = profile row (ring left, title/subtitle/hint beside); profile = same identity block centred beneath the ring.
titlestring—Bold primary text with the ring — inline/profile layouts only.
subtitlestring—Muted secondary text with the ring — inline/profile layouts only.
labelstring—Optional field label above the ring.
hintstring—Helper text — below the ring when stacked, in the side column when inline.
errorstring—Inline error below the ring.
requiredboolfalseShow a required marker next to the label.
aria-labelstringUpload photoAccessible name for the button (React ariaLabel).
fallbackstring—Initials/text shown when there is no image (React fallback).
overlay-iconstringimageBootstrap Icons glyph for the hover overlay (React overlayIcon).
max-size-mbint5Maximum accepted file size in MB (React maxSizeMb). Unset means 5. 0 or less means no size limit.