// Productivity app UI

Construction Project Management App UI Design in Expo

This construction management app UI gives site managers a quick read on a job. A project snapshot leads with completion and budget, tasks show progress by building, and a forecast chart compares plan to actual.

Screens
3
Built with
Expo SDK 58
Fonts
Plus Jakarta Sans
License
Free (MIT)
Construction progress screen with completion chart and forecast graph

Construction Manager app screens

Construction project dashboard with completion percent, budget and tasks

Project overview

A personal update headline, project snapshot with a bar chart, budget and spend cards, and today's tasks.

Construction task list with status tags, assignees and progress bars

Task list

Status filters, a sort control and a timeline of tasks with due dates, assignees and progress sliders.

Construction progress screen with completion chart and forecast graph

Progress charts

Progress and timeline tabs, overall completion and a forecast chart comparing planned and actual work.

Copy the Construction Manager 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

# Construction Manager: design artifact

This construction management app UI gives site managers a quick read on a job. A project snapshot leads with completion and budget, tasks show progress by building, and a forecast chart compares plan to actual.

- Type: Productivity mobile app UI
- Screens: 3
- Artboard: 390 × 844
- Target: Expo SDK 58, Expo Router, TypeScript, expo-blur, expo-image, expo-linear-gradient, react-native-svg
- Live page: https://developermill.com/app-designs/construction-management-app-ui-design

## Design direction

Bright white dashboards with a safety orange gradient, large numbers, soft stacked bar charts and a dark floating navigation pill.

- Completion and budget snapshot cards
- Task cards with status, assignees and sliders
- Progress forecast chart with a data callout
- Floating dark pill navigation

## Foundations

### Colour

| Token | Hex |
| --- | --- |
| Safety orange | `#F26A2E` |
| Burnt orange | `#C2410C` |
| Apricot | `#F59D72` |
| Peach wash | `#FDEBE1` |
| Ink | `#1A1A1A` |
| Concrete | `#F3F3F3` |

### Typography

- Typefaces: Plus Jakarta Sans
- Common sizes (px): 9, 10, 11, 12, 13, 14, 18, 22

### Shape and depth

- Common corner radii (px): 8, 12, 22, 26
- Shadows: `0 6px 20px rgba(0,0,0,0.08)`

## Screens

### 1. Project overview

A personal update headline, project snapshot with a bar chart, budget and spend cards, and today's tasks.

Preview: https://developermill.com/app-designs/construction-management-app-ui-design/overview.webp

Copy on this screen:

- Hey Rubel,
- Here’s your
- project update.
- Project Snapshot
- 72
- %
- Project completion
- On Track
- Budget
- $120,000
- Spent
- 40% Total
- $80,000
- Total Spent
- Today’s Tasks
- View All
- Install Steel Frame
- Building B · Level 2
- In progress
- Site Safety Inspection
- Building A

### 2. Task list

Status filters, a sort control and a timeline of tasks with due dates, assignees and progress sliders.

Preview: https://developermill.com/app-designs/construction-management-app-ui-design/tasks.webp

Copy on this screen:

- Tasks
- All (24)
- In Progress (6)
- Completed (12)
- Sort by:
- Due Date

### 3. Progress charts

Progress and timeline tabs, overall completion and a forecast chart comparing planned and actual work.

Preview: https://developermill.com/app-designs/construction-management-app-ui-design/progress.webp

Copy on this screen:

- Tasks
- Progress
- Timeline
- Daily Progress chart
- Work Areas
- Overall Completion
- 66
- %
- Project completion
- On Track
- Progress forecast
- Progress is 75% ahead of planned schedule
- 75
- Ahead of plan
- Planned
- Actual
- 100%
- 75%
- 50%
- 25%
- 0%
- 12,279
- cu yd completed
- This Week
- July

## Full source

The original artboards as HTML. Image URLs point at the hosted demo assets.

### Project overview (Main)

