v0.1 public beta early access on GitHub
Home / Screens / food-food-orders
Screen template

Food Orders Screen

Active/Past switch over order cards — live orders carry pulsing status badge, stage dots, and track action; delivered rows get a reorder button

pro Expo Go ✓ iosandroid gestures: tap · scroll haptics: light · selection
$ npx lumioui add food-food-orders
import { FoodOrdersScreen } from "@/screens/food/food-orders";
Native packages installed6
@lumioui/ui@latestreact-native-safe-area-context@*@lumioui/core@latestreact-native-reanimated@*react-native-svg@*nativewind@*
food/food-orders.tsxsource · yours to edit
import * as React from "react";
import { useState } from "react";
import { FlatList, View } from "react-native";
import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context";
import { Badge, Button, Card, EmptyState, Glass, Icon, Image, SegmentedControl, Separator, Steps, Text } from "@lumioui/ui";
import { LumioMark, Mount, Press, ROW_STAGGER, ROW_STAGGER_CAP, World } from "../shared";
export type FoodOrderStatus = "preparing" | "on-the-way" | "delivered" | "cancelled";

export interface FoodOrder {
  id: string;
  restaurant: string;
  restaurantImageUrl?: string;
  /** "Today, 6:12 PM" — when it was placed. */
  placedAt: string;
  /** Items line — "2× Margherita Verace, 1× Tiramisù". */
  itemsSummary: string;
  itemCount: number;
  total: number;
  status: FoodOrderStatus;
  /** Live orders only — "ETA 6:42 PM". */
  eta?: string;
}

export interface FoodOrdersScreenProps {
  orders?: FoodOrder[];
  currency?: string;
  onBack?: () => void;
  onOrderPress?: (order: FoodOrder) => void;
  onTrackOrder?: (order: FoodOrder) => void;
  onReorder?: (order: FoodOrder) => void;
  onBrowse?: () => void;
}

/** Pinned Unsplash food photography — each id visually verified to show
 *  the named food. */
const FOOD_PHOTOS = {
  pizza: "photo-1513104890138-7c749659a591",
  sushi: "photo-1579871494447-9811cf80d66c",
  burger: "photo-1568901346375-23c9450c58cd",
  tacos: "photo-1551504734-5ee1c4a1479b",
  bowl: "photo-1546069901-ba9599a7e63c",
} as const;

const img = (p: keyof typeof FOOD_PHOTOS) =>
  `https://images.unsplash.com/${FOOD_PHOTOS[p]}?w=200&h=200&fit=crop&q=70&auto=format`;

