> ## Documentation Index
> Fetch the complete documentation index at: https://www.beeq.design/llms.txt
> Use this file to discover all available pages before exploring further.

# Avatar

> Avatars represent a person, team, or entity using a profile image or initials.

export const CodeLivePreview = ({code, children, height, removePadding = false, mode = 'shadow'}) => {
  const previewRef = useRef(null);
  const BEEQ_ESM_URL = 'https://esm.sh/@beeq/core/dist/beeq/beeq.esm.js';
  const BEEQ_CSS_URL = 'https://esm.sh/@beeq/core/dist/beeq/beeq.css';
  const BEEQ_ICONS_URL = 'https://esm.sh/@beeq/core/dist/beeq/svg';
  const ensureParentBeeqRuntime = () => {
    if (document.querySelector('script[data-beeq-parent-runtime]')) return;
    const script = document.createElement('script');
    script.type = 'module';
    script.src = BEEQ_ESM_URL;
    script.dataset.beeqParentRuntime = BEEQ_ICONS_URL;
    document.head.appendChild(script);
  };
  const executeSnippetScripts = (root, runtimeWindow, previewRootArg, skipAttr) => {
    root.querySelectorAll('script').forEach(oldScript => {
      if (skipAttr && oldScript.hasAttribute(skipAttr)) return;
      if (oldScript.src) {
        const newScript = runtimeWindow.document.createElement('script');
        newScript.src = oldScript.src;
        oldScript.replaceWith(newScript);
        return;
      }
      runtimeWindow.Function('previewRoot', oldScript.textContent || '')(previewRootArg);
      oldScript.remove();
    });
  };
  const syncIframeMode = iframeDoc => {
    const root = document.documentElement;
    const explicitMode = root.getAttribute('bq-mode');
    const isDark = root.classList.contains('dark');
    const resolvedMode = explicitMode || (isDark ? 'dark' : 'light');
    iframeDoc.documentElement.setAttribute('bq-mode', resolvedMode);
    iframeDoc.body.setAttribute('bq-mode', resolvedMode);
  };
  useEffect(() => {
    if (mode === 'shadow') ensureParentBeeqRuntime();
  }, [mode]);
  useEffect(() => {
    const container = previewRef.current;
    if (!container) return;
    if (removePadding) container.style.padding = '0';
    container.innerHTML = '';
    if (mode === 'iframe') {
      const iframe = document.createElement('iframe');
      iframe.className = 'preview-iframe';
      iframe.style.width = '100%';
      iframe.style.border = '0';
      iframe.style.display = 'block';
      iframe.style.minHeight = height ?? '0px';
      iframe.setAttribute('title', 'Live code preview');
      iframe.setAttribute('loading', 'lazy');
      iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
      container.appendChild(iframe);
      const iframeDoc = iframe.contentDocument;
      const iframeWin = iframe.contentWindow;
      if (!iframeDoc || !iframeWin) return;
      iframeDoc.open();
      iframeDoc.write(['<!doctype html>', '<html>', '<head>', '  <meta charset="utf-8" />', '  <meta name="viewport" content="width=device-width, initial-scale=1" />', '  <style>html,body{margin:0;padding:0;min-height:100%;}</style>', `  <link rel="stylesheet" href="${BEEQ_CSS_URL}" />`, `  <script type="module" src="${BEEQ_ESM_URL}" data-beeq-iframe-runtime="${BEEQ_ICONS_URL}"></script>`, '</head>', '<body>', code, '</body>', '</html>'].join('\n'));
      iframeDoc.close();
      syncIframeMode(iframeDoc);
      const modeObserver = new MutationObserver(() => syncIframeMode(iframeDoc));
      modeObserver.observe(document.documentElement, {
        attributes: true,
        attributeFilter: ['class', 'bq-mode']
      });
      executeSnippetScripts(iframeDoc, iframeWin, iframeDoc, 'data-beeq-iframe-runtime');
      return () => modeObserver.disconnect();
    }
    const shadowRoot = container.shadowRoot ?? container.attachShadow({
      mode: 'open'
    });
    if (!shadowRoot.adoptedStyleSheets.length) {
      const fixSheet = new CSSStyleSheet();
      fixSheet.replaceSync(`
        bq-dropdown::part(panel),
        bq-panel::part(panel),
        bq-select::part(panel),
        bq-date-picker::part(panel) { z-index: 9999; }
        bq-tooltip::part(panel) { position: absolute; }
      `);
      shadowRoot.adoptedStyleSheets = [fixSheet];
    }
    shadowRoot.innerHTML = [`<link rel="stylesheet" href="${BEEQ_CSS_URL}">`, code].join('');
    executeSnippetScripts(shadowRoot, window, shadowRoot);
    return undefined;
  }, [code, mode, height]);
  return <div className="code-live-preview not-prose">
      {}
      <div className="preview" ref={previewRef} style={{
    minHeight: height
  }} />

      {}
      {children && <div className="code">{children}</div>}
    </div>;
};