```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Home — project update</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=Plus+Jakarta+Sans:wght@400;500;600;700;800&amp;display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#1A1A1A;text-decoration:none}a:hover{color:#C2410C}
button{font-family:inherit;cursor:pointer}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; position: relative; overflow: hidden; background: #F3F3F3; font-family: 'Plus Jakarta Sans', system-ui, sans-serif; color: #1A1A1A; padding: 56px 20px 0">

<header style="display: flex; align-items: center; justify-content: space-between">
<div role="img" aria-label="App logo" style="width: 48px; height: 48px; border-radius: 50%; background: {{accent}}; display: flex; align-items: center; justify-content: center">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3v18"></path><path d="M8 21V9l4-6 4 6v12"></path><path d="M5 21h14"></path><path d="M10 12h4"></path><path d="M10 16h4"></path></svg>
</div>
<div style="display: flex; gap: 10px; align-items: center">
<button aria-label="Notifications" style="width: 48px; height: 48px; border-radius: 50%; border: 0; background: #FFFFFF; display: flex; align-items: center; justify-content: center">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"></path><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"></path></svg>
</button>
<img src="https://developermill.com/app-designs/construction-management-app-ui-design/assets/50bb5fb797.png" alt="Rubel, profile photo" style="width: 48px; height: 48px; border-radius: 50%; object-fit: cover; display: block">
</div>
</header>

<h1 style="margin: 22px 0 0; font-size: 30px; line-height: 1.18; font-weight: 700; letter-spacing: -0.6px">Hey Rubel,<br><span style="color: #9A9A9A; font-weight: 600">Here’s your </span><span style="color: {{accent}}">project update.</span></h1>

<section aria-label="Project snapshot" style="margin-top: 18px; background: #FFFFFF; border-radius: 26px; padding: 16px 16px 0; height: 168px; box-sizing: border-box; position: relative; overflow: hidden">
<div style="display: flex; justify-content: space-between; align-items: center">
<h2 style="margin: 0; font-size: 14px; font-weight: 600">Project Snapshot</h2>
<button aria-label="More options" style="width: 32px; height: 32px; border-radius: 50%; border: 0; background: #F1F1F1; display: flex; align-items: center; justify-content: center"><svg width="16" height="16" viewBox="0 0 24 24" fill="#1A1A1A" aria-hidden="true"><circle cx="5" cy="12" r="2"></circle><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle></svg></button>
</div>
<p style="margin: 10px 0 0; font-size: 46px; font-weight: 700; letter-spacing: -1.5px; line-height: 1">72<span style="font-size: 22px; letter-spacing: 0">%</span></p>
<p style="margin: 6px 0 0; font-size: 12px; color: #767676">Project completion</p>
<p style="margin: 10px 0 0; display: inline-flex; align-items: center; gap: 6px; background: #F1F1F1; border-radius: 999px; padding: 6px 10px; font-size: 11px; font-weight: 600"><span style="width: 7px; height: 7px; border-radius: 50%; background: #16A34A"></span>On Track</p>
<div aria-hidden="true" style="position: absolute; right: 16px; bottom: 0; display: flex; align-items: flex-end; gap: 0; height: 110px">
<div style="width: 26px; height: 30px; background: linear-gradient(#F7B08C, #FDEBE1)"></div>
<div style="width: 26px; height: 54px; background: linear-gradient(#F59D72, #FDEBE1)"></div>
<div style="width: 26px; height: 42px; background: linear-gradient(#F7B08C, #FDEBE1)"></div>
<div style="width: 26px; height: 96px; background: linear-gradient(#F4895A, #FDEBE1)"></div>
<div style="width: 26px; height: 70px; background: linear-gradient(#F59D72, #FDEBE1)"></div>
<div style="width: 26px; height: 50px; background: linear-gradient(#F7B08C, #FDEBE1)"></div>
</div>
</section>

<div style="margin-top: 12px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px">
<section aria-label="Budget" style="background: #FFFFFF; border-radius: 22px; padding: 12px; height: 140px; box-sizing: border-box; display: flex; flex-direction: column">
<div style="display: flex; gap: 8px; align-items: center">
<div style="width: 30px; height: 30px; border-radius: 50%; border: 1px solid #E2E2E2; display: flex; align-items: center; justify-content: center"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><circle cx="12" cy="12" r="9"></circle><path d="M14.5 9.5c-.5-1-1.5-1.5-2.5-1.5-1.5 0-2.5.8-2.5 2s1 1.7 2.5 2 2.5.8 2.5 2-1 2-2.5 2c-1 0-2-.5-2.5-1.5"></path><path d="M12 6.5v11"></path></svg></div>
<div><p style="margin: 0; font-size: 10px; color: #767676">Budget</p><p style="margin: 0; font-size: 13px; font-weight: 700">$120,000</p></div>
</div>
<div aria-hidden="true" style="margin-top: auto; background: #EFEFEF; border-radius: 12px; height: 72px; display: flex; align-items: flex-end; justify-content: center; overflow: hidden">
<div style="width: 18px; height: 20px; background: linear-gradient(#F7B08C, #FDEBE1)"></div>
<div style="width: 18px; height: 34px; background: linear-gradient(#F59D72, #FDEBE1)"></div>
<div style="width: 18px; height: 56px; background: linear-gradient(#F4895A, #FDEBE1)"></div>
<div style="width: 18px; height: 40px; background: linear-gradient(#F59D72, #FDEBE1)"></div>
<div style="width: 18px; height: 26px; background: linear-gradient(#F7B08C, #FDEBE1)"></div>
<div style="width: 18px; height: 46px; background: linear-gradient(#F59D72, #FDEBE1)"></div>
<div style="width: 18px; height: 22px; background: linear-gradient(#F7B08C, #FDEBE1)"></div>
</div>
</section>
<section aria-label="Spent" style="background: #FFFFFF; border-radius: 22px; padding: 12px; height: 140px; box-sizing: border-box; display: flex; flex-direction: column">
<div style="display: flex; gap: 8px; align-items: center">
<div style="width: 30px; height: 30px; border-radius: 50%; border: 1px solid #E2E2E2; display: flex; align-items: center; justify-content: center"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 12h4l3-8 4 16 3-8h4"></path></svg></div>
<div><p style="margin: 0; font-size: 10px; color: #767676">Spent</p><p style="margin: 0; font-size: 13px; font-weight: 700">40% Total</p></div>
</div>
<div aria-hidden="true" style="margin-top: auto; background: #EFEFEF; border-radius: 12px; height: 72px; position: relative; overflow: hidden">
<div style="position: absolute; left: 0; right: 0; bottom: 0; height: 30px; background: linear-gradient(#F8B796, #FDEBE1)"></div>
<div style="position: absolute; left: 30px; top: 22px; width: 9px; height: 9px; border-radius: 50%; border: 2px solid #F26A2E; background: #FFFFFF"></div>
<div style="position: absolute; right: 6px; top: 14px; background: #FFFFFF; border-radius: 8px; padding: 4px 7px"><p style="margin: 0; font-size: 10px; font-weight: 700">$80,000</p><p style="margin: 0; font-size: 8px; color: #767676">Total Spent</p></div>
</div>
</section>
</div>

<div style="margin-top: 20px; display: flex; justify-content: space-between; align-items: center">
<h2 style="margin: 0; font-size: 16px; font-weight: 700">Today’s Tasks</h2>
<a href="Tasks.dc.html" style="font-size: 12px; color: #6B6B6B">View All</a>
</div>

<ul style="list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 10px">
<li style="background: #FFFFFF; border-radius: 22px; padding: 12px; display: flex; align-items: center; gap: 12px">
<div style="width: 40px; height: 40px; border-radius: 50%; background: #F3F3F3; display: flex; align-items: center; justify-content: center"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><path d="M3 7h18"></path><path d="M3 17h18"></path><path d="M6 7l4 10"></path><path d="M14 7l4 10"></path><path d="M18 7l-4 10"></path></svg></div>
<div style="flex: 1; min-width: 0"><p style="margin: 0; font-size: 14px; font-weight: 600">Install Steel Frame</p><p style="margin: 2px 0 0; font-size: 11px; color: #767676">Building B · Level 2</p></div>
<span style="font-size: 10px; font-weight: 600; color: #C2410C; border: 1px solid #F8C4A8; border-radius: 999px; padding: 4px 9px">In progress</span>
<button aria-label="Open task" style="width: 34px; height: 34px; border-radius: 50%; border: 1px solid #E2E2E2; background: #FFFFFF; display: flex; align-items: center; justify-content: center"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M9 6l6 6-6 6"></path></svg></button>
</li>
<li style="background: #FFFFFF; border-radius: 22px; padding: 12px; display: flex; align-items: center; gap: 12px">
<div style="width: 40px; height: 40px; border-radius: 50%; background: #F3F3F3; display: flex; align-items: center; justify-content: center"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><rect x="5" y="4" width="14" height="17" rx="2"></rect><path d="M9 4V3h6v1"></path><path d="M9 11h6"></path><path d="M9 15h4"></path></svg></div>
<div style="flex: 1; min-width: 0"><p style="margin: 0; font-size: 14px; font-weight: 600">Site Safety Inspection</p><p style="margin: 2px 0 0; font-size: 11px; color: #767676">Building A</p></div>
<button aria-label="Open task" style="width: 34px; height: 34px; border-radius: 50%; border: 1px solid #E2E2E2; background: #FFFFFF; display: flex; align-items: center; justify-content: center"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M9 6l6 6-6 6"></path></svg></button>
</li>
</ul>

<nav aria-label="Main" style="position: absolute; left: 50%; bottom: 28px; transform: translateX(-50%); display: flex; gap: 6px; align-items: center; background: rgba(214,214,214,0.82); backdrop-filter: blur(14px); border-radius: 999px; padding: 6px">
<a href="Main.dc.html" aria-label="Home" style="width: 50px; height: 50px; border-radius: 50%; background: #111111; display: flex; align-items: center; justify-content: center"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="1.8" stroke-linejoin="round" aria-hidden="true"><path d="M4 10l8-6 8 6v10H4z"></path><path d="M10 20v-5h4v5"></path></svg></a>
<a href="Tasks.dc.html" aria-label="Tasks" style="width: 50px; height: 50px; border-radius: 50%; display: flex; align-items: center; justify-content: center"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><rect x="5" y="4" width="14" height="17" rx="2"></rect><path d="M9 4V3h6v1"></path><path d="M9 11h6"></path><path d="M9 15h4"></path></svg></a>
<a href="Progress.dc.html" aria-label="Reports" style="width: 50px; height: 50px; border-radius: 50%; display: flex; align-items: center; justify-content: center"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"></path><path d="M14 3v5h5"></path><path d="M9 14h6"></path><path d="M9 17h4"></path></svg></a>
<button aria-label="More" style="width: 50px; height: 50px; border-radius: 50%; border: 0; background: transparent; display: flex; align-items: center; justify-content: center"><svg width="18" height="18" viewBox="0 0 24 24" fill="#1A1A1A" aria-hidden="true"><circle cx="5" cy="12" r="2"></circle><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle></svg></button>
</nav>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#F26A2E","options":["#F26A2E","#2563EB","#0F766E"]},"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
return { accent: this.props.accent ?? '#F26A2E' };
}
}
</script>
</body>
</html>
```