const fmt = (n: number, currency = "$") =>
  `${currency}${n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;

const DEFAULT_ORDERS: FoodOrder[] = [
  {
    id: "NR-4821",
    restaurant: "Nonna Rosa",
    restaurantImageUrl: img("pizza"),
    placedAt: "Today, 6:12 PM",
    itemsSummary: "Margherita Verace, 2× Spicy Salmon Roll, Tiramisù",
    itemCount: 4,
    total: 46.0,
    status: "on-the-way",
    eta: "ETA 6:42 PM",
  },
  {
    id: "CP-3390",
    restaurant: "Casa Poke",
    restaurantImageUrl: img("bowl"),
    placedAt: "Today, 6:20 PM",
    itemsSummary: "Spicy Tuna Bowl, Edamame, Yuzu Lemonade",
    itemCount: 3,
    total: 21.8,
    status: "preparing",
    eta: "ETA 7:05 PM",
  },
  {
    id: "SK-1207",
    restaurant: "Sakura Handroll Bar",
    restaurantImageUrl: img("sushi"),
    placedAt: "Yesterday, 1:30 PM",
    itemsSummary: "Salmon Nigiri Set, Miso Soup",
    itemCount: 2,
    total: 24.5,
    status: "delivered",
  },
  {
    id: "SS-0964",
    restaurant: "Smoky Stack",
    restaurantImageUrl: img("burger"),
    placedAt: "Sun, 7:45 PM",
    itemsSummary: "Double Smash & Fries, Vanilla Shake",
    itemCount: 2,
    total: 19.9,
    status: "delivered",
  },
  {
    id: "EC-0441",
    restaurant: "El Camino",
    restaurantImageUrl: img("tacos"),
    placedAt: "Sep 18, 8:20 PM",
    itemsSummary: "Al Pastor Trio, Chips & Guac",
    itemCount: 4,
    total: 22.4,
    status: "cancelled",
  },
];

const STATUS_LABEL: Record<FoodOrderStatus, string> = {
  preparing: "Preparing",
  "on-the-way": "On the way",
  delivered: "Delivered",
  cancelled: "Cancelled",
};

const STATUS_VARIANT: Record<FoodOrderStatus, "success" | "neutral" | "destructive"> = {
  preparing: "success",
  "on-the-way": "success",
  delivered: "neutral",
  cancelled: "destructive",
};

const LIVE_STAGES = ["Confirmed", "Preparing", "On the way", "Delivered"];
const isLive = (status: FoodOrderStatus) => status === "preparing" || status === "on-the-way";

/** One order card — restaurant thumb, status badge, items, stage dots for
 *  live orders, track/reorder action. */
function OrderCard({
  order,
  currency,
  onOrderPress,
  onTrackOrder,
  onReorder,
}: {
  order: FoodOrder;
  currency: string;
  onOrderPress?: (order: FoodOrder) => void;
  onTrackOrder?: (order: FoodOrder) => void;
  onReorder?: (order: FoodOrder) => void;
}) {
  const live = isLive(order.status);
  return (
    <Card
      variant="elevated"
      onPress={() => onOrderPress?.(order)}
      accessibilityLabel={`Order ${order.id} from ${order.restaurant}, ${STATUS_LABEL[order.status]}, ${fmt(order.total, currency)}`}
      className="rounded-3xl bg-white dark:bg-[#1A1A20]"
    >
      <Card.Content className="gap-3 p-4">
        <View className="flex-row items-center gap-3">
          <Image
            source={order.restaurantImageUrl ? { uri: order.restaurantImageUrl } : undefined}
            rounded="xl"
            className="h-11 w-11"
            accessibilityLabel={`${order.restaurant} logo`}
          />
          <View className="flex-1">
            <Text variant="small" className="font-semibold" numberOfLines={1}>
              {order.restaurant}
            </Text>
            <Text variant="muted" className="text-xs">
              {order.id} · {order.placedAt}
            </Text>
          </View>
          <Badge
            variant={STATUS_VARIANT[order.status]}
            pulse={live}
            accessibilityLabel={`Status: ${STATUS_LABEL[order.status]}`}
          >
            {STATUS_LABEL[order.status]}
          </Badge>
        </View>

        <Text variant="muted" className="text-xs" numberOfLines={1}>
          {order.itemCount} items — {order.itemsSummary}
        </Text>

        {live ? (
          <Steps
            steps={LIVE_STAGES}
            current={order.status === "preparing" ? 1 : 2}
            variant="dots"
            labels={false}
            interactive={false}
            haptic={false}
            accessibilityLabel={`Order progress: ${STATUS_LABEL[order.status]}`}
          />
        ) : null}

        <Separator />

        <View className="flex-row items-center justify-between">
          <Text variant="small" className="font-semibold tabular-nums">
            {fmt(order.total, currency)}
            {order.eta ? (
              <Text variant="muted" className="text-xs font-normal">
                {"  "}· {order.eta}
              </Text>
            ) : null}
          </Text>
          {live && onTrackOrder ? (
            <Button
              variant="secondary"
              size="sm"
              haptic="light"
              onPress={() => onTrackOrder(order)}
              accessibilityLabel={`Track order ${order.id}`}
              icon={<Icon name="map-pin" size="sm" color="#65A30D" />}
            >
              Track order
            </Button>
          ) : null}
          {!live && onReorder ? (
            <Button
              variant="secondary"
              size="sm"
              haptic="light"
              onPress={() => onReorder(order)}
              accessibilityLabel={`Reorder from ${order.restaurant}`}
              icon={<Icon name="repeat" size="sm" color="secondaryForeground" />}
            >
              Reorder
            </Button>
          ) : null}
        </View>
      </Card.Content>
    </Card>
  );
}
OrderCard.displayName = "OrderCard";

/** FoodOrders — Active/Past switch over order cards: live orders carry a
 *  pulsing status badge, stage dots, and a track action; past orders get
 *  a reorder button. */
export function FoodOrdersScreen({
  orders = DEFAULT_ORDERS,
  currency = "$",
  onBack,
  onOrderPress,
  onTrackOrder,
  onReorder,
  onBrowse,
}: FoodOrdersScreenProps) {
  const insets = useSafeAreaInsets();
  const [tab, setTab] = useState("Active");

  const activeOrders = orders.filter((o) => isLive(o.status));
  const pastOrders = orders.filter((o) => !isLive(o.status));
  const visible = tab === "Active" ? activeOrders : pastOrders;

  return (
    <World primary="#65A30D">
    <SafeAreaView className="flex-1 bg-[#F4F5F9] dark:bg-[#111114]" edges={["top"]}>
      <View pointerEvents="box-none" className="absolute inset-x-4 z-10" style={{ top: insets.top + 8 }}>
        <View className="flex-row items-center justify-between">
          <Glass interactive effect="regular" className="h-11 w-11 items-center justify-center rounded-full">
            <Press
              haptic="light"
              onPress={() => onBack?.()}
              accessibilityRole="button"
              accessibilityLabel="Go back"
              className="h-9 w-9 items-center justify-center"
            >
              <Icon name="chevron-left" size="md" color="foreground" />
            </Press>
          </Glass>
          <View className="h-11 w-11" />
        </View>
        <View pointerEvents="none" className="absolute inset-0 items-center justify-center">
          <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>
        </View>
      </View>

      <View className="px-4 pb-3" style={{ paddingTop: insets.top + 60 }}>
        <SegmentedControl
          options={["Active", "Past"]}
          value={tab}
          onValueChange={setTab}
          accessibilityLabel="Order history filter"
        />
        {/* Live-count caption — "2 on the way" reads better than a bare tab. */}
        <Text variant="muted" className="pt-2 text-xs">
          {activeOrders.length} on the way · {pastOrders.length} past
        </Text>
      </View>

      <FlatList
        data={visible}
        keyExtractor={(order) => order.id}
        contentContainerClassName="gap-4 px-6 pt-1"
        contentContainerStyle={{ paddingBottom: insets.bottom + 32 }}
        showsVerticalScrollIndicator={false}
        ListEmptyComponent={
          <EmptyState
            variant={tab === "Active" ? "default" : "search"}
            title={tab === "Active" ? "No orders on the way" : "No past orders"}
            description={
              tab === "Active"
                ? "When you place an order it shows up here live."
                : "Delivered and cancelled orders land here."
            }
            action={
              tab === "Active" && onBrowse ? (
                <Button variant="secondary" onPress={onBrowse}>
                  Find food
                </Button>
              ) : undefined
            }
            className="pt-24"
          />
        }
        renderItem={({ item, index }) => (
          <Mount delay={Math.min(index * ROW_STAGGER, ROW_STAGGER_CAP)}>
            <OrderCard
              order={item}
              currency={currency}
              onOrderPress={onOrderPress}
              onTrackOrder={onTrackOrder}
              onReorder={onReorder}
            />
          </Mount>
        )}
      />
    </SafeAreaView>
    </World>
  );
}
FoodOrdersScreen.displayName = "FoodOrdersScreen";
agent prompt — paste into Claude Code, Cursor, Devin…
Recreate the "Food Orders Screen" screen in React Native using LumioUI.

Goal: Active/Past switch over order cards — live orders carry pulsing status badge, stage dots, and track action; delivered rows get a reorder button 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 food-food-orders
```