export const CardTile = ({title, href, imageLightSrc, imageDarkSrc, children, enableImgZoom}) => {
  if (!href) {
    return <div className="card-tile block font-normal group relative my-2 ring-2 ring-transparent rounded-2xl overflow-hidden w-full">
        {imageLightSrc && <img className="w-full m-0 block dark:hidden" src={imageLightSrc} alt={title} {...enableImgZoom ? {
      zoom: true
    } : {
      noZoom: true
    }} />}
        {imageDarkSrc && <img className="w-full m-0 hidden dark:block" src={imageDarkSrc} alt={title} {...enableImgZoom ? {
      zoom: true
    } : {
      noZoom: true
    }} />}
        {title && <h2 className="mt-4 mb-2 px-6 text-base font-semibold">{title}</h2>}
        <div className="px-6 pb-5">{children}</div>
      </div>;
  }
  return <a href={href} className="card-tile block font-normal group relative my-2 ring-2 ring-transparent rounded-2xl overflow-hidden w-full cursor-pointer">
      {imageLightSrc && <img className="w-full m-0 block dark:hidden" src={imageLightSrc} alt={title} noZoom />}
      {imageDarkSrc && <img className="w-full m-0 hidden dark:block" src={imageDarkSrc} alt={title} noZoom />}
      {title && <h2 className="mt-4 mb-2 px-6 text-base font-semibold">{title}</h2>}
      <div className="px-6 pb-5">{children}</div>
    </a>;
};

<Frame className="px-4 py-4" caption="Avatar component overview">
  <img className="block dark:hidden" src="https://mintcdn.com/beeq/wg4EwK5G4l2plt8W/components/images/avatar/avatar-overview-light.svg?fit=max&auto=format&n=wg4EwK5G4l2plt8W&q=85&s=180062ff59124cddb3d8463beec835be" alt="BEEQ Avatar component overview" width="408" height="302" data-path="components/images/avatar/avatar-overview-light.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/beeq/wg4EwK5G4l2plt8W/components/images/avatar/avatar-overview-dark.svg?fit=max&auto=format&n=wg4EwK5G4l2plt8W&q=85&s=8e5578a525e651256a5b390e631dc9bd" alt="BEEQ Avatar component overview" width="408" height="302" data-path="components/images/avatar/avatar-overview-dark.svg" />
</Frame>

Avatars help people identify users, teams, or entities at a glance. Use them in places where identity matters, such as lists, comments, ownership indicators, profile surfaces, contact cards, and people pickers.

<Note>
  Provide a meaningful `label` for every avatar. When an image is used, add `alt-text` and keep `initials` short so they remain a clean fallback if the image cannot load.
</Note>

## When to use

<CardGroup cols={2}>
  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="thumbs-up" iconType="solid" size={20} color="var(--bq-stroke--success)" />

      Use avatars when
    </span>

    * People need to identify a person, team, or brand quickly
    * A list, card, or thread benefits from a compact visual identifier
    * A profile image or initials add useful context without extra text
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="thumbs-down" iconType="solid" size={20} color="var(--bq-stroke--danger)" />

      Do not use avatars when
    </span>

    * Identity is not relevant to the task or content
    * A dense layout would become noisy with extra visuals
    * Text labels alone already make ownership or authorship obvious
  </Card>
</CardGroup>

## Avatar patterns

These are the most common contexts where avatars add meaningful value. Use them as a reference when deciding whether an avatar fits the layout.

