Files
agent-skills/skills/vercel-react-native-skills/rules/ui-image-gallery.md
Jason Woltje f5792c40be feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories:
- anthropics/skills: 16 (docs, design, MCP, testing)
- obra/superpowers: 14 (TDD, debugging, agents, planning)
- coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth)
- better-auth/skills: 5 (auth patterns)
- vercel-labs/agent-skills: 5 (React, design, Vercel)
- antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo)
- Plus 13 individual skills from various repos

Mosaic Stack is not limited to coding — the Orchestrator and
subagents serve coding, business, design, marketing, writing,
logistics, analysis, and more.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:27:42 -06:00

105 lines
2.5 KiB
Markdown

---
title: Use Galeria for Image Galleries and Lightbox
impact: MEDIUM
impactDescription:
native shared element transitions, pinch-to-zoom, pan-to-close
tags: 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):**
```tsx
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):**
```tsx
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:**
```tsx
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:**
```tsx
<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:**
```tsx
<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](https://github.com/nandorojo/galeria)