Or pull just the components: `npx lumioui add badge button card empty-state icon image segmented-control separator steps text`

Native packages:
- @lumioui/ui@latest
- react-native-safe-area-context@*
- @lumioui/core@latest
- 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>` ×3

### `card` — Compound surface — header, title, content and footer slots.
- `<Card>` ×1

### `empty-state` — Illustrated placeholder with title, copy and action slot.
- `<EmptyState>` ×1

### `icon` — Lucide icon set mapped to theme colors and sizes.
- `<Icon>` ×3

### `image` — Cached image with placeholder, fallback and aspect handling.
- `<Image>` ×1

### `segmented-control` — iOS 26 segmented picker — glass capsule track with a gliding liquid indicator pill, spring motion + haptics
- `<SegmentedControl>` ×1

### `separator` — Hairline rule with orientation and spacing control.
- `<Separator>` ×1

### `steps` — Horizontal step indicator with numbered or dot markers, check-on-complete pop, and connectors that fill as progress advances
- `<Steps>` ×1

### `text` — Themed type scale from caption to display.
- `<Text>` ×7

## 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/food/food-orders.tsx` exporting FoodOrdersScreen. 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 { FlatList, View } from "react-native";
import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context";
import { Badge, Button, Card, EmptyState, Glass, Icon, Image, SegmentedControl, Separator, Steps, Text } from "@lumioui/ui";
import { LumioMark, Mount, Press, ROW_STAGGER, ROW_STAGGER_CAP, World } from "../shared";
export type FoodOrderStatus = "preparing" | "on-the-way" | "delivered" | "cancelled";