<CardGroup cols={2}>
  <Card title="Contact details">
    Pair an avatar with a name and supporting metadata when identity is central to the content, such as profile summaries or directory entries.
  </Card>

  <Card title="List">
    Use avatars in dense lists when a quick visual cue helps people scan authors, owners, assignees, or participants faster.
  </Card>

  <Card title="Contact card">
    Add an avatar to card-based layouts when the card represents a person, team, or brand and identity should be immediately recognizable.
  </Card>

  <Card title="Select user">
    Use avatars in selection patterns when people need to choose from multiple users and benefit from both a name and a visual identifier.
  </Card>
</CardGroup>

## Anatomy

<Frame className="px-4 py-4" caption="Avatar component anatomy">
  <img className="block dark:hidden" src="https://mintcdn.com/beeq/wg4EwK5G4l2plt8W/components/images/avatar/avatar-anatomy-light.svg?fit=max&auto=format&n=wg4EwK5G4l2plt8W&q=85&s=7ffa80cf6e9443ab384cf0eeb0228e91" alt="BEEQ Avatar component anatomy" width="483" height="175" data-path="components/images/avatar/avatar-anatomy-light.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/beeq/wg4EwK5G4l2plt8W/components/images/avatar/avatar-anatomy-dark.svg?fit=max&auto=format&n=wg4EwK5G4l2plt8W&q=85&s=6ece817bf3cdfe02afcaeefeaeaa141f" alt="BEEQ Avatar component anatomy" width="483" height="175" data-path="components/images/avatar/avatar-anatomy-dark.svg" />
</Frame>

An avatar is a single visual surface that shows either an image or initials, with optional badge content layered on top.

| Part  | Element | Description                                                |
| ----- | ------- | ---------------------------------------------------------- |
| **1** | Base    | The visible avatar surface (`base` part)                   |
| **2** | Visual  | The displayed image (`img` part) or initials (`text` part) |
| **3** | Badge   | Optional content placed in the `badge` slot                |

## Design guidelines

### Shape

<CardGroup cols={2}>
  <CardTile title="Circle — for people" imageLightSrc="/components/images/avatar/avatar-shape-circle-light.svg" imageDarkSrc="/components/images/avatar/avatar-shape-circle-dark.svg" enableImgZoom>
    Use `circle` when the avatar represents an individual person, such as a user profile, comment author, or chat participant. The round shape signals human identity at a glance.
  </CardTile>

  <CardTile title="Square — for entities" imageLightSrc="/components/images/avatar/avatar-shape-square-light.svg" imageDarkSrc="/components/images/avatar/avatar-shape-square-dark.svg" enableImgZoom>
    Use `square` when the avatar represents a team, brand, organization, or system entity. The sharper edge fits non-personal identity and aligns with logo conventions.
  </CardTile>
</CardGroup>

<Tip>
  Avatar shape can be further customized by adjusting the border-radius tokens (`--bq-avatar--border-radius-*`), allowing the shape to match the overall product aesthetic.
</Tip>

### Initials

Pass the full intended initials (e.g. `"JD"` for John Doe) and let the component handle trimming. The component automatically caps the visible characters based on `size`:

<Steps>
  <Step title="xsmall">
    Shows **1 character** — only the first initial fits at 24px.
  </Step>

  <Step title="small">
    Shows **2 characters** — first and last initial, the most common pattern.
  </Step>

  <Step title="medium">
    Shows **3 characters** — suits slightly longer abbreviations or team codes.
  </Step>

  <Step title="large">
    Shows **4 characters** — maximum at 64px; useful for multi-word team names.
  </Step>
</Steps>

### Image and initials together

<Note>
  Always pass both `image` and `initials` when showing a photo. If the image fails to load, the component automatically falls back to the initials — no extra logic required on your side.
</Note>

## Usage

Avatar supports two primary variants: `Text` for initials and `Image` for profile photos or logos.

### Text

Use initials when no uploaded image is available or when the interface is intentionally compact. Pass short values rather than full names; the component trims the visible text based on the selected `size`.

