shadimage
moduix-react
itemavatarsource: ok · hit

Avatar

moduix React Avatar component.

npx shadcn add "https://moduix.dev/r/react/avatar.json"
free

No selection tags yet — empty means no evidence, not lack of support.

Dependencies

Bundle weight · light
ui-primitives@ark-ui/react

Registry dependencies

@moduix-react/foundation

Files3 · source cached 10/14/2026, 11:56:04 AM

src/components/avatar/Avatar.tsx
import { Avatar as AvatarPrimitive, useAvatar, useAvatarContext } from '@ark-ui/react/avatar';
import { clsx } from 'clsx';
import { forwardRef, type ComponentProps, type ComponentRef } from 'react';
import styles from './Avatar.module.css';

type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
type AvatarRootProps = ComponentProps<typeof AvatarPrimitive.Root> & {
  size?: AvatarSize;
};
type AvatarRootProviderProps = ComponentProps<typeof AvatarPrimitive.RootProvider> & {
  size?: AvatarSize;
};

const Avatar = forwardRef<ComponentRef<typeof AvatarPrimitive.Root>, AvatarRootProps>(
  function Avatar({ className, size, ...props }, ref) {
    return (
      <AvatarPrimitive.Root
        ref={ref}
        data-size={size}
        className={clsx(styles.root, className)}
        {...props}
        data-slot="avatar-root"
      />
    );
  },
);

const AvatarRootProvider = forwardRef<
  ComponentRef<typeof AvatarPrimitive.RootProvider>,
  AvatarRootProviderProps
>(function AvatarRootProvider({ className, size, ...props }, ref) {
  return (
    <AvatarPrimitive.RootProvider
      ref={ref}
      className={clsx(styles.root, className)}
      {...props}
      data-size={size}
      data-slot="avatar-root-provider"
    />
  );
});

const AvatarImage = forwardRef<
  ComponentRef<typeof AvatarPrimitive.Image>,
  ComponentProps<typeof AvatarPrimitive.Image>
>(function AvatarImage({ className, ...props }, ref) {
  return (
    <AvatarPrimitive.Image
      ref={ref}
      className={clsx(styles.image, className)}
      {...props}
      data-slot="avatar-image"
    />
  );
});

const AvatarFallback = forwardRef<
  ComponentRef<typeof AvatarPrimitive.Fallback>,
  ComponentProps<typeof AvatarPrimitive.Fallback>
>(function AvatarFallback({ children, className, ...props }, ref) {
  return (
    <AvatarPrimitive.Fallback
      ref={ref}
      className={clsx(styles.fallback, className)}
      {...props}
      data-slot="avatar-fallback"
    >
      {children}
    </AvatarPrimitive.Fallback>
  );
});

const AvatarContext = AvatarPrimitive.Context;

export {
  Avatar,
  AvatarContext,
  AvatarFallback,
  AvatarImage,
  AvatarRootProvider,
  useAvatar,
  useAvatarContext,
};
src/components/avatar/Avatar.module.css
@layer moduix.components {
  .root {
    box-sizing: border-box;
    display: inline-flex;
    width: var(--moduix-avatar-size, var(--moduix-size-md));
    height: var(--moduix-avatar-size, var(--moduix-size-md));
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    position: relative;
    border-radius: var(--moduix-avatar-radius, var(--moduix-radius-full));
    background-color: var(--moduix-avatar-bg, var(--moduix-color-muted));
    color: var(--moduix-avatar-color, var(--moduix-color-foreground));
    font-size: var(--moduix-avatar-font-size, var(--moduix-text-md));
    font-weight: var(--moduix-avatar-font-weight, var(--moduix-weight-medium));
    line-height: var(--moduix-avatar-line-height, var(--moduix-line-height-text-md));
    user-select: none;
    vertical-align: middle;

    &:where([data-size='xs']) {
      --moduix-avatar-size: var(--moduix-size-xs);
      --moduix-avatar-font-size: var(--moduix-text-xs);
      --moduix-avatar-line-height: var(--moduix-line-height-text-xs);
    }

    &:where([data-size='sm']) {
      --moduix-avatar-size: var(--moduix-size-sm);
      --moduix-avatar-font-size: var(--moduix-text-sm);
      --moduix-avatar-line-height: var(--moduix-line-height-text-sm);
    }

    &:where([data-size='lg']) {
      --moduix-avatar-size: var(--moduix-size-lg);
      --moduix-avatar-font-size: var(--moduix-text-lg);
      --moduix-avatar-line-height: var(--moduix-line-height-text-lg);
    }

    &:where([data-size='xl']) {
      --moduix-avatar-size: var(--moduix-size-xl);
      --moduix-avatar-font-size: var(--moduix-text-lg);
      --moduix-avatar-line-height: var(--moduix-line-height-text-lg);
    }
  }

  .image {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: var(--moduix-avatar-image-object-fit, cover);
    object-position: var(--moduix-avatar-image-object-position, center);
    border-radius: inherit;

    &[data-state='hidden'] {
      display: none;
    }
  }

  .fallback {
    box-sizing: border-box;
    display: inline-flex;
    width: 100%;
    height: 100%;
    align-items: center;
    justify-content: center;
    padding: var(--moduix-avatar-fallback-padding, 0);
    background-color: var(
      --moduix-avatar-fallback-bg,
      var(--moduix-avatar-bg, var(--moduix-color-muted))
    );
    color: var(--moduix-avatar-fallback-color, inherit);
    border-radius: inherit;
    line-height: inherit;

    &[data-state='hidden'] {
      display: none;
    }
  }
}
src/components/avatar/index.ts
export * from './Avatar.js';

More from moduix-react

Browse all components in this library →