{
  "name": "Avatar",
  "source": "src/components/Avatar.tsx",
  "propsType": "AvatarProps",
  "description": "Avatar picks its content the way Figma's `Type` variant does, but by\nprecedence rather than by a prop: image, then initials, then icon. A caller\npassing `src` and `initials` gets the image with the initials as its alt\nfallback, which is what you want when the image 404s.\n\nA failed `src` falls through to initials (then icon) rather than leaving the\nbrowser's broken-image glyph — that is why initials exist alongside `src`.\n\nIt is a `<span>`, not a `<div>`, so it can sit inline beside text without the\ncaller fighting a block element.\n\nTHE MEDIA IS A CHILD, AND IT HAS TO BE\n\nThe box that clips the image is `.ion-avatar__media`, not the root. The root\ncannot clip: a corner indicator sits outside a circle's clip path and would\nbe sliced in half by the `overflow: hidden` that crops the photo. Figma\ndraws exactly this — an unclipped frame holding a clipped `Media` child and\nthe indicators as its siblings.",
  "import": "import { Avatar } from 'ionbase-ui';",
  "status": "stable",
  "summary": "A person or entity marker. Content is chosen by precedence — image, then initials, then icon — not by a type prop.",
  "useWhen": [
    "identifying who owns, authored or is assigned to something",
    "a table cell, menu row or header needs a compact identity marker beside a name"
  ],
  "useInstead": [
    {
      "when": "the thing being marked is a status, count or category rather than a person",
      "use": "Badge"
    },
    {
      "when": "you only need a decorative graphic with no identity behind it",
      "use": "Icon"
    }
  ],
  "variants": {
    "size": {
      "mini": {
        "use": "24px — inline beside body text, dense table rows"
      },
      "sm": {
        "use": "32px — menu rows, compact lists"
      },
      "md": {
        "use": "the default, 40px"
      },
      "lg": {
        "use": "48px — profile headers and detail pages"
      }
    },
    "shape": {
      "circle": {
        "use": "the default — people"
      },
      "square": {
        "use": "organisations, projects, workspaces and other non-human entities"
      }
    },
    "topIndicator": {
      "neutral": {
        "use": "no state, or a state this system has no colour for"
      },
      "primary": {
        "use": "attention rather than health — a request, an invite, a mention"
      },
      "success": {
        "use": "online, available, verified, complete"
      },
      "warning": {
        "use": "away, idle, needs attention but is not broken"
      },
      "error": {
        "use": "offline, blocked, failed"
      },
      "information": {
        "use": "a neutral fact about the person — a role or a badge, not a state"
      }
    },
    "bottomIndicator": {
      "neutral": {
        "use": "no state, or a state this system has no colour for"
      },
      "primary": {
        "use": "attention rather than health — a request, an invite, a mention"
      },
      "success": {
        "use": "online, available, verified, complete"
      },
      "warning": {
        "use": "away, idle, needs attention but is not broken"
      },
      "error": {
        "use": "offline, blocked, failed"
      },
      "information": {
        "use": "a neutral fact about the person — a role or a badge, not a state"
      }
    }
  },
  "slots": {
    "icon": {
      "accepts": "Icon",
      "note": "the last fallback — rendered only when there is neither `src` nor `initials`"
    },
    "topIndicatorIcon": {
      "accepts": "Icon",
      "note": "replaces the top indicator's default check glyph. The bottom indicator takes no glyph — Figma draws it bare, and at Mini it is 8px, which nothing legible fits inside."
    }
  },
  "a11y": {
    "guarantees": [
      "`alt` falls back to `initials`, so the avatar is never announced as an unlabelled image",
      "a `src` that fails to load falls through to initials, then icon — never the browser's broken-image glyph",
      "indicator labels are announced wherever they land: folded into the avatar's own `aria-label` when there is no image (the root is `role=\"img\"` and therefore a leaf), and carried as hidden text inside each indicator when there is"
    ],
    "requires": [
      "`alt` describing the person, not the picture — \"Ada Lovelace\", not \"profile photo\"",
      "`topIndicatorLabel` / `bottomIndicatorLabel` on any indicator that carries meaning. An indicator with no label is decorative, which is the right answer only when the same fact is already stated in text beside it."
    ]
  },
  "antiPatterns": [
    {
      "dont": "passing `src` without `initials`",
      "why": "a 404 leaves the fallback empty; initials are what make the failure invisible"
    },
    {
      "dont": "using Avatar as a button",
      "do": "put the Avatar inside a Button or Link",
      "why": "Avatar renders a <span> with no role and takes no focus"
    },
    {
      "dont": "using an indicator's colour as the only carrier of a status",
      "do": "pass `topIndicatorLabel` / `bottomIndicatorLabel`, or state the status in text nearby",
      "why": "WCAG 1.4.1. A green dot and a red dot are the same dot to a screen reader, and to a good share of sighted users too"
    },
    {
      "dont": "reaching for `ring` to mean selected or focused",
      "why": "it is a static brand ring from the design, not a focus indicator. Focus belongs on whatever interactive element wraps the avatar, and that element draws its own"
    }
  ],
  "stylesheet": "src/styles/avatar.css",
  "tokens": [
    "--border-strong",
    "--border-subtle",
    "--border-width-default",
    "--border-width-thick",
    "--font-family-sans",
    "--font-weight-medium",
    "--font-weight-regular",
    "--icon-size-2xs",
    "--icon-size-lg",
    "--icon-size-md",
    "--icon-size-sm",
    "--icon-tertiary",
    "--ion-avatar-border",
    "--ion-avatar-font-size",
    "--ion-avatar-font-weight",
    "--ion-avatar-group-overlap",
    "--ion-avatar-icon",
    "--ion-avatar-indicator-icon",
    "--ion-avatar-indicator-ring",
    "--ion-avatar-indicator-size",
    "--ion-avatar-line-height",
    "--ion-avatar-radius",
    "--ion-avatar-ring-width",
    "--ion-avatar-size",
    "--ion-avatar-surface",
    "--radius-full",
    "--radius-md",
    "--radius-sm",
    "--radius-xs",
    "--ring-offset",
    "--spacing-12",
    "--spacing-14",
    "--spacing-16",
    "--spacing-24",
    "--spacing-32",
    "--spacing-40",
    "--spacing-48",
    "--spacing-8",
    "--surface-error",
    "--surface-information",
    "--surface-inverse",
    "--surface-muted",
    "--surface-placeholder",
    "--surface-primary",
    "--surface-success",
    "--surface-warning",
    "--text-inverse",
    "--text-on-color",
    "--text-tertiary",
    "--type-body",
    "--type-body-lg",
    "--type-body-lg-line-height",
    "--type-body-line-height",
    "--type-body-sm",
    "--type-body-sm-line-height",
    "--type-caption",
    "--type-caption-line-height"
  ],
  "props": {
    "size": {
      "type": "AvatarSize | undefined",
      "required": false,
      "origin": "own",
      "description": "Matches the Figma `Size` variant: Mini 24, Small 32, Medium 40, Large 48.",
      "values": [
        "sm",
        "md",
        "lg",
        "mini"
      ]
    },
    "shape": {
      "type": "AvatarShape | undefined",
      "required": false,
      "origin": "own",
      "description": "Matches the Figma `Shape` variant.",
      "values": [
        "circle",
        "square"
      ]
    },
    "src": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Image source. Figma's `Type=Image`."
    },
    "alt": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Describes the person, not the picture. Falls back to `initials` so the\navatar is never announced as an unlabelled image."
    },
    "initials": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Figma's `Type=Character`. Rendered when there is no `src`, or when `src`\nfails to load."
    },
    "icon": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Figma's `Type=Icon`. Rendered when there is neither `src` nor `initials`."
    },
    "ring": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own",
      "description": "Figma's `Show Ring` — a 1px/2px brand ring drawn inside the avatar's edge."
    },
    "topIndicator": {
      "type": "AvatarIndicatorIntent | undefined",
      "required": false,
      "origin": "own",
      "description": "Figma's `Show Top Indicator`, as the intent of the `Status Indicator`\ninstance it holds. Top-right, and it carries a glyph: this is the corner\nthat says something was verified or requested, not who is online.",
      "values": [
        "neutral",
        "primary",
        "success",
        "warning",
        "error",
        "information"
      ]
    },
    "topIndicatorIcon": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Replaces the top indicator's default check glyph."
    },
    "topIndicatorLabel": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Names the top indicator for assistive tech. Without it the mark is decorative."
    },
    "bottomIndicator": {
      "type": "AvatarIndicatorIntent | undefined",
      "required": false,
      "origin": "own",
      "description": "Figma's `Show Bottom Indicator`. Bottom-right and glyphless — the presence\ndot.",
      "values": [
        "neutral",
        "primary",
        "success",
        "warning",
        "error",
        "information"
      ]
    },
    "bottomIndicatorLabel": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Names the bottom indicator for assistive tech. Colour alone is not a status."
    }
  },
  "propCounts": {
    "own": 12,
    "aria": 0,
    "dom": 278,
    "other": 0
  }
}