<CodeLivePreview
  mode="shadow"
  code={`
<bq-avatar
initials="BQ"
label="Avatar component label"
></bq-avatar>
`}
>
  <CodeGroup>
    ```html HTML icon="html5" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-avatar initials="BQ" label="Avatar component label"></bq-avatar>
    ```

    ```jsx React icon="react" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqAvatar } from "@beeq/react";

    <BqAvatar initials="BQ" label="Avatar component label" />
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqAvatar } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqAvatar],
      template: `
        <bq-avatar
          initials="BQ"
          label="Avatar component label"
          ></bq-avatar>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqAvatar } from "@beeq/vue";
    </script>

    <template>
      <BqAvatar initials="BQ" label="Avatar component label" />
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

<Tip>
  When using the `Text` variant, you can customise the avatar background color via the `--bq-avatar-background` CSS custom property. For example: `bq-avatar { --bq-avatar-background: var(--bq-ui--success); }`
</Tip>

### Image

When a profile photo or logo is available, pass both `image` and `initials`. The image is shown first, while initials remain a built-in fallback if the image fails to load.

<CodeLivePreview
  mode="shadow"
  code={`
<bq-avatar
alt-text="User profile"
image="https://images.unsplash.com/photo-1524593689594-aae2f26b75ab?auto=format&fit=crop&w=1000&q=80"
initials="BQ"
label="Avatar component label"
></bq-avatar>
`}
>
  <CodeGroup>
    ```html HTML icon="html5" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-avatar
      alt-text="User profile"
      image="https://images.unsplash.com/photo-1524593689594-aae2f26b75ab?auto=format&fit=crop&w=1000&q=80"
      initials="BQ"
      label="Avatar component label"
    ></bq-avatar>
    ```

    ```jsx React icon="react" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqAvatar } from "@beeq/react";

    <BqAvatar
      altText="User profile"
      image="https://images.unsplash.com/photo-1524593689594-aae2f26b75ab?auto=format&fit=crop&w=1000&q=80"
      initials="BQ"
      label="Avatar component label"
    />
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqAvatar } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqAvatar],
      template: `
        <bq-avatar
          alt-text="User profile"
          image="https://images.unsplash.com/photo-1524593689594-aae2f26b75ab?auto=format&fit=crop&w=1000&q=80"
          initials="BQ"
          label="Avatar component label"
          ></bq-avatar>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqAvatar } from "@beeq/vue";
    </script>

    <template>
      <BqAvatar
        altText="User profile"
        image="https://images.unsplash.com/photo-1524593689594-aae2f26b75ab?auto=format&fit=crop&w=1000&q=80"
        initials="BQ"
        label="Avatar component label"
      />
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

## Options

### Shape and size

Avatar supports four sizes (`xsmall`, `small`, `medium`, `large`) and two shapes (`circle`, `square`). Choose size based on context: `small` works well in dense lists and inline layouts; `large` suits profile headers and contact cards where identity is the focal point. Keep shape and size consistent within the same group so the UI feels intentional and easy to scan.

<CodeLivePreview
  mode="shadow"
  code={`
<style>
.avatar--sizes {
  display: flex;
  align-items: center;
  gap: var(--bq-spacing-m);
  flex-wrap: wrap;
}
</style>
<div class="avatar--sizes">
<bq-avatar label="Extra small avatar" initials="B" size="xsmall"></bq-avatar>
<bq-avatar label="Small avatar" initials="BQ" size="small"></bq-avatar>
<bq-avatar label="Medium square avatar" initials="BQ" shape="square" size="medium"></bq-avatar>
<bq-avatar label="Large square avatar" initials="BQ" shape="square" size="large"></bq-avatar>
</div>
`}
>
  <CodeGroup>
    ```html HTML icon="html5" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-avatar label="Extra small avatar" initials="B" size="xsmall"></bq-avatar>
    <bq-avatar label="Small avatar" initials="BQ" size="small"></bq-avatar>
    <bq-avatar label="Medium square avatar" initials="BQ" shape="square" size="medium"></bq-avatar>
    <bq-avatar label="Large square avatar" initials="BQ" shape="square" size="large"></bq-avatar>
    ```

    ```jsx React icon="react" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqAvatar } from "@beeq/react";

    <BqAvatar label="Extra small avatar" initials="B" size="xsmall" />
    <BqAvatar label="Small avatar" initials="BQ" size="small" />
    <BqAvatar label="Medium square avatar" initials="BQ" shape="square" size="medium" />
    <BqAvatar label="Large square avatar" initials="BQ" shape="square" size="large" />
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqAvatar } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqAvatar],
      template: `
        <bq-avatar label="Extra small avatar" initials="B" size="xsmall"></bq-avatar>
        <bq-avatar label="Small avatar" initials="BQ" size="small"></bq-avatar>
        <bq-avatar label="Medium square avatar" initials="BQ" shape="square" size="medium"></bq-avatar>
        <bq-avatar label="Large square avatar" initials="BQ" shape="square" size="large"></bq-avatar>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqAvatar } from "@beeq/vue";
    </script>

    <template>
      <BqAvatar label="Extra small avatar" initials="B" size="xsmall" />
      <BqAvatar label="Small avatar" initials="BQ" size="small" />
      <BqAvatar label="Medium square avatar" initials="BQ" shape="square" size="medium" />
      <BqAvatar label="Large square avatar" initials="BQ" shape="square" size="large" />
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

