Status filter chips and press-animated order cards with semantic status badges, thumbnail strips with +N more, ETAs, and contextual track/buy-again actions
import * as React from "react";
import { useState } from "react";
import { View, FlatList } from "react-native";
import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context";
import { Badge, Button, Card, EmptyState, Glass, Icon, Image, Separator, Text, type IconName } from "@lumioui/ui";
import { catalogImg, LumioMark, Mount, Press, ROW_STAGGER, ROW_STAGGER_CAP } from "../shared";
import { AnimatedPressable, useHaptic, usePressAnimation } from "@lumioui/core";
export type OrderStatus = "processing" | "in-transit" | "delivered" | "cancelled";
export interface OrderItem {
name: string;
imageUrl?: string;
quantity?: number;
}
export interface Order {
id: string;
date: string;
status: OrderStatus;
items: OrderItem[];
total: number;
currency?: string;
/** e.g. "Arrives Thu, Sep 18" — shown for active orders. */
eta?: string;
}
export interface OrdersScreenProps {
orders?: Order[];
onOrderPress?: (order: Order) => void;
onFilter?: (status: OrderStatus | "all") => void;
onTrack?: (order: Order) => void;
onReorder?: (order: Order) => void;
/** Empty-state action — sends the user back to browsing. */
onBrowse?: () => void;
}
const img = (p: Parameters<typeof catalogImg>[0]) => catalogImg(p, 160, 200);
const DEFAULT_ORDERS: Order[] = [
{
// The parcel the tracking screen opens on — same items and total.
// Confirmed Sep 15 (tracking's first timeline event), arriving Sep 18.
id: "HL-2094",
date: "Sep 15, 2026",
status: "in-transit",
eta: "Arrives Fri, Sep 18",
items: [
{ name: "Structured Wool Overcoat", imageUrl: img("overcoat") },
{ name: "Garment-Dyed Tee", imageUrl: img("tee"), quantity: 2 },
{ name: "Heritage Graphic Tee", imageUrl: img("graphicTee"), quantity: 2 },
],
total: 628.0,
},
{
id: "HL-2077",
date: "Sep 4, 2026",
status: "processing",
eta: "Ships by Sep 12",
items: [{ name: "Court Leather Sneakers", imageUrl: img("sneakers") }],
total: 145.0,
},
{
id: "HL-1982",
date: "Aug 12, 2026",
status: "delivered",
items: [
{ name: "Leather Lace-Up Boots", imageUrl: img("boots") },
{ name: "Cream Knit Poncho", imageUrl: img("poncho") },
],
total: 463.0,
},
{
id: "HL-1904",
date: "Jul 30, 2026",
status: "delivered",
items: [
{ name: "Tailored Check Blazer", imageUrl: img("blazer") },
{ name: "Heritage Graphic Tee", imageUrl: img("graphicTee") },
{ name: "Quilted Puffer Jacket", imageUrl: img("puffer") },
{ name: "Garment-Dyed Tee", imageUrl: img("tee") },
],
total: 681.0,
},
{
id: "HL-1877",
date: "Jul 22, 2026",
status: "cancelled",
items: [{ name: "Garment-Dyed Tee", imageUrl: img("tee") }],
total: 118.0,
},
];
const FILTERS: { key: OrderStatus | "all"; label: string }[] = [
{ key: "all", label: "All" },
{ key: "processing", label: "Processing" },
{ key: "in-transit", label: "In transit" },
{ key: "delivered", label: "Delivered" },
{ key: "cancelled", label: "Cancelled" },
];
const STATUS_META: Record<
OrderStatus,
{ label: string; variant: "warning" | "info" | "success" | "destructive"; icon: IconName }
> = {
// Badge variants ship their own status glyph (warning → alert-triangle,
// info → info-circle) which reads as an error — real carriers use
// neutral state glyphs, so each status pins its own icon.
processing: { label: "Processing", variant: "warning", icon: "clock" },
"in-transit": { label: "In transit", variant: "info", icon: "truck" },
delivered: { label: "Delivered", variant: "success", icon: "check" },
cancelled: { label: "Cancelled", variant: "destructive", icon: "x" },
};
/** Prices always render with two decimals ($628.00). */
const fmt = (n: number, currency = "$") =>
`${currency}${n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
const MAX_THUMBS = 3;
interface OrderCardProps {
order: Order;
index: number;
onPress?: (order: Order) => void;
onTrack?: (order: Order) => void;
onReorder?: (order: Order) => void;
}
function OrderCard({ order, index, onPress, onTrack, onReorder }: OrderCardProps) {
const haptics = useHaptic();
const press = usePressAnimation({ pressedScale: 0.98, fast: true });
const meta = STATUS_META[order.status];
const itemCount = order.items.reduce((s, i) => s + (i.quantity ?? 1), 0);
const extra = order.items.length - MAX_THUMBS;
const showTrack = order.status === "in-transit" || order.status === "processing";
const showReorder = order.status === "delivered" || order.status === "cancelled";
return (
<Mount delay={Math.min(index * ROW_STAGGER, ROW_STAGGER_CAP)}>
<AnimatedPressable
style={press.animatedStyle}
onPressIn={press.onPressIn}
onPressOut={press.onPressOut}
onPress={() => {
haptics.light();
onPress?.(order);
}}
accessibilityRole="button"
accessibilityLabel={`Order ${order.id}, ${meta.label}, total ${fmt(order.total, order.currency)}`}
>
<Card variant="elevated" className="rounded-3xl bg-white dark:bg-[#1A1A20]">
<Card.Content className="gap-3 p-5">
<View className="flex-row items-center justify-between">
<Text variant="small" className="font-semibold">
{order.id}
</Text>
<Badge variant={meta.variant} size="sm" icon={meta.icon}>
{meta.label}
</Badge>
</View>
<View className="flex-row items-center justify-between">
<Text variant="muted">
{order.date} · {itemCount} {itemCount === 1 ? "item" : "items"}
</Text>
{order.eta ? (
<View className="flex-row items-center gap-1">
<Icon name="clock" size="sm" color="mutedForeground" />
<Text variant="muted" className="text-xs">
{order.eta}
</Text>
</View>
) : null}
</View>
{/* Item thumbnails */}
<View className="flex-row items-center gap-2">
{order.items.slice(0, MAX_THUMBS).map((orderItem, i) => (
<Image
key={`${order.id}-${i}`}
source={orderItem.imageUrl ? { uri: orderItem.imageUrl } : undefined}
rounded="xl"
aspectRatio={4 / 5}
className="w-12"
accessibilityLabel={`Photo of ${orderItem.name}`}
/>
))}
{extra > 0 ? (
<Text variant="muted" className="pl-1">
+{extra} more
</Text>
) : null}
</View>
<Separator />
<View className="flex-row items-center justify-between">
<Text variant="small" className="font-semibold tabular-nums">
{fmt(order.total, order.currency)}
</Text>
<View className="flex-row items-center gap-2">
{showTrack ? (
<Button
tone="inverse"
size="sm"
className="bg-[#1B1B26]"
icon={<Icon name="package" size="sm" color="#FFFFFF" />}
onPress={() => onTrack?.(order)}
accessibilityLabel={`Track order ${order.id}`}
>
Track
</Button>
) : null}
{showReorder ? (
<Button
tone="inverse"
size="sm"
className="bg-[#1B1B26]"
icon={<Icon name="repeat" size="sm" color="#FFFFFF" />}
onPress={() => onReorder?.(order)}
accessibilityLabel={`Reorder items from order ${order.id}`}
>
Buy again
</Button>
) : null}
<View className="h-11 justify-center">
<Icon name="chevron-right" size="sm" color="mutedForeground" />
</View>
</View>
</View>
</Card.Content>
</Card>
</AnimatedPressable>
</Mount>
);
}
OrderCard.displayName = "OrderCard";
/** Orders — status filter chips plus order cards with badges, item
* thumbnails, totals, and track/reorder actions. */
export function OrdersScreen({
orders = DEFAULT_ORDERS,
onOrderPress,
onFilter,
onTrack,
onReorder,
onBrowse,
}: OrdersScreenProps) {
const insets = useSafeAreaInsets();
const [filter, setFilter] = useState<OrderStatus | "all">("all");
const pick = (status: OrderStatus | "all") => {
setFilter(status);
// Chip fires haptics.selection() internally — don't double it.
onFilter?.(status);
};
const visible = filter === "all" ? orders : orders.filter((o) => o.status === filter);
return (
<SafeAreaView className="flex-1 bg-[#F4F5F9] dark:bg-[#111114]" edges={["top"]}>
{/* Floating chrome — centered brand/title pill (root screen). */}
<View pointerEvents="none" className="absolute inset-x-4 z-10 items-center" style={{ top: insets.top + 8 }}>
<View className="h-11 flex-row items-center justify-center gap-2 rounded-full pl-3.5 pr-5">
<Glass effect="regular" className="absolute inset-0 rounded-full" />
<LumioMark size={18} />
<Text accessibilityRole="header" className="text-sm font-bold tracking-tight">
Orders
</Text>
<View className="rounded-full bg-[#BEF04C] px-1.5 py-px">
<Text className="text-[10px] font-bold text-[#1B1B26]">{orders.length}</Text>
</View>
</View>
</View>
{/* Underline tabs — the Zomato/District idiom: bare labels, accent
underline on the active one, hairline baseline. */}
<View className="flex-row gap-5 border-b border-border px-6" style={{ paddingTop: insets.top + 56 }}>
{FILTERS.map((f) => {
const active = f.key === filter;
return (
<Press
key={f.key}
haptic="light"
onPress={() => pick(f.key)}
accessibilityRole="tab"
accessibilityLabel={`Filter: ${f.label}`}
accessibilityState={{ selected: active }}
className="min-h-11 justify-center pb-2 pt-1"
>
<Text
className={`text-sm ${active ? "font-semibold text-foreground" : "text-muted-foreground"}`}
>
{f.label}
</Text>
{active ? (
<View className="absolute inset-x-0 bottom-0 h-[2.5px] rounded-full bg-[#65A30D]" />
) : null}
</Press>
);
})}
</View>
<FlatList
data={visible}
keyExtractor={(item) => item.id}
className="flex-1"
contentContainerClassName="gap-4 px-6"
contentContainerStyle={{ paddingBottom: insets.bottom + 16 }}
contentInsetAdjustmentBehavior="automatic"
showsVerticalScrollIndicator={false}
ListEmptyComponent={
<EmptyState
title="No orders"
description={
filter === "all"
? "Orders you place will appear here."
: "No orders in this state. Clear the filter to see everything."
}
action={
filter === "all" ? (
// An empty order book needs somewhere to go — send the
// user back to the store when the host wired browsing.
onBrowse ? (
<Button tone="inverse" className="bg-[#1B1B26]" onPress={onBrowse}>
Continue shopping
</Button>
) : undefined
) : (
<Button tone="inverse" className="bg-[#1B1B26]" onPress={() => pick("all")}>
Clear filter
</Button>
)
}
className="py-20"
/>
}
renderItem={({ item, index }) => (
<OrderCard
order={item}
index={index}
onPress={onOrderPress}
onTrack={onTrack}
onReorder={onReorder}
/>
)}
/>
</SafeAreaView>
);
}
Recreate the "Orders Screen" screen in React Native using LumioUI.
Goal: Status filter chips and press-animated order cards with semantic status badges, thumbnail strips with +N more, ETAs, and contextual track/buy-again actions Match the reference implementation's layout, behavior, and motion exactly — this is a production screen, not a mockup.
## Setup
Fastest path — install the screen plus its component deps:
```bash
npx lumioui add ecommerce-orders
```
Or pull just the components: `npx lumioui add badge button card chip empty-state icon image separator text`
Native packages:
- @lumioui/ui@latest
- @lumioui/core@latest
- react-native-safe-area-context@*
- react-native-reanimated@*
- react-native-svg@*
- nativewind@*
Stack assumptions: Expo SDK 54 / RN 0.81, Reanimated 4, NativeWind v4, TypeScript strict, Expo Go compatible.
## Components — how, where, when
### `badge` — Compact status pill with variants, icons and pulse option.
- `<Badge>` ×1
### `button` — Tactile pill button with press spring, ink wash and async loading.
- `<Button>` ×4
### `card` — Compound surface — header, title, content and footer slots.
- `<Card>` ×1
### `chip` — Compact selectable pill with press scale and ink overlay.
- imported but not rendered directly — likely used through a sibling or as a utility
### `empty-state` — Illustrated placeholder with title, copy and action slot.
- `<EmptyState>` ×1
### `icon` — Lucide icon set mapped to theme colors and sizes.
- `<Icon>` ×4
### `image` — Cached image with placeholder, fallback and aspect handling.
- `<Image>` ×1
### `separator` — Hairline rule with orientation and spacing control.
- `<Separator>` ×1
### `text` — Themed type scale from caption to display.
- `<Text>` ×8
## Conventions (non-negotiable)
- Styling via NativeWind `className` with semantic tokens only: `bg-background`, `text-foreground`, `bg-card`, `text-card-foreground`, `bg-secondary`, `bg-muted`, `text-muted-foreground`, `bg-accent`, `bg-destructive`, `border-border`. Hard-coded colors only inside media overlays (`text-white`, `bg-black/N`).
- Motion via the token presets from `@lumioui/core` (`spring.press`, `spring.surface`, `spring.glide`, `timing.fast`, `timing.slow`, …) — no bespoke spring configs or durations.
- Gate transform motion behind `useReducedMotion()`; keep opacity/color feedback, drop travel and overshoot.
- Haptics via `useHaptic()`: `light` on press, `selection` on toggle/select, `warning` on invalid input. Never import expo-haptics directly.
- Press feedback via `usePressAnimation()` (~0.97 scale), not `activeOpacity` tricks.
- a11y: `accessibilityRole` + `accessibilityLabel` on every control, touch targets ≥44pt.
- Entrance choreography: staggered `Mount` wrappers (delay 0/60/120…) so regions land in sequence instead of popping in at once.
- Wrap the screen in `SafeAreaView`; keep dark mode working via the semantic tokens.
## Deliverable
One file: `screens/ecommerce/orders.tsx` exporting OrdersScreen. Preserve the props interface — the host app wires the callbacks (navigation, submit handlers) through them.
## Reference implementation
The LumioUI source for this screen — reproduce it faithfully:
```tsx
import * as React from "react";
import { useState } from "react";
import { View, FlatList } from "react-native";
import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context";
import { Badge, Button, Card, EmptyState, Glass, Icon, Image, Separator, Text, type IconName } from "@lumioui/ui";
import { catalogImg, LumioMark, Mount, Press, ROW_STAGGER, ROW_STAGGER_CAP } from "../shared";
import { AnimatedPressable, useHaptic, usePressAnimation } from "@lumioui/core";
export type OrderStatus = "processing" | "in-transit" | "delivered" | "cancelled";
export interface OrderItem {
name: string;
imageUrl?: string;
quantity?: number;
}
export interface Order {
id: string;
date: string;
status: OrderStatus;
items: OrderItem[];
total: number;
currency?: string;
/** e.g. "Arrives Thu, Sep 18" — shown for active orders. */
eta?: string;
}
export interface OrdersScreenProps {
orders?: Order[];
onOrderPress?: (order: Order) => void;
onFilter?: (status: OrderStatus | "all") => void;
onTrack?: (order: Order) => void;
onReorder?: (order: Order) => void;
/** Empty-state action — sends the user back to browsing. */
onBrowse?: () => void;
}
const img = (p: Parameters<typeof catalogImg>[0]) => catalogImg(p, 160, 200);
const DEFAULT_ORDERS: Order[] = [
{
// The parcel the tracking screen opens on — same items and total.
// Confirmed Sep 15 (tracking's first timeline event), arriving Sep 18.
id: "HL-2094",
date: "Sep 15, 2026",
status: "in-transit",
eta: "Arrives Fri, Sep 18",
items: [
{ name: "Structured Wool Overcoat", imageUrl: img("overcoat") },
{ name: "Garment-Dyed Tee", imageUrl: img("tee"), quantity: 2 },
{ name: "Heritage Graphic Tee", imageUrl: img("graphicTee"), quantity: 2 },
],
total: 628.0,
},
{
id: "HL-2077",
date: "Sep 4, 2026",
status: "processing",
eta: "Ships by Sep 12",
items: [{ name: "Court Leather Sneakers", imageUrl: img("sneakers") }],
total: 145.0,
},
{
id: "HL-1982",
date: "Aug 12, 2026",
status: "delivered",
items: [
{ name: "Leather Lace-Up Boots", imageUrl: img("boots") },
{ name: "Cream Knit Poncho", imageUrl: img("poncho") },
],
total: 463.0,
},
{
id: "HL-1904",
date: "Jul 30, 2026",
status: "delivered",
items: [
{ name: "Tailored Check Blazer", imageUrl: img("blazer") },
{ name: "Heritage Graphic Tee", imageUrl: img("graphicTee") },
{ name: "Quilted Puffer Jacket", imageUrl: img("puffer") },
{ name: "Garment-Dyed Tee", imageUrl: img("tee") },
],
total: 681.0,
},
{
id: "HL-1877",
date: "Jul 22, 2026",
status: "cancelled",
items: [{ name: "Garment-Dyed Tee", imageUrl: img("tee") }],
total: 118.0,
},
];
const FILTERS: { key: OrderStatus | "all"; label: string }[] = [
{ key: "all", label: "All" },
{ key: "processing", label: "Processing" },
{ key: "in-transit", label: "In transit" },
{ key: "delivered", label: "Delivered" },
{ key: "cancelled", label: "Cancelled" },
];
const STATUS_META: Record<
OrderStatus,
{ label: string; variant: "warning" | "info" | "success" | "destructive"; icon: IconName }
> = {
// Badge variants ship their own status glyph (warning → alert-triangle,
// info → info-circle) which reads as an error — real carriers use
// neutral state glyphs, so each status pins its own icon.
processing: { label: "Processing", variant: "warning", icon: "clock" },
"in-transit": { label: "In transit", variant: "info", icon: "truck" },
delivered: { label: "Delivered", variant: "success", icon: "check" },
cancelled: { label: "Cancelled", variant: "destructive", icon: "x" },
};
/** Prices always render with two decimals ($628.00). */
const fmt = (n: number, currency = "$") =>
`${currency}${n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
const MAX_THUMBS = 3;
interface OrderCardProps {
order: Order;
index: number;
onPress?: (order: Order) => void;
onTrack?: (order: Order) => void;
onReorder?: (order: Order) => void;
}
function OrderCard({ order, index, onPress, onTrack, onReorder }: OrderCardProps) {
const haptics = useHaptic();
const press = usePressAnimation({ pressedScale: 0.98, fast: true });
const meta = STATUS_META[order.status];
const itemCount = order.items.reduce((s, i) => s + (i.quantity ?? 1), 0);
const extra = order.items.length - MAX_THUMBS;
const showTrack = order.status === "in-transit" || order.status === "processing";
const showReorder = order.status === "delivered" || order.status === "cancelled";
return (
<Mount delay={Math.min(index * ROW_STAGGER, ROW_STAGGER_CAP)}>
<AnimatedPressable
style={press.animatedStyle}
onPressIn={press.onPressIn}
onPressOut={press.onPressOut}
onPress={() => {
haptics.light();
onPress?.(order);
}}
accessibilityRole="button"
accessibilityLabel={`Order ${order.id}, ${meta.label}, total ${fmt(order.total, order.currency)}`}
>
<Card variant="elevated" className="rounded-3xl bg-white dark:bg-[#1A1A20]">
<Card.Content className="gap-3 p-5">
<View className="flex-row items-center justify-between">
<Text variant="small" className="font-semibold">
{order.id}
</Text>
<Badge variant={meta.variant} size="sm" icon={meta.icon}>
{meta.label}
</Badge>
</View>
<View className="flex-row items-center justify-between">
<Text variant="muted">
{order.date} · {itemCount} {itemCount === 1 ? "item" : "items"}
</Text>
{order.eta ? (
<View className="flex-row items-center gap-1">
<Icon name="clock" size="sm" color="mutedForeground" />
<Text variant="muted" className="text-xs">
{order.eta}
</Text>
</View>
) : null}
</View>
{/* Item thumbnails */}
<View className="flex-row items-center gap-2">
{order.items.slice(0, MAX_THUMBS).map((orderItem, i) => (
<Image
key={`${order.id}-${i}`}
source={orderItem.imageUrl ? { uri: orderItem.imageUrl } : undefined}
rounded="xl"
aspectRatio={4 / 5}
className="w-12"
accessibilityLabel={`Photo of ${orderItem.name}`}
/>
))}
{extra > 0 ? (
<Text variant="muted" className="pl-1">
+{extra} more
</Text>
) : null}
</View>
<Separator />
<View className="flex-row items-center justify-between">
<Text variant="small" className="font-semibold tabular-nums">
{fmt(order.total, order.currency)}
</Text>
<View className="flex-row items-center gap-2">
{showTrack ? (
<Button
tone="inverse"
size="sm"
className="bg-[#1B1B26]"
icon={<Icon name="package" size="sm" color="#FFFFFF" />}
onPress={() => onTrack?.(order)}
accessibilityLabel={`Track order ${order.id}`}
>
Track
</Button>
) : null}
{showReorder ? (
<Button
tone="inverse"
size="sm"
className="bg-[#1B1B26]"
icon={<Icon name="repeat" size="sm" color="#FFFFFF" />}
onPress={() => onReorder?.(order)}
accessibilityLabel={`Reorder items from order ${order.id}`}
>
Buy again
</Button>
) : null}
<View className="h-11 justify-center">
<Icon name="chevron-right" size="sm" color="mutedForeground" />
</View>
</View>
</View>
</Card.Content>
</Card>
</AnimatedPressable>
</Mount>
);
}
OrderCard.displayName = "OrderCard";
/** Orders — status filter chips plus order cards with badges, item
* thumbnails, totals, and track/reorder actions. */
export function OrdersScreen({
orders = DEFAULT_ORDERS,
onOrderPress,
onFilter,
onTrack,
onReorder,
onBrowse,
}: OrdersScreenProps) {
const insets = useSafeAreaInsets();
const [filter, setFilter] = useState<OrderStatus | "all">("all");
const pick = (status: OrderStatus | "all") => {
setFilter(status);
// Chip fires haptics.selection() internally — don't double it.
onFilter?.(status);
};
const visible = filter === "all" ? orders : orders.filter((o) => o.status === filter);
return (
<SafeAreaView className="flex-1 bg-[#F4F5F9] dark:bg-[#111114]" edges={["top"]}>
{/* Floating chrome — centered brand/title pill (root screen). */}
<View pointerEvents="none" className="absolute inset-x-4 z-10 items-center" style={{ top: insets.top + 8 }}>
<View className="h-11 flex-row items-center justify-center gap-2 rounded-full pl-3.5 pr-5">
<Glass effect="regular" className="absolute inset-0 rounded-full" />
<LumioMark size={18} />
<Text accessibilityRole="header" className="text-sm font-bold tracking-tight">
Orders
</Text>
<View className="rounded-full bg-[#BEF04C] px-1.5 py-px">
<Text className="text-[10px] font-bold text-[#1B1B26]">{orders.length}</Text>
</View>
</View>
</View>
{/* Underline tabs — the Zomato/District idiom: bare labels, accent
underline on the active one, hairline baseline. */}
<View className="flex-row gap-5 border-b border-border px-6" style={{ paddingTop: insets.top + 56 }}>
{FILTERS.map((f) => {
const active = f.key === filter;
return (
<Press
key={f.key}
haptic="light"
onPress={() => pick(f.key)}
accessibilityRole="tab"
accessibilityLabel={`Filter: ${f.label}`}
accessibilityState={{ selected: active }}
className="min-h-11 justify-center pb-2 pt-1"
>
<Text
className={`text-sm ${active ? "font-semibold text-foreground" : "text-muted-foreground"}`}
>
{f.label}
</Text>
{active ? (
<View className="absolute inset-x-0 bottom-0 h-[2.5px] rounded-full bg-[#65A30D]" />
) : null}
</Press>
);
})}
</View>
<FlatList
data={visible}
keyExtractor={(item) => item.id}
className="flex-1"
contentContainerClassName="gap-4 px-6"
contentContainerStyle={{ paddingBottom: insets.bottom + 16 }}
contentInsetAdjustmentBehavior="automatic"
showsVerticalScrollIndicator={false}
ListEmptyComponent={
<EmptyState
title="No orders"
description={
filter === "all"
? "Orders you place will appear here."
: "No orders in this state. Clear the filter to see everything."
}
action={
filter === "all" ? (
// An empty order book needs somewhere to go — send the
// user back to the store when the host wired browsing.
onBrowse ? (
<Button tone="inverse" className="bg-[#1B1B26]" onPress={onBrowse}>
Continue shopping
</Button>
) : undefined
) : (
<Button tone="inverse" className="bg-[#1B1B26]" onPress={() => pick("all")}>
Clear filter
</Button>
)
}
className="py-20"
/>
}
renderItem={({ item, index }) => (
<OrderCard
order={item}
index={index}
onPress={onOrderPress}
onTrack={onTrack}
onReorder={onReorder}
/>
)}
/>
</SafeAreaView>
);
}
```
Screen: https://lumioui.dev/screens/ecommerce-orders