orn-ui
Atom

Image

Requires <UIProvider> — Getting Started →

Installation

Install just this component (copies the source into your project, no npm dependency)

npx orn-ui add image

Or install the whole package and import it

pnpm add orn-ui
import { Image } from 'orn-ui/image';
Depends on:core (theme + icons)spinner

Usage

  • when to use — Remote images that need a loading and an error state — which is most of them.
  • radius — Same pattern as Avatar/Card. Set it here, not with an overflow wrapper.
  • loading / fallback — What to show while it loads and if it fails. Both accept a node, so an image-shaped skeleton is fine.
  • priority — `high` prefetches on mount — for the above-the-fold image of a screen, not for every item in a list.
Demo clip not recorded yet — see MEDIA.md

Variants

Basic

<Image
  source={{ uri: 'https://picsum.photos/200' }}
  width={120}
  height={120}
  radius={12}
/>

Sizes & radius

<VariantRow>
  <Image source={{ uri: 'https://picsum.photos/200' }} width={48} height={48} radius={24} />
  <Image source={{ uri: 'https://picsum.photos/200' }} width={72} height={72} radius={12} />
  <Image source={{ uri: 'https://picsum.photos/200' }} width={96} height={96} radius={0} />
</VariantRow>

Custom fallback

<Image
  source={{ uri: 'https://example.com/broken.png' }}
  width={120}
  height={120}
  radius={12}
  fallback={<Body style={{ textAlign: 'center', padding: 8 }}>Couldn’t load</Body>}
/>

Above-the-fold (priority="high")

<Image
  source={{ uri: 'https://picsum.photos/400' }}
  width={160}
  height={90}
  radius={8}
  priority="high"
/>
Full demo source
const variants: VariantDef[] = [
  {
    label: 'Basic',
    content: (
      <Image
        source={{ uri: 'https://picsum.photos/200' }}
        width={120}
        height={120}
        radius={12}
      />
    ),
  },
  {
    label: 'Sizes & radius',
    content: (
      <VariantRow>
        <Image source={{ uri: 'https://picsum.photos/200' }} width={48} height={48} radius={24} />
        <Image source={{ uri: 'https://picsum.photos/200' }} width={72} height={72} radius={12} />
        <Image source={{ uri: 'https://picsum.photos/200' }} width={96} height={96} radius={0} />
      </VariantRow>
    ),
  },
  {
    label: 'Custom fallback',
    content: (
      <Image
        source={{ uri: 'https://example.com/broken.png' }}
        width={120}
        height={120}
        radius={12}
        fallback={<Body style={{ textAlign: 'center', padding: 8 }}>Couldn’t load</Body>}
      />
    ),
  },
  {
    label: 'Above-the-fold (priority="high")',
    content: (
      <Image
        source={{ uri: 'https://picsum.photos/400' }}
        width={160}
        height={90}
        radius={8}
        priority="high"
      />
    ),
  },
];
return <VariantList variants={variants} />;

Props

Also accepts testID, forwarded to the root node. It exists for end-to-end tests (Maestro drives the app by the accessibility tree) and has no effect on how the component looks or behaves.

NameTypeDefaultDescription
sourceImageSourcePropType
width?number
height?number
resizeMode?'cover' | 'contain' | 'stretch' | 'repeat' | 'center' | 'none'cover
radius?number0Corner radius, same pattern as Avatar/Card.
loading?ReactNodetrueWhat to show while loading. `false` shows nothing.
fallback?ReactNodea plain grey placeholder, no contentWhat to show if loading fails.
priority?'low' | 'normal' | 'high'normal'high' fires Image.prefetch() on mount, before <Image> starts its own loading cycle — meant for the above-the-fold image of a screen (the first one the user sees). Free if it is already cached.
style?StyleProp<ViewStyle>
onLoadEnd?() => void
onError?(error: NativeSyntheticEvent<ImageErrorEventData>) => void