// Logistics app UI
Delivery Tracking App UI Design in Expo
This delivery tracking app UI gives customers a clear view of every parcel. The home screen shows the current shipment, the list filters by status, and the map screen follows the route to the door.
- Screens
- 3
- Built with
- Expo SDK 58
- Fonts
- Inter
- License
- Free (MIT)
Parcel Delivery Tracking app screens

Shipment home
Delivery address, search, new delivery and track package cards, the current shipment and recent shipments.

My shipping
Status chips filter a list of parcels, each with a route, dates and a box image.

Location tracking
A map with the delivery route above a dark sheet with booking details, parcel data and the courier.
Copy the Parcel Delivery Tracking kit
Use the artifact as a design brief, the skill to generate the UI with an AI agent, or the code to run it right away.
Design artifact
The full design: tokens, screens and source
# Parcel Delivery Tracking: design artifact
This delivery tracking app UI gives customers a clear view of every parcel. The home screen shows the current shipment, the list filters by status, and the map screen follows the route to the door.
- Type: Logistics mobile app UI
- Screens: 3
- Artboard: 390 × 844
- Target: Expo SDK 58, Expo Router, TypeScript, expo-image, react-native-svg
- Live page: https://developermill.com/app-designs/delivery-tracking-app-ui-design
## Design direction
Clean greys and white cards with an ink tab bar, one orange tracking accent and 3D cardboard box imagery.
- Shipment cards with a progress timeline
- Status filters with an empty state
- Route map with a dark details sheet
- Courier card with call and message actions
## Foundations
### Colour
| Token | Hex |
| --- | --- |
| Ink | `#161616` |
| Tracking orange | `#F2683C` |
| Graphite | `#3A3A3A` |
| Steel | `#6B6B6B` |
| Mist | `#F4F4F4` |
| White | `#FFFFFF` |
### Typography
- Typefaces: Inter
- Common sizes (px): 9, 10, 11, 12, 13, 14, 15, 19
### Shape and depth
- Common corner radii (px): 3, 8, 9, 10, 22, 24
- Shadows: `0 4px 12px rgba(0,0,0,0.06)`, `0 12px 30px rgba(0,0,0,0.25)`
## Screens
### 1. Shipment home
Delivery address, search, new delivery and track package cards, the current shipment and recent shipments.
Preview: https://developermill.com/app-designs/delivery-tracking-app-ui-design/home.webp
Copy on this screen:
- Delivery to
- 11/2 Diriyah, Riyadh
- Search shipments
- New
- Delivery
- Track
- Package
- Current Shipment
- See All
- ID: H314315796
- Mac Mini M4 Pro
- Transit
- 4h Away
- 18 Oct 2025
- Estimated 19 Oct 2025
- Diriyah, Riyadh
- Jawhra, Jeddah
- Recent Shipment
- Home
- Shipment
- Tracking
- Profile
### 2. My shipping
Status chips filter a list of parcels, each with a route, dates and a box image.
Preview: https://developermill.com/app-designs/delivery-tracking-app-ui-design/shipping.webp
Copy on this screen:
- My Shipping
- Search shipments
- 4h Away
- 18 Oct 2025
- Estimated 19 Oct 2025
- No shipments in this status yet.
### 3. Location tracking
A map with the delivery route above a dark sheet with booking details, parcel data and the courier.
Preview: https://developermill.com/app-designs/delivery-tracking-app-ui-design/tracking.webp
Copy on this screen:
- Location Tracking
- Booking Id:
- H314315796
- Status
- Transit
- Created, 18 Oct 2025
- Estimated, 19 Oct 2025
- Diriyah, Riyadh
- Jawhra, Jeddah
- From
- To
- Customer
- Ahmad Kawsar
- Order Cost
- $120.00
- Quantity
- 1 Box
- Weight
- 10 Kg
- Khalid Omor
- Courier
## Full source
The original artboards as HTML. Image URLs point at the hosted demo assets.
### Shipment home (Main)
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Home</title>
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#5F5F5F;text-decoration:none}a:hover{color:#161616}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; background: #F4F4F4; font-family: 'Inter', system-ui, sans-serif; color: #161616; position: relative; overflow: hidden; display: flex; flex-direction: column">
<div style="height: 50px; padding: 14px 30px 0; box-sizing: border-box; display: flex; justify-content: space-between; align-items: center; font-size: 15px; font-weight: 600">
<span>9:41</span>
<span style="display: flex; gap: 6px; align-items: center">
<svg aria-hidden="true" width="18" height="12" viewBox="0 0 18 12"><rect x="0" y="8" width="3" height="4" rx="1" fill="#161616"></rect><rect x="5" y="5" width="3" height="7" rx="1" fill="#161616"></rect><rect x="10" y="2" width="3" height="10" rx="1" fill="#161616"></rect><rect x="15" y="0" width="3" height="12" rx="1" fill="#161616"></rect></svg>
<svg aria-hidden="true" width="16" height="12" viewBox="0 0 16 12" fill="none" stroke="#161616" stroke-width="2" stroke-linecap="round"><path d="M1 4.5a10 10 0 0 1 14 0"></path><path d="M4 7.5a6 6 0 0 1 8 0"></path><circle cx="8" cy="10.5" r="1" fill="#161616"></circle></svg>
<svg aria-hidden="true" width="26" height="12" viewBox="0 0 26 12"><rect x="0.5" y="0.5" width="22" height="11" rx="3" fill="none" stroke="#161616" opacity="0.4"></rect><rect x="2" y="2" width="19" height="8" rx="2" fill="#161616"></rect><rect x="24" y="4" width="2" height="4" rx="1" fill="#161616" opacity="0.4"></rect></svg>
</span>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; padding: 12px 20px 0">
<div style="display: flex; align-items: center; gap: 12px">
<div style="width: 44px; height: 44px; border-radius: 22px; background: #FFFFFF; display: flex; align-items: center; justify-content: center">
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#161616" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h11v10H3z"></path><path d="M14 9h4l3 3v4h-7"></path><circle cx="7" cy="17.5" r="1.8"></circle><circle cx="17" cy="17.5" r="1.8"></circle><path d="M1 9h4M1 12h3"></path></svg>
</div>
<div style="display: flex; flex-direction: column; gap: 2px">
<span style="font-size: 11px; color: #6B6B6B">Delivery to</span>
<span style="font-size: 13px; font-weight: 500">11/2 Diriyah, Riyadh</span>
</div>
</div>
<button aria-label="Notifications" style="width: 44px; height: 44px; border-radius: 22px; border: 0; background: #FFFFFF; display: flex; align-items: center; justify-content: center; position: relative; cursor: pointer; padding: 0">
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#161616" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9a6 6 0 0 1 12 0c0 6 2.5 7.5 2.5 7.5h-17S6 15 6 9z"></path><path d="M10 20a2 2 0 0 0 4 0"></path></svg>
<span style="position: absolute; top: 9px; right: 10px; width: 8px; height: 8px; border-radius: 4px; background: #F2683C; border: 1.5px solid #FFFFFF"></span>
</button>
</div>
<div style="display: flex; gap: 10px; padding: 16px 20px 0; align-items: center">
<label style="flex: 1; height: 48px; border-radius: 24px; background: #FFFFFF; display: flex; align-items: center; gap: 10px; padding: 0 18px; box-sizing: border-box">
<svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#6B6B6B" stroke-width="1.8" stroke-linecap="round"><circle cx="11" cy="11" r="7"></circle><path d="M20 20l-3.5-3.5"></path></svg>
<span style="position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0)">Search shipments</span>
<input type="search" placeholder="Search" style="border: 0; outline: 0; background: transparent; font-family: inherit; font-size: 13px; color: #161616; flex: 1; min-width: 0">
</label>
<button aria-label="Scan package" style="width: 48px; height: 48px; border-radius: 24px; border: 0; background: #161616; display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0">
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 8V5a1 1 0 0 1 1-1h3M16 4h3a1 1 0 0 1 1 1v3M20 16v3a1 1 0 0 1-1 1h-3M8 20H5a1 1 0 0 1-1-1v-3"></path><circle cx="12" cy="12" r="3.2"></circle><path d="M8 12h-1M17 12h-1"></path></svg>
</button>
</div>
<div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; padding: 16px 20px 0">
<button style="height: 112px; border-radius: 20px; border: 0; background: #FFFFFF; position: relative; overflow: hidden; text-align: left; padding: 16px; box-sizing: border-box; cursor: pointer; font-family: inherit">
<span style="display: block; font-size: 14px; font-weight: 500; line-height: 1.25; color: #161616; position: relative; z-index: 1">New<br>Delivery</span>
<img src="https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/92e2070a16.jpg" alt="" style="position: absolute; right: -6px; bottom: -4px; width: 104px; height: 104px; object-fit: contain; mix-blend-mode: multiply">
</button>
<a href="Tracking.dc.html" style="height: 112px; border-radius: 20px; background: #FFFFFF; position: relative; overflow: hidden; padding: 16px; box-sizing: border-box; display: block; color: #161616">
<span style="display: block; font-size: 14px; font-weight: 500; line-height: 1.25; position: relative; z-index: 1">Track<br>Package</span>
<img src="https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/08942a69e7.jpg" alt="" style="position: absolute; right: -14px; bottom: -14px; width: 104px; height: 104px; object-fit: contain; mix-blend-mode: multiply">
</a>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; padding: 20px 20px 10px">
<h2 style="margin: 0; font-size: 15px; font-weight: 500">Current Shipment</h2>
<a href="Shipping.dc.html" style="font-size: 12px">See All</a>
</div>
<a href="Tracking.dc.html" style="margin: 0 20px; border-radius: 22px; background: #FFFFFF; padding: 16px; position: relative; overflow: hidden; display: block; color: #161616">
<div style="display: flex; align-items: center; gap: 12px">
<div style="width: 44px; height: 44px; border-radius: 22px; background: #F1F1F1; overflow: hidden; flex-shrink: 0; display: flex; align-items: center; justify-content: center">
<img src="https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/53e440c7dc.jpg" alt="" style="width: 40px; height: 40px; object-fit: contain; mix-blend-mode: multiply">
</div>
<div style="flex: 1; min-width: 0">
<div style="font-size: 19px; font-weight: 500; letter-spacing: -0.2px">ID: H314315796</div>
<div style="font-size: 12px; color: #6B6B6B; margin-top: 2px">Mac Mini M4 Pro</div>
</div>
<span style="align-self: flex-start; font-size: 11px; padding: 6px 12px; border-radius: 14px; background: #F2F2F2; color: #3A3A3A">Transit</span>
</div>
<div style="display: flex; align-items: center; margin-top: 22px; width: 64%; position: relative">
<span style="width: 20px; height: 20px; border-radius: 10px; background: #F2683C; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg aria-hidden="true" width="10" height="10" viewBox="0 0 12 12" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6.2l2.3 2.3 4.7-5"></path></svg></span>
<span style="flex: 1; border-top: 2px dotted #F2683C; margin: 0 4px"></span>
<span style="width: 20px; height: 20px; border-radius: 10px; background: #F2683C; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg aria-hidden="true" width="10" height="10" viewBox="0 0 12 12" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6.2l2.3 2.3 4.7-5"></path></svg></span>
<span style="flex: 1; border-top: 2px dotted #F2683C; margin: 0 4px"></span>
<span style="position: relative; width: 22px; height: 22px; border-radius: 11px; background: #FDE7DE; display: flex; align-items: center; justify-content: center; flex-shrink: 0">
<span style="position: absolute; top: -17px; left: 50%; transform: translateX(-50%); font-size: 9px; white-space: nowrap; color: #3A3A3A">4h Away</span>
<svg aria-hidden="true" width="13" height="13" viewBox="0 0 24 24" fill="#F2683C"><path d="M2 6h12v10H2zM14 9h4l4 4v3h-8z"></path><circle cx="6" cy="18" r="2"></circle><circle cx="17" cy="18" r="2"></circle></svg>
</span>
<span style="flex: 1; border-top: 2px dotted #CFCFCF; margin: 0 4px"></span>
<span style="width: 18px; height: 18px; border-radius: 9px; background: #E3E3E3; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg aria-hidden="true" width="9" height="9" viewBox="0 0 12 12" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6.2l2.3 2.3 4.7-5"></path></svg></span>
</div>
<div style="display: flex; justify-content: space-between; width: 64%; margin-top: 14px; font-size: 10px; color: #6B6B6B">
<span>18 Oct 2025</span><span>Estimated 19 Oct 2025</span>
</div>
<div style="display: flex; justify-content: space-between; width: 64%; margin-top: 4px; font-size: 13px; font-weight: 500">
<span>Diriyah, Riyadh</span><span>Jawhra, Jeddah</span>
</div>
<img src="https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/08942a69e7.jpg" alt="" style="position: absolute; right: -22px; bottom: 4px; width: 118px; height: 118px; object-fit: contain; mix-blend-mode: multiply">
</a>
<div style="flex: 1; margin-top: 16px; background: #FFFFFF; border-radius: 28px 28px 0 0; padding: 10px 20px 0; position: relative">
<div style="width: 36px; height: 4px; border-radius: 2px; background: #E2E2E2; margin: 0 auto 12px"></div>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px">
<h2 style="margin: 0; font-size: 15px; font-weight: 500">Recent Shipment</h2>
<a href="Shipping.dc.html" style="font-size: 12px">See All</a>
</div>
<div style="display: flex; flex-direction: column; gap: 8px">
<sc-for list="{{recent}}" as="item" hint-placeholder-count="3">
<div style="border-radius: 18px; background: #F7F7F7; padding: 12px 14px; display: flex; align-items: center; gap: 12px">
<div style="width: 40px; height: 40px; border-radius: 20px; background: #EDEDED; overflow: hidden; flex-shrink: 0; display: flex; align-items: center; justify-content: center">
<img src="{{item.img}}" alt="" style="width: 36px; height: 36px; object-fit: contain; mix-blend-mode: multiply">
</div>
<div style="flex: 1; min-width: 0">
<div style="font-size: 16px; font-weight: 500">{{item.id}}</div>
<div style="font-size: 11px; color: #6B6B6B; margin-top: 2px">{{item.name}}</div>
</div>
<span style="align-self: flex-start; font-size: 10px; padding: 5px 11px; border-radius: 12px; background: #FFFFFF; color: #3A3A3A">{{item.status}}</span>
</div>
</sc-for>
</div>
</div>
<nav aria-label="Main" style="position: absolute; left: 24px; right: 24px; bottom: 28px; height: 64px; border-radius: 32px; background: #161616; display: flex; align-items: center; justify-content: space-around; padding: 0 8px; box-shadow: 0 12px 30px rgba(0,0,0,0.25)">
<a href="Main.dc.html" aria-current="page" style="display: flex; flex-direction: column; align-items: center; gap: 4px; color: #FFFFFF; font-size: 10px; font-weight: 500; min-width: 48px">
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M4 10.5L12 4l8 6.5V20a1 1 0 0 1-1 1h-5v-6h-4v6H5a1 1 0 0 1-1-1z"></path></svg>Home</a>
<a href="Shipping.dc.html" style="display: flex; flex-direction: column; align-items: center; gap: 4px; color: #A8A8A8; font-size: 10px; min-width: 48px">
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#A8A8A8" stroke-width="1.7" stroke-linejoin="round"><path d="M4 7l8-4 8 4v10l-8 4-8-4z"></path><path d="M4 7l8 4 8-4M12 11v10"></path></svg>Shipment</a>
<button aria-label="New shipment" style="width: 56px; height: 56px; border-radius: 28px; background: #FFFFFF; border: 3px solid #F2683C; display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0">
<svg aria-hidden="true" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#161616" stroke-width="2.2" stroke-linecap="round"><path d="M12 5v14M5 12h14"></path></svg>
</button>
<a href="Tracking.dc.html" style="display: flex; flex-direction: column; align-items: center; gap: 4px; color: #A8A8A8; font-size: 10px; min-width: 48px">
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#A8A8A8" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 9h12v11H4z"></path><path d="M8 9V6h4"></path><circle cx="18.5" cy="5.5" r="2.5"></circle></svg>Tracking</a>
<a href="Main.dc.html" style="display: flex; flex-direction: column; align-items: center; gap: 4px; color: #A8A8A8; font-size: 10px; min-width: 48px">
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#A8A8A8" stroke-width="1.7" stroke-linecap="round"><circle cx="12" cy="8" r="4"></circle><path d="M4 21c1.5-4 4.5-6 8-6s6.5 2 8 6"></path></svg>Profile</a>
</nav>
<div style="position: absolute; bottom: 8px; left: 50%; transform: translateX(-50%); width: 134px; height: 5px; border-radius: 3px; background: #161616"></div>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
return {
recent: [
{ id: 'ID: H314315796', name: 'Mac Mini M4 Pro', status: 'On Process', img: 'https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/53e440c7dc.jpg' },
{ id: 'ID: K37856307', name: 'Sonos Speaker', status: 'Delivered', img: 'https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/62a0adf408.jpg' },
{ id: 'ID: B314315764', name: 'DJI Drone', status: 'Delivered', img: 'https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/e3e9b210df.jpg' }
]
};
}
}
</script>
</body>
</html>
```
### My shipping (Shipping)
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Shipping</title>
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#161616;text-decoration:none}a:hover{color:#000000}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; background: #F4F4F4; font-family: 'Inter', system-ui, sans-serif; color: #161616; position: relative; overflow: hidden; display: flex; flex-direction: column">
<div style="height: 50px; padding: 14px 30px 0; box-sizing: border-box; display: flex; justify-content: space-between; align-items: center; font-size: 15px; font-weight: 600; flex-shrink: 0">
<span>9:41</span>
<span style="display: flex; gap: 6px; align-items: center">
<svg aria-hidden="true" width="18" height="12" viewBox="0 0 18 12"><rect x="0" y="8" width="3" height="4" rx="1" fill="#161616"></rect><rect x="5" y="5" width="3" height="7" rx="1" fill="#161616"></rect><rect x="10" y="2" width="3" height="10" rx="1" fill="#161616"></rect><rect x="15" y="0" width="3" height="12" rx="1" fill="#161616"></rect></svg>
<svg aria-hidden="true" width="16" height="12" viewBox="0 0 16 12" fill="none" stroke="#161616" stroke-width="2" stroke-linecap="round"><path d="M1 4.5a10 10 0 0 1 14 0"></path><path d="M4 7.5a6 6 0 0 1 8 0"></path><circle cx="8" cy="10.5" r="1" fill="#161616"></circle></svg>
<svg aria-hidden="true" width="26" height="12" viewBox="0 0 26 12"><rect x="0.5" y="0.5" width="22" height="11" rx="3" fill="none" stroke="#161616" opacity="0.4"></rect><rect x="2" y="2" width="19" height="8" rx="2" fill="#161616"></rect><rect x="24" y="4" width="2" height="4" rx="1" fill="#161616" opacity="0.4"></rect></svg>
</span>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; padding: 12px 20px 0; flex-shrink: 0">
<a href="Main.dc.html" aria-label="Back" style="width: 44px; height: 44px; border-radius: 22px; background: #FFFFFF; display: flex; align-items: center; justify-content: center">
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#161616" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5M11 6l-6 6 6 6"></path></svg>
</a>
<h1 style="margin: 0; font-size: 19px; font-weight: 500">My Shipping</h1>
<button aria-label="More options" style="width: 44px; height: 44px; border-radius: 22px; border: 0; background: #FFFFFF; display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0">
<svg aria-hidden="true" width="4" height="16" viewBox="0 0 4 16" fill="#161616"><circle cx="2" cy="2" r="1.8"></circle><circle cx="2" cy="8" r="1.8"></circle><circle cx="2" cy="14" r="1.8"></circle></svg>
</button>
</div>
<div style="display: flex; gap: 10px; padding: 16px 20px 0; align-items: center; flex-shrink: 0">
<label style="flex: 1; height: 48px; border-radius: 24px; background: #FFFFFF; display: flex; align-items: center; gap: 10px; padding: 0 18px; box-sizing: border-box">
<svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#6B6B6B" stroke-width="1.8" stroke-linecap="round"><circle cx="11" cy="11" r="7"></circle><path d="M20 20l-3.5-3.5"></path></svg>
<span style="position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0)">Search shipments</span>
<input type="search" placeholder="Search" style="border: 0; outline: 0; background: transparent; font-family: inherit; font-size: 13px; color: #161616; flex: 1; min-width: 0">
</label>
<button aria-label="Scan package" style="width: 48px; height: 48px; border-radius: 24px; border: 0; background: #161616; display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0">
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 8V5a1 1 0 0 1 1-1h3M16 4h3a1 1 0 0 1 1 1v3M20 16v3a1 1 0 0 1-1 1h-3M8 20H5a1 1 0 0 1-1-1v-3"></path><circle cx="12" cy="12" r="3.2"></circle><path d="M8 12h-1M17 12h-1"></path></svg>
</button>
</div>
<div role="tablist" aria-label="Filter shipments" style="display: flex; gap: 8px; padding: 16px 20px 0; flex-shrink: 0">
<sc-for list="{{chips}}" as="chip" hint-placeholder-count="4">
<button role="tab" aria-selected="{{chip.selected}}" onClick="{{chip.pick}}" style="{{chip.style}}">{{chip.label}}</button>
</sc-for>
</div>
<div style="flex: 1; overflow-y: auto; padding: 14px 20px 40px; display: flex; flex-direction: column; gap: 10px">
<sc-for list="{{items}}" as="item" hint-placeholder-count="3">
<a href="Tracking.dc.html" style="border-radius: 22px; background: #FFFFFF; padding: 16px; position: relative; overflow: hidden; display: block; flex-shrink: 0; color: #161616">
<div style="display: flex; align-items: center; gap: 12px">
<div style="width: 44px; height: 44px; border-radius: 22px; background: #F1F1F1; overflow: hidden; flex-shrink: 0; display: flex; align-items: center; justify-content: center">
<img src="{{item.img}}" alt="" style="width: 40px; height: 40px; object-fit: contain; mix-blend-mode: multiply">
</div>
<div style="flex: 1; min-width: 0">
<div style="font-size: 19px; font-weight: 500; letter-spacing: -0.2px">{{item.id}}</div>
<div style="font-size: 12px; color: #6B6B6B; margin-top: 2px">{{item.name}}</div>
</div>
<span style="align-self: flex-start; font-size: 11px; padding: 6px 12px; border-radius: 14px; background: #F2F2F2; color: #3A3A3A">{{item.status}}</span>
</div>
<div style="display: flex; align-items: center; margin-top: 22px; width: 62%">
<span style="width: 20px; height: 20px; border-radius: 10px; background: #F2683C; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg aria-hidden="true" width="10" height="10" viewBox="0 0 12 12" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6.2l2.3 2.3 4.7-5"></path></svg></span>
<span style="flex: 1; border-top: 2px dotted #F2683C; margin: 0 4px"></span>
<span style="width: 20px; height: 20px; border-radius: 10px; background: #F2683C; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg aria-hidden="true" width="10" height="10" viewBox="0 0 12 12" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6.2l2.3 2.3 4.7-5"></path></svg></span>
<span style="flex: 1; border-top: 2px dotted #F2683C; margin: 0 4px"></span>
<span style="position: relative; width: 22px; height: 22px; border-radius: 11px; background: #FDE7DE; display: flex; align-items: center; justify-content: center; flex-shrink: 0">
<span style="position: absolute; top: -17px; left: 50%; transform: translateX(-50%); font-size: 9px; white-space: nowrap; color: #3A3A3A">4h Away</span>
<svg aria-hidden="true" width="13" height="13" viewBox="0 0 24 24" fill="#F2683C"><path d="M2 6h12v10H2zM14 9h4l4 4v3h-8z"></path><circle cx="6" cy="18" r="2"></circle><circle cx="17" cy="18" r="2"></circle></svg>
</span>
<span style="flex: 1; border-top: 2px dotted #CFCFCF; margin: 0 4px"></span>
<span style="width: 18px; height: 18px; border-radius: 9px; background: #E3E3E3; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg aria-hidden="true" width="9" height="9" viewBox="0 0 12 12" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6.2l2.3 2.3 4.7-5"></path></svg></span>
</div>
<div style="display: flex; justify-content: space-between; width: 62%; margin-top: 14px; font-size: 10px; color: #6B6B6B">
<span>18 Oct 2025</span><span>Estimated 19 Oct 2025</span>
</div>
<div style="display: flex; justify-content: space-between; width: 62%; margin-top: 4px; font-size: 13px; font-weight: 500">
<span>{{item.from}}</span><span>{{item.to}}</span>
</div>
<img src="{{item.box}}" alt="" style="position: absolute; right: -20px; bottom: 6px; width: 116px; height: 116px; object-fit: contain; mix-blend-mode: multiply">
</a>
</sc-for>
<sc-if value="{{empty}}" hint-placeholder-val="{{ false }}">
<p style="margin: 40px 0 0; text-align: center; font-size: 13px; color: #6B6B6B">No shipments in this status yet.</p>
</sc-if>
</div>
<div style="position: absolute; bottom: 8px; left: 50%; transform: translateX(-50%); width: 134px; height: 5px; border-radius: 3px; background: #161616"></div>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
constructor(props) {
super(props);
this.state = { filter: 'all' };
}
renderVals() {
const BOX = 'https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/08942a69e7.jpg';
const BOXES = 'https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/a6d91032ce.jpg';
const all = [
{ id: 'ID: D314315783', name: 'Mac Mini M4 Pro', status: 'Transit', from: 'Jawhra, Jeddah', to: 'Diriyah, Riyadh', img: 'https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/53e440c7dc.jpg', box: BOX },
{ id: 'ID: H314315796', name: 'Sonos Speaker', status: 'On Process', from: 'Diriyah, Riyadh', to: 'Jawhra, Jeddah', img: 'https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/62a0adf408.jpg', box: BOXES },
{ id: 'ID: B314315764', name: 'DJI Drone', status: 'Delivered', from: 'Diriyah, Riyadh', to: 'Jawhra, Jeddah', img: 'https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/e3e9b210df.jpg', box: BOX }
];
const defs = [
{ key: 'all', label: 'All Package' },
{ key: 'Transit', label: 'Transit' },
{ key: 'On Process', label: 'On Process' },
{ key: 'Delivered', label: 'Delivered' }
];
const f = this.state.filter;
const base = 'height: 36px; padding: 0 14px; border-radius: 18px; border: 0; font-family: inherit; font-size: 12px; cursor: pointer; white-space: nowrap; ';
const chips = defs.map((d) => ({
label: d.label,
selected: d.key === f ? 'true' : 'false',
style: base + (d.key === f ? 'background: #161616; color: #FFFFFF;' : 'background: #FFFFFF; color: #3A3A3A;'),
pick: () => this.setState({ filter: d.key })
}));
const items = f === 'all' ? all : all.filter((x) => x.status === f);
return { chips, items, empty: items.length === 0 };
}
}
</script>
</body>
</html>
```
### Location tracking (Tracking)
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Location Tracking</title>
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#161616;text-decoration:none}a:hover{color:#000000}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; background: #EEEFF1; font-family: 'Inter', system-ui, sans-serif; color: #161616; position: relative; overflow: hidden">
<svg aria-hidden="true" width="390" height="440" viewBox="0 0 390 440" style="position: absolute; top: 0; left: 0">
<rect width="390" height="440" fill="#EEEFF1"></rect>
<rect x="40" y="170" width="70" height="56" rx="6" fill="#DDE9DC"></rect>
<rect x="232" y="232" width="92" height="64" rx="6" fill="#DDE9DC"></rect>
<rect x="300" y="140" width="60" height="40" rx="6" fill="#DDE9DC"></rect>
<g stroke="#FFFFFF" stroke-width="7" fill="none" stroke-linecap="round">
<path d="M-10 120 L400 100"></path>
<path d="M-10 250 L400 236"></path>
<path d="M-10 360 L400 350"></path>
<path d="M70 0 L80 440"></path>
<path d="M190 0 L196 440"></path>
<path d="M330 0 L322 440"></path>
</g>
<g stroke="#FFFFFF" stroke-width="3.5" fill="none" stroke-linecap="round">
<path d="M-10 60 L400 50"></path>
<path d="M-10 180 L400 168"></path>
<path d="M-10 300 L400 292"></path>
<path d="M-10 410 L400 404"></path>
<path d="M20 0 L28 440"></path>
<path d="M130 0 L136 440"></path>
<path d="M255 0 L260 440"></path>
<path d="M375 0 L370 440"></path>
<path d="M110 230 L200 140"></path>
<path d="M200 300 L300 390"></path>
</g>
<path d="M128 352 L128 318 Q128 304 142 304 L180 304 Q194 304 194 290 L194 240 Q194 226 208 226 L248 226 Q262 226 262 212 L262 176 Q262 162 276 162 L300 162 Q314 162 314 148 L314 122" stroke="#2B2B2B" stroke-width="4" fill="none" stroke-linecap="round" stroke-linejoin="round"></path>
<circle cx="314" cy="112" r="22" fill="#F2683C" opacity="0.18"></circle>
<circle cx="314" cy="112" r="12" fill="#F2683C"></circle>
<circle cx="314" cy="112" r="5" fill="#FFFFFF"></circle>
<circle cx="128" cy="364" r="18" fill="#161616"></circle>
<path d="M128 354 L136 371 L128 367 L120 371 Z" fill="#FFFFFF"></path>
</svg>
<div style="position: relative; height: 50px; padding: 14px 30px 0; box-sizing: border-box; display: flex; justify-content: space-between; align-items: center; font-size: 15px; font-weight: 600">
<span>9:41</span>
<span style="display: flex; gap: 6px; align-items: center">
<svg aria-hidden="true" width="18" height="12" viewBox="0 0 18 12"><rect x="0" y="8" width="3" height="4" rx="1" fill="#161616"></rect><rect x="5" y="5" width="3" height="7" rx="1" fill="#161616"></rect><rect x="10" y="2" width="3" height="10" rx="1" fill="#161616"></rect><rect x="15" y="0" width="3" height="12" rx="1" fill="#161616"></rect></svg>
<svg aria-hidden="true" width="16" height="12" viewBox="0 0 16 12" fill="none" stroke="#161616" stroke-width="2" stroke-linecap="round"><path d="M1 4.5a10 10 0 0 1 14 0"></path><path d="M4 7.5a6 6 0 0 1 8 0"></path><circle cx="8" cy="10.5" r="1" fill="#161616"></circle></svg>
<svg aria-hidden="true" width="26" height="12" viewBox="0 0 26 12"><rect x="0.5" y="0.5" width="22" height="11" rx="3" fill="none" stroke="#161616" opacity="0.4"></rect><rect x="2" y="2" width="19" height="8" rx="2" fill="#161616"></rect><rect x="24" y="4" width="2" height="4" rx="1" fill="#161616" opacity="0.4"></rect></svg>
</span>
</div>
<div style="position: relative; display: flex; align-items: center; justify-content: space-between; padding: 12px 20px 0">
<a href="Main.dc.html" aria-label="Back" style="width: 44px; height: 44px; border-radius: 22px; background: #FFFFFF; display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 12px rgba(0,0,0,0.06)">
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#161616" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5M11 6l-6 6 6 6"></path></svg>
</a>
<h1 style="margin: 0; font-size: 19px; font-weight: 500">Location Tracking</h1>
<button aria-label="More options" style="width: 44px; height: 44px; border-radius: 22px; border: 0; background: #FFFFFF; display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0; box-shadow: 0 4px 12px rgba(0,0,0,0.06)">
<svg aria-hidden="true" width="4" height="16" viewBox="0 0 4 16" fill="#161616"><circle cx="2" cy="2" r="1.8"></circle><circle cx="2" cy="8" r="1.8"></circle><circle cx="2" cy="14" r="1.8"></circle></svg>
</button>
</div>
<section aria-label="Shipment details" style="position: absolute; left: 0; right: 0; bottom: 0; height: 450px; background: #1C1C1C; border-radius: 30px 30px 0 0; color: #FFFFFF; padding: 10px 20px 0; box-sizing: border-box; overflow: hidden">
<div style="width: 36px; height: 4px; border-radius: 2px; background: #FFFFFF; opacity: 0.85; margin: 0 auto 18px"></div>
<div style="display: flex; justify-content: space-between; align-items: flex-start">
<div>
<div style="font-size: 11px; color: #A3A3A3">Booking Id:</div>
<div style="font-size: 20px; font-weight: 500; margin-top: 6px; letter-spacing: -0.2px">H314315796</div>
</div>
<div style="display: flex; flex-direction: column; align-items: flex-end; gap: 6px">
<span style="font-size: 11px; color: #A3A3A3">Status</span>
<span style="font-size: 11px; padding: 6px 12px; border-radius: 14px; background: #333333; color: #FFFFFF">Transit</span>
</div>
</div>
<div style="display: flex; align-items: center; margin-top: 18px">
<span style="width: 18px; height: 18px; border-radius: 9px; background: #FFFFFF; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg aria-hidden="true" width="9" height="9" viewBox="0 0 12 12" fill="none" stroke="#1C1C1C" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6.2l2.3 2.3 4.7-5"></path></svg></span>
<span style="flex: 1; border-top: 2px dotted #5A5A5A; margin: 0 5px"></span>
<span style="width: 16px; height: 16px; border-radius: 8px; background: #4A4A4A; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg aria-hidden="true" width="8" height="8" viewBox="0 0 12 12" fill="none" stroke="#1C1C1C" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6.2l2.3 2.3 4.7-5"></path></svg></span>
<span style="flex: 1; border-top: 2px dotted #5A5A5A; margin: 0 5px"></span>
<span style="width: 16px; height: 16px; border-radius: 8px; background: #4A4A4A; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg aria-hidden="true" width="8" height="8" viewBox="0 0 12 12" fill="none" stroke="#1C1C1C" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6.2l2.3 2.3 4.7-5"></path></svg></span>
<span style="flex: 1; border-top: 2px dotted #5A5A5A; margin: 0 5px"></span>
<span style="width: 16px; height: 16px; border-radius: 8px; background: #4A4A4A; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg aria-hidden="true" width="8" height="8" viewBox="0 0 12 12" fill="none" stroke="#1C1C1C" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6.2l2.3 2.3 4.7-5"></path></svg></span>
</div>
<div style="display: flex; justify-content: space-between; margin-top: 14px; font-size: 10px; color: #A3A3A3">
<span>Created, 18 Oct 2025</span><span>Estimated, 19 Oct 2025</span>
</div>
<div style="display: flex; justify-content: space-between; margin-top: 4px; font-size: 13px; font-weight: 500">
<span>Diriyah, Riyadh</span><span>Jawhra, Jeddah</span>
</div>
<div style="height: 1px; background: #2E2E2E; margin: 16px 0"></div>
<div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 14px; column-gap: 16px; width: 66%">
<div><div style="font-size: 10px; color: #A3A3A3">From</div><div style="font-size: 13px; font-weight: 500; margin-top: 4px">Diriyah, Riyadh</div></div>
<div><div style="font-size: 10px; color: #A3A3A3">To</div><div style="font-size: 13px; font-weight: 500; margin-top: 4px">Jawhra, Jeddah</div></div>
<div><div style="font-size: 10px; color: #A3A3A3">Customer</div><div style="font-size: 13px; font-weight: 500; margin-top: 4px">Ahmad Kawsar</div></div>
<div><div style="font-size: 10px; color: #A3A3A3">Order Cost</div><div style="font-size: 13px; font-weight: 500; margin-top: 4px">$120.00</div></div>
<div><div style="font-size: 10px; color: #A3A3A3">Quantity</div><div style="font-size: 13px; font-weight: 500; margin-top: 4px">1 Box</div></div>
<div><div style="font-size: 10px; color: #A3A3A3">Weight</div><div style="font-size: 13px; font-weight: 500; margin-top: 4px">10 Kg</div></div>
</div>
<div style="position: absolute; right: -18px; top: 238px; width: 132px; height: 132px; border-radius: 26px; background: #F4F4F4; overflow: hidden; display: flex; align-items: center; justify-content: center">
<img src="https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/08942a69e7.jpg" alt="" style="width: 120px; height: 120px; object-fit: contain; mix-blend-mode: multiply">
</div>
<div style="position: absolute; left: 16px; right: 16px; bottom: 30px; height: 68px; border-radius: 34px; background: #2A2A2A; display: flex; align-items: center; gap: 12px; padding: 0 10px 0 10px">
<img src="https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets/a0795f305f.jpg" alt="Khalid Omor, courier" style="width: 46px; height: 46px; border-radius: 23px; object-fit: cover; flex-shrink: 0">
<div style="flex: 1; min-width: 0">
<div style="font-size: 14px; font-weight: 500">Khalid Omor</div>
<div style="font-size: 11px; color: #A3A3A3; margin-top: 2px">Courier</div>
</div>
<button aria-label="Call courier" style="width: 46px; height: 46px; border-radius: 23px; border: 0; background: #F2683C; display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0">
<svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M5 4h4l2 5-2.5 1.5a11 11 0 0 0 5 5L15 13l5 2v4a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2"></path></svg>
</button>
<button aria-label="Message courier" style="width: 46px; height: 46px; border-radius: 23px; border: 0; background: #FFFFFF; display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0">
<svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#161616" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a8 8 0 0 1-11.6 7.1L4 20l1-4.6A8 8 0 1 1 21 12z"></path><path d="M8.5 12h.01M12 12h.01M15.5 12h.01"></path></svg>
</button>
</div>
<div style="position: absolute; bottom: 8px; left: 50%; transform: translateX(-50%); width: 134px; height: 5px; border-radius: 3px; background: #FFFFFF"></div>
</section>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
return {};
}
}
</script>
</body>
</html>
```SKILL.md
Save as .claude/skills/delivery-tracking-app-ui/SKILL.md
--- name: delivery-tracking-app-ui description: Build the Parcel Delivery Tracking mobile app UI in Expo React Native. Use when asked to create a delivery tracking app UI or a new screen in this visual style. --- # Parcel Delivery Tracking app UI Build this logistics app UI in an Expo Router project with TypeScript. Reference: https://developermill.com/app-designs/delivery-tracking-app-ui-design ## Visual direction Clean greys and white cards with an ink tab bar, one orange tracking accent and 3D cardboard box imagery. Keep these signature details: - Shipment cards with a progress timeline - Status filters with an empty state - Route map with a dark details sheet - Courier card with call and message actions ## Set up ```bash npx expo install expo-image react-native-svg @expo-google-fonts/inter expo-font ``` ## Tokens | Name | Hex | | --- | --- | | Ink | `#161616` | | Tracking orange | `#F2683C` | | Graphite | `#3A3A3A` | | Steel | `#6B6B6B` | | Mist | `#F4F4F4` | | White | `#FFFFFF` | - Typefaces: Inter - Text sizes (px): 9, 10, 11, 12, 13, 14, 15, 19 - Corner radii (px): 3, 8, 9, 10, 22, 24 Define these once and reuse them. Do not add new colours. ## Screens 1. **Shipment home.** Delivery address, search, new delivery and track package cards, the current shipment and recent shipments. 2. **My shipping.** Status chips filter a list of parcels, each with a route, dates and a box image. 3. **Location tracking.** A map with the delivery route above a dark sheet with booking details, parcel data and the courier. ## Build rules - Draw each screen on a 390 × 844 artboard and scale it to the device width. - Load each custom font weight by family name with expo-font. Do not set fontWeight with custom fonts. - Draw icons, charts and illustrations with react-native-svg. - Use Pressable with an accessibilityLabel for controls, with at least a 44px target. - Navigate with router.navigate and keep sample data as constants at the top of the file. - Use expo-image with contentFit for photos. ## Done when - All routes are linked and reachable. - Colours, type and radii match the tokens above. - `npx tsc --noEmit` and `npx expo lint` pass. - The layout holds up on small and large phones.
Set up the project
npx create-expo-app@latest delivery-tracking-app --template default cd delivery-tracking-app rm -rf src npx expo install expo-image react-native-svg @expo-google-fonts/inter expo-font
src/app/_layout.tsx
import { Inter_400Regular, Inter_500Medium } from '@expo-google-fonts/inter';
import { useFonts } from 'expo-font';
import { Stack } from 'expo-router';
export default function RootLayout() {
const [fontsLoaded] = useFonts({ Inter_400Regular, Inter_500Medium });
if (!fontsLoaded) return null;
return <Stack screenOptions={{ headerShown: false }} />;
}src/app/index.tsx
import { Image } from 'expo-image';
import { router } from 'expo-router';
import { Pressable, Text, TextInput, View } from 'react-native';
import Svg, { Circle, Path } from 'react-native-svg';
import { Screen } from '@/components/screen';
import { asset } from '@/lib/assets';
const recent = [
{ id: 'ID: H314315796', name: 'Mac Mini M4 Pro', status: 'On Process', img: '53e440c7dc.jpg' },
{ id: 'ID: K37856307', name: 'Sonos Speaker', status: 'Delivered', img: '62a0adf408.jpg' },
{ id: 'ID: B314315764', name: 'DJI Drone', status: 'Delivered', img: 'e3e9b210df.jpg' },
];
export default function MainScreen() {
return (
<Screen background="#F4F4F4" statusBar="dark">
<View style={{ flex: 1 }}>
<View
style={{
height: 50,
paddingTop: 14,
paddingBottom: 0,
paddingHorizontal: 30,
justifyContent: 'space-between',
alignItems: 'center',
flexDirection: 'row',
}}
/>
<View
style={{
alignItems: 'center',
justifyContent: 'space-between',
paddingTop: 12,
paddingBottom: 0,
paddingHorizontal: 20,
flexDirection: 'row',
}}>
<View style={{ alignItems: 'center', gap: 12, flexShrink: 1, flexDirection: 'row' }}>
<View
style={{
width: 44,
height: 44,
borderRadius: 22,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#161616"
strokeWidth="1.7"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M3 6h11v10H3z" />
<Path d="M14 9h4l3 3v4h-7" />
<Circle cx="7" cy="17.5" r="1.8" />
<Circle cx="17" cy="17.5" r="1.8" />
<Path d="M1 9h4M1 12h3" />
</Svg>
</View>
<View style={{ gap: 2, flexShrink: 1 }}>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 11, color: '#6B6B6B' }}>
Delivery to
</Text>
<Text style={{ fontFamily: 'Inter_500Medium', fontSize: 13, color: '#161616' }}>
11/2 Diriyah, Riyadh
</Text>
</View>
</View>
<Pressable
accessibilityRole="button"
accessibilityLabel="Notifications"
style={{
width: 44,
height: 44,
borderRadius: 22,
borderWidth: 0,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#161616"
strokeWidth="1.7"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M6 9a6 6 0 0 1 12 0c0 6 2.5 7.5 2.5 7.5h-17S6 15 6 9z" />
<Path d="M10 20a2 2 0 0 0 4 0" />
</Svg>
<View
style={{
position: 'absolute',
top: 9,
right: 10,
width: 11,
height: 11,
borderRadius: 4,
backgroundColor: '#F2683C',
borderWidth: 1.5,
borderColor: '#FFFFFF',
}}
/>
</Pressable>
</View>
<View
style={{
gap: 10,
paddingTop: 16,
paddingBottom: 0,
paddingHorizontal: 20,
alignItems: 'center',
flexDirection: 'row',
}}>
<View
style={{
flex: 1,
height: 48,
borderRadius: 24,
backgroundColor: '#FFFFFF',
alignItems: 'center',
gap: 10,
paddingVertical: 0,
paddingHorizontal: 18,
flexDirection: 'row',
}}>
<Svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="#6B6B6B"
strokeWidth="1.8"
strokeLinecap="round">
<Circle cx="11" cy="11" r="7" />
<Path d="M20 20l-3.5-3.5" />
</Svg>
<TextInput
placeholder="Search"
placeholderTextColor="#8A8A8A"
style={{
borderWidth: 0,
flex: 1,
minWidth: 0,
fontFamily: 'Inter_400Regular',
fontSize: 13,
color: '#161616',
}}
/>
</View>
<Pressable
accessibilityRole="button"
accessibilityLabel="Scan package"
style={{
width: 48,
height: 48,
borderRadius: 24,
borderWidth: 0,
backgroundColor: '#161616',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M4 8V5a1 1 0 0 1 1-1h3M16 4h3a1 1 0 0 1 1 1v3M20 16v3a1 1 0 0 1-1 1h-3M8 20H5a1 1 0 0 1-1-1v-3" />
<Circle cx="12" cy="12" r="3.2" />
<Path d="M8 12h-1M17 12h-1" />
</Svg>
</Pressable>
</View>
<View
style={{
paddingTop: 16,
paddingBottom: 0,
paddingHorizontal: 20,
flexDirection: 'row',
gap: 10,
}}>
<Pressable
accessibilityRole="button"
style={{
height: 112,
borderRadius: 20,
borderWidth: 0,
backgroundColor: '#FFFFFF',
overflow: 'hidden',
padding: 16,
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}>
<Text
style={{
zIndex: 1,
fontFamily: 'Inter_500Medium',
fontSize: 14,
color: '#161616',
lineHeight: 17.5,
textAlign: 'left',
}}>
New{'\n'}Delivery
</Text>
<Image
source={{ uri: asset('92e2070a16.jpg') }}
contentFit="contain"
style={{
position: 'absolute',
right: -6,
bottom: -4,
width: 104,
height: 104,
mixBlendMode: 'multiply',
}}
/>
</Pressable>
<Pressable
accessibilityRole="link"
onPress={() => router.navigate('/tracking')}
style={{
height: 112,
borderRadius: 20,
backgroundColor: '#FFFFFF',
overflow: 'hidden',
padding: 16,
flex: 1,
}}>
<Text
style={{
zIndex: 1,
fontFamily: 'Inter_500Medium',
fontSize: 14,
color: '#161616',
lineHeight: 17.5,
}}>
Track{'\n'}Package
</Text>
<Image
source={{ uri: asset('08942a69e7.jpg') }}
contentFit="contain"
style={{
position: 'absolute',
right: -14,
bottom: -14,
width: 104,
height: 104,
mixBlendMode: 'multiply',
}}
/>
</Pressable>
</View>
<View
style={{
justifyContent: 'space-between',
alignItems: 'center',
paddingTop: 20,
paddingBottom: 10,
paddingHorizontal: 20,
flexDirection: 'row',
}}>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'Inter_500Medium',
fontSize: 15,
color: '#161616',
}}>
Current Shipment
</Text>
<Pressable
accessibilityRole="link"
onPress={() => router.navigate('/shipping')}
style={{ flexShrink: 1 }}>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 12, color: '#5F5F5F' }}>
See All
</Text>
</Pressable>
</View>
<Pressable
accessibilityRole="link"
onPress={() => router.navigate('/tracking')}
style={{
marginVertical: 0,
marginHorizontal: 20,
borderRadius: 22,
backgroundColor: '#FFFFFF',
padding: 16,
overflow: 'hidden',
}}>
<View style={{ alignItems: 'center', gap: 12, flexDirection: 'row' }}>
<View
style={{
width: 44,
height: 44,
borderRadius: 22,
backgroundColor: '#F1F1F1',
overflow: 'hidden',
flexShrink: 0,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Image
source={{ uri: asset('53e440c7dc.jpg') }}
contentFit="contain"
style={{ width: 40, height: 40, mixBlendMode: 'multiply' }}
/>
</View>
<View style={{ flex: 1, minWidth: 0 }}>
<Text
style={{
fontFamily: 'Inter_500Medium',
fontSize: 19,
color: '#161616',
letterSpacing: -0.2,
}}>
ID: H314315796
</Text>
<Text
style={{
marginTop: 2,
fontFamily: 'Inter_400Regular',
fontSize: 12,
color: '#6B6B6B',
}}>
Mac Mini M4 Pro
</Text>
</View>
<Text
style={{
alignSelf: 'flex-start',
paddingVertical: 6,
paddingHorizontal: 12,
borderRadius: 14,
backgroundColor: '#F2F2F2',
flexShrink: 1,
fontFamily: 'Inter_400Regular',
fontSize: 11,
color: '#3A3A3A',
}}>
Transit
</Text>
</View>
<View style={{ alignItems: 'center', marginTop: 22, width: '64%', flexDirection: 'row' }}>
<View
style={{
width: 20,
height: 20,
borderRadius: 10,
backgroundColor: '#F2683C',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Svg
width="10"
height="10"
viewBox="0 0 12 12"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M2.5 6.2l2.3 2.3 4.7-5" />
</Svg>
</View>
<View
style={{
flex: 1,
borderTopWidth: 2,
borderTopColor: '#F2683C',
borderStyle: 'dotted',
marginVertical: 0,
marginHorizontal: 4,
}}
/>
<View
style={{
width: 20,
height: 20,
borderRadius: 10,
backgroundColor: '#F2683C',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Svg
width="10"
height="10"
viewBox="0 0 12 12"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M2.5 6.2l2.3 2.3 4.7-5" />
</Svg>
</View>
<View
style={{
flex: 1,
borderTopWidth: 2,
borderTopColor: '#F2683C',
borderStyle: 'dotted',
marginVertical: 0,
marginHorizontal: 4,
}}
/>
<View
style={{
width: 22,
height: 22,
borderRadius: 11,
backgroundColor: '#FDE7DE',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Text
numberOfLines={1}
style={{
position: 'absolute',
top: -17,
left: '50%',
transform: [{ translateX: '-50%' }],
zIndex: 1,
fontFamily: 'Inter_400Regular',
fontSize: 9,
color: '#3A3A3A',
flexShrink: 1,
}}>
4h Away
</Text>
<Svg width="13" height="13" viewBox="0 0 24 24" fill="#F2683C">
<Path d="M2 6h12v10H2zM14 9h4l4 4v3h-8z" />
<Circle cx="6" cy="18" r="2" />
<Circle cx="17" cy="18" r="2" />
</Svg>
</View>
<View
style={{
flex: 1,
borderTopWidth: 2,
borderTopColor: '#CFCFCF',
borderStyle: 'dotted',
marginVertical: 0,
marginHorizontal: 4,
}}
/>
<View
style={{
width: 18,
height: 18,
borderRadius: 9,
backgroundColor: '#E3E3E3',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Svg
width="9"
height="9"
viewBox="0 0 12 12"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M2.5 6.2l2.3 2.3 4.7-5" />
</Svg>
</View>
</View>
<View
style={{
justifyContent: 'space-between',
width: '64%',
marginTop: 14,
flexDirection: 'row',
}}>
<Text
style={{
flexShrink: 1,
fontFamily: 'Inter_400Regular',
fontSize: 10,
color: '#6B6B6B',
}}>
18 Oct 2025
</Text>
<Text
style={{
flexShrink: 1,
fontFamily: 'Inter_400Regular',
fontSize: 10,
color: '#6B6B6B',
}}>
Estimated 19 Oct 2025
</Text>
</View>
<View
style={{
justifyContent: 'space-between',
width: '64%',
marginTop: 4,
flexDirection: 'row',
}}>
<Text
style={{
flexShrink: 1,
fontFamily: 'Inter_500Medium',
fontSize: 13,
color: '#161616',
}}>
Diriyah, Riyadh
</Text>
<Text
style={{
flexShrink: 1,
fontFamily: 'Inter_500Medium',
fontSize: 13,
color: '#161616',
}}>
Jawhra, Jeddah
</Text>
</View>
<Image
source={{ uri: asset('08942a69e7.jpg') }}
contentFit="contain"
style={{
position: 'absolute',
right: -22,
bottom: 4,
width: 118,
height: 118,
mixBlendMode: 'multiply',
}}
/>
</Pressable>
<View
style={{
flex: 1,
marginTop: 16,
backgroundColor: '#FFFFFF',
borderTopLeftRadius: 28,
borderTopRightRadius: 28,
borderBottomRightRadius: 0,
borderBottomLeftRadius: 0,
paddingTop: 10,
paddingBottom: 0,
paddingHorizontal: 20,
}}>
<View
style={{
width: 36,
height: 4,
borderRadius: 2,
backgroundColor: '#E2E2E2',
marginTop: 0,
marginBottom: 12,
marginHorizontal: 'auto',
}}
/>
<View
style={{
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 10,
flexDirection: 'row',
}}>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'Inter_500Medium',
fontSize: 15,
color: '#161616',
}}>
Recent Shipment
</Text>
<Pressable
accessibilityRole="link"
onPress={() => router.navigate('/shipping')}
style={{ flexShrink: 1 }}>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 12, color: '#5F5F5F' }}>
See All
</Text>
</Pressable>
</View>
<View style={{ gap: 8 }}>
{recent.map((item, index) => (
<View
key={index}
style={{
borderRadius: 18,
backgroundColor: '#F7F7F7',
paddingVertical: 12,
paddingHorizontal: 14,
alignItems: 'center',
gap: 12,
flexDirection: 'row',
}}>
<View
style={{
width: 40,
height: 40,
borderRadius: 20,
backgroundColor: '#EDEDED',
overflow: 'hidden',
flexShrink: 0,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Image
source={{ uri: asset(item.img) }}
contentFit="contain"
style={{ width: 36, height: 36, mixBlendMode: 'multiply' }}
/>
</View>
<View style={{ flex: 1, minWidth: 0 }}>
<Text style={{ fontFamily: 'Inter_500Medium', fontSize: 16, color: '#161616' }}>
{item.id}
</Text>
<Text
style={{
marginTop: 2,
fontFamily: 'Inter_400Regular',
fontSize: 11,
color: '#6B6B6B',
}}>
{item.name}
</Text>
</View>
<Text
style={{
alignSelf: 'flex-start',
paddingVertical: 5,
paddingHorizontal: 11,
borderRadius: 12,
backgroundColor: '#FFFFFF',
flexShrink: 1,
fontFamily: 'Inter_400Regular',
fontSize: 10,
color: '#3A3A3A',
}}>
{item.status}
</Text>
</View>
))}
</View>
</View>
<View
style={{
position: 'absolute',
left: 24,
right: 24,
bottom: 28,
height: 64,
borderRadius: 32,
backgroundColor: '#161616',
alignItems: 'center',
justifyContent: 'space-around',
paddingVertical: 0,
paddingHorizontal: 8,
boxShadow: '0 12px 30px rgba(0,0,0,0.25)',
flexDirection: 'row',
}}>
<Pressable
accessibilityRole="link"
onPress={() => router.navigate('/')}
style={{ alignItems: 'center', gap: 4, minWidth: 48, flexShrink: 1 }}>
<Svg width="20" height="20" viewBox="0 0 24 24" fill="#FFFFFF">
<Path d="M4 10.5L12 4l8 6.5V20a1 1 0 0 1-1 1h-5v-6h-4v6H5a1 1 0 0 1-1-1z" />
</Svg>
<Text style={{ fontFamily: 'Inter_500Medium', fontSize: 10, color: '#FFFFFF' }}>
Home
</Text>
</Pressable>
<Pressable
accessibilityRole="link"
onPress={() => router.navigate('/shipping')}
style={{ alignItems: 'center', gap: 4, minWidth: 48, flexShrink: 1 }}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#A8A8A8"
strokeWidth="1.7"
strokeLinejoin="round">
<Path d="M4 7l8-4 8 4v10l-8 4-8-4z" />
<Path d="M4 7l8 4 8-4M12 11v10" />
</Svg>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 10, color: '#A8A8A8' }}>
Shipment
</Text>
</Pressable>
<Pressable
accessibilityRole="button"
accessibilityLabel="New shipment"
style={{
width: 56,
height: 56,
borderRadius: 28,
backgroundColor: '#FFFFFF',
borderWidth: 3,
borderColor: '#F2683C',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
stroke="#161616"
strokeWidth="2.2"
strokeLinecap="round">
<Path d="M12 5v14M5 12h14" />
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
onPress={() => router.navigate('/tracking')}
style={{ alignItems: 'center', gap: 4, minWidth: 48, flexShrink: 1 }}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#A8A8A8"
strokeWidth="1.7"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M4 9h12v11H4z" />
<Path d="M8 9V6h4" />
<Circle cx="18.5" cy="5.5" r="2.5" />
</Svg>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 10, color: '#A8A8A8' }}>
Tracking
</Text>
</Pressable>
<Pressable
accessibilityRole="link"
onPress={() => router.navigate('/')}
style={{ alignItems: 'center', gap: 4, minWidth: 48, flexShrink: 1 }}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#A8A8A8"
strokeWidth="1.7"
strokeLinecap="round">
<Circle cx="12" cy="8" r="4" />
<Path d="M4 21c1.5-4 4.5-6 8-6s6.5 2 8 6" />
</Svg>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 10, color: '#A8A8A8' }}>
Profile
</Text>
</Pressable>
</View>
</View>
</Screen>
);
}src/app/shipping.tsx
import { Image } from 'expo-image';
import { router } from 'expo-router';
import { useState } from 'react';
import { Pressable, ScrollView, Text, TextInput, View } from 'react-native';
import Svg, { Circle, Path } from 'react-native-svg';
import { Screen } from '@/components/screen';
import { asset } from '@/lib/assets';
import { css, cssText } from '@/lib/css';
// Screen state, and the values the layout below reads from it.
function useScreen() {
const [state, setScreenState] = useState<Record<string, any>>({ filter: 'all' });
const setState = (patch: Record<string, any>) =>
setScreenState((current) => ({ ...current, ...patch }));
const BOX = '08942a69e7.jpg';
const BOXES = 'a6d91032ce.jpg';
const all = [
{
id: 'ID: D314315783',
name: 'Mac Mini M4 Pro',
status: 'Transit',
from: 'Jawhra, Jeddah',
to: 'Diriyah, Riyadh',
img: '53e440c7dc.jpg',
box: BOX,
},
{
id: 'ID: H314315796',
name: 'Sonos Speaker',
status: 'On Process',
from: 'Diriyah, Riyadh',
to: 'Jawhra, Jeddah',
img: '62a0adf408.jpg',
box: BOXES,
},
{
id: 'ID: B314315764',
name: 'DJI Drone',
status: 'Delivered',
from: 'Diriyah, Riyadh',
to: 'Jawhra, Jeddah',
img: 'e3e9b210df.jpg',
box: BOX,
},
];
const defs = [
{ key: 'all', label: 'All Package' },
{ key: 'Transit', label: 'Transit' },
{ key: 'On Process', label: 'On Process' },
{ key: 'Delivered', label: 'Delivered' },
];
const f = state.filter;
const base =
'height: 36px; padding: 0 14px; border-radius: 18px; border: 0; font-family: inherit; font-size: 12px; cursor: pointer; white-space: nowrap; ';
const chips = defs.map((d) => ({
label: d.label,
selected: d.key === f ? 'true' : 'false',
style:
base +
(d.key === f
? 'background: #161616; color: #FFFFFF;'
: 'background: #FFFFFF; color: #3A3A3A;'),
pick: () => setState({ filter: d.key }),
}));
const items = f === 'all' ? all : all.filter((x) => x.status === f);
return { chips, items, empty: items.length === 0 };
}
export default function ShippingScreen() {
const { chips, items, empty } = useScreen();
return (
<Screen background="#F4F4F4" statusBar="dark">
<View style={{ flex: 1 }}>
<View
style={{
height: 50,
paddingTop: 14,
paddingBottom: 0,
paddingHorizontal: 30,
justifyContent: 'space-between',
alignItems: 'center',
flexShrink: 0,
flexDirection: 'row',
}}
/>
<View
style={{
alignItems: 'center',
justifyContent: 'space-between',
paddingTop: 12,
paddingBottom: 0,
paddingHorizontal: 20,
flexShrink: 0,
flexDirection: 'row',
}}>
<Pressable
accessibilityRole="link"
accessibilityLabel="Back"
onPress={() => router.navigate('/')}
style={{
width: 44,
height: 44,
borderRadius: 22,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#161616"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M19 12H5M11 6l-6 6 6 6" />
</Svg>
</Pressable>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'Inter_500Medium',
fontSize: 19,
color: '#161616',
}}>
My Shipping
</Text>
<Pressable
accessibilityRole="button"
accessibilityLabel="More options"
style={{
width: 44,
height: 44,
borderRadius: 22,
borderWidth: 0,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg width="4" height="16" viewBox="0 0 4 16" fill="#161616">
<Circle cx="2" cy="2" r="1.8" />
<Circle cx="2" cy="8" r="1.8" />
<Circle cx="2" cy="14" r="1.8" />
</Svg>
</Pressable>
</View>
<View
style={{
gap: 10,
paddingTop: 16,
paddingBottom: 0,
paddingHorizontal: 20,
alignItems: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<View
style={{
flex: 1,
height: 48,
borderRadius: 24,
backgroundColor: '#FFFFFF',
alignItems: 'center',
gap: 10,
paddingVertical: 0,
paddingHorizontal: 18,
flexDirection: 'row',
}}>
<Svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="#6B6B6B"
strokeWidth="1.8"
strokeLinecap="round">
<Circle cx="11" cy="11" r="7" />
<Path d="M20 20l-3.5-3.5" />
</Svg>
<TextInput
placeholder="Search"
placeholderTextColor="#8A8A8A"
style={{
borderWidth: 0,
flex: 1,
minWidth: 0,
fontFamily: 'Inter_400Regular',
fontSize: 13,
color: '#161616',
}}
/>
</View>
<Pressable
accessibilityRole="button"
accessibilityLabel="Scan package"
style={{
width: 48,
height: 48,
borderRadius: 24,
borderWidth: 0,
backgroundColor: '#161616',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M4 8V5a1 1 0 0 1 1-1h3M16 4h3a1 1 0 0 1 1 1v3M20 16v3a1 1 0 0 1-1 1h-3M8 20H5a1 1 0 0 1-1-1v-3" />
<Circle cx="12" cy="12" r="3.2" />
<Path d="M8 12h-1M17 12h-1" />
</Svg>
</Pressable>
</View>
<View
style={{
gap: 8,
paddingTop: 16,
paddingBottom: 0,
paddingHorizontal: 20,
flexShrink: 0,
flexDirection: 'row',
}}>
{chips.map((chip, index) => (
<Pressable
key={index}
accessibilityRole="button"
onPress={chip.pick}
style={{
flexShrink: 1,
alignItems: 'center',
justifyContent: 'center',
...css(chip.style),
}}>
<Text
style={[
{
fontFamily: 'Inter_400Regular',
fontSize: 13.33,
color: '#000000',
textAlign: 'center',
},
cssText(chip.style),
]}>
{chip.label}
</Text>
</Pressable>
))}
</View>
<ScrollView
showsVerticalScrollIndicator={false}
contentContainerStyle={{ gap: 10, paddingHorizontal: 20, paddingBottom: 40 }}
style={{ flex: 1, paddingTop: 14 }}>
{items.map((item, index) => (
<Pressable
key={index}
accessibilityRole="link"
onPress={() => router.navigate('/tracking')}
style={{
borderRadius: 22,
backgroundColor: '#FFFFFF',
padding: 16,
overflow: 'hidden',
flexShrink: 0,
}}>
<View style={{ alignItems: 'center', gap: 12, flexDirection: 'row' }}>
<View
style={{
width: 44,
height: 44,
borderRadius: 22,
backgroundColor: '#F1F1F1',
overflow: 'hidden',
flexShrink: 0,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Image
source={{ uri: asset(item.img) }}
contentFit="contain"
style={{ width: 40, height: 40, mixBlendMode: 'multiply' }}
/>
</View>
<View style={{ flex: 1, minWidth: 0 }}>
<Text
style={{
fontFamily: 'Inter_500Medium',
fontSize: 19,
color: '#161616',
letterSpacing: -0.2,
}}>
{item.id}
</Text>
<Text
style={{
marginTop: 2,
fontFamily: 'Inter_400Regular',
fontSize: 12,
color: '#6B6B6B',
}}>
{item.name}
</Text>
</View>
<Text
style={{
alignSelf: 'flex-start',
paddingVertical: 6,
paddingHorizontal: 12,
borderRadius: 14,
backgroundColor: '#F2F2F2',
flexShrink: 1,
fontFamily: 'Inter_400Regular',
fontSize: 11,
color: '#3A3A3A',
}}>
{item.status}
</Text>
</View>
<View
style={{ alignItems: 'center', marginTop: 22, width: '62%', flexDirection: 'row' }}>
<View
style={{
width: 20,
height: 20,
borderRadius: 10,
backgroundColor: '#F2683C',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Svg
width="10"
height="10"
viewBox="0 0 12 12"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M2.5 6.2l2.3 2.3 4.7-5" />
</Svg>
</View>
<View
style={{
flex: 1,
borderTopWidth: 2,
borderTopColor: '#F2683C',
borderStyle: 'dotted',
marginVertical: 0,
marginHorizontal: 4,
}}
/>
<View
style={{
width: 20,
height: 20,
borderRadius: 10,
backgroundColor: '#F2683C',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Svg
width="10"
height="10"
viewBox="0 0 12 12"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M2.5 6.2l2.3 2.3 4.7-5" />
</Svg>
</View>
<View
style={{
flex: 1,
borderTopWidth: 2,
borderTopColor: '#F2683C',
borderStyle: 'dotted',
marginVertical: 0,
marginHorizontal: 4,
}}
/>
<View
style={{
width: 22,
height: 22,
borderRadius: 11,
backgroundColor: '#FDE7DE',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Text
numberOfLines={1}
style={{
position: 'absolute',
top: -17,
left: '50%',
transform: [{ translateX: '-50%' }],
zIndex: 1,
fontFamily: 'Inter_400Regular',
fontSize: 9,
color: '#3A3A3A',
flexShrink: 1,
}}>
4h Away
</Text>
<Svg width="13" height="13" viewBox="0 0 24 24" fill="#F2683C">
<Path d="M2 6h12v10H2zM14 9h4l4 4v3h-8z" />
<Circle cx="6" cy="18" r="2" />
<Circle cx="17" cy="18" r="2" />
</Svg>
</View>
<View
style={{
flex: 1,
borderTopWidth: 2,
borderTopColor: '#CFCFCF',
borderStyle: 'dotted',
marginVertical: 0,
marginHorizontal: 4,
}}
/>
<View
style={{
width: 18,
height: 18,
borderRadius: 9,
backgroundColor: '#E3E3E3',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Svg
width="9"
height="9"
viewBox="0 0 12 12"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M2.5 6.2l2.3 2.3 4.7-5" />
</Svg>
</View>
</View>
<View
style={{
justifyContent: 'space-between',
width: '62%',
marginTop: 14,
flexDirection: 'row',
}}>
<Text
style={{
flexShrink: 1,
fontFamily: 'Inter_400Regular',
fontSize: 10,
color: '#6B6B6B',
}}>
18 Oct 2025
</Text>
<Text
style={{
flexShrink: 1,
fontFamily: 'Inter_400Regular',
fontSize: 10,
color: '#6B6B6B',
}}>
Estimated 19 Oct 2025
</Text>
</View>
<View
style={{
justifyContent: 'space-between',
width: '62%',
marginTop: 4,
flexDirection: 'row',
}}>
<Text
style={{
flexShrink: 1,
fontFamily: 'Inter_500Medium',
fontSize: 13,
color: '#161616',
}}>
{item.from}
</Text>
<Text
style={{
flexShrink: 1,
fontFamily: 'Inter_500Medium',
fontSize: 13,
color: '#161616',
}}>
{item.to}
</Text>
</View>
<Image
source={{ uri: asset(item.box) }}
contentFit="contain"
style={{
position: 'absolute',
right: -20,
bottom: 6,
width: 116,
height: 116,
mixBlendMode: 'multiply',
}}
/>
</Pressable>
))}
{empty ? (
<Text
style={{
marginTop: 40,
marginBottom: 0,
marginHorizontal: 0,
fontFamily: 'Inter_400Regular',
fontSize: 13,
color: '#6B6B6B',
textAlign: 'center',
}}>
No shipments in this status yet.
</Text>
) : null}
</ScrollView>
</View>
</Screen>
);
}src/app/tracking.tsx
import { Image } from 'expo-image';
import { router } from 'expo-router';
import { Pressable, Text, View } from 'react-native';
import Svg, { Circle, G, Path, Rect } from 'react-native-svg';
import { Screen } from '@/components/screen';
import { asset } from '@/lib/assets';
export default function TrackingScreen() {
return (
<Screen background="#EEEFF1" statusBar="dark">
<View style={{ flex: 1 }}>
<Svg
width="390"
height="440"
viewBox="0 0 390 440"
style={{ position: 'absolute', top: 0, left: 0 }}>
<Rect width="390" height="440" fill="#EEEFF1" />
<Rect x="40" y="170" width="70" height="56" rx="6" fill="#DDE9DC" />
<Rect x="232" y="232" width="92" height="64" rx="6" fill="#DDE9DC" />
<Rect x="300" y="140" width="60" height="40" rx="6" fill="#DDE9DC" />
<G stroke="#FFFFFF" strokeWidth="7" fill="none" strokeLinecap="round">
<Path d="M-10 120 L400 100" />
<Path d="M-10 250 L400 236" />
<Path d="M-10 360 L400 350" />
<Path d="M70 0 L80 440" />
<Path d="M190 0 L196 440" />
<Path d="M330 0 L322 440" />
</G>
<G stroke="#FFFFFF" strokeWidth="3.5" fill="none" strokeLinecap="round">
<Path d="M-10 60 L400 50" />
<Path d="M-10 180 L400 168" />
<Path d="M-10 300 L400 292" />
<Path d="M-10 410 L400 404" />
<Path d="M20 0 L28 440" />
<Path d="M130 0 L136 440" />
<Path d="M255 0 L260 440" />
<Path d="M375 0 L370 440" />
<Path d="M110 230 L200 140" />
<Path d="M200 300 L300 390" />
</G>
<Path
d="M128 352 L128 318 Q128 304 142 304 L180 304 Q194 304 194 290 L194 240 Q194 226 208 226 L248 226 Q262 226 262 212 L262 176 Q262 162 276 162 L300 162 Q314 162 314 148 L314 122"
stroke="#2B2B2B"
strokeWidth="4"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
/>
<Circle cx="314" cy="112" r="22" fill="#F2683C" opacity="0.18" />
<Circle cx="314" cy="112" r="12" fill="#F2683C" />
<Circle cx="314" cy="112" r="5" fill="#FFFFFF" />
<Circle cx="128" cy="364" r="18" fill="#161616" />
<Path d="M128 354 L136 371 L128 367 L120 371 Z" fill="#FFFFFF" />
</Svg>
<View
style={{
height: 50,
paddingTop: 14,
paddingBottom: 0,
paddingHorizontal: 30,
justifyContent: 'space-between',
alignItems: 'center',
flexDirection: 'row',
}}
/>
<View
style={{
alignItems: 'center',
justifyContent: 'space-between',
paddingTop: 12,
paddingBottom: 0,
paddingHorizontal: 20,
flexDirection: 'row',
}}>
<Pressable
accessibilityRole="link"
accessibilityLabel="Back"
onPress={() => router.navigate('/')}
style={{
width: 44,
height: 44,
borderRadius: 22,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
boxShadow: '0 4px 12px rgba(0,0,0,0.06)',
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#161616"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M19 12H5M11 6l-6 6 6 6" />
</Svg>
</Pressable>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'Inter_500Medium',
fontSize: 19,
color: '#161616',
}}>
Location Tracking
</Text>
<Pressable
accessibilityRole="button"
accessibilityLabel="More options"
style={{
width: 44,
height: 44,
borderRadius: 22,
borderWidth: 0,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
boxShadow: '0 4px 12px rgba(0,0,0,0.06)',
flexDirection: 'row',
}}>
<Svg width="4" height="16" viewBox="0 0 4 16" fill="#161616">
<Circle cx="2" cy="2" r="1.8" />
<Circle cx="2" cy="8" r="1.8" />
<Circle cx="2" cy="14" r="1.8" />
</Svg>
</Pressable>
</View>
<View
style={{
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
height: 450,
backgroundColor: '#1C1C1C',
borderTopLeftRadius: 30,
borderTopRightRadius: 30,
borderBottomRightRadius: 0,
borderBottomLeftRadius: 0,
paddingTop: 10,
paddingBottom: 0,
paddingHorizontal: 20,
overflow: 'hidden',
}}>
<View
style={{
width: 36,
height: 4,
borderRadius: 2,
backgroundColor: '#FFFFFF',
opacity: 0.85,
marginTop: 0,
marginBottom: 18,
marginHorizontal: 'auto',
}}
/>
<View
style={{
justifyContent: 'space-between',
alignItems: 'flex-start',
flexDirection: 'row',
}}>
<View style={{ flexShrink: 1 }}>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 11, color: '#A3A3A3' }}>
Booking Id:
</Text>
<Text
style={{
marginTop: 6,
fontFamily: 'Inter_500Medium',
fontSize: 20,
color: '#FFFFFF',
letterSpacing: -0.2,
}}>
H314315796
</Text>
</View>
<View style={{ alignItems: 'flex-end', gap: 6, flexShrink: 1 }}>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 11, color: '#A3A3A3' }}>
Status
</Text>
<Text
style={{
paddingVertical: 6,
paddingHorizontal: 12,
borderRadius: 14,
backgroundColor: '#333333',
fontFamily: 'Inter_400Regular',
fontSize: 11,
color: '#FFFFFF',
}}>
Transit
</Text>
</View>
</View>
<View style={{ alignItems: 'center', marginTop: 18, flexDirection: 'row' }}>
<View
style={{
width: 18,
height: 18,
borderRadius: 9,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Svg
width="9"
height="9"
viewBox="0 0 12 12"
fill="none"
stroke="#1C1C1C"
strokeWidth="2.2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M2.5 6.2l2.3 2.3 4.7-5" />
</Svg>
</View>
<View
style={{
flex: 1,
borderTopWidth: 2,
borderTopColor: '#5A5A5A',
borderStyle: 'dotted',
marginVertical: 0,
marginHorizontal: 5,
}}
/>
<View
style={{
width: 16,
height: 16,
borderRadius: 8,
backgroundColor: '#4A4A4A',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Svg
width="8"
height="8"
viewBox="0 0 12 12"
fill="none"
stroke="#1C1C1C"
strokeWidth="2.2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M2.5 6.2l2.3 2.3 4.7-5" />
</Svg>
</View>
<View
style={{
flex: 1,
borderTopWidth: 2,
borderTopColor: '#5A5A5A',
borderStyle: 'dotted',
marginVertical: 0,
marginHorizontal: 5,
}}
/>
<View
style={{
width: 16,
height: 16,
borderRadius: 8,
backgroundColor: '#4A4A4A',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Svg
width="8"
height="8"
viewBox="0 0 12 12"
fill="none"
stroke="#1C1C1C"
strokeWidth="2.2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M2.5 6.2l2.3 2.3 4.7-5" />
</Svg>
</View>
<View
style={{
flex: 1,
borderTopWidth: 2,
borderTopColor: '#5A5A5A',
borderStyle: 'dotted',
marginVertical: 0,
marginHorizontal: 5,
}}
/>
<View
style={{
width: 16,
height: 16,
borderRadius: 8,
backgroundColor: '#4A4A4A',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Svg
width="8"
height="8"
viewBox="0 0 12 12"
fill="none"
stroke="#1C1C1C"
strokeWidth="2.2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M2.5 6.2l2.3 2.3 4.7-5" />
</Svg>
</View>
</View>
<View style={{ justifyContent: 'space-between', marginTop: 14, flexDirection: 'row' }}>
<Text
style={{
flexShrink: 1,
fontFamily: 'Inter_400Regular',
fontSize: 10,
color: '#A3A3A3',
}}>
Created, 18 Oct 2025
</Text>
<Text
style={{
flexShrink: 1,
fontFamily: 'Inter_400Regular',
fontSize: 10,
color: '#A3A3A3',
}}>
Estimated, 19 Oct 2025
</Text>
</View>
<View style={{ justifyContent: 'space-between', marginTop: 4, flexDirection: 'row' }}>
<Text
style={{
flexShrink: 1,
fontFamily: 'Inter_500Medium',
fontSize: 13,
color: '#FFFFFF',
}}>
Diriyah, Riyadh
</Text>
<Text
style={{
flexShrink: 1,
fontFamily: 'Inter_500Medium',
fontSize: 13,
color: '#FFFFFF',
}}>
Jawhra, Jeddah
</Text>
</View>
<View
style={{
height: 1,
backgroundColor: '#2E2E2E',
marginVertical: 16,
marginHorizontal: 0,
}}
/>
<View style={{ width: '66%', gap: 14 }}>
<View style={{ flexDirection: 'row', gap: 16 }}>
<View style={{ flex: 1 }}>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 10, color: '#A3A3A3' }}>
From
</Text>
<Text
style={{
marginTop: 4,
fontFamily: 'Inter_500Medium',
fontSize: 13,
color: '#FFFFFF',
}}>
Diriyah, Riyadh
</Text>
</View>
<View style={{ flex: 1 }}>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 10, color: '#A3A3A3' }}>
To
</Text>
<Text
style={{
marginTop: 4,
fontFamily: 'Inter_500Medium',
fontSize: 13,
color: '#FFFFFF',
}}>
Jawhra, Jeddah
</Text>
</View>
</View>
<View style={{ flexDirection: 'row', gap: 16 }}>
<View style={{ flex: 1 }}>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 10, color: '#A3A3A3' }}>
Customer
</Text>
<Text
style={{
marginTop: 4,
fontFamily: 'Inter_500Medium',
fontSize: 13,
color: '#FFFFFF',
}}>
Ahmad Kawsar
</Text>
</View>
<View style={{ flex: 1 }}>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 10, color: '#A3A3A3' }}>
Order Cost
</Text>
<Text
style={{
marginTop: 4,
fontFamily: 'Inter_500Medium',
fontSize: 13,
color: '#FFFFFF',
}}>
$120.00
</Text>
</View>
</View>
<View style={{ flexDirection: 'row', gap: 16 }}>
<View style={{ flex: 1 }}>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 10, color: '#A3A3A3' }}>
Quantity
</Text>
<Text
style={{
marginTop: 4,
fontFamily: 'Inter_500Medium',
fontSize: 13,
color: '#FFFFFF',
}}>
1 Box
</Text>
</View>
<View style={{ flex: 1 }}>
<Text style={{ fontFamily: 'Inter_400Regular', fontSize: 10, color: '#A3A3A3' }}>
Weight
</Text>
<Text
style={{
marginTop: 4,
fontFamily: 'Inter_500Medium',
fontSize: 13,
color: '#FFFFFF',
}}>
10 Kg
</Text>
</View>
</View>
</View>
<View
style={{
position: 'absolute',
right: -18,
top: 238,
width: 132,
height: 132,
borderRadius: 26,
backgroundColor: '#F4F4F4',
overflow: 'hidden',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Image
source={{ uri: asset('08942a69e7.jpg') }}
contentFit="contain"
style={{ width: 120, height: 120, mixBlendMode: 'multiply' }}
/>
</View>
<View
style={{
position: 'absolute',
left: 16,
right: 16,
bottom: 30,
height: 68,
borderRadius: 34,
backgroundColor: '#2A2A2A',
alignItems: 'center',
gap: 12,
paddingVertical: 0,
paddingHorizontal: 10,
flexDirection: 'row',
}}>
<Image
source={{ uri: asset('a0795f305f.jpg') }}
contentFit="cover"
accessibilityLabel="Khalid Omor, courier"
style={{ width: 46, height: 46, borderRadius: 23, flexShrink: 0 }}
/>
<View style={{ flex: 1, minWidth: 0 }}>
<Text style={{ fontFamily: 'Inter_500Medium', fontSize: 14, color: '#FFFFFF' }}>
Khalid Omor
</Text>
<Text
style={{
marginTop: 2,
fontFamily: 'Inter_400Regular',
fontSize: 11,
color: '#A3A3A3',
}}>
Courier
</Text>
</View>
<Pressable
accessibilityRole="button"
accessibilityLabel="Call courier"
style={{
width: 46,
height: 46,
borderRadius: 23,
borderWidth: 0,
backgroundColor: '#F2683C',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="1.9"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M5 4h4l2 5-2.5 1.5a11 11 0 0 0 5 5L15 13l5 2v4a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2" />
</Svg>
</Pressable>
<Pressable
accessibilityRole="button"
accessibilityLabel="Message courier"
style={{
width: 46,
height: 46,
borderRadius: 23,
borderWidth: 0,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="#161616"
strokeWidth="1.9"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M21 12a8 8 0 0 1-11.6 7.1L4 20l1-4.6A8 8 0 1 1 21 12z" />
<Path d="M8.5 12h.01M12 12h.01M15.5 12h.01" />
</Svg>
</Pressable>
</View>
</View>
</View>
</Screen>
);
}src/components/screen.tsx
import { StatusBar } from 'expo-status-bar';
import type { ReactNode } from 'react';
import { ScrollView, useWindowDimensions, View } from 'react-native';
// Every screen is drawn on a 390 wide artboard, then scaled to the device width.
const ARTBOARD_WIDTH = 390;
type Props = {
background: string;
statusBar: 'light' | 'dark';
height?: number;
children: ReactNode;
};
export function Screen({ background, statusBar, height: artboardHeight = 844, children }: Props) {
const { width, height } = useWindowDimensions();
const scale = width / ARTBOARD_WIDTH;
return (
<ScrollView
bounces={false}
showsVerticalScrollIndicator={false}
style={{ flex: 1, backgroundColor: background }}
contentContainerStyle={{ height: Math.max(artboardHeight * scale, height) }}>
<StatusBar style={statusBar} />
<View
style={{
width: ARTBOARD_WIDTH,
height: artboardHeight,
overflow: 'hidden',
transformOrigin: 'left top',
transform: [{ scale }],
}}>
{children}
</View>
</ScrollView>
);
}src/lib/assets.ts
// Demo images are hosted by DeveloperMill. Point this at your own CDN, or swap to require().
const ASSET_BASE = 'https://developermill.com/app-designs/delivery-tracking-app-ui-design/assets';
export const asset = (name: string) => `${ASSET_BASE}/${name}`;src/lib/css.ts
import type { TextStyle, ViewStyle } from 'react-native';
// A few styles change with state, so they are kept as short CSS strings from the design.
const FACES: Record<number, string> = {400: 'Inter_400Regular', 500: 'Inter_500Medium', 600: 'Inter_600SemiBold', 700: 'Inter_700Bold', 800: 'Inter_800ExtraBold'};
const px = (value: string) => (value.endsWith('%') ? (value as `${number}%`) : parseFloat(value));
function declarations(source: string) {
return source
.split(';')
.map((rule) => rule.split(':').map((part) => part.trim()))
.filter(([name, value]) => name && value);
}
export function css(source: string): ViewStyle {
const style: Record<string, unknown> = {};
for (const [name, ...rest] of declarations(source)) {
const value = rest.join(':');
if (name === 'background' || name === 'background-color') {
style.backgroundColor = value;
} else if (name === 'border') {
const [width, , ...color] = value.split(' ');
if (value === 'none' || value === '0') style.borderWidth = 0;
else {
style.borderWidth = parseFloat(width);
style.borderColor = color.join(' ');
}
} else if (name === 'display' && value === 'flex') {
style.flexDirection = style.flexDirection ?? 'row';
} else if (name === 'flex-direction') {
style.flexDirection = value;
} else if (name === 'align-items') {
style.alignItems = value;
} else if (name === 'justify-content') {
style.justifyContent = value;
} else if (name === 'box-shadow') {
style.boxShadow = value;
} else if (name === 'position') {
style.position = value === 'absolute' ? 'absolute' : 'relative';
} else if (name === 'opacity') {
style.opacity = parseFloat(value);
} else if (name === 'gap' || name === 'width' || name === 'height' || name === 'left' || name === 'top') {
style[name] = px(value);
} else if (name === 'border-radius') {
style.borderRadius = px(value);
} else if (name === 'padding') {
const [vertical, horizontal = vertical] = value.split(' ');
style.paddingVertical = px(vertical);
style.paddingHorizontal = px(horizontal);
} else if (name === 'white-space' && value === 'nowrap') {
style.flexShrink = 0;
} else if (name === 'flex-shrink') {
style.flexShrink = parseFloat(value);
} else if (name === 'flex') {
if (value === 'none') style.flexGrow = 0;
else style.flex = parseFloat(value);
}
}
return style as ViewStyle;
}
export function cssText(source: string): TextStyle {
const style: Record<string, unknown> = {};
for (const [name, value] of declarations(source)) {
if (name === 'color') style.color = value;
if (name === 'font-size') style.fontSize = parseFloat(value);
if (name === 'font-weight' && FACES[Number(value)]) style.fontFamily = FACES[Number(value)];
if (name === 'text-decoration' && value.startsWith('line-through')) {
style.textDecorationLine = 'line-through';
}
}
return style as TextStyle;
}About this design
Each shipment card carries a progress line with dates and both cities, so people get the answer at a glance. The status filters work and include an empty state, ready for a courier, logistics or marketplace app.
Clean greys and white cards with an ink tab bar, one orange tracking accent and 3D cardboard box imagery.
- Shipment cards with a progress timeline
- Status filters with an empty state
- Route map with a dark details sheet
- Courier card with call and message actions
Colour palette
Ink
#161616
Tracking orange
#F2683C
Graphite
#3A3A3A
Steel
#6B6B6B
Mist
#F4F4F4
White
#FFFFFF
How to use this design
- 01
Pick what to copy
Copy the Parcel Delivery Tracking artifact, skill or code from this page.
- 02
Run it or generate it
Paste the code into a new Expo app and start it, or give the skill to your AI coding agent.
- 03
Make it yours
Replace the demo images and sample content, then connect your own data.
Frequently asked questions
Do the status filters work?
Yes. All, Transit, On Process and Delivered filter the list, and an empty message appears if a status has no parcels.
Does the map show live positions?
The route is drawn in SVG as a design. Replace it with react-native-maps and your courier location feed for live tracking.
Can it work for food or grocery delivery?
Yes. Replace the parcel fields with order items. The route, timeline and courier card carry over.
Is the Parcel Delivery Tracking design free to use?
Yes. The design, skill and Expo code are free and MIT licensed, including for commercial apps. Replace the demo images and sample content with your own before you ship.
What is the difference between the artifact, skill and code?
The artifact is the full design: tokens, screens and source. The skill is a SKILL.md that teaches an AI coding agent to build the UI. The code is the finished Expo app you can paste in and run.
Which Expo version does the code use?
It targets Expo SDK 58 with Expo Router and TypeScript. It uses packages installed through npx expo install, with no custom native code.



