Files
René Schober 4e34270786 initial commit
2026-03-13 06:23:06 +01:00

2.5 KiB

title, impact, impactDescription, tags
title impact impactDescription tags
Use Galeria for Image Galleries and Lightbox MEDIUM native shared element transitions, pinch-to-zoom, pan-to-close images, gallery, lightbox, expo-image, ui

Use Galeria for Image Galleries and Lightbox

For image galleries with lightbox (tap to fullscreen), use @nandorojo/galeria. It provides native shared element transitions with pinch-to-zoom, double-tap zoom, and pan-to-close. Works with any image component including expo-image.

Incorrect (custom modal implementation):

function ImageGallery({ urls }: { urls: string[] }) {
  const [selected, setSelected] = useState<string | null>(null);

  return (
    <>
      {urls.map((url) => (
        <Pressable key={url} onPress={() => setSelected(url)}>
          <Image source={{ uri: url }} style={styles.thumbnail} />
        </Pressable>
      ))}
      <Modal visible={!!selected} onRequestClose={() => setSelected(null)}>
        <Image source={{ uri: selected! }} style={styles.fullscreen} />
      </Modal>
    </>
  );
}

Correct (Galeria with expo-image):

import { Galeria } from "@nandorojo/galeria";
import { Image } from "expo-image";

function ImageGallery({ urls }: { urls: string[] }) {
  return (
    <Galeria urls={urls}>
      {urls.map((url, index) => (
        <Galeria.Image index={index} key={url}>
          <Image source={{ uri: url }} style={styles.thumbnail} />
        </Galeria.Image>
      ))}
    </Galeria>
  );
}

Single image:

import { Galeria } from "@nandorojo/galeria";
import { Image } from "expo-image";

function Avatar({ url }: { url: string }) {
  return (
    <Galeria urls={[url]}>
      <Galeria.Image>
        <Image source={{ uri: url }} style={styles.avatar} />
      </Galeria.Image>
    </Galeria>
  );
}

With low-res thumbnails and high-res fullscreen:

<Galeria urls={highResUrls}>
  {lowResUrls.map((url, index) => (
    <Galeria.Image index={index} key={url}>
      <Image source={{ uri: url }} style={styles.thumbnail} />
    </Galeria.Image>
  ))}
</Galeria>

With FlashList:

<Galeria urls={urls}>
  <FlashList
    data={urls}
    renderItem={({ item, index }) => (
      <Galeria.Image index={index}>
        <Image source={{ uri: item }} style={styles.thumbnail} />
      </Galeria.Image>
    )}
    numColumns={3}
    estimatedItemSize={100}
  />
</Galeria>

Works with expo-image, SolitoImage, react-native Image, or any image component.

Reference: Galeria