{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"avatar-group","title":"Avatar Group","description":"Show several people as a row of overlapping avatars with an optional overflow count. Search terms: avatar stack, facepile, members.","dependencies":["@base-ui/react@1.7.0"],"registryDependencies":["@siteplane/base","@siteplane/badge"],"files":[{"path":"packages/ui/src/components/avatar-group/avatar-group.tsx","content":"\"use client\";\n\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport type * as React from \"react\";\n\nimport type { BadgeProps } from \"../badge\";\nimport { KitBadge } from \"../badge/badge-internal\";\nimport { normalizeFormattedText } from \"../../system/locale/formatted-text\";\nimport { slotClass } from \"../../system/utils/slot-class\";\nimport { cn } from \"../../system/utils/cn\";\n\nexport type AvatarGroupSize = \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nexport interface AvatarGroupProps extends useRender.ComponentProps<\"div\"> {\n  /**\n   * The size of every avatar and the count in the group: `sm` 24 px, `md`\n   * 32 px (the default, the size of a single Avatar), `lg` 40 px and `xl`\n   * 48 px. The avatars overlap by a quarter of it.\n   */\n  size?: AvatarGroupSize;\n}\n\n/**\n * A row of overlapping avatars. The group sizes its avatars and its count;\n * each item after the first overlaps the one before it by a quarter of that\n * size, and every avatar draws a 2 px ring in the color of the surface it\n * sits on, so the circles stay apart on a page, a Card or a Dialog. The kit\n * stylesheet owns the size, the overlap and the ring.\n */\nexport function AvatarGroup({\n  className,\n  render,\n  size = \"md\",\n  ...props\n}: AvatarGroupProps): React.ReactElement {\n  const defaultProps = {\n    \"data-size\": size,\n    \"data-slot\": \"avatar-group\",\n    className: cn(slotClass(\"avatar-group\", props, render), className),\n  };\n\n  return useRender({\n    defaultTagName: \"div\",\n    props: mergeProps<\"div\">(defaultProps, props),\n    render,\n  });\n}\n\nexport type AvatarGroupCountProps = Omit<\n  BadgeProps,\n  \"light\" | \"profile\" | \"shape\" | \"size\" | \"variant\"\n> & {\n  /**\n   * The number of members the group does not show. The count writes it as\n   * \"+N\", from 1,000 on in compact notation (\"+1.3K\", with the exact number as\n   * its title), and gives assistive technology the exact number. Children\n   * follow it, such as visually hidden text that says what it counts.\n   */\n  count?: number | undefined;\n  /**\n   * The locale that writes `count`. en-US unless set, as in the charts, so the\n   * server and the browser write the same text.\n   */\n  locale?: string | undefined;\n};\n\n/** Counts from this many members on take compact notation. */\nconst COMPACT_FROM = 1000;\n\n/**\n * The count as the group writes it, and as assistive technology reads it: the\n * exact number with its sign, and from 1,000 on the visible text in compact\n * notation, with one fraction digit at most so that the server and the\n * browser round it alike.\n */\nfunction countText(\n  count: number,\n  locale: string,\n): { exact: string; shown: string } {\n  const exact = normalizeFormattedText(\n    new Intl.NumberFormat(locale, { signDisplay: \"exceptZero\" }).format(count),\n  );\n  if (Math.abs(count) < COMPACT_FROM) return { exact, shown: exact };\n  const shown = normalizeFormattedText(\n    new Intl.NumberFormat(locale, {\n      maximumFractionDigits: 1,\n      minimumFractionDigits: 0,\n      notation: \"compact\",\n      signDisplay: \"exceptZero\",\n    }).format(count),\n  );\n  return { exact, shown };\n}\n\n/**\n * The count of the members a group does not show, such as \"+2\", at the end\n * of an AvatarGroup: a circle of the group's size with the same surface ring\n * as the avatars. A longer count grows as a pill of the same height and never\n * truncates. Pass the number as `count`, or the text as children; either way,\n * give it an accessible name that says what it counts, for example with\n * visually hidden text.\n */\nexport function AvatarGroupCount({\n  children,\n  count,\n  locale = \"en-US\",\n  ...props\n}: AvatarGroupCountProps): React.ReactElement {\n  let content: React.ReactNode = children;\n  if (count !== undefined) {\n    const { exact, shown } = countText(count, locale);\n    content = (\n      <>\n        <span\n          aria-hidden=\"true\"\n          className=\"sp-avatar-group-count-value\"\n          data-slot=\"avatar-group-count-value\"\n          title={shown === exact ? undefined : exact}\n        >\n          {shown}\n        </span>\n        <span className=\"sr-only\">{exact}</span>\n        {children}\n      </>\n    );\n  }\n  return (\n    <KitBadge\n      data-slot=\"avatar-group-count\"\n      {...props}\n      profile=\"group-overflow-count\"\n    >\n      {content}\n    </KitBadge>\n  );\n}\n","type":"registry:ui","target":"~/src/siteplane/components/avatar-group/avatar-group.tsx"},{"path":"packages/ui/src/components/avatar-group/index.ts","content":"export * from \"./avatar-group\";\n","type":"registry:ui","target":"~/src/siteplane/components/avatar-group/index.ts"}],"type":"registry:ui","docs":"https://ui.siteplane.io/docs-markdown/components/avatar-group.md","categories":["Data display"],"meta":{"avoidWhen":["Avoid when every person needs a name on screen; list them, for example in a Resource List.","Avoid for a single person; use Avatar."],"description":"Show several people as a row of overlapping avatars with an optional overflow count.","knownLimitations":["The application decides how many avatars to show and what the count says; the group does not measure or cut its children.","The ring takes the color of the kit surface the group sits on, such as a Card, Dialog or Popover, and the page background elsewhere.","The size prop sizes every avatar and the count, 24, 32, 40 or 48 px, and the overlap is a quarter of it; a size class on one avatar changes that avatar alone.","The count needs an accessible name that says what it counts, for example visually hidden text after the number."],"providerNotes":[],"releaseStatus":"stable","searchTerms":["avatar-group","avatar group","avatar stack","facepile","members","people","overflow count"],"useWhen":["Use to show the people of a project, a team or a conversation in little space.","Use with a count when a group has more members than it shows."]}}