Wrapper around the HTML img element, used for displaying images and custom icons.

Importing

The component can be imported via:

import { Image } from '@customerio/pluma-components/react';

Usage

Example image
<Image 
  src="https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300"
  alt="Example image"
  width={300}
  height={200}
/>

Color scheme variants

Pass an array of ImageSource entries as src to render a <picture> with one <source> per entry plus a fallback <img> (the same props you'd otherwise pass — alt, width, sizing, etc. — apply to that fallback <img>).

Each entry accepts:

  • src (required) — the image URL.
  • colorScheme ('light' | 'dark') — translated to a prefers-color-scheme media query when the surrounding PlumaProvider is in 'auto' mode. When the Provider is in an explicit 'light' / 'dark' mode, sources whose colorScheme doesn't match are filtered out (and matching ones drop the media query so they always apply).
  • media — an arbitrary media query (e.g. responsive breakpoints), passed through to the <source> element verbatim.
  • srcSet, sizes, width, height — passed through to the <source> element. If srcSet is omitted, src is used as the source's srcset value.

Entries without a colorScheme (or media) render regardless of scheme — they're treated as unconditional defaults. When picking the fallback <img> src, the component prefers an unconditional entry, otherwise falls back to the first entry.

Note: in Ember, the array form must be passed as the @src arg (<PlumaImage @src={{this.sources}} … />), not as a plain HTML attribute.

Switching by color scheme

Tag entries with colorScheme: 'light' | 'dark' and the matching variant is rendered for the current color scheme.

A landscape that swaps with the system color scheme
<Image
  src={[
    {
      src: 'https://images.unsplash.com/photo-1505144808419-1957a94ca61e?q=80&w=300',
      colorScheme: 'light',
    },
    {
      src: 'https://images.unsplash.com/photo-1419242902214-272b3f66ee7a?q=80&w=300',
      colorScheme: 'dark',
    },
  ]}
  alt="A landscape that swaps with the system color scheme"
  width={300}
  height={200}
/>

Responsive sources

media accepts any media query string, so <source> entries can also be used to swap variants based on viewport size, resolution, etc.

A photo of a dog at different sizes
<Image
  src={[
    {
      src: 'https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=900',
      media: '(min-width: 600px)',
    },
    {
      src: 'https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300',
    },
  ]}
  alt="A photo of a dog at different sizes"
/>

With Icon Sizing

The Image component can leverage predefined icon sizes using the size prop with the icon- prefix:

v2 Icon Sizes (Recommended)

  • icon-v2-sm (16px)
  • icon-v2-md (20px)
  • icon-v2-lg (24px)
  • icon-v2-xl (32px)

v1 Icon Sizes (Deprecated)

⚠️ Deprecated: v1 icon sizing is deprecated and will be removed in a future release. Please migrate to v2 sizing.

  • icon-xxs (12px)
  • icon-xs (14px)
  • icon-sm (16px)
  • icon-md (24px)
  • icon-lg (32px)
  • icon-xl (48px)

v2 Icon Sizing Examples

Example imageExample imageExample imageExample image
<Box display="flex" justifyContent="space-between" width="400px">
  <Image 
    src="https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300"
    alt="Example image"
    size="icon-v2-sm"
    withBoundingBox
  />
  <Image 
    src="https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300"
    alt="Example image"
    size="icon-v2-md"
    withBoundingBox
  />
  <Image 
    src="https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300"
    alt="Example image"
    size="icon-v2-lg"
    withBoundingBox
  />
  <Image 
    src="https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300"
    alt="Example image"
    size="icon-v2-xl"
    withBoundingBox
  />
</Box>

v1 Icon Sizing Examples (Deprecated)

Example imageExample imageExample image
<Box display="flex" justifyContent="space-between" width="400px">
  <Image 
    src="https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300"
    alt="Example image"
    size="icon-sm"
    withBoundingBox
  />
  <Image 
    src="https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300"
    alt="Example image"
    size="icon-md"
    withBoundingBox
  />
  <Image 
    src="https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300"
    alt="Example image"
    size="icon-lg"
    withBoundingBox
  />
</Box>

With Bounding Box

When displaying custom icons or images, use the withBoundingBox prop to add padding that correctly represents the icon's bounding box. Icons are designed on a 24x24 grid with a 2px border, creating a 20x20 inner bounding box. When enabled, this prop automatically calculates the correct padding based on the icon size, ensuring the bounding box scales proportionally.

Note: This prop is intended for custom icons/images. The Icon component handles bounding box spacing automatically and doesn't require this prop.

This is particularly useful when displaying custom icons in components like buttons, where you need consistent spacing that matches the Icon component regardless of the icon size. See the examples above for usage with different icon sizes.

Inline Images

Use the isInline prop to display images inline with text:

This is text with an inline image Example image that appears in the middle of a sentence.
<Box>
  <span>This is text with an inline image </span>
  <Image 
    src="https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300"
    alt="Example image"
    size="icon-sm"
    isInline
  />
  <span> that appears in the middle of a sentence.</span>
</Box>

Object Fit

Use the objectFit prop to control how the image is resized to fit its container:

contain

Example image

cover

Example image

fill

Example image
<Box display="flex" gap="200" flexWrap="wrap">
  <Box>
    <p>contain</p>
    <Image
      src="https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300"
      alt="Example image"
      width={200}
      height={100}
      objectFit="contain"
    />
  </Box>
  <Box>
    <p>cover</p>
    <Image
      src="https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300"
      alt="Example image"
      width={200}
      height={100}
      objectFit="cover"
    />
  </Box>
  <Box>
    <p>fill</p>
    <Image
      src="https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300"
      alt="Example image"
      width={200}
      height={100}
      objectFit="fill"
    />
  </Box>
</Box>

With Box Props

Since Image extends Box, you can use any Box props:

Example image
<Image
  src="https://images.unsplash.com/photo-1605460375648-278bcbd579a6?q=80&w=300"
  alt="Example image"
  my="100"
/>