### Task list (Tasks)

```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tasks — timeline</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=Plus+Jakarta+Sans:wght@400;500;600;700;800&amp;display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#1A1A1A;text-decoration:none}a:hover{color:#C2410C}
button{font-family:inherit;cursor:pointer}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; position: relative; overflow: hidden; background: #F3F3F3; font-family: 'Plus Jakarta Sans', system-ui, sans-serif; color: #1A1A1A; padding: 56px 20px 0">

<header style="display: flex; align-items: center; justify-content: space-between">
<a href="Main.dc.html" aria-label="Back" style="width: 46px; height: 46px; border-radius: 50%; background: #FFFFFF; display: flex; align-items: center; justify-content: center"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M15 6l-6 6 6 6"></path></svg></a>
<h1 style="margin: 0; font-size: 18px; font-weight: 700">Tasks</h1>
<button aria-label="Filters" style="width: 46px; height: 46px; border-radius: 50%; border: 0; background: #FFFFFF; display: flex; align-items: center; justify-content: center"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><path d="M4 7h10"></path><path d="M18 7h2"></path><circle cx="16" cy="7" r="2"></circle><path d="M4 17h2"></path><path d="M10 17h10"></path><circle cx="8" cy="17" r="2"></circle></svg></button>
</header>

<div role="tablist" aria-label="Task status" style="margin-top: 22px; display: flex; gap: 8px">
<button role="tab" aria-selected="true" style="flex: 1; height: 44px; border-radius: 999px; border: 0; background: #111111; color: #FFFFFF; font-size: 12px; font-weight: 600">All (24)</button>
<button role="tab" aria-selected="false" style="flex: 1.2; height: 44px; border-radius: 999px; border: 0; background: #FFFFFF; color: #1A1A1A; font-size: 12px; font-weight: 500">In Progress (6)</button>
<button role="tab" aria-selected="false" style="flex: 1.2; height: 44px; border-radius: 999px; border: 0; background: #FFFFFF; color: #1A1A1A; font-size: 12px; font-weight: 500">Completed (12)</button>
</div>

<div style="margin-top: 14px; display: flex; justify-content: space-between; align-items: center">
<button style="height: 38px; border-radius: 999px; border: 0; background: #FFFFFF; padding: 0 14px; display: flex; gap: 6px; align-items: center; font-size: 12px; color: #6B6B6B">Sort by: <span style="color: #1A1A1A; font-weight: 600">Due Date</span><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M6 9l6 6 6-6"></path></svg></button>
<button aria-label="List view" style="width: 44px; height: 44px; border-radius: 50%; border: 0; background: #FFFFFF; display: flex; align-items: center; justify-content: center"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><path d="M9 6h11"></path><path d="M9 12h11"></path><path d="M9 18h11"></path><path d="M4 6h1"></path><path d="M4 12h1"></path><path d="M4 18h1"></path></svg></button>
</div>

<div style="margin-top: 16px; position: relative; padding-left: 26px">
<div aria-hidden="true" style="position: absolute; left: 7px; top: 8px; bottom: -200px; width: 2px; background: #E2E2E2"></div>
<ul style="list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px">
<sc-for list="{{ tasks }}" as="t" hint-placeholder-count="4">
<li style="position: relative">
<div aria-hidden="true" style="position: absolute; left: -26px; top: 4px; width: 16px; height: 16px; border-radius: 50%; background: #FFFFFF; border: 4px solid {{ t.color }}; box-sizing: border-box"></div>
<div style="background: #FFFFFF; border-radius: 22px; padding: 14px">
<div style="display: flex; gap: 10px; align-items: flex-start">
<div aria-hidden="true" style="width: 34px; height: 34px; border-radius: 50%; background: {{ t.color }}; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="{{ t.icon }}"></path></svg></div>
<div style="flex: 1; min-width: 0"><h2 style="margin: 0; font-size: 14px; font-weight: 700">{{ t.title }}</h2><p style="margin: 2px 0 0; font-size: 11px; color: #767676">{{ t.place }}</p></div>
<span style="font-size: 10px; font-weight: 600; color: {{ t.text }}; background: {{ t.soft }}; border: 1px solid {{ t.line }}; border-radius: 999px; padding: 4px 9px">{{ t.status }}</span>
</div>
<div style="margin-top: 12px; display: flex; align-items: center; justify-content: space-between">
<p style="margin: 0; display: flex; align-items: center; gap: 6px; font-size: 11px; color: #555555"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#555555" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><rect x="4" y="5" width="16" height="16" rx="2"></rect><path d="M8 3v4"></path><path d="M16 3v4"></path><path d="M4 10h16"></path></svg>{{ t.date }}</p>
<div style="display: flex; align-items: center">
<img src="{{ t.a1 }}" alt="Assignee" style="width: 24px; height: 24px; border-radius: 50%; border: 2px solid #FFFFFF; object-fit: cover; display: block">
<img src="{{ t.a2 }}" alt="Assignee" style="width: 24px; height: 24px; border-radius: 50%; border: 2px solid #FFFFFF; object-fit: cover; display: block; margin-left: -8px">
<span style="margin-left: 4px; width: 24px; height: 24px; border-radius: 50%; background: #F1F1F1; font-size: 9px; font-weight: 600; display: flex; align-items: center; justify-content: center">{{ t.more }}</span>
</div>
</div>
<div style="margin-top: 12px; display: flex; align-items: center; gap: 10px">
<div role="progressbar" aria-valuenow="{{ t.pct }}" aria-valuemin="0" aria-valuemax="100" aria-label="Progress" style="flex: 1; height: 6px; border-radius: 999px; background: #EDEDED; position: relative">
<div style="width: {{ t.width }}; height: 6px; border-radius: 999px; background: {{ t.color }}"></div>
<div aria-hidden="true" style="position: absolute; left: {{ t.knob }}; top: -5px; width: 16px; height: 16px; border-radius: 50%; background: #FFFFFF; border: 2px solid {{ t.color }}; box-sizing: border-box"></div>
</div>
<span style="font-size: 11px; font-weight: 700; min-width: 32px; text-align: right">{{ t.pct }}%</span>
</div>
</div>
</li>
</sc-for>
</ul>
</div>

<nav aria-label="Main" style="position: absolute; left: 50%; bottom: 28px; transform: translateX(-50%); display: flex; gap: 6px; align-items: center; background: rgba(214,214,214,0.82); backdrop-filter: blur(14px); border-radius: 999px; padding: 6px">
<a href="Main.dc.html" aria-label="Home" style="width: 50px; height: 50px; border-radius: 50%; display: flex; align-items: center; justify-content: center"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linejoin="round" aria-hidden="true"><path d="M4 10l8-6 8 6v10H4z"></path><path d="M10 20v-5h4v5"></path></svg></a>
<a href="Tasks.dc.html" aria-label="Tasks" aria-current="page" style="width: 50px; height: 50px; border-radius: 50%; background: #111111; display: flex; align-items: center; justify-content: center"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><rect x="5" y="4" width="14" height="17" rx="2"></rect><path d="M9 4V3h6v1"></path><path d="M9 11h6"></path><path d="M9 15h4"></path></svg></a>
<a href="Progress.dc.html" aria-label="Reports" style="width: 50px; height: 50px; border-radius: 50%; display: flex; align-items: center; justify-content: center"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"></path><path d="M14 3v5h5"></path><path d="M9 14h6"></path><path d="M9 17h4"></path></svg></a>
<button aria-label="More" style="width: 50px; height: 50px; border-radius: 50%; border: 0; background: transparent; display: flex; align-items: center; justify-content: center"><svg width="18" height="18" viewBox="0 0 24 24" fill="#1A1A1A" aria-hidden="true"><circle cx="5" cy="12" r="2"></circle><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle></svg></button>
</nav>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
var tone = {
progress: { color: '#F26A2E', text: '#C2410C', soft: '#FFFFFF', line: '#F8C4A8' },
done: { color: '#16A34A', text: '#15803D', soft: '#EAF7EE', line: '#B7E4C4' },
late: { color: '#E5484D', text: '#C42B30', soft: '#FFFFFF', line: '#F5B8BA' }
};
var eng = 'https://developermill.com/app-designs/construction-management-app-ui-design/assets/b26cb59928.png', mgr = 'https://developermill.com/app-designs/construction-management-app-ui-design/assets/91feabbcba.png', sup = 'https://developermill.com/app-designs/construction-management-app-ui-design/assets/2c12743178.png';
var rows = [
{ title: 'Concrete Pouring', place: 'Level 3 · Zone B', status: 'In progress', tone: 'progress', date: 'May 5, 2025 · 9:00 AM', pct: 60, a1: eng, a2: mgr, more: '2+', icon: 'M4 18h16M6 18l3-9h6l3 9M10 9V5h4v4' },
{ title: 'Steel Structure', place: 'Level 2 · Zone A', status: 'Completed', tone: 'done', date: 'Apr 30, 2025 · 10:00 AM', pct: 100, a1: sup, a2: eng, more: '3+', icon: 'M5 9h14M5 15h14M9 5v14M15 5v14' },
{ title: 'Electrical Rough-In', place: 'Level 4 · Zone C', status: 'Delayed', tone: 'late', date: 'May 6, 2026 · 1:00 PM', pct: 25, a1: mgr, a2: sup, more: '1+', icon: 'M13 3L5 13h6l-1 8 8-10h-6z' },
{ title: 'Plumbing Install', place: 'Level 1 · Zone D', status: 'In progress', tone: 'progress', date: 'May 9, 2025 · 11:00 AM', pct: 40, a1: eng, a2: sup, more: '2+', icon: 'M5 8h8a3 3 0 0 1 3 3v8M16 19h3M5 5v6' }
];
return {
tasks: rows.map(function (r) {
var t = tone[r.tone];
return Object.assign({}, r, t, { width: r.pct + '%', knob: 'calc(' + r.pct + '% - 8px)' });
})
};
}
}
</script>
</body>
</html>
```