### Avatar group

Use a grouped avatar pattern when you need to represent multiple participants in a compact space, such as shared ownership, collaborators, or team members. Keep the same size and shape across the whole group.

<Tip>
  Avatar grouping is not a built-in feature — the component renders avatars independently. A few lines of CSS are all you need to create an overlapping stack, as shown in the example below.
</Tip>

<CodeLivePreview
  mode="shadow"
  code={`
<style>
.avatar--group {
  display: flex;
  align-items: center;

  & bq-avatar {
    cursor: pointer;
    margin-inline-start: calc(var(--bq-spacing-xs) * -1);

    &::part(base) {
      transition: scale 0.25s ease-in-out;
    }

    &::part(base):hover {
      scale: 1.2;
      z-index: 1;
    }

    &:first-child {
      margin-inline-start: 0;
    }
  }
}
</style>
<div class="avatar--group">
<bq-avatar
  alt-text="User profile"
  image="https://i.pravatar.cc/500?img=12"
  label="Olivia Bennett"
></bq-avatar>
<bq-avatar
  alt-text="User profile"
  image="https://i.pravatar.cc/500?img=32"
  label="Liam Carter"
></bq-avatar>
<bq-avatar
  alt-text="User profile"
  image="https://i.pravatar.cc/500?img=52"
  label="Emma Wilson"
></bq-avatar>
<bq-avatar
  alt-text="User profile"
  image="https://i.pravatar.cc/500?img=10"
  label="Noah Davis"
></bq-avatar>
</div>
`}
>
  <CodeGroup>
    ```css styles.css icon="css" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    .avatar--group {
      display: flex;
      align-items: center;

      & bq-avatar {
        cursor: pointer;
        margin-inline-start: calc(var(--bq-spacing-xs) * -1);

        &::part(base) {
          transition: scale 0.25s ease-in-out;
        }

        &::part(base):hover {
          scale: 1.2;
          z-index: 1;
        }

        &:first-child {
          margin-inline-start: 0;
        }
      }
    }
    ```

    ```html HTML icon="html5" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <div class="avatar--group">
      <bq-avatar
        alt-text="User profile"
        image="https://i.pravatar.cc/500?img=12"
        label="Olivia Bennett"
        size="small"
      ></bq-avatar>
      <bq-avatar
        alt-text="User profile"
        image="https://i.pravatar.cc/500?img=32"
        label="Liam Carter"
        size="small"
      ></bq-avatar>
      <bq-avatar initials="BQ" label="BEEQ team" size="small"></bq-avatar>
    </div>
    ```

    ```jsx React icon="react" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqAvatar } from "@beeq/react";
    import "./styles.css";

    <div className="avatar--group">
      <BqAvatar
        altText="User profile"
        image="https://i.pravatar.cc/500?img=12"
        label="Olivia Bennett"
        size="small"
      />
      <BqAvatar
        altText="User profile"
        image="https://i.pravatar.cc/500?img=32"
        label="Liam Carter"
        size="small"
      />
      <BqAvatar initials="BQ" label="BEEQ team" size="small" />
    </div>
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqAvatar } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqAvatar],
      template: `
        <div class="avatar--group">
          <bq-avatar
            alt-text="User profile"
            image="https://i.pravatar.cc/500?img=12"
            label="Olivia Bennett"
            size="small"
            ></bq-avatar>
            <bq-avatar
              alt-text="User profile"
              image="https://i.pravatar.cc/500?img=32"
              label="Liam Carter"
              size="small"
              ></bq-avatar>
              <bq-avatar initials="BQ" label="BEEQ team" size="small"></bq-avatar>
            </div>
      `,
      styles: [`
        .avatar--group {
          display: flex;
          align-items: center;

          & bq-avatar {
            cursor: pointer;
            margin-inline-start: calc(var(--bq-spacing-xs) * -1);

            &::part(base) {
              transition: scale 0.25s ease-in-out;
            }

            &::part(base):hover {
              scale: 1.2;
              z-index: 1;
            }

            &:first-child {
              margin-inline-start: 0;
            }
          }
        }
      `],
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqAvatar } from "@beeq/vue";
    </script>

    <template>
      <div class="avatar--group">
        <BqAvatar
          altText="User profile"
          image="https://i.pravatar.cc/500?img=12"
          label="Olivia Bennett"
          size="small"
        />
        <BqAvatar
          altText="User profile"
          image="https://i.pravatar.cc/500?img=32"
          label="Liam Carter"
          size="small"
        />
        <BqAvatar initials="BQ" label="BEEQ team" size="small" />
      </div>
    </template>


    <style>
      .avatar--group {
        display: flex;
        align-items: center;

        & bq-avatar {
          cursor: pointer;
          margin-inline-start: calc(var(--bq-spacing-xs) * -1);

          &::part(base) {
            transition: scale 0.25s ease-in-out;
          }

          &::part(base):hover {
            scale: 1.2;
            z-index: 1;
          }

          &:first-child {
            margin-inline-start: 0;
          }
        }
      }
    </style>
    ```
  </CodeGroup>
