-
Notifications
You must be signed in to change notification settings - Fork 0
LayrzAvatar
A static display component that renders a user avatar in one of five forms: image (URL or base64), icon, emoji, or initials generated from a name. The avatar is always a rounded box using the r12 radius token, consistent with LayrzCard and LayrzAlert, and carries a fixed tokens.shadow.compact1 drop shadow in all render modes.
Metadata
Mirrors: ThemedAvatar (layrz_theme)
Phase: M2 (Core primitives)
Domain: Display
Primitive: Hand-rolled (ClipRRect + Container + Image + Icon + Text)
Status: Confirmed scope.
LayrzAvatar renders a static, non-interactive avatar display. It is display-only and does not support interaction callbacks (onTap, onLongPress, etc.). Callers who need interactivity should wrap the avatar in a GestureDetector or similar widget themselves. This keeps the API minimal and separation of concerns clear.
The avatar resolves what to display using a strict fallback order:
-
Image from a named constructor (
.image()) — renders from URL or base64 -
Icon from a named constructor (
.icon()) — renders fromLayrzIcon -
Emoji from a named constructor (
.emoji()) — renders a Unicode glyph -
Initials from a named constructor (
.initials()) — renders fromnameText -
Avatar descriptor from
Avatarmodel (avatarparameter) — resolves byAvatarType -
Fallback to initials — from
nameTextwhen the avatar is null or missing
-
Static display only: No interaction callbacks. Wrap with
GestureDetectorif needed. -
Multiple render modes: Image (URL/base64), icon, emoji, or initials — all from a single
Avatarobject. - Smart fallback: Falls through gracefully when any mode's required field is missing.
-
Fixed sizing: A single
sizeparameter defines both width and height. -
Consistent rounding: Always a rounded box using the
r12radius token, matching other surface components. - Color-aware text: Text color (for initials and emoji) is automatically contrasted against the background for readability.
-
Fixed drop shadow: Every avatar carries a fixed
tokens.shadow.compact1drop shadow in all modes. This shadow is intentionally not configurable.
class LayrzAvatar extends StatelessWidget {
/// Avatar descriptor from layrz_sdk; its `type` selects what is rendered.
///
/// When null, falls back to initials from [nameText]. When the type's required
/// field is missing (e.g., [AvatarType.url] but `url` is null), also falls back
/// to initials.
final Avatar? avatar;
/// Name text from which initials are generated when [avatar] is null, has type
/// [AvatarType.none], or is missing the field its type requires.
///
/// If null and no usable avatar is available, displays `"NA"` as a placeholder.
final String? nameText;
/// Width and height of the avatar in logical pixels.
///
/// Defaults to 40. The avatar is always square with rounded corners, so this
/// single value defines both dimensions.
final double size;
/// Background fill color of the avatar.
///
/// Defaults to the primary token color when null. Ignored when rendering an
/// image (images have transparent backgrounds).
final Color? color;
/// Creates a new [LayrzAvatar].
///
/// Renders the avatar described by the [Avatar] object from layrz_sdk.
/// Falls back to initials from [nameText] when the avatar is null or missing.
/// At least one of [avatar] or [nameText] should be provided for useful output.
const LayrzAvatar({
super.key,
this.avatar,
this.nameText,
this.size = 40,
this.color,
});
}Renders an avatar from an image source (URL or base64).
const LayrzAvatar.image({
required String source,
this.size = 40,
});-
source: An http(s) URL, a
data:URI, or a bare base64 string. Routed toLayrzImage. - Background: Transparent (image is displayed directly).
Renders an avatar from a LayrzIcon (from layrz_icons).
const LayrzAvatar.icon({
required LayrzIcon icon,
this.size = 40,
this.color,
});-
icon: The
LayrzIconto display (accessed via its.iconDatagetter). - Color: Defaults to the primary token color.
-
Icon size: 70% of
size.
Renders an avatar from a Unicode emoji glyph.
const LayrzAvatar.emoji({
required String emoji,
this.size = 40,
});- emoji: A single Unicode emoji or emoji sequence.
- Background: White.
-
Emoji size: 60% of
size.
Renders an avatar from generated initials.
const LayrzAvatar.initials({
required this.nameText,
this.size = 40,
this.color,
});- nameText: The name from which initials are derived.
- Color: Defaults to the primary token color.
When the main constructor receives an Avatar object, the type field selects the rendering:
| Type | Behaviour | Fallback |
|---|---|---|
AvatarType.url |
Displays the image from avatar.url via LayrzImage
|
Initials from nameText if url is null |
AvatarType.base64 |
Displays the image from avatar.base64 via LayrzImage
|
Initials from nameText if base64 is null |
AvatarType.icon |
Displays the icon from avatar.icon (a LayrzIcon) |
Initials from nameText if icon is null |
AvatarType.emoji |
Displays the emoji from avatar.emoji
|
Initials from nameText if emoji is null |
AvatarType.none |
Falls back to initials from nameText
|
"NA" if nameText is null/empty |
The initials algorithm (when falling back to text):
- Strip all non-alphanumeric characters from the input name.
- If empty, display
"NA"(Not Available). - If one character, display that character.
- If two or more characters, display the first two characters in uppercase.
Known limitation: This algorithm is not Unicode-aware (combining characters, non-Latin scripts, ligatures are treated as separate characters). This is an accepted limitation, not a bug to solve. Most real-world use cases involve Latin-script names.
-
Size: A single
sizeparameter (default 40) defines both width and height. -
Shape: Always a rounded box using the
r12radius token, consistent withLayrzCard,LayrzAlert, and the dropdown panel. - Background color: Defaults to the primary token color when null. Ignored for images (transparent).
- Text color (for initials/icons): Automatically contrasted against the background using a luminance heuristic — black text for light backgrounds, white text for dark backgrounds.
-
Fixed drop shadow: Every avatar carries
tokens.shadow.compact1as a fixed drop shadow in all render modes (initials, icon, emoji, URL/base64 image). This is the small-component shadow ramp used byLayrzButton, chosen because a soft low-offset shadow disappears at avatar sizes; compact shadows provide clear separation at 40px width. This shadow is intentionally not configurable — it is part of the avatar's baseline visual treatment.
The .image() constructor and URL/base64 types in the Avatar model route image rendering through LayrzImage. See LayrzImage for details on:
- Supported source formats (http(s) URLs, data-URIs, bare base64, asset paths)
- SVG detection and handling
- Placeholder and fallback rendering
- Base64 decoding cache and eviction policy
- LayrzAvatarInput — Input-side component for selecting an avatar from a system image picker.
- LayrzDynamicAvatarInput — Input-side component for selecting an avatar from multiple sources (URL, base64, icon, emoji).
// The Avatar model comes from layrz_sdk
final user = Avatar(
type: AvatarType.url,
url: 'https://example.com/user.png',
);
LayrzAvatar(
avatar: user,
nameText: 'Jane Smith', // Fallback if URL fails to load
size: 48,
)LayrzAvatar.image(
source: 'https://cdn.layrz.com/resources/com.layrz.one/favicon/normal.png',
size: 56,
)LayrzAvatar.icon(
icon: LayrzIcons.solarUserBold,
size: 40,
color: context.tokens.colors.info,
)LayrzAvatar.emoji(
emoji: '🎨',
size: 48,
)LayrzAvatar.initials(
nameText: 'Alice Johnson',
size: 40,
color: context.tokens.colors.success,
)// Avatar model with missing `url`; falls back to initials
final incompleteAvatar = Avatar(
type: AvatarType.url,
url: null, // Missing!
);
LayrzAvatar(
avatar: incompleteAvatar,
nameText: 'Bob Brown',
// Displays initials "BB" because url is null
)- Avatars are static display elements with no interaction affordances.
- Initials text is painted directly and is accessible to screen readers if wrapped in semantic containers (e.g., a
Semanticswidget). - Icons are rendered as icon glyphs without semantic labeling (intentional, to avoid noise in screen readers for decorative avatars).
-
Static display only: No
onTap,onLongPress,onSecondaryTap. Wrap withGestureDetectorif needed. -
Avatar model source: The
Avatartype comes frompackage:layrz_sdk/layrz_sdk.dart. See the SDK documentation for the fullAvatarmodel structure. -
Image rendering: Images are processed by
LayrzImage, which handles multiple formats and caching transparently. -
No interaction states: Unlike
LayrzButtonorLayrzChip, there is no hover, press, or focus state. The component is purely presentational.
- LayrzImage — Image component used for URL and base64 rendering
- LayrzAvatarInput — Input component for avatar selection from camera/gallery
- LayrzDynamicAvatarInput — Input component for multi-source avatar selection
Made with ❤️ by Golden M, Inc.
- LayrzAnchoredPanel
- LayrzBottomSheet
- LayrzDialog
- LayrzDropdownMenu
- LayrzResponsiveModal
- LayrzPageTransition
- LayrzTextInput
- LayrzSelectableAction
- LayrzSelectionToolbar
- LayrzTextSelectionControls
- LayrzSelectionMagnifier
- LayrzSelectionHandlePainter
- LayrzTextAreaInput
- LayrzComboBoxInput
- LayrzNumberInput
- LayrzPasswordInput
- LayrzCheckboxInput
- LayrzRadioInput
- LayrzSelectInput
- LayrzMultiSelectInput
- LayrzSearchInput
- LayrzDualListInput
- LayrzDurationInput
- LayrzSlider
- LayrzStepper