Repository: adobe/react-spectrum
File: packages/@react-spectrum/s2/src/Avatar.tsx (TypeScript)

Code before:
   * @default 24
   */
  size?: 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 56 | 64 | 80 | 96 | 112 | (number & {}),
  /** Whether the avatar is over a color background. */
  isOverBackground?: boolean
}

const imageStyles = style({
  borderRadius: 'full',
  size: 20,
  flexShrink: 0,
  flexGrow: 0,
  disableTapHighlight: true,
  outlineStyle: {
    default: 'none',
    isOverBackground: 'solid'
  },
  outlineColor: '--s2-container-bg',
  outlineWidth: {
    default: 1,
    isLarge: 2
  }
}, getAllowedOverrides({width: false}));

export interface AvatarContextValue extends AvatarProps {
  render?: (avatar: ReactNode) => ReactNode
}

export const AvatarContext = createContext<ContextValue<Partial<AvatarContextValue>, DOMRefValue<HTMLImageElement>>>(null);

/**
 * An avatar is a thumbnail representation of an entity, such as a user or an organization.
 */
export const Avatar = forwardRef(function Avatar(props: AvatarProps, ref: DOMRef<HTMLImageElement>) {
  [props, ref] = useSpectrumContextProps(props as AvatarContextValue, ref, AvatarContext);
  let domRef = useDOMRef(ref);
  let {
    alt = '',
    src,
    UNSAFE_style,
    UNSAFE_className = '',
    size = 24,
    isOverBackground,
    slot = 'avatar',
    ...otherProps
  } = props;
  let render = (props as AvatarContextValue).render;
  const domProps = filterDOMProps(otherProps);

  let remSize = size / 16 + 'rem';
  let isLarge = size >= 64;

Review comment (suggestion):
I think rather than adding this prop we could just make Avatar have CenterBaseline by default. I can't really think of a case where you'd want to align text with it at the bottom. We may be able to avoid the extra wrapper div as well since Image already has a wrapper div. We could potentially put the `::before` directly on that.

Code after:
   * The size of the avatar.
   * @default 24
   */
  size?: 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 56 | 64 | 80 | 96 | 112 | (number & {}),
  /** Whether the avatar is over a color background. */
  isOverBackground?: boolean
}

const imageStyles = style({
  display: 'flex',
  alignItems: 'center',
  borderRadius: 'full',
  size: 20,
  flexShrink: 0,
  flexGrow: 0,
  disableTapHighlight: true,
  outlineStyle: {
    default: 'none',
    isOverBackground: 'solid'
  },
  outlineColor: '--s2-container-bg',
  outlineWidth: {
    default: 1,
    isLarge: 2
  }
}, getAllowedOverrides({width: false}));

export const AvatarContext = createContext<ContextValue<Partial<AvatarProps>, DOMRefValue<HTMLImageElement>>>(null);

/**
 * An avatar is a thumbnail representation of an entity, such as a user or an organization.
 */
export const Avatar = forwardRef(function Avatar(props: AvatarProps, ref: DOMRef<HTMLImageElement>) {
  [props, ref] = useSpectrumContextProps(props, ref, AvatarContext);
  let domRef = useDOMRef(ref);
  let {
    alt = '',
    src,
    UNSAFE_style,
    UNSAFE_className = '',
    size = 24,
    isOverBackground,
    slot = 'avatar',
    ...otherProps
  } = props;
  const domProps = filterDOMProps(otherProps);

  let remSize = size / 16 + 'rem';
  let isLarge = size >= 64;
  return (
    <Image