Cached image with placeholder, fallback and aspect handling.
$ npx lumioui add image
import { Image } from "@/components/ui/image/image";
Files installed into your repo
components/ui/image/image.tsx
Native packages required
@lumioui/core@latestreact-native-reanimated@*
Props7
| rounded? | "none" | "sm" | "md" | "lg" | "xl" | "full" | Corner radius preset. |
| aspectRatio? | number | width / height ratio applied via style. |
| fallback? | React.ReactNode | Slot rendered when the image fails to load. |
| hidePlaceholder? | boolean | Hide the loading placeholder. Default false. |
| alt? | string | Alt text for the image — alias for `accessibilityLabel`. When neither is provided the label is left unset so the OS can decide what to announce. |
| className? | string | |
| style? | RNImageProps["style"] | |
Image — Fallbackfallback.tsx
Live preview offline the relay is unreachable — check back shortly
image/variants/fallback.tsx open Cached image with placeholder, fallback and aspect handling.
import { ImageFallback } from "@/components/ui/image/variants/fallback";
export function Example() {
return (
<ImageFallback />
);
}
import * as React from "react";
import { View } from "react-native";
import { Image } from "../image";
import { Icon } from "../../icon/icon";
import { Text } from "../../text/text";
import { Glass } from "../../glass/glass";
/** ImageFallback — custom fallback slot when the source fails. */
export function ImageFallback() {
return (
<View className="w-full gap-3">
<Text variant="small" className="text-white drop-shadow">Error fallback</Text>
<Image
source={{ uri: "https://invalid.lumio.local/missing.jpg" }}
className="h-24 w-full rounded-lg"
accessibilityLabel="Order photo (failed to load)"
fallback={
<Glass interactive curvature="edge" className="flex-1 items-center justify-center gap-1.5 rounded-lg">
<Icon name="eye-off" size="sm" color="mutedForeground" />
<Text variant="muted">Photo unavailable — retry</Text>
</Glass>
}
/>
</View>
);
}
Image — Photophoto.tsx
Live preview offline the relay is unreachable — check back shortly
image/variants/photo.tsx open Cached image with placeholder, fallback and aspect handling.
import { ImagePhoto } from "@/components/ui/image/variants/photo";
export function Example() {
return (
<ImagePhoto />
);
}
import * as React from "react";
import { View } from "react-native";
import { Image } from "../image";
import { Text } from "../../text/text";
import { Glass } from "../../glass/glass";
/** ImagePhoto — full-width photo with caption metadata. */
export function ImagePhoto() {
return (
<View className="w-full gap-3">
<Text variant="small" className="text-white drop-shadow">Kyoto at Dusk — photo by Amara Chen</Text>
<Image
source={{ uri: "https://images.unsplash.com/photo-1545569341-9eb8b30979d9?w=600&h=400&fit=crop&q=70&auto=format" }}
className="h-44 w-full rounded-lg"
rounded="lg"
accessibilityLabel="Kyoto at dusk — photo by Amara Chen"
/>
<Glass interactive curvature="edge" className="self-start rounded-full px-3 py-1.5">
<Text variant="muted">4.2 MB • posted 2m ago • 248 views</Text>
</Glass>
</View>
);
}
Image — Roundedrounded.tsx
Live preview offline the relay is unreachable — check back shortly
image/variants/rounded.tsx open Cached image with placeholder, fallback and aspect handling.
import { ImageRounded } from "@/components/ui/image/variants/rounded";
export function Example() {
return (
<ImageRounded />
);
}
import * as React from "react";
import { View } from "react-native";
import { Image } from "../image";
import { Text } from "../../text/text";
import { Glass } from "../../glass/glass";
/** ImageRounded — radius options on a thumbnail strip. */
export function ImageRounded() {
return (
<View className="w-full gap-3">
<Text variant="small" className="text-white drop-shadow">Lisbon album — rounded variants</Text>
<Glass interactive curvature="edge" className="flex-row gap-2 rounded-2xl p-3">
{/* Pinned Unsplash IDs verified to match their a11y labels. */}
<Image source={{ uri: "https://images.unsplash.com/photo-1768042298555-d9b893fcf31b?w=300&h=300&fit=crop&q=70&auto=format" }} className="flex-1" rounded="sm" aspectRatio={1} accessibilityLabel="Lisbon rooftops" />
<Image source={{ uri: "https://images.unsplash.com/photo-1767357583916-583f50641618?w=300&h=300&fit=crop&q=70&auto=format" }} className="flex-1" rounded="xl" aspectRatio={1} accessibilityLabel="Lisbon tram" />
<Image source={{ uri: "https://images.unsplash.com/photo-1569718212165-3a8278d5f624?w=300&h=300&fit=crop&q=70&auto=format" }} className="flex-1" rounded="full" aspectRatio={1} accessibilityLabel="Ramen bowl" />
</Glass>
</View>
);
}