</CodeLivePreview>

### With badge

Use the `badge` slot when the avatar needs a compact status or count indicator. `bq-badge` is the most common choice.

<CodeLivePreview
  mode="shadow"
  code={`
<bq-avatar
alt-text="User profile"
image="https://i.pravatar.cc/500"
label="Avatar component label"
>
<bq-badge slot="badge" size="medium" background-color="ui--tertiary"></bq-badge>
</bq-avatar>

<bq-avatar
alt-text="User profile"
image="https://i.pravatar.cc/500"
label="Avatar component label"
>
<bq-badge slot="badge" size="medium" background-color="ui--success"></bq-badge>
</bq-avatar>

<bq-avatar
alt-text="User profile"
image="https://i.pravatar.cc/500"
label="Avatar component label"
>
<bq-badge slot="badge">16</bq-badge>
</bq-avatar>
`}
>
  <CodeGroup>
    ```html HTML icon="html5" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <!-- Offline user -->
    <bq-avatar
      alt-text="User profile"
      image="https://i.pravatar.cc/500"
      label="Avatar component label"
    >
      <bq-badge slot="badge" size="medium" background-color="ui--tertiary"></bq-badge>
    </bq-avatar>

    <!-- Online user -->
    <bq-avatar
      alt-text="User profile"
      image="https://i.pravatar.cc/500"
      label="Avatar component label"
    >
      <bq-badge slot="badge" size="medium" background-color="ui--success"></bq-badge>
    </bq-avatar>

    <!-- Unread notifications -->
    <bq-avatar
      alt-text="User profile"
      image="https://i.pravatar.cc/500"
      label="Avatar component label"
    >
      <bq-badge slot="badge">16</bq-badge>
    </bq-avatar>
    ```

    ```jsx React icon="react" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqAvatar, BqBadge } from "@beeq/react";

    <div className="avatar--with-badge">
      {/* Offline user */}
      <BqAvatar
        altText="User profile"
        image="https://i.pravatar.cc/500"
        label="Avatar component label"
      >
        <BqBadge slot="badge" size="medium" backgroundColor="ui--tertiary" />
      </BqAvatar>

      {/* Online user */}
      <BqAvatar
        altText="User profile"
        image="https://i.pravatar.cc/500"
        label="Avatar component label"
      >
        <BqBadge slot="badge" size="medium" backgroundColor="ui--success" />
      </BqAvatar>

      {/* Unread notifications */}
      <BqAvatar
        altText="User profile"
        image="https://i.pravatar.cc/500"
        label="Avatar component label"
      >
        <BqBadge slot="badge">16</BqBadge>
      </BqAvatar>
    </div>
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqAvatar, BqBadge } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqAvatar, BqBadge],
      template: `
        <div class="avatar--with-badge">
          <!-- Offline user -->
          <bq-avatar
            alt-text="User profile"
            image="https://i.pravatar.cc/500"
            label="Avatar component label"
            >
            <bq-badge slot="badge" size="medium" background-color="ui--tertiary"></bq-badge>
          </bq-avatar>

          <!-- Online user -->
          <bq-avatar
            alt-text="User profile"
            image="https://i.pravatar.cc/500"
            label="Avatar component label"
            >
            <bq-badge slot="badge" size="medium" background-color="ui--success"></bq-badge>
          </bq-avatar>

          <!-- Unread notifications -->
          <bq-avatar
            alt-text="User profile"
            image="https://i.pravatar.cc/500"
            label="Avatar component label"
            >
            <bq-badge slot="badge">16</bq-badge>
          </bq-avatar>
        </div>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqAvatar, BqBadge } from "@beeq/vue";
    </script>

    <template>
      <div class="avatar--with-badge">
        <!-- Offline user -->
        <BqAvatar
          altText="User profile"
          image="https://i.pravatar.cc/500"
          label="Avatar component label"
        >
          <BqBadge slot="badge" size="medium" background-color="ui--tertiary" />
        </BqAvatar>

        <!-- Online user -->
        <BqAvatar
          altText="User profile"
          image="https://i.pravatar.cc/500"
          label="Avatar component label"
        >
          <BqBadge slot="badge" size="medium" background-color="ui--success" />
        </BqAvatar>

        <!-- Unread notifications -->
        <BqAvatar
          altText="User profile"
          image="https://i.pravatar.cc/500"
          label="Avatar component label"
        >
          <BqBadge slot="badge">16</BqBadge>
        </BqAvatar>
      </div>
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