export interface FoodOrder {
  id: string;
  restaurant: string;
  restaurantImageUrl?: string;
  /** "Today, 6:12 PM" — when it was placed. */
  placedAt: string;
  /** Items line — "2× Margherita Verace, 1× Tiramisù". */
  itemsSummary: string;
  itemCount: number;
  total: number;
  status: FoodOrderStatus;
  /** Live orders only — "ETA 6:42 PM". */
  eta?: string;
}

export interface FoodOrdersScreenProps {
  orders?: FoodOrder[];
  currency?: string;
  onBack?: () => void;
  onOrderPress?: (order: FoodOrder) => void;
  onTrackOrder?: (order: FoodOrder) => void;
  onReorder?: (order: FoodOrder) => void;
  onBrowse?: () => void;
}

/** Pinned Unsplash food photography — each id visually verified to show
 *  the named food. */
const FOOD_PHOTOS = {
  pizza: "photo-1513104890138-7c749659a591",
  sushi: "photo-1579871494447-9811cf80d66c",
  burger: "photo-1568901346375-23c9450c58cd",
  tacos: "photo-1551504734-5ee1c4a1479b",
  bowl: "photo-1546069901-ba9599a7e63c",
} as const;

const img = (p: keyof typeof FOOD_PHOTOS) =>
  `https://images.unsplash.com/${FOOD_PHOTOS[p]}?w=200&h=200&fit=crop&q=70&auto=format`;

