// Education app UI
Learning App UI Design in Expo
This learning app UI keeps study motivating: a bold hero card, simple lesson and hour counters, course cards with progress rings, and a clear weekly chart.
- Screens
- 3
- Built with
- Expo SDK 58
- Fonts
- Plus Jakarta Sans
- License
- Free (MIT)

Learning Platform app screens

Student home
Greeting with progress, a large Olympiads hero with a 3D trophy, lesson and hour counters, and monthly performance.

My courses
An orange header with a 3D graduation cap, subject chips and course cards with classmates and progress rings.

Progress
A subject filter, weekly and monthly toggle, lesson and hour totals, rounded day bars and a student rating row.
Copy the Learning Platform 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
# Learning Platform: design artifact
This learning app UI keeps study motivating: a bold hero card, simple lesson and hour counters, course cards with progress rings, and a clear weekly chart.
- Type: Education 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/learning-app-ui-design
## Design direction
Periwinkle and tangerine on white, large rounded cards with glossy 3D objects and sketched lines behind them.
- Hero card with progress ring action
- Course cards with avatars and completion rings
- Weekly progress bars with a striped peak day
- Dark floating tab bar with a raised active item
## Foundations
### Colour
| Token | Hex |
| --- | --- |
| Periwinkle | `#8C86E3` |
| Tangerine | `#F29A5C` |
| Charcoal | `#222226` |
| Sun | `#F7C94E` |
| Lilac | `#ECEBFB` |
| Cloud | `#F3F3F2` |
### Typography
- Typefaces: Plus Jakarta Sans
- Common sizes (px): 11, 11.5, 12.5, 13, 13.5, 17, 19, 44
### Shape and depth
- Common corner radii (px): 10, 23, 24, 25, 30, 40
- Shadows: None
## Screens
### 1. Student home
Greeting with progress, a large Olympiads hero with a 3D trophy, lesson and hour counters, and monthly performance.
Preview: https://developermill.com/app-designs/learning-app-ui-design/home.webp
Copy on this screen:
- Hello, Jacob
- Progress: 76%
- A series of Olympiads
- A series of
- Olympiads
- for erudite people from all over the world
- Lessons
- 78
- Hours
- 43
- Progress perfomance
- June
- 23 lessons
- July
- 43 lessons
- August
- 12 lessons
### 2. My courses
An orange header with a 3D graduation cap, subject chips and course cards with classmates and progress rings.
Preview: https://developermill.com/app-designs/learning-app-ui-design/courses.webp
Copy on this screen:
- My
- courses
- 12 Subjects
- 43 Lessons
- Literature
- Math
- Biology
- GEOMETRY IN ACTION
- Creative approaches to plane shapes
- +43
- THE MICROCOSM AROUND US
- Discoveries in cell biology
- +12
### 3. Progress
A subject filter, weekly and monthly toggle, lesson and hour totals, rounded day bars and a student rating row.
Preview: https://developermill.com/app-designs/learning-app-ui-design/progress.webp
Copy on this screen:
- Hello, Jacob
- Progress: 76%
- Progress
- All subjects
- Weekly
- Month
- 48
- lessons
- 12
- hours
- Rating of students
- 10 best students
## Full source
The complete design source for each screen. Images point at hosted demo files.
### 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=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#5B55C9}a:hover{color:#3F3A9E}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; padding: 56px 18px 22px; display: flex; flex-direction: column; gap: 14px; background: #FFFFFF; font-family: 'Plus Jakarta Sans', system-ui, sans-serif; color: #1E1E22; overflow: hidden">
<div style="display: flex; align-items: center; gap: 12px">
<div style="width: 54px; height: 54px; border-radius: 50%; background: #D9D6F7; display: flex; align-items: center; justify-content: center; flex-shrink: 0">
<img src="https://developermill.com/app-designs/learning-app-ui-design/assets/f7d3a0c391.jpg" alt="Jacob" style="width: 54px; height: 54px; border-radius: 50%; object-fit: cover">
</div>
<div style="display: flex; flex-direction: column; gap: 3px; flex-grow: 1">
<div style="font-size: 19px; font-weight: 700">Hello, Jacob</div>
<div style="display: flex; align-items: center; gap: 5px; font-size: 13px; color: #55545C">
<svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true"><path d="M13 2 4 14h7l-1 8 9-12h-7z" fill="#8C86E3"></path></svg>
<span>Progress: 76%</span>
</div>
</div>
<button aria-label="Notifications" style="position: relative; width: 50px; height: 50px; border-radius: 50%; border: 1.5px solid #DCDAD6; background: #FFFFFF; display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#1E1E22" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><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 2.2 0 0 0 4 0"></path></svg>
<span style="position: absolute; top: 2px; right: 4px; width: 9px; height: 9px; border-radius: 50%; background: #F0645A"></span>
</button>
</div>
<div style="position: relative; height: 290px; flex-shrink: 0">
<div style="position: absolute; left: 8px; right: 8px; bottom: 0; height: 80px; border-radius: 0 0 36px 36px; background: #6C67CF; transform: rotate(-1.6deg); transform-origin: right bottom"></div>
<div style="position: absolute; left: 0; right: 0; top: 0; bottom: 12px; border-radius: 38px; background: #7F7BDE; padding: 30px 22px 22px; box-sizing: border-box; overflow: hidden">
<svg width="354" height="278" viewBox="0 0 354 278" aria-hidden="true" style="position: absolute; left: 0; top: 0">
<path d="M70 18l2 5 5 2-5 2-2 5-2-5-5-2 5-2z" fill="#9C98E8"></path>
<path d="M178 8l1.6 4 4 1.6-4 1.6-1.6 4-1.6-4-4-1.6 4-1.6z" fill="#2F2B7A" opacity=".55"></path>
<path d="M300 22l3.5 7.5 8 1-6 5.5 1.6 8-7.1-4-7.1 4 1.6-8-6-5.5 8-1z" fill="#F7C94E" stroke="#1E1E22" stroke-width="1.5" stroke-linejoin="round"></path>
<path d="M200 200l2.5 6 6 2.5-6 2.5-2.5 6-2.5-6-6-2.5 6-2.5z" fill="#F7C94E" stroke="#1E1E22" stroke-width="1.2" stroke-linejoin="round"></path>
<path d="M320 238l2.5 6 6 2.5-6 2.5-2.5 6-2.5-6-6-2.5 6-2.5z" fill="#F7C94E" stroke="#1E1E22" stroke-width="1.2" stroke-linejoin="round"></path>
<path d="M250 50c20-10 40-12 60-6" fill="none" stroke="#9C98E8" stroke-width="1.5" stroke-linecap="round"></path>
<text x="172" y="182" font-family="Plus Jakarta Sans, sans-serif" font-size="17" fill="#A9A6EE">y=?</text>
</svg>
<img src="https://developermill.com/app-designs/learning-app-ui-design/assets/d13b1ea5dd.png" alt="" aria-hidden="true" style="position: absolute; right: -26px; top: 58px; width: 196px; height: auto; transform: rotate(12deg)">
<div style="position: relative; display: flex; flex-direction: column; gap: 12px">
<h1 style="margin: 0; max-width: 220px; font-size: 34px; line-height: 1.1; font-weight: 800; letter-spacing: -0.5px; color: #FFFFFF">A series of Olympiads</h1>
<p style="margin: 0; max-width: 250px; font-size: 13px; line-height: 1.55; color: #EFEEFF">A series of <span style="color: #FFB86B; font-weight: 700">Olympiads</span> for erudite people from all over the world</p>
</div>
<div style="position: absolute; left: 16px; bottom: 16px; width: 76px; height: 76px">
<svg width="76" height="76" viewBox="0 0 76 76" aria-hidden="true" style="position: absolute; left: 0; top: 0"><circle cx="38" cy="38" r="35" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-dasharray="160 220" transform="rotate(-70 38 38)"></circle></svg>
<button aria-label="Open Olympiads" style="position: absolute; left: 8px; top: 8px; width: 60px; height: 60px; border-radius: 50%; background: #222226; border: 0; display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"></path></svg>
</button>
</div>
</div>
</div>
<div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px">
<div style="position: relative; height: 128px; border-radius: 30px; background: #F8F3EF; border: 1.5px solid #F29A5C; box-sizing: border-box; overflow: hidden">
<svg width="110" height="90" viewBox="0 0 110 90" aria-hidden="true" style="position: absolute; left: 0; top: 0"><path d="M0 0H92C74 2 66 14 58 30C48 50 30 58 0 64Z" fill="#F29A5C"></path></svg>
<div style="position: absolute; left: 12px; top: 10px; width: 44px; height: 44px; border-radius: 50%; background: #E2864A; display: flex; align-items: center; justify-content: center">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#6A3517" stroke-width="2" stroke-linecap="round" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="4" fill="#B5612D" stroke="none"></rect><path d="M7 9h4M14 9h3M7 15h3M14 15h3" stroke="#F7C9A6"></path></svg>
</div>
<span style="position: absolute; left: 70px; top: 24px; font-size: 13px; font-weight: 500; color: #1E1E22">Lessons</span>
<div style="position: absolute; left: 0; right: 0; top: 50px; font-size: 44px; font-weight: 700; letter-spacing: -1px; text-align: center; padding-left: 10px">78</div>
</div>
<div style="position: relative; height: 128px; border-radius: 30px; background: #EDECFA; border: 1.5px solid #8C86E3; box-sizing: border-box; overflow: hidden">
<svg width="110" height="90" viewBox="0 0 110 90" aria-hidden="true" style="position: absolute; left: 0; top: 0"><path d="M0 0H92C74 2 66 14 58 30C48 50 30 58 0 64Z" fill="#8C86E3"></path></svg>
<div style="position: absolute; left: 12px; top: 10px; width: 44px; height: 44px; border-radius: 50%; background: #7C76D8; display: flex; align-items: center; justify-content: center">
<svg width="20" height="20" viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="13" r="7" fill="#C9C6F5"></circle><rect x="9" y="3" width="4" height="3" rx="1" fill="#C9C6F5"></rect><circle cx="17" cy="18" r="4" fill="#FFFFFF"></circle><path d="M17 16v2h1.6" stroke="#7C76D8" stroke-width="1.4" fill="none" stroke-linecap="round"></path></svg>
</div>
<span style="position: absolute; left: 70px; top: 24px; font-size: 13px; font-weight: 500; color: #1E1E22">Hours</span>
<div style="position: absolute; left: 0; right: 0; top: 50px; font-size: 44px; font-weight: 700; letter-spacing: -1px; text-align: center; padding-left: 10px">43</div>
</div>
</div>
<div style="border-radius: 24px; background: #F3F3F2; padding: 16px 16px 14px; display: flex; flex-direction: column; gap: 14px">
<div style="display: flex; align-items: center; justify-content: space-between">
<h2 style="margin: 0; font-size: 15px; font-weight: 700">Progress perfomance</h2>
<button aria-label="More options" style="width: 44px; height: 28px; border: 0; background: transparent; display: flex; align-items: center; justify-content: flex-end; padding: 0; cursor: pointer">
<svg width="20" height="6" viewBox="0 0 20 6" aria-hidden="true"><circle cx="3" cy="3" r="2.4" fill="#1E1E22"></circle><circle cx="10" cy="3" r="2.4" fill="#1E1E22"></circle><circle cx="17" cy="3" r="2.4" fill="#1E1E22"></circle></svg>
</button>
</div>
<div style="display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: end; height: 48px; border-radius: 10px; overflow: hidden; background: repeating-linear-gradient(180deg, #E6E5E2 0 3px, #F2F1EE 3px 6px)">
<div style="height: 40px; display: flex; flex-direction: column; justify-content: flex-start"><div style="height: 14px; background: #F29A5C; border-radius: 10px 0 0 0"></div><div style="flex-grow: 1; background: repeating-linear-gradient(180deg, #F7C4A0 0 3px, #FBDCC6 3px 6px)"></div></div>
<div style="height: 48px; display: flex; flex-direction: column"><div style="height: 18px; background: #8C86E3; border-radius: 10px 10px 0 0"></div><div style="flex-grow: 1; background: repeating-linear-gradient(180deg, #C2BEF2 0 3px, #DAD7F8 3px 6px)"></div></div>
<div style="height: 38px; display: flex; flex-direction: column"><div style="height: 12px; background: #D4D3CF; border-radius: 0 10px 0 0"></div><div style="flex-grow: 1"></div></div>
</div>
<div style="display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); text-align: center">
<div style="display: flex; flex-direction: column; gap: 2px"><span style="font-size: 12.5px; font-weight: 600; display: flex; align-items: center; justify-content: center; gap: 6px"><span style="width: 8px; height: 8px; border-radius: 50%; background: #F29A5C"></span>June</span><span style="font-size: 11px; color: #5F5E66">23 lessons</span></div>
<div style="display: flex; flex-direction: column; gap: 2px"><span style="font-size: 12.5px; font-weight: 600; display: flex; align-items: center; justify-content: center; gap: 6px"><span style="width: 8px; height: 8px; border-radius: 50%; background: #8C86E3"></span>July</span><span style="font-size: 11px; color: #5F5E66">43 lessons</span></div>
<div style="display: flex; flex-direction: column; gap: 2px"><span style="font-size: 12.5px; font-weight: 600; display: flex; align-items: center; justify-content: center; gap: 6px"><span style="width: 8px; height: 8px; border-radius: 50%; background: #B9B8B4"></span>August</span><span style="font-size: 11px; color: #5F5E66">12 lessons</span></div>
</div>
</div>
<div style="flex-grow: 1"></div>
<nav aria-label="Main" style="height: 73px; border-radius: 40px; background: #2B2C31; display: flex; align-items: center; justify-content: space-between; padding: 0 22px 0 6px; flex-shrink: 0">
<a href="Main.dc.html" aria-label="Home" style="width: 68px; height: 68px; border-radius: 50%; background: #0D0D0F; display: flex; align-items: center; justify-content: center">
<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><path d="M10.6 3.5a2.2 2.2 0 0 1 2.8 0l6 5A2.2 2.2 0 0 1 20.2 10.2V18a3 3 0 0 1-3 3H6.8a3 3 0 0 1-3-3v-7.8a2.2 2.2 0 0 1 .8-1.7z" fill="#8C86E3"></path><rect x="10.5" y="15" width="3" height="4" rx="1.2" fill="#0D0D0F" opacity=".35"></rect></svg>
</a>
<a href="Courses.dc.html" aria-label="Tasks" style="width: 48px; height: 48px; display: flex; align-items: center; justify-content: center">
<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="3" width="18" height="18" rx="5" fill="#9C9CA4"></rect><path d="M7 9l1.5 1.5L11 8M7 15l1.5 1.5L11 14M13.5 9.5h3.5M13.5 15.5h3.5" fill="none" stroke="#2B2C31" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"></path></svg>
</a>
<a href="Progress.dc.html" aria-label="Timer" style="width: 48px; height: 48px; display: flex; align-items: center; justify-content: center">
<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><rect x="9.5" y="2" width="5" height="3" rx="1.2" fill="#9C9CA4"></rect><circle cx="12" cy="13.5" r="7.5" fill="#9C9CA4"></circle><path d="M12 10v4" stroke="#2B2C31" stroke-width="1.8" stroke-linecap="round"></path><circle cx="12" cy="14.5" r="1.4" fill="#2B2C31"></circle></svg>
</a>
<a href="Courses.dc.html" aria-label="Library" style="width: 48px; height: 48px; display: flex; align-items: center; justify-content: center">
<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 5.5c3-1 6-1 8.3.8V20c-2.3-1.6-5.3-1.8-8.3-.8zM21 5.5c-3-1-6-1-8.3.8V20c2.3-1.6 5.3-1.8 8.3-.8z" fill="#9C9CA4"></path></svg>
</a>
<a href="Progress.dc.html" aria-label="Settings" style="width: 48px; height: 48px; display: flex; align-items: center; justify-content: center">
<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><path d="M10.3 2h3.4l.5 2.6 1.9.8 2.2-1.5 2.4 2.4-1.5 2.2.8 1.9 2.6.5v3.4l-2.6.5-.8 1.9 1.5 2.2-2.4 2.4-2.2-1.5-1.9.8-.5 2.6h-3.4l-.5-2.6-1.9-.8-2.2 1.5-2.4-2.4 1.5-2.2-.8-1.9L2 13.7v-3.4l2.6-.5.8-1.9-1.5-2.2 2.4-2.4 2.2 1.5 1.9-.8z" fill="#9C9CA4"></path><circle cx="12" cy="12" r="3.2" fill="#2B2C31"></circle></svg>
</a>
</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>
```
### Courses
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My courses</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&display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#5B55C9}a:hover{color:#3F3A9E}
</style>
</helmet>
<div style="width: 390px; height: 844px; position: relative; background: #F29A5C; font-family: 'Plus Jakarta Sans', system-ui, sans-serif; color: #1E1E22; overflow: hidden">
<svg width="390" height="380" viewBox="0 0 390 380" aria-hidden="true" style="position: absolute; left: 0; top: 0">
<path d="M150 0c10 60 60 90 20 150s30 120 80 160" fill="none" stroke="#1E1E22" stroke-width="1.2" stroke-dasharray="5 6" opacity=".35"/>
<circle cx="310" cy="70" r="2.5" fill="#FFFFFF"/>
</svg>
<img src="https://developermill.com/app-designs/learning-app-ui-design/assets/8952f89f88.png" alt="" aria-hidden="true" style="position: absolute; right: -36px; top: 74px; width: 230px; height: auto; transform: rotate(-6deg)">
<div style="position: relative; padding: 58px 18px 0; display: flex; flex-direction: column; gap: 20px">
<a href="Main.dc.html" aria-label="Back" style="width: 48px; height: 48px; border-radius: 50%; border: 1.5px solid #1E1E22; display: flex; align-items: center; justify-content: center; box-sizing: border-box">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#1E1E22" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 5l-7 7 7 7"/></svg>
</a>
<h1 style="margin: 18px 0 0; font-size: 40px; line-height: 1.08; font-weight: 800; color: #1E1E22">My<br>courses</h1>
<div style="display: flex; gap: 10px">
<div style="height: 50px; padding: 0 20px; border-radius: 25px; background: #222226; color: #FFFFFF; display: flex; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 600">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="1.8" stroke-linejoin="round" aria-hidden="true"><path d="M3 5c3-1 6-1 9 1v14c-3-2-6-2-9-1zM21 5c-3-1-6-1-9 1v14c3-2 6-2 9-1z"/></svg>
<span>12 Subjects</span>
</div>
<div style="height: 50px; padding: 0 20px; border-radius: 25px; background: #F8B98C; color: #1E1E22; display: flex; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 600; flex-grow: 1; justify-content: center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#1E1E22" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><rect x="3" y="5" width="18" height="14" rx="3"/><path d="M7 10h10M7 14h6"/></svg>
<span>43 Lessons</span>
</div>
</div>
</div>
<div style="position: absolute; left: 0; right: 0; top: 368px; bottom: 0; background: #FFFFFF; border-radius: 34px 34px 0 0; padding: 18px 14px 0; display: flex; flex-direction: column; gap: 14px">
<div style="display: flex; gap: 8px; overflow: hidden">
<div style="height: 46px; padding: 0 16px 0 6px; border-radius: 23px; background: #F3F3F2; display: flex; align-items: center; gap: 10px; font-size: 13px; font-weight: 600; flex-shrink: 0">
<span style="width: 34px; height: 34px; border-radius: 50%; background: #E8F2EC; display: flex; align-items: center; justify-content: center"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#2F8A5B" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 19V6a2 2 0 0 1 2-2h12v15H6a2 2 0 0 0-2 2zM8 8h6"/></svg></span>Literature
</div>
<div style="height: 46px; padding: 0 16px 0 6px; border-radius: 23px; background: #F3F3F2; display: flex; align-items: center; gap: 10px; font-size: 13px; font-weight: 600; flex-shrink: 0">
<span style="width: 34px; height: 34px; border-radius: 50%; background: #FCE6E1; display: flex; align-items: center; justify-content: center"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#C2463A" stroke-width="2" stroke-linecap="round" aria-hidden="true"><rect x="4" y="3" width="16" height="18" rx="2"/><path d="M8 7h8M8 12h2M14 12h2M8 16h2M14 16h2"/></svg></span>Math
</div>
<div style="height: 46px; padding: 0 16px 0 6px; border-radius: 23px; background: #F3F3F2; display: flex; align-items: center; gap: 10px; font-size: 13px; font-weight: 600; flex-shrink: 0">
<span style="width: 34px; height: 34px; border-radius: 50%; background: #ECEBFB; display: flex; align-items: center; justify-content: center"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#5B55C9" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M7 3c0 6 10 6 10 12s-10 3-10 6M17 3c0 6-10 6-10 12M9 7h6M9 17h6"/></svg></span>Biology
</div>
</div>
<div style="position: relative; height: 214px; border-radius: 30px; background: #222226; padding: 18px; box-sizing: border-box; display: flex; flex-direction: column; justify-content: space-between; overflow: hidden">
<svg width="220" height="196" viewBox="0 0 220 196" aria-hidden="true" style="position: absolute; right: 0; top: 0"><path d="M40 196c20-60 80-40 90-100s60-60 90-40" fill="none" stroke="#3A3A40" stroke-width="2"/><circle cx="150" cy="120" r="34" fill="none" stroke="#3A3A40" stroke-width="2"/></svg>
<div style="position: relative; display: flex; justify-content: space-between">
<div style="width: 44px; height: 44px; border-radius: 50%; background: #34343A; display: flex; align-items: center; justify-content: center">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#F29A5C" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 20A16 16 0 0 1 20 4M8 20A12 12 0 0 1 20 8M12 20a8 8 0 0 1 8-8"/></svg>
</div>
<button aria-label="Open in new view" style="width: 36px; height: 36px; border-radius: 10px; border: 1.5px solid #5A5A62; background: transparent; display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 4h6v6M20 4l-9 9M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/></svg>
</button>
</div>
<div style="position: relative; display: flex; flex-direction: column; gap: 4px; max-width: 230px">
<span style="font-size: 10.5px; font-weight: 700; letter-spacing: .06em; color: #F29A5C">GEOMETRY IN ACTION</span>
<span style="font-size: 17px; line-height: 1.25; font-weight: 700; color: #FFFFFF">Creative approaches to plane shapes</span>
</div>
<div style="position: relative; display: flex; align-items: center; justify-content: space-between">
<div style="display: flex; align-items: center">
<img src="https://developermill.com/app-designs/learning-app-ui-design/assets/c010df960b.jpg" alt="" style="width: 32px; height: 32px; border-radius: 50%; background: #F7C94E; border: 2px solid #222226; object-fit: cover">
<img src="https://developermill.com/app-designs/learning-app-ui-design/assets/2d27f11ef0.jpg" alt="" style="width: 32px; height: 32px; border-radius: 50%; background: #D9D6F7; border: 2px solid #222226; margin-left: -10px; object-fit: cover">
<img src="https://developermill.com/app-designs/learning-app-ui-design/assets/bdc0ee622c.jpg" alt="" style="width: 32px; height: 32px; border-radius: 50%; background: #BFE3CF; border: 2px solid #222226; margin-left: -10px; object-fit: cover">
<span style="margin-left: 8px; font-size: 13px; font-weight: 600; color: #FFFFFF">+43</span>
</div>
<div style="position: relative; width: 74px; height: 74px; margin: 0 -8px -8px 0"><svg width="74" height="74" viewBox="0 0 74 74" role="img" aria-label="82% complete" style="position: absolute; left: 0; top: 0"><circle cx="37" cy="37" r="34" fill="none" stroke="#F29A5C" stroke-width="3" stroke-linecap="round" stroke-dasharray="175.2 400" transform="rotate(-80 37 37)"/></svg><button aria-label="Open course" style="position: absolute; left: 9px; top: 9px; width: 56px; height: 56px; border-radius: 50%; background: #FFFFFF; border: 0; display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#1E1E22" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
</button>
</div>
</div>
</div>
<div style="position: relative; height: 214px; border-radius: 30px; background: #A9A4EE; padding: 18px; box-sizing: border-box; display: flex; flex-direction: column; justify-content: space-between; overflow: hidden">
<svg width="220" height="196" viewBox="0 0 220 196" aria-hidden="true" style="position: absolute; right: 0; top: 0"><circle cx="160" cy="140" r="56" fill="none" stroke="#BDB9F3" stroke-width="2"/><circle cx="160" cy="140" r="30" fill="none" stroke="#BDB9F3" stroke-width="2"/></svg>
<div style="position: relative; display: flex; justify-content: space-between">
<div style="width: 44px; height: 44px; border-radius: 50%; background: #222226; display: flex; align-items: center; justify-content: center">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M7 3c0 6 10 6 10 12s-10 3-10 6M17 3c0 6-10 6-10 12M9 7h6M9 17h6"/></svg>
</div>
<button aria-label="Open in new view" style="width: 40px; height: 40px; border-radius: 50%; border: 0; background: #222226; display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 4h6v6M20 4l-9 9M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/></svg>
</button>
</div>
<div style="position: relative; display: flex; flex-direction: column; gap: 4px; max-width: 230px">
<span style="font-size: 10.5px; font-weight: 700; letter-spacing: .06em; color: #2D2A6E">THE MICROCOSM AROUND US</span>
<span style="font-size: 17px; line-height: 1.25; font-weight: 700; color: #1E1E22">Discoveries in cell biology</span>
</div>
<div style="position: relative; display: flex; align-items: center; justify-content: space-between">
<div style="display: flex; align-items: center">
<img src="https://developermill.com/app-designs/learning-app-ui-design/assets/f7d3a0c391.jpg" alt="" style="width: 32px; height: 32px; border-radius: 50%; background: #F7C94E; border: 2px solid #A9A4EE; object-fit: cover">
<img src="https://developermill.com/app-designs/learning-app-ui-design/assets/bdc0ee622c.jpg" alt="" style="width: 32px; height: 32px; border-radius: 50%; background: #FDEBDD; border: 2px solid #A9A4EE; margin-left: -10px; object-fit: cover">
<img src="https://developermill.com/app-designs/learning-app-ui-design/assets/2d27f11ef0.jpg" alt="" style="width: 32px; height: 32px; border-radius: 50%; background: #BFE3CF; border: 2px solid #A9A4EE; margin-left: -10px; object-fit: cover">
<span style="margin-left: 8px; font-size: 13px; font-weight: 600; color: #1E1E22">+12</span>
</div>
<div style="position: relative; width: 74px; height: 74px; margin: 0 -8px -8px 0"><svg width="74" height="74" viewBox="0 0 74 74" role="img" aria-label="50% complete" style="position: absolute; left: 0; top: 0"><circle cx="37" cy="37" r="34" fill="none" stroke="#1E1E22" stroke-width="3" stroke-linecap="round" stroke-dasharray="106.8 400" transform="rotate(-80 37 37)"/></svg><button aria-label="Open course" style="position: absolute; left: 9px; top: 9px; width: 56px; height: 56px; border-radius: 50%; background: #FFFFFF; border: 0; display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#1E1E22" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
</button>
</div>
</div>
</div>
</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 {};
}
}
</script>
</body>
</html>
```
### Progress
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Progress</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&display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#5B55C9}a:hover{color:#3F3A9E}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; padding: 56px 18px 22px; display: flex; flex-direction: column; gap: 16px; background: #FFFFFF; font-family: 'Plus Jakarta Sans', system-ui, sans-serif; color: #1E1E22; overflow: hidden">
<div style="display: flex; align-items: center; gap: 12px">
<div style="width: 54px; height: 54px; border-radius: 50%; background: #D9D6F7; display: flex; align-items: center; justify-content: center; flex-shrink: 0">
<img src="https://developermill.com/app-designs/learning-app-ui-design/assets/f7d3a0c391.jpg" alt="Jacob" style="width: 54px; height: 54px; border-radius: 50%; object-fit: cover">
</div>
<div style="display: flex; flex-direction: column; gap: 3px; flex-grow: 1">
<div style="font-size: 19px; font-weight: 700">Hello, Jacob</div>
<div style="display: flex; align-items: center; gap: 5px; font-size: 13px; color: #55545C">
<svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true"><path d="M13 2 4 14h7l-1 8 9-12h-7z" fill="#8C86E3"></path></svg>
<span>Progress: 76%</span>
</div>
</div>
<button aria-label="Notifications" style="position: relative; width: 50px; height: 50px; border-radius: 50%; border: 1.5px solid #DCDAD6; background: #FFFFFF; display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#1E1E22" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><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 2.2 0 0 0 4 0"></path></svg>
<span style="position: absolute; top: 2px; right: 4px; width: 9px; height: 9px; border-radius: 50%; background: #F0645A"></span>
</button>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; margin-top: 6px">
<h1 style="margin: 0; font-size: 32px; font-weight: 800">Progress</h1>
<button style="height: 44px; padding: 0 14px 0 8px; border-radius: 22px; border: 0; background: #F3F3F2; display: flex; align-items: center; gap: 8px; font-family: inherit; font-size: 13px; font-weight: 600; color: #1E1E22; cursor: pointer">
<span style="width: 30px; height: 30px; border-radius: 9px; background: #ECEBFB; display: flex; align-items: center; justify-content: center"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="#5B55C9" stroke-width="2" stroke-linecap="round" aria-hidden="true"><rect x="3" y="5" width="18" height="14" rx="3"></rect><path d="M7 10h10M7 14h6"></path></svg></span>
All subjects
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#1E1E22" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 9l6 6 6-6"></path></svg>
</button>
</div>
<div style="position: relative; border-radius: 30px; background: #FBEADC; border: 1.5px solid #F2C29E; padding: 16px 18px 18px; display: flex; flex-direction: column; gap: 14px; overflow: hidden">
<svg width="360" height="380" viewBox="0 0 360 380" aria-hidden="true" style="position: absolute; left: 0; top: 0"><path d="M-20 300c80-40 120 20 200-40s120-40 200-10" fill="none" stroke="#F5D6BF" stroke-width="2"></path></svg>
<div style="position: relative; display: flex; align-items: center; justify-content: space-between">
<div style="width: 46px; height: 46px; border-radius: 50%; background: #222226; display: flex; align-items: center; justify-content: center">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2.2" stroke-linecap="round" aria-hidden="true"><path d="M6 20V12M12 20V5M18 20v-6"></path></svg>
</div>
<div style="display: flex; padding: 4px; border-radius: 22px; background: #F6D5BE">
<button style="height: 36px; padding: 0 16px; border-radius: 18px; border: 0; background: #222226; color: #FFFFFF; font-family: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer">Weekly</button>
<button style="height: 36px; padding: 0 14px; border-radius: 18px; border: 0; background: transparent; color: #1E1E22; font-family: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer">Month</button>
</div>
</div>
<div style="position: relative; display: flex; gap: 28px; align-items: baseline">
<div style="display: flex; align-items: baseline; gap: 6px"><span style="font-size: 30px; font-weight: 700">48</span><span style="font-size: 17px; font-weight: 500">lessons</span></div>
<div style="display: flex; align-items: baseline; gap: 6px"><span style="font-size: 30px; font-weight: 700">12</span><span style="font-size: 17px; font-weight: 500">hours</span></div>
</div>
<div style="position: relative; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); align-items: end; height: 220px">
<sc-for list="{{bars}}" as="bar" hint-placeholder-count="5">
<div style="display: flex; flex-direction: column; align-items: center; gap: 8px">
<div style="width: 38px; height: 192px; border-radius: 19px; display: flex; flex-direction: column; justify-content: flex-end">
<div style="{{bar.fillStyle}}">
<span style="margin-top: 13px; font-size: 11.5px; font-weight: 700; color: #FFFFFF">{{bar.value}}</span>
</div>
</div>
<span style="font-size: 11.5px; color: #5F5E66">{{bar.day}}</span>
</div>
</sc-for>
</div>
</div>
<div style="display: flex; justify-content: center; gap: 6px" aria-hidden="true">
<span style="width: 8px; height: 8px; border-radius: 50%; background: #222226"></span>
<span style="width: 8px; height: 8px; border-radius: 50%; background: #C9C8C4"></span>
<span style="width: 8px; height: 8px; border-radius: 50%; background: #C9C8C4"></span>
</div>
<div style="height: 70px; border-radius: 24px; background: #F3F3F2; padding: 0 14px; display: flex; align-items: center; gap: 12px">
<div style="width: 44px; height: 44px; border-radius: 50%; background: #FDF0C7; display: flex; align-items: center; justify-content: center">
<div style="width: 30px; height: 30px; border-radius: 50%; background: #F7C94E; display: flex; align-items: center; justify-content: center">
<svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3l2.6 5.6 6 .7-4.5 4.1 1.2 6L12 16.4 6.7 19.4l1.2-6L3.4 9.3l6-.7z" fill="#FFFFFF"></path></svg>
</div>
</div>
<div style="display: flex; flex-direction: column; gap: 2px; flex-grow: 1">
<span style="font-size: 14px; font-weight: 700">Rating of students</span>
<span style="font-size: 11.5px; color: #5F5E66">10 best students</span>
</div>
<div style="display: flex; align-items: center">
<img src="https://developermill.com/app-designs/learning-app-ui-design/assets/bdc0ee622c.jpg" alt="" style="width: 32px; height: 32px; border-radius: 50%; background: #FDEBDD; border: 2px solid #FFFFFF; object-fit: cover">
<img src="https://developermill.com/app-designs/learning-app-ui-design/assets/c010df960b.jpg" alt="" style="width: 32px; height: 32px; border-radius: 50%; background: #F7C94E; border: 2px solid #FFFFFF; margin-left: -10px; object-fit: cover">
<img src="https://developermill.com/app-designs/learning-app-ui-design/assets/2d27f11ef0.jpg" alt="" style="width: 32px; height: 32px; border-radius: 50%; background: #BFE3CF; border: 2px solid #FFFFFF; margin-left: -10px; object-fit: cover">
</div>
</div>
<div style="flex-grow: 1"></div>
<nav aria-label="Main" style="height: 74px; border-radius: 40px; background: #2B2C31; display: flex; align-items: center; justify-content: space-between; padding: 0 22px; flex-shrink: 0">
<a href="Main.dc.html" aria-label="Home" style="width: 48px; height: 48px; display: flex; align-items: center; justify-content: center">
<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><path d="M10.6 3.5a2.2 2.2 0 0 1 2.8 0l6 5A2.2 2.2 0 0 1 20.2 10.2V18a3 3 0 0 1-3 3H6.8a3 3 0 0 1-3-3v-7.8a2.2 2.2 0 0 1 .8-1.7z" fill="#9C9CA4"></path><rect x="10.5" y="15" width="3" height="4" rx="1.2" fill="#2B2C31"></rect></svg>
</a>
<a href="Courses.dc.html" aria-label="Tasks" style="width: 48px; height: 48px; display: flex; align-items: center; justify-content: center">
<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="3" width="18" height="18" rx="5" fill="#9C9CA4"></rect><path d="M7 9l1.5 1.5L11 8M7 15l1.5 1.5L11 14M13.5 9.5h3.5M13.5 15.5h3.5" fill="none" stroke="#2B2C31" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"></path></svg>
</a>
<a href="Progress.dc.html" aria-label="Timer" aria-current="page" style="width: 68px; height: 68px; border-radius: 50%; background: #0D0D0F; display: flex; align-items: center; justify-content: center">
<svg width="26" height="26" viewBox="0 0 24 24" aria-hidden="true"><rect x="9.5" y="2" width="5" height="3" rx="1.2" fill="#F29A5C"></rect><circle cx="12" cy="13.5" r="7.5" fill="#8C86E3"></circle><path d="M12 10v4" stroke="#FFFFFF" stroke-width="1.8" stroke-linecap="round"></path><circle cx="12" cy="14.5" r="1.4" fill="#FFFFFF"></circle></svg>
</a>
<a href="Courses.dc.html" aria-label="Library" style="width: 48px; height: 48px; display: flex; align-items: center; justify-content: center">
<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 5.5c3-1 6-1 8.3.8V20c-2.3-1.6-5.3-1.8-8.3-.8zM21 5.5c-3-1-6-1-8.3.8V20c2.3-1.6 5.3-1.8 8.3-.8z" fill="#9C9CA4"></path></svg>
</a>
<a href="Main.dc.html" aria-label="Settings" style="width: 48px; height: 48px; display: flex; align-items: center; justify-content: center">
<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><path d="M10.3 2h3.4l.5 2.6 1.9.8 2.2-1.5 2.4 2.4-1.5 2.2.8 1.9 2.6.5v3.4l-2.6.5-.8 1.9 1.5 2.2-2.4 2.4-2.2-1.5-1.9.8-.5 2.6h-3.4l-.5-2.6-1.9-.8-2.2 1.5-2.4-2.4 1.5-2.2-.8-1.9L2 13.7v-3.4l2.6-.5.8-1.9-1.5-2.2 2.4-2.4 2.2 1.5 1.9-.8z" fill="#9C9CA4"></path><circle cx="12" cy="12" r="3.2" fill="#2B2C31"></circle></svg>
</a>
</nav>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"barColor":{"editor":"color","default":"#C8693A","options":["#C8693A","#8C86E3","#222226"]},"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
const color = this.props.barColor ?? '#C8693A';
const data = [['Mon', 39], ['Tue', 14], ['Wed', 48], ['Thr', 24], ['Fri', 22]];
const bars = data.map(([day, value]) => {
const h = Math.round(44 + (value / 48) * 148);
const striped = day === 'Wed';
const bg = striped
? `linear-gradient(180deg, ${color} 0 40px, transparent 40px), repeating-linear-gradient(135deg, ${color} 0 6px, #E9A57E 6px 12px)`
: `linear-gradient(180deg, ${color} 0 40px, #EFC3A4 40px)`;
return {
day, value,
fillStyle: `height: ${h}px; width: 38px; border-radius: 19px; background: ${bg}; display: flex; justify-content: center`
};
});
return { bars };
}
}
</script>
</body>
</html>
```SKILL.md
Save as .claude/skills/learning-app-ui/SKILL.md
--- name: learning-app-ui description: Build the Learning Platform mobile app UI in Expo React Native. Use when asked to create a learning app UI or a new screen in this visual style. --- # Learning Platform app UI Build this UI in an Expo SDK 58 app with Expo Router and strict TypeScript. Match the spec below rather than inventing a new look. The finished reference lives at https://developermill.com/app-designs/learning-app-ui-design ## Visual direction Periwinkle and tangerine on white, large rounded cards with glossy 3D objects and sketched lines behind them. Keep these signature details: - Hero card with progress ring action - Course cards with avatars and completion rings - Weekly progress bars with a striped peak day - Dark floating tab bar with a raised active item ## Set up ```bash npx expo install expo-image react-native-svg @expo-google-fonts/plus-jakarta-sans expo-font ``` ## Tokens | Token | Hex | | --- | --- | | Periwinkle | `#8C86E3` | | Tangerine | `#F29A5C` | | Charcoal | `#222226` | | Sun | `#F7C94E` | | Lilac | `#ECEBFB` | | Cloud | `#F3F3F2` | - Typefaces: Plus Jakarta Sans - Common sizes (px): 11, 11.5, 12.5, 13, 13.5, 17, 19, 44 - Common corner radii (px): 10, 23, 24, 25, 30, 40 Define these once and reuse them. Do not add new colours. ## Screens Build one Expo Router route per screen, in this order: 1. **Student home**: Greeting with progress, a large Olympiads hero with a 3D trophy, lesson and hour counters, and monthly performance. 2. **My courses**: An orange header with a 3D graduation cap, subject chips and course cards with classmates and progress rings. 3. **Progress**: A subject filter, weekly and monthly toggle, lesson and hour totals, rounded day bars and a student rating row. ## Build rules - Design on a 390 × 844 artboard, then scale to the device width so layouts match on every phone. - Load each custom font weight by its own family name with expo-font. Do not rely on `fontWeight` with custom fonts. - Draw icons, charts and illustrations with react-native-svg rather than image files or chart libraries. - Use `Pressable` with an `accessibilityLabel` for every icon-only control, and keep touch targets at 44 px or larger. - Wire navigation with `router.navigate`, and keep sample data in constants at the top of each file so it is easy to replace. - Use expo-image for photos, with `contentFit` set explicitly. ## Done when - Every screen above exists as a route and they link together. - Colours, type and radii match the tokens exactly. - `npx tsc --noEmit` and `npx expo lint` both pass. - Layouts hold up on small and large phones.
Set up the project
npx create-expo-app@latest learning-app --template default cd learning-app rm -rf src npx expo install expo-image react-native-svg @expo-google-fonts/plus-jakarta-sans expo-font
src/app/_layout.tsx
import {
PlusJakartaSans_400Regular,
PlusJakartaSans_500Medium,
PlusJakartaSans_600SemiBold,
PlusJakartaSans_700Bold,
PlusJakartaSans_800ExtraBold,
} 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,
PlusJakartaSans_800ExtraBold,
});
if (!fontsLoaded) return null;
return <Stack screenOptions={{ headerShown: false }} />;
}src/app/courses.tsx
import { Image } from 'expo-image';
import { router } from 'expo-router';
import { Pressable, Text, View } from 'react-native';
import Svg, { Circle, Path, Rect } from 'react-native-svg';
import { Screen } from '@/components/screen';
import { asset } from '@/lib/assets';
export default function CoursesScreen() {
return (
<Screen background="#F29A5C" statusBar="dark">
<View style={{ flex: 1 }}>
<Svg
width="390"
height="380"
viewBox="0 0 390 380"
style={{ position: 'absolute', left: 0, top: 0 }}>
<Path
d="M150 0c10 60 60 90 20 150s30 120 80 160"
fill="none"
stroke="#1E1E22"
strokeWidth="1.2"
strokeDasharray="5 6"
opacity=".35"
/>
<Circle cx="310" cy="70" r="2.5" fill="#FFFFFF" />
</Svg>
<Image
source={{ uri: asset('8952f89f88.png') }}
contentFit="fill"
style={{
position: 'absolute',
right: -36,
top: 74,
width: 230,
transform: [{ rotate: '-6deg' }],
aspectRatio: 1.208,
}}
/>
<View style={{ paddingTop: 58, paddingBottom: 0, paddingHorizontal: 18, gap: 20 }}>
<Pressable
accessibilityRole="link"
accessibilityLabel="Back"
onPress={() => router.navigate('/')}
style={{
width: 48,
height: 48,
borderRadius: '50%',
borderWidth: 1.5,
borderColor: '#1E1E22',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="#1E1E22"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M15 5l-7 7 7 7" />
</Svg>
</Pressable>
<Text
style={{
marginTop: 18,
marginBottom: 0,
marginHorizontal: 0,
fontFamily: 'PlusJakartaSans_800ExtraBold',
fontSize: 40,
color: '#1E1E22',
lineHeight: 43.2,
}}>
My{'\n'}courses
</Text>
<View style={{ gap: 10, flexDirection: 'row' }}>
<View
style={{
height: 50,
paddingVertical: 0,
paddingHorizontal: 20,
borderRadius: 25,
backgroundColor: '#222226',
alignItems: 'center',
gap: 8,
flexShrink: 1,
flexDirection: 'row',
}}>
<Svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="1.8"
strokeLinejoin="round">
<Path d="M3 5c3-1 6-1 9 1v14c-3-2-6-2-9-1zM21 5c-3-1-6-1-9 1v14c3-2 6-2 9-1z" />
</Svg>
<Text
style={{
flexShrink: 1,
fontFamily: 'PlusJakartaSans_600SemiBold',
fontSize: 13.5,
color: '#FFFFFF',
}}>
12 Subjects
</Text>
</View>
<View
style={{
height: 50,
paddingVertical: 0,
paddingHorizontal: 20,
borderRadius: 25,
backgroundColor: '#F8B98C',
alignItems: 'center',
gap: 8,
flexGrow: 1,
justifyContent: 'center',
flexShrink: 1,
flexDirection: 'row',
}}>
<Svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="#1E1E22"
strokeWidth="1.8"
strokeLinecap="round">
<Rect x="3" y="5" width="18" height="14" rx="3" />
<Path d="M7 10h10M7 14h6" />
</Svg>
<Text
style={{
flexShrink: 1,
fontFamily: 'PlusJakartaSans_600SemiBold',
fontSize: 13.5,
color: '#1E1E22',
}}>
43 Lessons
</Text>
</View>
</View>
</View>
<View
style={{
position: 'absolute',
left: 0,
right: 0,
top: 368,
bottom: 0,
backgroundColor: '#FFFFFF',
borderTopLeftRadius: 34,
borderTopRightRadius: 34,
borderBottomRightRadius: 0,
borderBottomLeftRadius: 0,
paddingTop: 18,
paddingBottom: 0,
paddingHorizontal: 14,
gap: 14,
}}>
<View style={{ gap: 8, overflow: 'hidden', flexDirection: 'row' }}>
<View
style={{
height: 46,
paddingVertical: 0,
paddingLeft: 6,
paddingRight: 16,
borderRadius: 23,
backgroundColor: '#F3F3F2',
alignItems: 'center',
gap: 10,
flexShrink: 0,
flexDirection: 'row',
}}>
<View
style={{
width: 34,
height: 34,
borderRadius: '50%',
backgroundColor: '#E8F2EC',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="#2F8A5B"
strokeWidth="2"
strokeLinecap="round">
<Path d="M4 19V6a2 2 0 0 1 2-2h12v15H6a2 2 0 0 0-2 2zM8 8h6" />
</Svg>
</View>
<Text
style={{
fontFamily: 'PlusJakartaSans_600SemiBold',
fontSize: 13,
color: '#1E1E22',
flexShrink: 1,
}}>
Literature
</Text>
</View>
<View
style={{
height: 46,
paddingVertical: 0,
paddingLeft: 6,
paddingRight: 16,
borderRadius: 23,
backgroundColor: '#F3F3F2',
alignItems: 'center',
gap: 10,
flexShrink: 0,
flexDirection: 'row',
}}>
<View
style={{
width: 34,
height: 34,
borderRadius: '50%',
backgroundColor: '#FCE6E1',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="#C2463A"
strokeWidth="2"
strokeLinecap="round">
<Rect x="4" y="3" width="16" height="18" rx="2" />
<Path d="M8 7h8M8 12h2M14 12h2M8 16h2M14 16h2" />
</Svg>
</View>
<Text
style={{
fontFamily: 'PlusJakartaSans_600SemiBold',
fontSize: 13,
color: '#1E1E22',
flexShrink: 1,
}}>
Math
</Text>
</View>
<View
style={{
height: 46,
paddingVertical: 0,
paddingLeft: 6,
paddingRight: 16,
borderRadius: 23,
backgroundColor: '#F3F3F2',
alignItems: 'center',
gap: 10,
flexShrink: 0,
flexDirection: 'row',
}}>
<View
style={{
width: 34,
height: 34,
borderRadius: '50%',
backgroundColor: '#ECEBFB',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="#5B55C9"
strokeWidth="2"
strokeLinecap="round">
<Path d="M7 3c0 6 10 6 10 12s-10 3-10 6M17 3c0 6-10 6-10 12M9 7h6M9 17h6" />
</Svg>
</View>
<Text
style={{
fontFamily: 'PlusJakartaSans_600SemiBold',
fontSize: 13,
color: '#1E1E22',
flexShrink: 1,
}}>
Biology
</Text>
</View>
</View>
<View
style={{
height: 214,
flexShrink: 1,
borderRadius: 30,
backgroundColor: '#222226',
padding: 18,
justifyContent: 'space-between',
overflow: 'hidden',
}}>
<Svg
width="220"
height="196"
viewBox="0 0 220 196"
style={{ position: 'absolute', right: 0, top: 0 }}>
<Path
d="M40 196c20-60 80-40 90-100s60-60 90-40"
fill="none"
stroke="#3A3A40"
strokeWidth="2"
/>
<Circle cx="150" cy="120" r="34" fill="none" stroke="#3A3A40" strokeWidth="2" />
</Svg>
<View style={{ justifyContent: 'space-between', flexDirection: 'row' }}>
<View
style={{
width: 44,
height: 44,
borderRadius: '50%',
backgroundColor: '#34343A',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#F29A5C"
strokeWidth="2"
strokeLinecap="round">
<Path d="M4 20A16 16 0 0 1 20 4M8 20A12 12 0 0 1 20 8M12 20a8 8 0 0 1 8-8" />
</Svg>
</View>
<Pressable
accessibilityRole="button"
accessibilityLabel="Open in new view"
style={{
width: 36,
height: 36,
borderRadius: 10,
borderWidth: 1.5,
borderColor: '#5A5A62',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M14 4h6v6M20 4l-9 9M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5" />
</Svg>
</Pressable>
</View>
<View style={{ gap: 4, maxWidth: 230 }}>
<Text
style={{
fontFamily: 'PlusJakartaSans_700Bold',
fontSize: 10.5,
color: '#F29A5C',
letterSpacing: 0.63,
}}>
GEOMETRY IN ACTION
</Text>
<Text
style={{
fontFamily: 'PlusJakartaSans_700Bold',
fontSize: 17,
color: '#FFFFFF',
lineHeight: 21.25,
}}>
Creative approaches to plane shapes
</Text>
</View>
<View
style={{
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
}}>
<View style={{ alignItems: 'center', flexShrink: 1, flexDirection: 'row' }}>
<Image
source={{ uri: asset('c010df960b.jpg') }}
contentFit="cover"
style={{
width: 36,
height: 36,
borderRadius: '50%',
backgroundColor: '#F7C94E',
borderWidth: 2,
borderColor: '#222226',
}}
/>
<Image
source={{ uri: asset('2d27f11ef0.jpg') }}
contentFit="cover"
style={{
width: 36,
height: 36,
borderRadius: '50%',
backgroundColor: '#D9D6F7',
borderWidth: 2,
borderColor: '#222226',
marginLeft: -10,
}}
/>
<Image
source={{ uri: asset('bdc0ee622c.jpg') }}
contentFit="cover"
style={{
width: 36,
height: 36,
borderRadius: '50%',
backgroundColor: '#BFE3CF',
borderWidth: 2,
borderColor: '#222226',
marginLeft: -10,
}}
/>
<Text
style={{
marginLeft: 8,
flexShrink: 1,
fontFamily: 'PlusJakartaSans_600SemiBold',
fontSize: 13,
color: '#FFFFFF',
}}>
+43
</Text>
</View>
<View
style={{
width: 74,
height: 74,
marginTop: 0,
marginBottom: -8,
marginLeft: 0,
marginRight: -8,
}}>
<Svg
width="74"
height="74"
viewBox="0 0 74 74"
accessibilityRole="image"
accessibilityLabel="82% complete"
style={{ position: 'absolute', left: 0, top: 0 }}>
<Circle
cx="37"
cy="37"
r="34"
fill="none"
stroke="#F29A5C"
strokeWidth="3"
strokeLinecap="round"
strokeDasharray="175.2 400"
transform="rotate(-80 37 37)"
/>
</Svg>
<Pressable
accessibilityRole="button"
accessibilityLabel="Open course"
style={{
position: 'absolute',
left: 9,
top: 9,
width: 56,
height: 56,
borderRadius: '50%',
backgroundColor: '#FFFFFF',
borderWidth: 0,
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#1E1E22"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M5 12h14M13 6l6 6-6 6" />
</Svg>
</Pressable>
</View>
</View>
</View>
<View
style={{
height: 214,
flexShrink: 1,
borderRadius: 30,
backgroundColor: '#A9A4EE',
padding: 18,
justifyContent: 'space-between',
overflow: 'hidden',
}}>
<Svg
width="220"
height="196"
viewBox="0 0 220 196"
style={{ position: 'absolute', right: 0, top: 0 }}>
<Circle cx="160" cy="140" r="56" fill="none" stroke="#BDB9F3" strokeWidth="2" />
<Circle cx="160" cy="140" r="30" fill="none" stroke="#BDB9F3" strokeWidth="2" />
</Svg>
<View style={{ justifyContent: 'space-between', flexDirection: 'row' }}>
<View
style={{
width: 44,
height: 44,
borderRadius: '50%',
backgroundColor: '#222226',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round">
<Path d="M7 3c0 6 10 6 10 12s-10 3-10 6M17 3c0 6-10 6-10 12M9 7h6M9 17h6" />
</Svg>
</View>
<Pressable
accessibilityRole="button"
accessibilityLabel="Open in new view"
style={{
width: 40,
height: 40,
borderRadius: '50%',
borderWidth: 0,
backgroundColor: '#222226',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M14 4h6v6M20 4l-9 9M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5" />
</Svg>
</Pressable>
</View>
<View style={{ gap: 4, maxWidth: 230 }}>
<Text
style={{
fontFamily: 'PlusJakartaSans_700Bold',
fontSize: 10.5,
color: '#2D2A6E',
letterSpacing: 0.63,
}}>
THE MICROCOSM AROUND US
</Text>
<Text
style={{
fontFamily: 'PlusJakartaSans_700Bold',
fontSize: 17,
color: '#1E1E22',
lineHeight: 21.25,
}}>
Discoveries in cell biology
</Text>
</View>
<View
style={{
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
}}>
<View style={{ alignItems: 'center', flexShrink: 1, flexDirection: 'row' }}>
<Image
source={{ uri: asset('f7d3a0c391.jpg') }}
contentFit="cover"
style={{
width: 36,
height: 36,
borderRadius: '50%',
backgroundColor: '#F7C94E',
borderWidth: 2,
borderColor: '#A9A4EE',
}}
/>
<Image
source={{ uri: asset('bdc0ee622c.jpg') }}
contentFit="cover"
style={{
width: 36,
height: 36,
borderRadius: '50%',
backgroundColor: '#FDEBDD',
borderWidth: 2,
borderColor: '#A9A4EE',
marginLeft: -10,
}}
/>
<Image
source={{ uri: asset('2d27f11ef0.jpg') }}
contentFit="cover"
style={{
width: 36,
height: 36,
borderRadius: '50%',
backgroundColor: '#BFE3CF',
borderWidth: 2,
borderColor: '#A9A4EE',
marginLeft: -10,
}}
/>
<Text
style={{
marginLeft: 8,
flexShrink: 1,
fontFamily: 'PlusJakartaSans_600SemiBold',
fontSize: 13,
color: '#1E1E22',
}}>
+12
</Text>
</View>
<View
style={{
width: 74,
height: 74,
marginTop: 0,
marginBottom: -8,
marginLeft: 0,
marginRight: -8,
}}>
<Svg
width="74"
height="74"
viewBox="0 0 74 74"
accessibilityRole="image"
accessibilityLabel="50% complete"
style={{ position: 'absolute', left: 0, top: 0 }}>
<Circle
cx="37"
cy="37"
r="34"
fill="none"
stroke="#1E1E22"
strokeWidth="3"
strokeLinecap="round"
strokeDasharray="106.8 400"
transform="rotate(-80 37 37)"
/>
</Svg>
<Pressable
accessibilityRole="button"
accessibilityLabel="Open course"
style={{
position: 'absolute',
left: 9,
top: 9,
width: 56,
height: 56,
borderRadius: '50%',
backgroundColor: '#FFFFFF',
borderWidth: 0,
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#1E1E22"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M5 12h14M13 6l6 6-6 6" />
</Svg>
</Pressable>
</View>
</View>
</View>
</View>
</View>
</Screen>
);
}src/app/index.tsx
import { Image } from 'expo-image';
import { router } from 'expo-router';
import { Pressable, Text, View } from 'react-native';
import Svg, { Circle, Path, Rect, Text as SvgText } from 'react-native-svg';
import { Screen } from '@/components/screen';
import { Stripes } from '@/components/stripes';
import { asset } from '@/lib/assets';
export default function MainScreen() {
return (
<Screen background="#FFFFFF" statusBar="dark">
<View style={{ paddingTop: 56, paddingBottom: 22, paddingHorizontal: 18, gap: 14, flex: 1 }}>
<View style={{ alignItems: 'center', gap: 12, flexDirection: 'row' }}>
<View
style={{
width: 54,
height: 54,
borderRadius: '50%',
backgroundColor: '#D9D6F7',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Image
source={{ uri: asset('f7d3a0c391.jpg') }}
contentFit="cover"
accessibilityLabel="Jacob"
style={{ width: 54, height: 54, borderRadius: '50%' }}
/>
</View>
<View style={{ gap: 3, flexGrow: 1, flexShrink: 1 }}>
<Text style={{ fontFamily: 'PlusJakartaSans_700Bold', fontSize: 19, color: '#1E1E22' }}>
Hello, Jacob
</Text>
<View style={{ alignItems: 'center', gap: 5, flexDirection: 'row' }}>
<Svg width="14" height="14" viewBox="0 0 24 24">
<Path d="M13 2 4 14h7l-1 8 9-12h-7z" fill="#8C86E3" />
</Svg>
<Text
style={{
flexShrink: 1,
fontFamily: 'PlusJakartaSans_400Regular',
fontSize: 13,
color: '#55545C',
}}>
Progress: 76%
</Text>
</View>
</View>
<Pressable
accessibilityRole="button"
accessibilityLabel="Notifications"
style={{
width: 50,
height: 50,
borderRadius: '50%',
borderWidth: 1.5,
borderColor: '#DCDAD6',
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#1E1E22"
strokeWidth="1.8"
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 2.2 0 0 0 4 0" />
</Svg>
<View
style={{
position: 'absolute',
top: 2,
right: 4,
width: 9,
height: 9,
borderRadius: '50%',
backgroundColor: '#F0645A',
}}
/>
</Pressable>
</View>
<View style={{ height: 290, flexShrink: 0 }}>
<View
style={{
position: 'absolute',
left: 8,
right: 8,
bottom: 0,
height: 80,
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
borderBottomRightRadius: 36,
borderBottomLeftRadius: 36,
backgroundColor: '#6C67CF',
transform: [{ rotate: '-1.6deg' }],
transformOrigin: 'right bottom',
}}
/>
<View
style={{
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 12,
borderRadius: 38,
backgroundColor: '#7F7BDE',
paddingTop: 30,
paddingBottom: 22,
paddingHorizontal: 22,
overflow: 'hidden',
}}>
<Svg
width="354"
height="278"
viewBox="0 0 354 278"
style={{ position: 'absolute', left: 0, top: 0 }}>
<Path d="M70 18l2 5 5 2-5 2-2 5-2-5-5-2 5-2z" fill="#9C98E8" />
<Path
d="M178 8l1.6 4 4 1.6-4 1.6-1.6 4-1.6-4-4-1.6 4-1.6z"
fill="#2F2B7A"
opacity=".55"
/>
<Path
d="M300 22l3.5 7.5 8 1-6 5.5 1.6 8-7.1-4-7.1 4 1.6-8-6-5.5 8-1z"
fill="#F7C94E"
stroke="#1E1E22"
strokeWidth="1.5"
strokeLinejoin="round"
/>
<Path
d="M200 200l2.5 6 6 2.5-6 2.5-2.5 6-2.5-6-6-2.5 6-2.5z"
fill="#F7C94E"
stroke="#1E1E22"
strokeWidth="1.2"
strokeLinejoin="round"
/>
<Path
d="M320 238l2.5 6 6 2.5-6 2.5-2.5 6-2.5-6-6-2.5 6-2.5z"
fill="#F7C94E"
stroke="#1E1E22"
strokeWidth="1.2"
strokeLinejoin="round"
/>
<Path
d="M250 50c20-10 40-12 60-6"
fill="none"
stroke="#9C98E8"
strokeWidth="1.5"
strokeLinecap="round"
/>
<SvgText
x="172"
y="182"
fontFamily="PlusJakartaSans_400Regular"
fontSize="17"
fill="#A9A6EE">
y=?
</SvgText>
</Svg>
<Image
source={{ uri: asset('d13b1ea5dd.png') }}
contentFit="fill"
style={{
position: 'absolute',
right: -26,
top: 58,
width: 196,
transform: [{ rotate: '12deg' }],
aspectRatio: 0.95,
}}
/>
<View style={{ gap: 12 }}>
<Text
style={{
margin: 0,
maxWidth: 220,
fontFamily: 'PlusJakartaSans_800ExtraBold',
fontSize: 34,
color: '#FFFFFF',
letterSpacing: -0.5,
lineHeight: 37.4,
}}>
A series of Olympiads
</Text>
<Text
style={{
margin: 0,
maxWidth: 250,
fontFamily: 'PlusJakartaSans_400Regular',
fontSize: 13,
color: '#EFEEFF',
lineHeight: 20.15,
}}>
{'A series of '}
<Text style={{ fontFamily: 'PlusJakartaSans_700Bold', color: '#FFB86B' }}>
Olympiads
</Text>
{' for erudite people from all over the world'}
</Text>
</View>
<View style={{ position: 'absolute', left: 16, bottom: 16, width: 76, height: 76 }}>
<Svg
width="76"
height="76"
viewBox="0 0 76 76"
style={{ position: 'absolute', left: 0, top: 0 }}>
<Circle
cx="38"
cy="38"
r="35"
fill="none"
stroke="#FFFFFF"
strokeWidth="3"
strokeLinecap="round"
strokeDasharray="160 220"
transform="rotate(-70 38 38)"
/>
</Svg>
<Pressable
accessibilityRole="button"
accessibilityLabel="Open Olympiads"
style={{
position: 'absolute',
left: 8,
top: 8,
width: 60,
height: 60,
borderRadius: '50%',
backgroundColor: '#222226',
borderWidth: 0,
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M5 12h14M13 6l6 6-6 6" />
</Svg>
</Pressable>
</View>
</View>
</View>
<View style={{ flexDirection: 'row', gap: 12 }}>
<View
style={{
height: 128,
borderRadius: 30,
backgroundColor: '#F8F3EF',
borderWidth: 1.5,
borderColor: '#F29A5C',
overflow: 'hidden',
flex: 1,
}}>
<Svg
width="110"
height="90"
viewBox="0 0 110 90"
style={{ position: 'absolute', left: 0, top: 0 }}>
<Path d="M0 0H92C74 2 66 14 58 30C48 50 30 58 0 64Z" fill="#F29A5C" />
</Svg>
<View
style={{
position: 'absolute',
left: 12,
top: 10,
width: 44,
height: 44,
borderRadius: '50%',
backgroundColor: '#E2864A',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#6A3517"
strokeWidth="2"
strokeLinecap="round">
<Rect x="3" y="4" width="18" height="16" rx="4" fill="#B5612D" stroke="none" />
<Path d="M7 9h4M14 9h3M7 15h3M14 15h3" stroke="#F7C9A6" />
</Svg>
</View>
<Text
style={{
position: 'absolute',
left: 70,
top: 24,
fontFamily: 'PlusJakartaSans_500Medium',
fontSize: 13,
color: '#1E1E22',
}}>
Lessons
</Text>
<Text
style={{
position: 'absolute',
left: 0,
right: 0,
top: 50,
paddingLeft: 10,
fontFamily: 'PlusJakartaSans_700Bold',
fontSize: 44,
color: '#1E1E22',
letterSpacing: -1,
textAlign: 'center',
}}>
78
</Text>
</View>
<View
style={{
height: 128,
borderRadius: 30,
backgroundColor: '#EDECFA',
borderWidth: 1.5,
borderColor: '#8C86E3',
overflow: 'hidden',
flex: 1,
}}>
<Svg
width="110"
height="90"
viewBox="0 0 110 90"
style={{ position: 'absolute', left: 0, top: 0 }}>
<Path d="M0 0H92C74 2 66 14 58 30C48 50 30 58 0 64Z" fill="#8C86E3" />
</Svg>
<View
style={{
position: 'absolute',
left: 12,
top: 10,
width: 44,
height: 44,
borderRadius: '50%',
backgroundColor: '#7C76D8',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="20" height="20" viewBox="0 0 24 24">
<Circle cx="11" cy="13" r="7" fill="#C9C6F5" />
<Rect x="9" y="3" width="4" height="3" rx="1" fill="#C9C6F5" />
<Circle cx="17" cy="18" r="4" fill="#FFFFFF" />
<Path
d="M17 16v2h1.6"
stroke="#7C76D8"
strokeWidth="1.4"
fill="none"
strokeLinecap="round"
/>
</Svg>
</View>
<Text
style={{
position: 'absolute',
left: 70,
top: 24,
fontFamily: 'PlusJakartaSans_500Medium',
fontSize: 13,
color: '#1E1E22',
}}>
Hours
</Text>
<Text
style={{
position: 'absolute',
left: 0,
right: 0,
top: 50,
paddingLeft: 10,
fontFamily: 'PlusJakartaSans_700Bold',
fontSize: 44,
color: '#1E1E22',
letterSpacing: -1,
textAlign: 'center',
}}>
43
</Text>
</View>
</View>
<View
style={{
borderRadius: 24,
backgroundColor: '#F3F3F2',
paddingTop: 16,
paddingBottom: 14,
paddingHorizontal: 16,
gap: 14,
}}>
<View
style={{ alignItems: 'center', justifyContent: 'space-between', flexDirection: 'row' }}>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'PlusJakartaSans_700Bold',
fontSize: 15,
color: '#1E1E22',
}}>
Progress perfomance
</Text>
<Pressable
accessibilityRole="button"
accessibilityLabel="More options"
style={{
width: 44,
height: 28,
borderWidth: 0,
alignItems: 'center',
justifyContent: 'flex-end',
padding: 0,
flexDirection: 'row',
}}>
<Svg width="20" height="6" viewBox="0 0 20 6">
<Circle cx="3" cy="3" r="2.4" fill="#1E1E22" />
<Circle cx="10" cy="3" r="2.4" fill="#1E1E22" />
<Circle cx="17" cy="3" r="2.4" fill="#1E1E22" />
</Svg>
</Pressable>
</View>
<View
style={{
height: 48,
borderRadius: 10,
overflow: 'hidden',
flexDirection: 'row',
alignItems: 'flex-end',
}}>
<Stripes first={'#E6E5E2'} second={'#F2F1EE'} size={3} angle={180} />
<View style={{ height: 40, justifyContent: 'flex-start', flex: 1 }}>
<View
style={{
height: 14,
backgroundColor: '#F29A5C',
borderTopLeftRadius: 10,
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
borderBottomLeftRadius: 0,
}}
/>
<View style={{ flexGrow: 1 }}>
<Stripes first={'#F7C4A0'} second={'#FBDCC6'} size={3} angle={180} />
</View>
</View>
<View style={{ height: 48, flex: 1 }}>
<View
style={{
height: 18,
backgroundColor: '#8C86E3',
borderTopLeftRadius: 10,
borderTopRightRadius: 10,
borderBottomRightRadius: 0,
borderBottomLeftRadius: 0,
}}
/>
<View style={{ flexGrow: 1 }}>
<Stripes first={'#C2BEF2'} second={'#DAD7F8'} size={3} angle={180} />
</View>
</View>
<View style={{ height: 38, flex: 1 }}>
<View
style={{
height: 12,
backgroundColor: '#D4D3CF',
borderTopLeftRadius: 0,
borderTopRightRadius: 10,
borderBottomRightRadius: 0,
borderBottomLeftRadius: 0,
}}
/>
<View style={{ flexGrow: 1 }} />
</View>
</View>
<View style={{ flexDirection: 'row' }}>
<View style={{ gap: 2, flex: 1 }}>
<View
style={{
alignItems: 'center',
justifyContent: 'center',
gap: 6,
flexDirection: 'row',
}}>
<View
style={{ width: 8, height: 8, borderRadius: '50%', backgroundColor: '#F29A5C' }}
/>
<Text
style={{
fontFamily: 'PlusJakartaSans_600SemiBold',
fontSize: 12.5,
color: '#1E1E22',
textAlign: 'center',
flexShrink: 1,
}}>
June
</Text>
</View>
<Text
style={{
fontFamily: 'PlusJakartaSans_400Regular',
fontSize: 11,
color: '#5F5E66',
textAlign: 'center',
}}>
23 lessons
</Text>
</View>
<View style={{ gap: 2, flex: 1 }}>
<View
style={{
alignItems: 'center',
justifyContent: 'center',
gap: 6,
flexDirection: 'row',
}}>
<View
style={{ width: 8, height: 8, borderRadius: '50%', backgroundColor: '#8C86E3' }}
/>
<Text
style={{
fontFamily: 'PlusJakartaSans_600SemiBold',
fontSize: 12.5,
color: '#1E1E22',
textAlign: 'center',
flexShrink: 1,
}}>
July
</Text>
</View>
<Text
style={{
fontFamily: 'PlusJakartaSans_400Regular',
fontSize: 11,
color: '#5F5E66',
textAlign: 'center',
}}>
43 lessons
</Text>
</View>
<View style={{ gap: 2, flex: 1 }}>
<View
style={{
alignItems: 'center',
justifyContent: 'center',
gap: 6,
flexDirection: 'row',
}}>
<View
style={{ width: 8, height: 8, borderRadius: '50%', backgroundColor: '#B9B8B4' }}
/>
<Text
style={{
fontFamily: 'PlusJakartaSans_600SemiBold',
fontSize: 12.5,
color: '#1E1E22',
textAlign: 'center',
flexShrink: 1,
}}>
August
</Text>
</View>
<Text
style={{
fontFamily: 'PlusJakartaSans_400Regular',
fontSize: 11,
color: '#5F5E66',
textAlign: 'center',
}}>
12 lessons
</Text>
</View>
</View>
</View>
<View style={{ flexGrow: 1 }} />
<View
style={{
height: 73,
borderRadius: 40,
backgroundColor: '#2B2C31',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: 0,
paddingLeft: 6,
paddingRight: 22,
flexShrink: 0,
flexDirection: 'row',
}}>
<Pressable
accessibilityRole="link"
accessibilityLabel="Home"
onPress={() => router.navigate('/')}
style={{
width: 68,
height: 68,
borderRadius: '50%',
backgroundColor: '#0D0D0F',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="24" height="24" viewBox="0 0 24 24">
<Path
d="M10.6 3.5a2.2 2.2 0 0 1 2.8 0l6 5A2.2 2.2 0 0 1 20.2 10.2V18a3 3 0 0 1-3 3H6.8a3 3 0 0 1-3-3v-7.8a2.2 2.2 0 0 1 .8-1.7z"
fill="#8C86E3"
/>
<Rect x="10.5" y="15" width="3" height="4" rx="1.2" fill="#0D0D0F" opacity=".35" />
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Tasks"
onPress={() => router.navigate('/courses')}
style={{
width: 48,
height: 48,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="24" height="24" viewBox="0 0 24 24">
<Rect x="3" y="3" width="18" height="18" rx="5" fill="#9C9CA4" />
<Path
d="M7 9l1.5 1.5L11 8M7 15l1.5 1.5L11 14M13.5 9.5h3.5M13.5 15.5h3.5"
fill="none"
stroke="#2B2C31"
strokeWidth="1.6"
strokeLinecap="round"
strokeLinejoin="round"
/>
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Timer"
onPress={() => router.navigate('/progress')}
style={{
width: 48,
height: 48,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="24" height="24" viewBox="0 0 24 24">
<Rect x="9.5" y="2" width="5" height="3" rx="1.2" fill="#9C9CA4" />
<Circle cx="12" cy="13.5" r="7.5" fill="#9C9CA4" />
<Path d="M12 10v4" stroke="#2B2C31" strokeWidth="1.8" strokeLinecap="round" />
<Circle cx="12" cy="14.5" r="1.4" fill="#2B2C31" />
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Library"
onPress={() => router.navigate('/courses')}
style={{
width: 48,
height: 48,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="24" height="24" viewBox="0 0 24 24">
<Path
d="M3 5.5c3-1 6-1 8.3.8V20c-2.3-1.6-5.3-1.8-8.3-.8zM21 5.5c-3-1-6-1-8.3.8V20c2.3-1.6 5.3-1.8 8.3-.8z"
fill="#9C9CA4"
/>
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Settings"
onPress={() => router.navigate('/progress')}
style={{
width: 48,
height: 48,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="24" height="24" viewBox="0 0 24 24">
<Path
d="M10.3 2h3.4l.5 2.6 1.9.8 2.2-1.5 2.4 2.4-1.5 2.2.8 1.9 2.6.5v3.4l-2.6.5-.8 1.9 1.5 2.2-2.4 2.4-2.2-1.5-1.9.8-.5 2.6h-3.4l-.5-2.6-1.9-.8-2.2 1.5-2.4-2.4 1.5-2.2-.8-1.9L2 13.7v-3.4l2.6-.5.8-1.9-1.5-2.2 2.4-2.4 2.2 1.5 1.9-.8z"
fill="#9C9CA4"
/>
<Circle cx="12" cy="12" r="3.2" fill="#2B2C31" />
</Svg>
</Pressable>
</View>
</View>
</Screen>
);
}src/app/progress.tsx
import { Image } from 'expo-image';
import { router } from 'expo-router';
import { Pressable, Text, View } from 'react-native';
import Svg, { Circle, Path, Rect } from 'react-native-svg';
import { Screen } from '@/components/screen';
import { Stripes } from '@/components/stripes';
import { asset } from '@/lib/assets';
const bars = [
{
day: 'Mon',
value: 39,
h: 164,
striped: false,
fillStyle:
'height: 164px; width: 38px; border-radius: 19px; background: linear-gradient(180deg, #C8693A 0 40px, #EFC3A4 40px); display: flex; justify-content: center',
},
{
day: 'Tue',
value: 14,
h: 87,
striped: false,
fillStyle:
'height: 87px; width: 38px; border-radius: 19px; background: linear-gradient(180deg, #C8693A 0 40px, #EFC3A4 40px); display: flex; justify-content: center',
},
{
day: 'Wed',
value: 48,
h: 192,
striped: true,
fillStyle:
'height: 192px; width: 38px; border-radius: 19px; background: linear-gradient(180deg, #C8693A 0 40px, transparent 40px), repeating-linear-gradient(135deg, #C8693A 0 6px, #E9A57E 6px 12px); display: flex; justify-content: center',
},
{
day: 'Thr',
value: 24,
h: 118,
striped: false,
fillStyle:
'height: 118px; width: 38px; border-radius: 19px; background: linear-gradient(180deg, #C8693A 0 40px, #EFC3A4 40px); display: flex; justify-content: center',
},
{
day: 'Fri',
value: 22,
h: 112,
striped: false,
fillStyle:
'height: 112px; width: 38px; border-radius: 19px; background: linear-gradient(180deg, #C8693A 0 40px, #EFC3A4 40px); display: flex; justify-content: center',
},
];
export default function ProgressScreen() {
return (
<Screen background="#FFFFFF" statusBar="dark">
<View style={{ paddingTop: 56, paddingBottom: 22, paddingHorizontal: 18, gap: 16, flex: 1 }}>
<View style={{ alignItems: 'center', gap: 12, flexDirection: 'row' }}>
<View
style={{
width: 54,
height: 54,
borderRadius: '50%',
backgroundColor: '#D9D6F7',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
flexDirection: 'row',
}}>
<Image
source={{ uri: asset('f7d3a0c391.jpg') }}
contentFit="cover"
accessibilityLabel="Jacob"
style={{ width: 54, height: 54, borderRadius: '50%' }}
/>
</View>
<View style={{ gap: 3, flexGrow: 1, flexShrink: 1 }}>
<Text style={{ fontFamily: 'PlusJakartaSans_700Bold', fontSize: 19, color: '#1E1E22' }}>
Hello, Jacob
</Text>
<View style={{ alignItems: 'center', gap: 5, flexDirection: 'row' }}>
<Svg width="14" height="14" viewBox="0 0 24 24">
<Path d="M13 2 4 14h7l-1 8 9-12h-7z" fill="#8C86E3" />
</Svg>
<Text
style={{
flexShrink: 1,
fontFamily: 'PlusJakartaSans_400Regular',
fontSize: 13,
color: '#55545C',
}}>
Progress: 76%
</Text>
</View>
</View>
<Pressable
accessibilityRole="button"
accessibilityLabel="Notifications"
style={{
width: 50,
height: 50,
borderRadius: '50%',
borderWidth: 1.5,
borderColor: '#DCDAD6',
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#1E1E22"
strokeWidth="1.8"
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 2.2 0 0 0 4 0" />
</Svg>
<View
style={{
position: 'absolute',
top: 2,
right: 4,
width: 9,
height: 9,
borderRadius: '50%',
backgroundColor: '#F0645A',
}}
/>
</Pressable>
</View>
<View
style={{
alignItems: 'center',
justifyContent: 'space-between',
marginTop: 6,
flexDirection: 'row',
}}>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'PlusJakartaSans_800ExtraBold',
fontSize: 32,
color: '#1E1E22',
}}>
Progress
</Text>
<Pressable
accessibilityRole="button"
style={{
height: 44,
paddingVertical: 0,
paddingLeft: 8,
paddingRight: 14,
borderRadius: 22,
borderWidth: 0,
backgroundColor: '#F3F3F2',
alignItems: 'center',
gap: 8,
flexShrink: 1,
flexDirection: 'row',
}}>
<View
style={{
width: 30,
height: 30,
borderRadius: 9,
backgroundColor: '#ECEBFB',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="15"
height="15"
viewBox="0 0 24 24"
fill="none"
stroke="#5B55C9"
strokeWidth="2"
strokeLinecap="round">
<Rect x="3" y="5" width="18" height="14" rx="3" />
<Path d="M7 10h10M7 14h6" />
</Svg>
</View>
<Text
style={{
fontFamily: 'PlusJakartaSans_600SemiBold',
fontSize: 13,
color: '#1E1E22',
flexShrink: 1,
}}>
All subjects
</Text>
<Svg
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="#1E1E22"
strokeWidth="2.4"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M6 9l6 6 6-6" />
</Svg>
</Pressable>
</View>
<View
style={{
borderRadius: 30,
backgroundColor: '#FBEADC',
borderWidth: 1.5,
borderColor: '#F2C29E',
paddingTop: 16,
paddingBottom: 18,
paddingHorizontal: 18,
gap: 14,
overflow: 'hidden',
}}>
<Svg
width="360"
height="380"
viewBox="0 0 360 380"
style={{ position: 'absolute', left: 0, top: 0 }}>
<Path
d="M-20 300c80-40 120 20 200-40s120-40 200-10"
fill="none"
stroke="#F5D6BF"
strokeWidth="2"
/>
</Svg>
<View
style={{ alignItems: 'center', justifyContent: 'space-between', flexDirection: 'row' }}>
<View
style={{
width: 46,
height: 46,
borderRadius: '50%',
backgroundColor: '#222226',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2.2"
strokeLinecap="round">
<Path d="M6 20V12M12 20V5M18 20v-6" />
</Svg>
</View>
<View
style={{
padding: 4,
borderRadius: 22,
backgroundColor: '#F6D5BE',
flexShrink: 1,
flexDirection: 'row',
}}>
<Pressable
accessibilityRole="button"
style={{
height: 36,
paddingVertical: 0,
paddingHorizontal: 16,
borderRadius: 18,
borderWidth: 0,
backgroundColor: '#222226',
flexShrink: 1,
alignItems: 'center',
justifyContent: 'center',
}}>
<Text
style={{
fontFamily: 'PlusJakartaSans_600SemiBold',
fontSize: 12.5,
color: '#FFFFFF',
textAlign: 'center',
}}>
Weekly
</Text>
</Pressable>
<Pressable
accessibilityRole="button"
style={{
height: 36,
paddingVertical: 0,
paddingHorizontal: 14,
borderRadius: 18,
borderWidth: 0,
flexShrink: 1,
alignItems: 'center',
justifyContent: 'center',
}}>
<Text
style={{
fontFamily: 'PlusJakartaSans_600SemiBold',
fontSize: 12.5,
color: '#1E1E22',
textAlign: 'center',
}}>
Month
</Text>
</Pressable>
</View>
</View>
<View style={{ gap: 28, alignItems: 'baseline', flexDirection: 'row' }}>
<View style={{ alignItems: 'baseline', gap: 6, flexShrink: 1, flexDirection: 'row' }}>
<Text
style={{
flexShrink: 1,
fontFamily: 'PlusJakartaSans_700Bold',
fontSize: 30,
color: '#1E1E22',
}}>
48
</Text>
<Text
style={{
flexShrink: 1,
fontFamily: 'PlusJakartaSans_500Medium',
fontSize: 17,
color: '#1E1E22',
}}>
lessons
</Text>
</View>
<View style={{ alignItems: 'baseline', gap: 6, flexShrink: 1, flexDirection: 'row' }}>
<Text
style={{
flexShrink: 1,
fontFamily: 'PlusJakartaSans_700Bold',
fontSize: 30,
color: '#1E1E22',
}}>
12
</Text>
<Text
style={{
flexShrink: 1,
fontFamily: 'PlusJakartaSans_500Medium',
fontSize: 17,
color: '#1E1E22',
}}>
hours
</Text>
</View>
</View>
<View style={{ height: 220, flexDirection: 'row', alignItems: 'flex-end' }}>
{bars.map((bar, index) => (
<View key={index} style={{ alignItems: 'center', gap: 8, flex: 1 }}>
<View
style={{ width: 38, height: 192, borderRadius: 19, justifyContent: 'flex-end' }}>
<View
style={{
height: bar.h,
width: 38,
borderRadius: 19,
overflow: 'hidden',
backgroundColor: '#EFC3A4',
}}>
{bar.striped && (
<View style={{ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 }}>
<Stripes first={'#C8693A'} second={'#E9A57E'} size={6} angle={135} />
</View>
)}
<View
style={{
position: 'absolute',
left: 0,
right: 0,
top: 0,
height: 40,
backgroundColor: '#C8693A',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Text
style={{
marginTop: 13,
flexShrink: 1,
fontFamily: 'PlusJakartaSans_700Bold',
fontSize: 11.5,
color: '#FFFFFF',
}}>
{bar.value}
</Text>
</View>
</View>
</View>
<Text
style={{
fontFamily: 'PlusJakartaSans_400Regular',
fontSize: 11.5,
color: '#5F5E66',
}}>
{bar.day}
</Text>
</View>
))}
</View>
</View>
<View style={{ justifyContent: 'center', gap: 6, flexDirection: 'row' }}>
<View style={{ width: 8, height: 8, borderRadius: '50%', backgroundColor: '#222226' }} />
<View style={{ width: 8, height: 8, borderRadius: '50%', backgroundColor: '#C9C8C4' }} />
<View style={{ width: 8, height: 8, borderRadius: '50%', backgroundColor: '#C9C8C4' }} />
</View>
<View
style={{
height: 70,
borderRadius: 24,
backgroundColor: '#F3F3F2',
paddingVertical: 0,
paddingHorizontal: 14,
alignItems: 'center',
gap: 12,
flexDirection: 'row',
}}>
<View
style={{
width: 44,
height: 44,
borderRadius: '50%',
backgroundColor: '#FDF0C7',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<View
style={{
width: 30,
height: 30,
borderRadius: '50%',
backgroundColor: '#F7C94E',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="16" height="16" viewBox="0 0 24 24">
<Path
d="M12 3l2.6 5.6 6 .7-4.5 4.1 1.2 6L12 16.4 6.7 19.4l1.2-6L3.4 9.3l6-.7z"
fill="#FFFFFF"
/>
</Svg>
</View>
</View>
<View style={{ gap: 2, flexGrow: 1, flexShrink: 1 }}>
<Text style={{ fontFamily: 'PlusJakartaSans_700Bold', fontSize: 14, color: '#1E1E22' }}>
Rating of students
</Text>
<Text
style={{
fontFamily: 'PlusJakartaSans_400Regular',
fontSize: 11.5,
color: '#5F5E66',
}}>
10 best students
</Text>
</View>
<View style={{ alignItems: 'center', flexShrink: 1, flexDirection: 'row' }}>
<Image
source={{ uri: asset('bdc0ee622c.jpg') }}
contentFit="cover"
style={{
width: 36,
height: 36,
borderRadius: '50%',
backgroundColor: '#FDEBDD',
borderWidth: 2,
borderColor: '#FFFFFF',
}}
/>
<Image
source={{ uri: asset('c010df960b.jpg') }}
contentFit="cover"
style={{
width: 36,
height: 36,
borderRadius: '50%',
backgroundColor: '#F7C94E',
borderWidth: 2,
borderColor: '#FFFFFF',
marginLeft: -10,
}}
/>
<Image
source={{ uri: asset('2d27f11ef0.jpg') }}
contentFit="cover"
style={{
width: 36,
height: 36,
borderRadius: '50%',
backgroundColor: '#BFE3CF',
borderWidth: 2,
borderColor: '#FFFFFF',
marginLeft: -10,
}}
/>
</View>
</View>
<View style={{ flexGrow: 1 }} />
<View
style={{
height: 74,
borderRadius: 40,
backgroundColor: '#2B2C31',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: 0,
paddingHorizontal: 22,
flexShrink: 0,
flexDirection: 'row',
}}>
<Pressable
accessibilityRole="link"
accessibilityLabel="Home"
onPress={() => router.navigate('/')}
style={{
width: 48,
height: 48,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="24" height="24" viewBox="0 0 24 24">
<Path
d="M10.6 3.5a2.2 2.2 0 0 1 2.8 0l6 5A2.2 2.2 0 0 1 20.2 10.2V18a3 3 0 0 1-3 3H6.8a3 3 0 0 1-3-3v-7.8a2.2 2.2 0 0 1 .8-1.7z"
fill="#9C9CA4"
/>
<Rect x="10.5" y="15" width="3" height="4" rx="1.2" fill="#2B2C31" />
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Tasks"
onPress={() => router.navigate('/courses')}
style={{
width: 48,
height: 48,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="24" height="24" viewBox="0 0 24 24">
<Rect x="3" y="3" width="18" height="18" rx="5" fill="#9C9CA4" />
<Path
d="M7 9l1.5 1.5L11 8M7 15l1.5 1.5L11 14M13.5 9.5h3.5M13.5 15.5h3.5"
fill="none"
stroke="#2B2C31"
strokeWidth="1.6"
strokeLinecap="round"
strokeLinejoin="round"
/>
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Timer"
onPress={() => router.navigate('/progress')}
style={{
width: 68,
height: 68,
borderRadius: '50%',
backgroundColor: '#0D0D0F',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="26" height="26" viewBox="0 0 24 24">
<Rect x="9.5" y="2" width="5" height="3" rx="1.2" fill="#F29A5C" />
<Circle cx="12" cy="13.5" r="7.5" fill="#8C86E3" />
<Path d="M12 10v4" stroke="#FFFFFF" strokeWidth="1.8" strokeLinecap="round" />
<Circle cx="12" cy="14.5" r="1.4" fill="#FFFFFF" />
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Library"
onPress={() => router.navigate('/courses')}
style={{
width: 48,
height: 48,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="24" height="24" viewBox="0 0 24 24">
<Path
d="M3 5.5c3-1 6-1 8.3.8V20c-2.3-1.6-5.3-1.8-8.3-.8zM21 5.5c-3-1-6-1-8.3.8V20c2.3-1.6 5.3-1.8 8.3-.8z"
fill="#9C9CA4"
/>
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Settings"
onPress={() => router.navigate('/')}
style={{
width: 48,
height: 48,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="24" height="24" viewBox="0 0 24 24">
<Path
d="M10.3 2h3.4l.5 2.6 1.9.8 2.2-1.5 2.4 2.4-1.5 2.2.8 1.9 2.6.5v3.4l-2.6.5-.8 1.9 1.5 2.2-2.4 2.4-2.2-1.5-1.9.8-.5 2.6h-3.4l-.5-2.6-1.9-.8-2.2 1.5-2.4-2.4 1.5-2.2-.8-1.9L2 13.7v-3.4l2.6-.5.8-1.9-1.5-2.2 2.4-2.4 2.2 1.5 1.9-.8z"
fill="#9C9CA4"
/>
<Circle cx="12" cy="12" r="3.2" fill="#2B2C31" />
</Svg>
</Pressable>
</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 x 844 artboard, then scaled to the device width.
const ARTBOARD_WIDTH = 390;
const ARTBOARD_HEIGHT = 844;
type Props = {
background: string;
statusBar: 'light' | 'dark';
children: ReactNode;
};
export function Screen({ background, statusBar, 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(ARTBOARD_HEIGHT * scale, height) }}>
<StatusBar style={statusBar} />
<View
style={{
width: ARTBOARD_WIDTH,
height: ARTBOARD_HEIGHT,
overflow: 'hidden',
transformOrigin: 'left top',
transform: [{ scale }],
}}>
{children}
</View>
</ScrollView>
);
}src/components/stripes.tsx
import { useId } from 'react';
import { StyleSheet } from 'react-native';
import Svg, { Defs, Pattern, Rect } from 'react-native-svg';
type Props = {
first: string;
second: string;
/** Width of one band in px. */
size: number;
/** CSS gradient angle in degrees. */
angle: number;
};
export function Stripes({ first, second, size, angle }: Props) {
const id = useId();
return (
<Svg style={StyleSheet.absoluteFill} width="100%" height="100%">
<Defs>
<Pattern
id={id}
patternUnits="userSpaceOnUse"
width={size * 2}
height={size * 2}
patternTransform={`rotate(${angle - 90})`}>
<Rect width={size} height={size * 2} fill={first} />
<Rect x={size} width={size} height={size * 2} fill={second} />
</Pattern>
</Defs>
<Rect width="100%" height="100%" fill={`url(#${id})`} />
</Svg>
);
}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/learning-app-ui-design/assets';
export const asset = (name: string) => `${ASSET_BASE}/${name}`;About this design
It suits schools, course marketplaces and tutoring products, and each screen shares one calm card system so adding new sections is straightforward.
Periwinkle and tangerine on white, large rounded cards with glossy 3D objects and sketched lines behind them.
- Hero card with progress ring action
- Course cards with avatars and completion rings
- Weekly progress bars with a striped peak day
- Dark floating tab bar with a raised active item
Colour palette
Periwinkle
#8C86E3
Tangerine
#F29A5C
Charcoal
#222226
Sun
#F7C94E
Lilac
#ECEBFB
Cloud
#F3F3F2
How to use this design
- 01
Pick what to copy
Copy the Learning Platform 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
Is this for students or for teachers?
The screens are student-facing, covering a personal dashboard, enrolled courses and progress. The same card system extends well to teacher views.
Is the Learning Platform 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.