## Best practices

<CardGroup cols={2}>
  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="check" iconType="solid" size={20} color="var(--bq-stroke--success)" />

      Do
    </span>

    Use the supported `shape` options to keep avatars aligned with the system and the surrounding UI.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="xmark" iconType="solid" size={20} color="var(--bq-stroke--danger)" />

      Don't
    </span>

    Do not resize avatars outside the available sizes. It can distort the component and break visual consistency.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="check" iconType="solid" size={20} color="var(--bq-stroke--success)" />

      Do
    </span>

    Keep initials short, ideally using the first letters of a first and last name so they remain legible at every size.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="xmark" iconType="solid" size={20} color="var(--bq-stroke--danger)" />

      Don't
    </span>

    Do not pass full names as initials. Long strings quickly become unreadable and visually unbalanced.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="check" iconType="solid" size={20} color="var(--bq-stroke--success)" />

      Do
    </span>

    Keep avatar style consistent within the same group. Use the same shape, size, and image-vs-initials pattern where possible.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="xmark" iconType="solid" size={20} color="var(--bq-stroke--danger)" />

      Don't
    </span>

    Do not mix mismatched avatar treatments in one group unless the difference carries meaning. It makes lists harder to scan.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="check" iconType="solid" size={20} color="var(--bq-stroke--success)" />

      Do
    </span>

    Use well-cropped images that fit the avatar area cleanly and keep the subject centered and recognizable.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="xmark" iconType="solid" size={20} color="var(--bq-stroke--danger)" />

      Don't
    </span>

    Do not use clipped, stretched, or low-quality images. If the image is not clear, initials are often the better fallback.
  </Card>
</CardGroup>

## Accessibility

The component automatically applies `role="img"` and `aria-label` to its root element. You do not need to add ARIA attributes manually — provide a descriptive `label` and the component handles the rest.

When the avatar displays an image, also pass `alt-text` to describe what the image shows. Keep `initials` short so the text fallback remains readable if the image cannot load.

If the avatar appears alongside other interactive elements such as names, links, or buttons, make sure the surrounding pattern is accessible as a whole — the avatar's built-in label describes the avatar itself, not the composite component around it.

## API reference

### Properties