const fmt = (n: number, currency = "$") =>
  `${currency}${n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;

const DEFAULT_ORDERS: FoodOrder[] = [
  {
    id: "NR-4821",
    restaurant: "Nonna Rosa",
    restaurantImageUrl: img("pizza"),
    placedAt: "Today, 6:12 PM",
    itemsSummary: "Margherita Verace, 2× Spicy Salmon Roll, Tiramisù",
    itemCount: 4,
    total: 46.0,
    status: "on-the-way",
    eta: "ETA 6:42 PM",
  },
  {
    id: "CP-3390",
    restaurant: "Casa Poke",
    restaurantImageUrl: img("bowl"),
    placedAt: "Today, 6:20 PM",
    itemsSummary: "Spicy Tuna Bowl, Edamame, Yuzu Lemonade",
    itemCount: 3,
    total: 21.8,
    status: "preparing",
    eta: "ETA 7:05 PM",
  },
  {
    id: "SK-1207",
    restaurant: "Sakura Handroll Bar",
    restaurantImageUrl: img("sushi"),
    placedAt: "Yesterday, 1:30 PM",
    itemsSummary: "Salmon Nigiri Set, Miso Soup",
    itemCount: 2,
    total: 24.5,
    status: "delivered",
  },
  {
    id: "SS-0964",
    restaurant: "Smoky Stack",
    restaurantImageUrl: img("burger"),
    placedAt: "Sun, 7:45 PM",
    itemsSummary: "Double Smash & Fries, Vanilla Shake",
    itemCount: 2,
    total: 19.9,
    status: "delivered",
  },
  {
    id: "EC-0441",
    restaurant: "El Camino",
    restaurantImageUrl: img("tacos"),
    placedAt: "Sep 18, 8:20 PM",
    itemsSummary: "Al Pastor Trio, Chips & Guac",
    itemCount: 4,
    total: 22.4,
    status: "cancelled",
  },
];

const STATUS_LABEL: Record<FoodOrderStatus, string> = {
  preparing: "Preparing",
  "on-the-way": "On the way",
  delivered: "Delivered",
  cancelled: "Cancelled",
};

const STATUS_VARIANT: Record<FoodOrderStatus, "success" | "neutral" | "destructive"> = {
  preparing: "success",
  "on-the-way": "success",
  delivered: "neutral",
  cancelled: "destructive",
};

const LIVE_STAGES = ["Confirmed", "Preparing", "On the way", "Delivered"];
const isLive = (status: FoodOrderStatus) => status === "preparing" || status === "on-the-way";

/** One order card — restaurant thumb, status badge, items, stage dots for
 *  live orders, track/reorder action. */
function OrderCard({
  order,
  currency,
  onOrderPress,
  onTrackOrder,
  onReorder,
}: {
  order: FoodOrder;
  currency: string;
  onOrderPress?: (order: FoodOrder) => void;
  onTrackOrder?: (order: FoodOrder) => void;
  onReorder?: (order: FoodOrder) => void;
}) {
  const live = isLive(order.status);
  return (
    <Card
      variant="elevated"
      onPress={() => onOrderPress?.(order)}
      accessibilityLabel={`Order ${order.id} from ${order.restaurant}, ${STATUS_LABEL[order.status]}, ${fmt(order.total, currency)}`}
      className="rounded-3xl bg-white dark:bg-[#1A1A20]"
    >
      <Card.Content className="gap-3 p-4">
        <View className="flex-row items-center gap-3">
          <Image
            source={order.restaurantImageUrl ? { uri: order.restaurantImageUrl } : undefined}
            rounded="xl"
            className="h-11 w-11"
            accessibilityLabel={`${order.restaurant} logo`}
          />
          <View className="flex-1">
            <Text variant="small" className="font-semibold" numberOfLines={1}>
              {order.restaurant}
            </Text>
            <Text variant="muted" className="text-xs">
              {order.id} · {order.placedAt}
            </Text>
          </View>
          <Badge
            variant={STATUS_VARIANT[order.status]}
            pulse={live}
            accessibilityLabel={`Status: ${STATUS_LABEL[order.status]}`}
          >
            {STATUS_LABEL[order.status]}
          </Badge>
        </View>

        <Text variant="muted" className="text-xs" numberOfLines={1}>
          {order.itemCount} items — {order.itemsSummary}
        </Text>

        {live ? (
          <Steps
            steps={LIVE_STAGES}
            current={order.status === "preparing" ? 1 : 2}
            variant="dots"
            labels={false}
            interactive={false}
            haptic={false}
            accessibilityLabel={`Order progress: ${STATUS_LABEL[order.status]}`}
          />
        ) : null}

        <Separator />

        <View className="flex-row items-center justify-between">
          <Text variant="small" className="font-semibold tabular-nums">
            {fmt(order.total, currency)}
            {order.eta ? (
              <Text variant="muted" className="text-xs font-normal">
                {"  "}· {order.eta}
              </Text>
            ) : null}
          </Text>
          {live && onTrackOrder ? (
            <Button
              variant="secondary"
              size="sm"
              haptic="light"
              onPress={() => onTrackOrder(order)}
              accessibilityLabel={`Track order ${order.id}`}
              icon={<Icon name="map-pin" size="sm" color="#65A30D" />}
            >
              Track order
            </Button>
          ) : null}
          {!live && onReorder ? (
            <Button
              variant="secondary"
              size="sm"
              haptic="light"
              onPress={() => onReorder(order)}
              accessibilityLabel={`Reorder from ${order.restaurant}`}
              icon={<Icon name="repeat" size="sm" color="secondaryForeground" />}
            >
              Reorder
            </Button>
          ) : null}
        </View>
      </Card.Content>
    </Card>
  );
}
OrderCard.displayName = "OrderCard";

/** FoodOrders — Active/Past switch over order cards: live orders carry a
 *  pulsing status badge, stage dots, and a track action; past orders get
 *  a reorder button. */
export function FoodOrdersScreen({
  orders = DEFAULT_ORDERS,
  currency = "$",
  onBack,
  onOrderPress,
  onTrackOrder,
  onReorder,
  onBrowse,
}: FoodOrdersScreenProps) {
  const insets = useSafeAreaInsets();
  const [tab, setTab] = useState("Active");

  const activeOrders = orders.filter((o) => isLive(o.status));
  const pastOrders = orders.filter((o) => !isLive(o.status));
  const visible = tab === "Active" ? activeOrders : pastOrders;

  return (
    <World primary="#65A30D">
    <SafeAreaView className="flex-1 bg-[#F4F5F9] dark:bg-[#111114]" edges={["top"]}>
      <View pointerEvents="box-none" className="absolute inset-x-4 z-10" style={{ top: insets.top + 8 }}>
        <View className="flex-row items-center justify-between">
          <Glass interactive effect="regular" className="h-11 w-11 items-center justify-center rounded-full">
            <Press
              haptic="light"
              onPress={() => onBack?.()}
              accessibilityRole="button"
              accessibilityLabel="Go back"
              className="h-9 w-9 items-center justify-center"
            >
              <Icon name="chevron-left" size="md" color="foreground" />
            </Press>
          </Glass>
          <View className="h-11 w-11" />
        </View>
        <View pointerEvents="none" className="absolute inset-0 items-center justify-center">
          <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>
        </View>
      </View>

      <View className="px-4 pb-3" style={{ paddingTop: insets.top + 60 }}>
        <SegmentedControl
          options={["Active", "Past"]}
          value={tab}
          onValueChange={setTab}
          accessibilityLabel="Order history filter"
        />
        {/* Live-count caption — "2 on the way" reads better than a bare tab. */}
        <Text variant="muted" className="pt-2 text-xs">
          {activeOrders.length} on the way · {pastOrders.length} past
        </Text>
      </View>

      <FlatList
        data={visible}
        keyExtractor={(order) => order.id}
        contentContainerClassName="gap-4 px-6 pt-1"
        contentContainerStyle={{ paddingBottom: insets.bottom + 32 }}
        showsVerticalScrollIndicator={false}
        ListEmptyComponent={
          <EmptyState
            variant={tab === "Active" ? "default" : "search"}
            title={tab === "Active" ? "No orders on the way" : "No past orders"}
            description={
              tab === "Active"
                ? "When you place an order it shows up here live."
                : "Delivered and cancelled orders land here."
            }
            action={
              tab === "Active" && onBrowse ? (
                <Button variant="secondary" onPress={onBrowse}>
                  Find food
                </Button>
              ) : undefined
            }
            className="pt-24"
          />
        }
        renderItem={({ item, index }) => (
          <Mount delay={Math.min(index * ROW_STAGGER, ROW_STAGGER_CAP)}>
            <OrderCard
              order={item}
              currency={currency}
              onOrderPress={onOrderPress}
              onTrackOrder={onTrackOrder}
              onReorder={onReorder}
            />
          </Mount>
        )}
      />
    </SafeAreaView>
    </World>
  );
}
FoodOrdersScreen.displayName = "FoodOrdersScreen";
```

Screen: https://lumioui.dev/screens/food-food-orders
iPhone 17 · iOS
9:41
Live preview — the real screen via Expo Web · open full ↗