### Progress charts (Progress)

```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Progress — overall completion</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=Plus+Jakarta+Sans:wght@400;500;600;700;800&amp;display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#1A1A1A;text-decoration:none}a:hover{color:#C2410C}
button{font-family:inherit;cursor:pointer}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; position: relative; overflow: hidden; background: #F3F3F3; font-family: 'Plus Jakarta Sans', system-ui, sans-serif; color: #1A1A1A; padding: 56px 20px 0">

<header style="display: flex; align-items: center; gap: 10px">
<a href="Tasks.dc.html" aria-label="Back" style="width: 46px; height: 46px; border-radius: 50%; background: #FFFFFF; display: flex; align-items: center; justify-content: center"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M15 6l-6 6 6 6"></path></svg></a>
<h1 style="margin: 0 0 0 6px; flex: 1; font-size: 18px; font-weight: 700">Tasks</h1>
<button aria-label="Add task" style="width: 46px; height: 46px; border-radius: 50%; border: 0; background: #FFFFFF; display: flex; align-items: center; justify-content: center"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M12 5v14"></path><path d="M5 12h14"></path></svg></button>
<button aria-label="Sites" style="width: 46px; height: 46px; border-radius: 50%; border: 0; background: #FFFFFF; display: flex; align-items: center; justify-content: center"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linejoin="round" aria-hidden="true"><path d="M4 10l8-6 8 6v10H4z"></path><path d="M9 14c1 1 5 1 6 0"></path></svg></button>
<button aria-label="More options" style="width: 46px; height: 46px; border-radius: 50%; border: 0; background: #FFFFFF; display: flex; align-items: center; justify-content: center"><svg width="16" height="16" viewBox="0 0 24 24" fill="#1A1A1A" aria-hidden="true"><circle cx="5" cy="12" r="2"></circle><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle></svg></button>
</header>

<section style="margin-top: 20px; background: #FFFFFF; border-radius: 26px; padding: 10px">
<div role="tablist" aria-label="View" style="display: flex; background: #F3F3F3; border-radius: 999px; padding: 0">
<button role="tab" aria-selected="true" style="flex: 1; height: 44px; border-radius: 999px; border: 0; background: #111111; color: #FFFFFF; font-size: 13px; font-weight: 600">Progress</button>
<button role="tab" aria-selected="false" style="flex: 1; height: 44px; border-radius: 999px; border: 0; background: transparent; color: #1A1A1A; font-size: 13px; font-weight: 500">Timeline</button>
</div>
<div style="margin-top: 10px; display: flex; gap: 8px">
<button style="flex: 1; height: 44px; border-radius: 999px; border: 1px solid #E6E6E6; background: #FFFFFF; display: flex; gap: 8px; align-items: center; justify-content: center; font-size: 12px; color: #1A1A1A"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><path d="M4 20h16"></path><path d="M4 16l5-5 4 3 7-7"></path></svg>Daily Progress chart</button>
<button style="flex: 0.8; height: 44px; border-radius: 999px; border: 1px solid #E6E6E6; background: #FFFFFF; display: flex; gap: 8px; align-items: center; justify-content: center; font-size: 12px; color: #1A1A1A"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" aria-hidden="true"><rect x="4" y="4" width="7" height="7" rx="1.5"></rect><rect x="13" y="4" width="7" height="7" rx="1.5"></rect><rect x="4" y="13" width="7" height="7" rx="1.5"></rect><rect x="13" y="13" width="7" height="7" rx="1.5"></rect></svg>Work Areas</button>
</div>
</section>

<section aria-label="Overall completion" style="margin-top: 12px; background: #FFFFFF; border-radius: 26px; padding: 16px 16px 0; height: 166px; box-sizing: border-box; position: relative; overflow: hidden">
<div style="display: flex; justify-content: space-between; align-items: center">
<h2 style="margin: 0; font-size: 14px; font-weight: 600">Overall Completion</h2>
<button aria-label="More options" style="width: 32px; height: 32px; border-radius: 50%; border: 0; background: #F1F1F1; display: flex; align-items: center; justify-content: center"><svg width="16" height="16" viewBox="0 0 24 24" fill="#1A1A1A" aria-hidden="true"><circle cx="5" cy="12" r="2"></circle><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle></svg></button>
</div>
<p style="margin: 10px 0 0; font-size: 44px; font-weight: 700; letter-spacing: -1.5px; line-height: 1">66<span style="font-size: 22px; letter-spacing: 0">%</span></p>
<p style="margin: 6px 0 0; font-size: 12px; color: #767676">Project completion</p>
<p style="margin: 10px 0 0; display: inline-flex; align-items: center; gap: 6px; background: #F1F1F1; border-radius: 999px; padding: 6px 10px; font-size: 11px; font-weight: 600"><span style="width: 7px; height: 7px; border-radius: 50%; background: #16A34A"></span>On Track</p>
<div aria-hidden="true" style="position: absolute; right: 16px; bottom: 0; display: flex; align-items: flex-end; height: 112px">
<div style="width: 24px; height: 36px; background: linear-gradient(#F7B08C, #FDEBE1)"></div>
<div style="width: 24px; height: 62px; background: linear-gradient(#F59D72, #FDEBE1)"></div>
<div style="width: 24px; height: 106px; background: linear-gradient(#F4895A, #FDEBE1)"></div>
<div style="width: 24px; height: 80px; background: linear-gradient(#F59D72, #FDEBE1)"></div>
<div style="width: 24px; height: 52px; background: linear-gradient(#F7B08C, #FDEBE1)"></div>
<div style="width: 24px; height: 72px; background: linear-gradient(#F59D72, #FDEBE1)"></div>
</div>
</section>

<section aria-label="Progress forecast" style="margin-top: 12px; background: #FFFFFF; border-radius: 26px; padding: 16px; height: 330px; box-sizing: border-box; position: relative; overflow: hidden">
<div style="display: flex; justify-content: space-between; align-items: flex-start">
<div><h2 style="margin: 0; font-size: 14px; font-weight: 600">Progress forecast</h2><p style="margin: 3px 0 0; font-size: 11px; color: #767676">Progress is 75% ahead of planned schedule</p></div>
<button aria-label="More options" style="width: 32px; height: 32px; border-radius: 50%; border: 0; background: #F1F1F1; display: flex; align-items: center; justify-content: center"><svg width="16" height="16" viewBox="0 0 24 24" fill="#1A1A1A" aria-hidden="true"><circle cx="5" cy="12" r="2"></circle><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle></svg></button>
</div>
<div style="margin-top: 12px; display: flex; align-items: center; justify-content: space-between">
<div style="display: flex; align-items: baseline; gap: 8px"><p style="margin: 0; font-size: 34px; font-weight: 700; letter-spacing: -1px; line-height: 1">75<span style="font-size: 18px; letter-spacing: 0">%</span></p><p style="margin: 0; display: flex; align-items: center; gap: 3px; font-size: 10px; font-weight: 600"><svg width="10" height="10" viewBox="0 0 10 10" aria-hidden="true"><path d="M5 1l4 7H1z" fill="#16A34A"></path></svg>Ahead of plan</p></div>
<div role="tablist" aria-label="Series" style="display: flex; background: #F3F3F3; border-radius: 999px; padding: 3px">
<button role="tab" aria-selected="false" style="height: 28px; border-radius: 999px; border: 0; background: transparent; padding: 0 10px; font-size: 10px; color: #1A1A1A">Planned</button>
<button role="tab" aria-selected="true" style="height: 28px; border-radius: 999px; border: 0; background: #111111; padding: 0 10px; font-size: 10px; color: #FFFFFF">Actual</button>
</div>
</div>

<div style="margin-top: 16px; position: relative; height: 170px; padding-left: 34px">
<div aria-hidden="true" style="position: absolute; left: 0; top: 0; bottom: 18px; display: flex; flex-direction: column; justify-content: space-between; font-size: 10px; color: #767676"><span>100%</span><span>75%</span><span>50%</span><span>25%</span><span>0%</span></div>
<div aria-hidden="true" style="position: absolute; left: 34px; right: 0; bottom: 18px; height: 152px; display: flex; align-items: flex-end">
<div style="flex: 1; height: 38px; background: linear-gradient(#F7B08C, #FDEBE1)"></div>
<div style="flex: 1; height: 70px; background: linear-gradient(#F59D72, #FDEBE1)"></div>
<div style="flex: 1; height: 98px; background: linear-gradient(#F4895A, #FDEBE1)"></div>
<div style="flex: 1; height: 62px; background: linear-gradient(#F59D72, #FDEBE1)"></div>
<div style="flex: 1; height: 120px; background: linear-gradient(#F4895A, #FDEBE1)"></div>
<div style="flex: 1; height: 84px; background: linear-gradient(#F59D72, #FDEBE1)"></div>
<div style="flex: 1; height: 52px; background: linear-gradient(#F7B08C, #FDEBE1)"></div>
</div>
<div aria-hidden="true" style="position: absolute; left: 82px; top: 40px; width: 104px; height: 1px; border-top: 1px dashed #F26A2E"></div>
<div aria-hidden="true" style="position: absolute; left: 76px; top: 34px; width: 14px; height: 14px; border-radius: 50%; background: #FFFFFF; border: 2px solid #F26A2E; box-sizing: border-box"></div>
<div style="position: absolute; left: 150px; top: 6px; background: #FFFFFF; border-radius: 12px; padding: 8px 12px; box-shadow: 0 6px 20px rgba(0,0,0,0.08)">
<p style="margin: 0; font-size: 14px; font-weight: 700; color: #C2410C">12,279</p>
<p style="margin: 1px 0 0; font-size: 11px; font-weight: 600">cu yd completed</p>
<p style="margin: 1px 0 0; font-size: 9px; color: #767676">This Week</p>
</div>
<span style="position: absolute; right: 0; bottom: 0; font-size: 10px; color: #767676">July</span>
</div>
</section>

<nav aria-label="Main" style="position: absolute; left: 50%; bottom: 28px; transform: translateX(-50%); display: flex; gap: 6px; align-items: center; background: rgba(214,214,214,0.82); backdrop-filter: blur(14px); border-radius: 999px; padding: 6px">
<a href="Main.dc.html" aria-label="Home" style="width: 50px; height: 50px; border-radius: 50%; display: flex; align-items: center; justify-content: center"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linejoin="round" aria-hidden="true"><path d="M4 10l8-6 8 6v10H4z"></path><path d="M10 20v-5h4v5"></path></svg></a>
<a href="Tasks.dc.html" aria-label="Tasks" aria-current="page" style="width: 50px; height: 50px; border-radius: 50%; background: #111111; display: flex; align-items: center; justify-content: center"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><rect x="5" y="4" width="14" height="17" rx="2"></rect><path d="M9 4V3h6v1"></path><path d="M9 11h6"></path><path d="M9 15h4"></path></svg></a>
<a href="Progress.dc.html" aria-label="Reports" style="width: 50px; height: 50px; border-radius: 50%; display: flex; align-items: center; justify-content: center"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#1A1A1A" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"></path><path d="M14 3v5h5"></path><path d="M9 14h6"></path><path d="M9 17h4"></path></svg></a>
<button aria-label="More" style="width: 50px; height: 50px; border-radius: 50%; border: 0; background: transparent; display: flex; align-items: center; justify-content: center"><svg width="18" height="18" viewBox="0 0 24 24" fill="#1A1A1A" aria-hidden="true"><circle cx="5" cy="12" r="2"></circle><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle></svg></button>
</nav>
</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/construction-management-app-ui/SKILL.md

---
name: construction-management-app-ui
description: Build the Construction Manager mobile app UI in Expo React Native. Use when asked to create a construction management app UI or a new screen in this visual style.
---

# Construction Manager app UI

Build this productivity app UI in an Expo Router project with TypeScript.

Reference: https://developermill.com/app-designs/construction-management-app-ui-design

## Visual direction

Bright white dashboards with a safety orange gradient, large numbers, soft stacked bar charts and a dark floating navigation pill.

Keep these signature details:

- Completion and budget snapshot cards
- Task cards with status, assignees and sliders
- Progress forecast chart with a data callout
- Floating dark pill navigation

## Set up

```bash
npx expo install expo-blur expo-image expo-linear-gradient react-native-svg @expo-google-fonts/plus-jakarta-sans expo-font
```

## Tokens

| Name | Hex |
| --- | --- |
| Safety orange | `#F26A2E` |
| Burnt orange | `#C2410C` |
| Apricot | `#F59D72` |
| Peach wash | `#FDEBE1` |
| Ink | `#1A1A1A` |
| Concrete | `#F3F3F3` |