| Property   | Attribute  | Description                                          | Type                                               | Default     |
| ---------- | ---------- | ---------------------------------------------------- | -------------------------------------------------- | ----------- |
| `altText`  | `alt-text` | Alternate text applied to the internal image element | `string`                                           | `undefined` |
| `image`    | `image`    | Image source to display inside the avatar            | `string`                                           | `undefined` |
| `initials` | `initials` | Short text shown when no image is visible            | `string`                                           | `undefined` |
| `label`    | `label`    | Accessible name announced for the avatar             | `string`                                           | `undefined` |
| `shape`    | `shape`    | Visual shape of the avatar                           | `'circle'` \| `'square'`                           | `'circle'`  |
| `size`     | `size`     | Size of the avatar                                   | `'xsmall'` \| `'small'` \| `'medium'` \| `'large'` | `'medium'`  |

### Slots

| Slot    | Description                                          |
| ------- | ---------------------------------------------------- |
| `badge` | Optional badge content positioned on the avatar edge |

### Shadow parts

| Part    | Description                             |
| ------- | --------------------------------------- |
| `base`  | The visible avatar wrapper              |
| `img`   | The internal `<img>` element            |
| `text`  | The initials text element               |
| `badge` | The container wrapping the `badge` slot |

### CSS custom properties

<Expandable title="CSS variables" defaultOpen={true}>
  | Variable                              | Description                                       | Default                      |
  | ------------------------------------- | ------------------------------------------------- | ---------------------------- |
  | `--bq-avatar-background`              | Avatar background color                           | `var(--bq-ui--alt)`          |
  | `--bq-avatar--border-color`           | Avatar border color                               | `var(--bq-stroke--tertiary)` |
  | `--bq-avatar--border-style`           | Avatar border style                               | `solid`                      |
  | `--bq-avatar--border-width`           | Avatar border width                               | `var(--bq-stroke-m)`         |
  | `--bq-avatar--border-radius-circle`   | Border radius for circle avatars                  | `var(--bq-radius--full)`     |
  | `--bq-avatar--border-radius-squareXs` | Border radius for `square` + `xsmall`             | `var(--bq-radius--xs)`       |
  | `--bq-avatar--border-radius-squareS`  | Border radius for `square` + `small`              | `var(--bq-radius--s)`        |
  | `--bq-avatar--border-radius-squareM`  | Border radius for `square` + `medium` and `large` | `var(--bq-radius--m)`        |
  | `--bq-avatar--size-xsmall`            | Xsmall avatar size                                | `24px`                       |
  | `--bq-avatar--size-small`             | Small avatar size                                 | `32px`                       |
  | `--bq-avatar--size-medium`            | Medium avatar size                                | `48px`                       |
  | `--bq-avatar--size-large`             | Large avatar size                                 | `64px`                       |
  | `--bq-avatar--font-size-xsmall`       | Initials font size for `xsmall`                   | `var(--bq-font-size--xs)`    |
  | `--bq-avatar--font-size-small`        | Initials font size for `small`                    | `var(--bq-font-size--xs)`    |
  | `--bq-avatar--font-size-medium`       | Initials font size for `medium`                   | `var(--bq-font-size--m)`     |
  | `--bq-avatar--font-size-large`        | Initials font size for `large`                    | `var(--bq-font-size--m)`     |
  | `--bq-avatar--badge-top-square`       | Badge top offset for square avatars               | `-5px`                       |
  | `--bq-avatar--badge-left-square`      | Badge left offset for square avatars              | `80%`                        |
  | `--bq-avatar--badge-top-circle`       | Badge top offset for circle avatars               | `0`                          |
  | `--bq-avatar--badge-left-circle`      | Badge left offset for circle avatars              | `75%`                        |
</Expandable>

<Tip>
  Learn more about [styling with shadow parts](/guides/styles#component-shadow-dom-parts) and [CSS custom properties](/guides/styles#global-css-custom-properties).
</Tip>

## Resources

<CardGroup cols={2}>
  <Card horizontal title="Interactive playground" icon="code" href="https://storybook.beeq.design/?path=/story/components-avatar--image">
    Explore avatar variants and states in Storybook
  </Card>

  <Card horizontal title="Source code" icon="github" href="https://github.com/Endava/BEEQ/tree/main/packages/beeq/src/components/avatar">
    View the component source on GitHub
  </Card>
</CardGroup>