- Typefaces: Plus Jakarta Sans
- Text sizes (px): 9, 10, 11, 12, 13, 14, 18, 22
- Corner radii (px): 8, 12, 22, 26

Define these once and reuse them. Do not add new colours.

## Screens

1. **Project overview.** A personal update headline, project snapshot with a bar chart, budget and spend cards, and today's tasks.
2. **Task list.** Status filters, a sort control and a timeline of tasks with due dates, assignees and progress sliders.
3. **Progress charts.** Progress and timeline tabs, overall completion and a forecast chart comparing planned and actual work.

## 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 construction-management-app --template default
cd construction-management-app
rm -rf src
npx expo install expo-blur expo-image expo-linear-gradient react-native-svg @expo-google-fonts/plus-jakarta-sans expo-font

src/app/_layout.tsx

import {
  PlusJakartaSans_400Regular,
  PlusJakartaSans_500Medium,
  PlusJakartaSans_600SemiBold,
  PlusJakartaSans_700Bold,
} from '@expo-google-fonts/plus-jakarta-sans';
import { useFonts } from 'expo-font';
import { Stack } from 'expo-router';

export default function RootLayout() {
  const [fontsLoaded] = useFonts({
    PlusJakartaSans_400Regular,
    PlusJakartaSans_500Medium,
    PlusJakartaSans_600SemiBold,
    PlusJakartaSans_700Bold,
  });

  if (!fontsLoaded) return null;

  return <Stack screenOptions={{ headerShown: false }} />;
}

About this design

The charts are drawn from views and SVG, so there is no chart library to install. The dashboard pattern suits any field team, from property maintenance to event production.

Bright white dashboards with a safety orange gradient, large numbers, soft stacked bar charts and a dark floating navigation pill.

  • Completion and budget snapshot cards
  • Task cards with status, assignees and sliders
  • Progress forecast chart with a data callout
  • Floating dark pill navigation

Colour palette

  • Safety orange

    #F26A2E

  • Burnt orange

    #C2410C

  • Apricot

    #F59D72

  • Peach wash

    #FDEBE1

  • Ink

    #1A1A1A

  • Concrete

    #F3F3F3

How to use this design

  1. 01

    Pick what to copy

    Copy the Construction Manager artifact, skill or code from this page.

  2. 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.

  3. 03

    Make it yours

    Replace the demo images and sample content, then connect your own data.

Frequently asked questions

Do I need a chart library?

No. The bars are plain views and the forecast line is drawn with react-native-svg, so there are no extra dependencies.

Can I use it for general project management?

Yes. Rename the buildings and levels to projects and sprints. The cards and charts work for any team.

How do I add real data?

Tasks and chart values are plain data on each screen. Load them from your API and pass the same fields.

Is the Construction Manager 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.

More app UI designs