// Entertainment app UI

Movie Ticket Booking App UI Design in Expo

This movie ticket booking app UI covers the full path from browsing to a held seat: a ranked movie chart, a poster-led detail page, showtimes by theatre, and a seat map you can actually tap.

Screens
4
Built with
Expo SDK 58
Fonts
Inter, Bebas Neue
License
Free (MIT)
Movie detail screen with a full-bleed poster, title and book now button

Movie Ticket Booking app screens

Movie booking app home screen with a ranked poster carousel and book now button

Home and movie chart

Primary tabs, a peeking poster carousel with chart rank overlays, booking stats and a floating BOOK action in the tab bar.

Movie detail screen with a full-bleed poster, title and book now button

Movie detail

A full-bleed poster fades to black behind the title lockup, runtime, languages, synopsis and a single Book Now action.

Cinema showtimes screen with date picker and theatre show times

Booking by theatre

Format chips and a poster row on black, then a white sheet with a date strip, city filters and showtime chips colour-coded by availability.

Cinema seat selection screen with a seat map and ticket total

Seat selection

A curved screen, tappable seat grid with aisles and two price tiers, a legend, and a dark ticket stub with a hold action.

Copy the Movie Ticket Booking 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

# Movie Ticket Booking: design artifact

This movie ticket booking app UI covers the full path from browsing to a held seat: a ranked movie chart, a poster-led detail page, showtimes by theatre, and a seat map you can actually tap.

- Type: Entertainment mobile app UI
- Screens: 4
- Artboard: 390 × 844
- Target: Expo SDK 58, Expo Router, TypeScript, expo-image, expo-linear-gradient, react-native-svg
- Live page: https://developermill.com/app-designs/movie-ticket-booking-app-ui-design

## Design direction

A cinematic black and white base with a single ember accent, tall poster cards and a dark ticket stub that anchors the checkout.

- Interactive seat map with classic and premium pricing
- Live ticket stub with seats, show time and total
- Peeking poster carousel with ranked overlays
- Date strip, format chips and theatre showtime cards

## Foundations

### Colour

| Token | Hex |
| --- | --- |
| Ember | `#CC3A0E` |
| Ink | `#141414` |
| Screen black | `#000000` |
| Gold rating | `#F0A52B` |
| Available | `#23A55A` |
| Hairline | `#E0E0E0` |

### Typography

- Typefaces: Inter, Bebas Neue
- Common sizes (px): 10, 11, 12, 13, 14, 15, 16, 17

### Shape and depth

- Common corner radii (px): 3, 4, 8, 9, 14, 999
- Shadows: `0 18px 36px rgba(196, 30, 30, 0.28)`, `0 -4px 18px rgba(0,0,0,0.06)`, `0 10px 22px rgba(204,58,14,0.4)`, `0 10px 24px rgba(204,58,14,0.35)`

## Screens

### 1. Home and movie chart

Primary tabs, a peeking poster carousel with chart rank overlays, booking stats and a floating BOOK action in the tab bar.

Preview: https://developermill.com/app-designs/movie-ticket-booking-app-ui-design/home.webp

Copy on this screen:

- Movies
- Events / Benefits
- Activities
- Movie Chart
- Now Showing
- Coming Soon
- See all
- 2
- 1
- Iron Petal – The Movie: Akane Arc
- 16+
- Booking Rate: 28.4% • Cumulative: 1.4 million •
- 8,123
- Book Now
- Home
- Cine Talk
- BOOK
- Store
- More

### 2. Movie detail

A full-bleed poster fades to black behind the title lockup, runtime, languages, synopsis and a single Book Now action.

Preview: https://developermill.com/app-designs/movie-ticket-booking-app-ui-design/detail.webp

Copy on this screen:

- Iron Petal – The Movie: Akane Arc
- Trailer (2)
- IRON PETAL
- THE MOVIE · AKANE ARC
- Japanese, Hindi
- Streaming Now
- Book Now
- 1h 42m • Action, Adventure, Anime, Fantasy • A • 13 Nov, 2026
- Japanese • Languages:
- Audio(2)
- ,
- Subtitles(1)
- Akane, a sword-for-hire with a blade that blooms, is drawn into a turf war when an old ally resurfaces with a debt she can’t …
- Read more…

### 3. Booking by theatre

Format chips and a poster row on black, then a white sheet with a date strip, city filters and showtime chips colour-coded by availability.

Preview: https://developermill.com/app-designs/movie-ticket-booking-app-ui-design/showtimes.webp

Copy on this screen:

- Movies Showing
- |
- Booking by Theatre
- All
- SCREENX
- 4DX
- IMAX
- DOLBY
- 1
- Iron Petal – The Movie: Akane Arc
- 16+
- 1h 42m
- MON
- 16
- TUE
- 17
- WED
- 18
- THU
- 19
- FRI
- 20
- SAT
- 21
- Mumbai
- Special Theatre
- CV
- Cineverse, Skyline Mall, Borivali
- Non-cancellable.
- 4:25 PM
- 4:45 PM
- 7:35 PM
- · LUX
- 7:45 PM
- 10:50 PM
- 11:00 PM
- 11:05 PM
- Make favourite cinemas by tapping the
- 3/3

### 4. Seat selection

A curved screen, tappable seat grid with aisles and two price tiers, a legend, and a dark ticket stub with a hold action.

Preview: https://developermill.com/app-designs/movie-ticket-booking-app-ui-design/seats.webp

Copy on this screen:

- Iron Petal – The Movie
- Cineverse, Skyline Mall, Borivali
- Mon, 16 Nov · 1h 42m · Japanese
- 4:25 PM
- 4:45 PM
- 7:35 PM
- LUX
- 7:45 PM
- 10:50 PM
- Screen this way
- CLASSIC
- ₹250
- PREMIUM RECLINER
- ₹420
- Classic
- Premium
- Taken
- Your pick
- Seats
- Show
- Mon · 7:35 PM
- Total
- Seats held for 10 minutes. Complete payment to confirm your tickets.
- Clear selection

## 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 – Movie Chart</title>
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&amp;family=Bebas+Neue&amp;display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#1a1a1a}a:hover{color:#000}
button{font-family:inherit;cursor:pointer}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; background: #ffffff; font-family: Inter, system-ui, sans-serif; color: #141414; position: relative; overflow: hidden; display: flex; flex-direction: column">

<!-- Header -->
<div style="display: flex; align-items: center; justify-content: space-between; padding: 58px 20px 14px">
<svg width="36" height="32" viewBox="0 0 36 32" role="img" aria-label="Reelo logo"><path d="M18 2 L34 28 Q35 30 33 30 L3 30 Q1 30 2 28 Z" fill="{{accent}}"></path><path d="M18 13 L25 25 L11 25 Z" fill="#ffffff"></path></svg>
<div style="display: flex; gap: 18px; align-items: center">
<button aria-label="My tickets" style="background: none; border: 0; padding: 0; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#141414" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6h16v4a2 2 0 0 0 0 4v4H4v-4a2 2 0 0 0 0-4z"></path><path d="M12 6v12" stroke-dasharray="2 2"></path></svg></button>
<button aria-label="Notifications" style="background: none; border: 0; padding: 0; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#141414" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 16V11a6 6 0 0 1 12 0v5l1.5 2h-15z"></path><path d="M10 20a2 2 0 0 0 4 0"></path></svg></button>
<button aria-label="Search" style="background: none; border: 0; padding: 0; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#141414" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><circle cx="11" cy="11" r="7"></circle><path d="M16.5 16.5L21 21"></path></svg></button>
</div>
</div>

<!-- Primary tabs -->
<div style="display: flex; align-items: center; gap: 22px; padding: 0 20px">
<button style="display: flex; align-items: center; gap: 7px; background: #141414; color: #ffffff; border: 0; border-radius: 999px; padding: 9px 16px; font-size: 15px; font-weight: 600"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="5" width="18" height="15" rx="2"></rect><path d="M3 10h18M8 5l2 5M14 5l2 5"></path></svg>Movies</button>
<button style="background: none; border: 0; padding: 0; font-size: 14px; color: #5c5c5c">Events / Benefits</button>
<button style="background: none; border: 0; padding: 0; font-size: 14px; color: #5c5c5c">Activities</button>
</div>

<!-- Sub tabs -->
<div style="display: flex; align-items: center; gap: 18px; padding: 18px 20px 0; font-size: 13px; color: #6b6b6b">
<span style="color: #141414; font-weight: 600; padding-bottom: 6px; border-bottom: 2px solid #141414">Movie Chart</span>
<span style="padding-bottom: 8px">Now Showing</span>
<span style="padding-bottom: 8px">Coming Soon</span>
<span style="padding-bottom: 8px; display: flex; align-items: center; gap: 2px">See all <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#6b6b6b" stroke-width="2.4" stroke-linecap="round" aria-hidden="true"><path d="M9 6l6 6-6 6"></path></svg></span>
</div>

<!-- Carousel -->
<div style="position: relative; height: 330px; margin-top: 22px">
<div aria-hidden="true" style="position: absolute; left: -200px; top: 26px; width: 228px; height: 278px; border-radius: 26px; overflow: hidden"><img src="https://developermill.com/app-designs/movie-ticket-booking-app-ui-design/assets/c27d246b2a.svg" alt="" style="width: 100%; height: 100%; object-fit: cover; display: block"></div>
<div aria-hidden="true" style="position: absolute; right: -200px; top: 26px; width: 228px; height: 278px; border-radius: 26px; overflow: hidden"><img src="https://developermill.com/app-designs/movie-ticket-booking-app-ui-design/assets/c84f4e1efb.svg" alt="" style="width: 100%; height: 100%; object-fit: cover; display: block"><span style="position: absolute; left: 14px; top: 10px; font-family: 'Bebas Neue', sans-serif; font-size: 34px; color: #ffffff">2</span></div>

<div style="position: absolute; left: 50%; top: 0; transform: translateX(-50%); width: 252px; height: 330px; border-radius: 30px; overflow: hidden; box-shadow: 0 18px 36px rgba(196, 30, 30, 0.28); background: #6e0610">
<img src="https://developermill.com/app-designs/movie-ticket-booking-app-ui-design/assets/18e23cdfc9.svg" alt="Iron Petal – The Movie: Akane Arc poster" style="position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block">
<span style="position: absolute; left: 18px; top: 10px; font-family: 'Bebas Neue', sans-serif; font-size: 44px; color: #ffffff; font-style: italic">1</span>
<button aria-label="Add to favourites" style="position: absolute; right: 14px; top: 14px; width: 36px; height: 36px; border: 0; background: none; padding: 0; display: flex; align-items: center; justify-content: center"><svg width="26" height="26" viewBox="0 0 24 24" fill="#ffffff" aria-hidden="true"><path d="M12 21s-7.5-4.6-9.5-9.2C1 8.2 3.3 4.5 7 4.5c2.1 0 3.7 1.1 5 2.9 1.3-1.8 2.9-2.9 5-2.9 3.7 0 6 3.7 4.5 7.3C19.5 16.4 12 21 12 21z"></path></svg></button>
</div>
</div>

<!-- Movie info -->
<div style="display: flex; flex-direction: column; align-items: center; padding: 22px 20px 0">
<div style="display: flex; align-items: center; gap: 8px">
<h1 style="margin: 0; font-size: 16px; font-weight: 700">Iron Petal – The Movie: Akane Arc</h1>
<span style="background: #f0a52b; color: #141414; font-size: 11px; font-weight: 800; border-radius: 5px; padding: 3px 5px">16+</span>
</div>
<div style="display: flex; align-items: center; gap: 6px; margin-top: 12px; font-size: 12px; color: #3d3d3d">
<svg width="13" height="13" viewBox="0 0 24 24" fill="{{accent}}" aria-hidden="true"><path d="M12 2c1 4 6 6 6 12a6 6 0 0 1-12 0c0-3 2-5 3-6 0 2 1 3 2 3 0-3 1-6 1-9z"></path></svg>
<span>Booking Rate: 28.4% • Cumulative: 1.4 million •</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="#c0392b" aria-hidden="true"><path d="M12 21s-7.5-4.6-9.5-9.2C1 8.2 3.3 4.5 7 4.5c2.1 0 3.7 1.1 5 2.9 1.3-1.8 2.9-2.9 5-2.9 3.7 0 6 3.7 4.5 7.3C19.5 16.4 12 21 12 21z"></path></svg>
<span>8,123</span>
</div>
<a href="Detail.dc.html" style="margin-top: 22px; background: #141414; color: #ffffff; text-decoration: none; border-radius: 999px; padding: 13px 34px; font-size: 15px; font-weight: 600">Book Now</a>
</div>

<!-- Bottom nav -->
<div style="position: absolute; left: 0; right: 0; bottom: 0; height: 92px; background: #ffffff; box-shadow: 0 -4px 18px rgba(0,0,0,0.06); display: flex; align-items: flex-start; justify-content: space-around; padding: 12px 8px 0; box-sizing: border-box">
<a href="Main.dc.html" style="display: flex; flex-direction: column; align-items: center; gap: 5px; text-decoration: none; color: #141414; font-size: 11px; width: 56px"><svg width="22" height="22" viewBox="0 0 24 24" fill="#141414" aria-hidden="true"><path d="M3 10.5L12 3l9 7.5V20a1 1 0 0 1-1 1h-5v-6h-6v6H4a1 1 0 0 1-1-1z"></path></svg>Home</a>
<a href="#" style="display: flex; flex-direction: column; align-items: center; gap: 5px; text-decoration: none; color: #141414; font-size: 11px; width: 56px"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#141414" stroke-width="1.8" stroke-linejoin="round" aria-hidden="true"><path d="M4 5h16v11H9l-5 4z"></path><path d="M8 10.5h.01M12 10.5h.01M16 10.5h.01" stroke-width="2.6" stroke-linecap="round"></path></svg>Cine Talk</a>
<a href="Showtimes.dc.html" aria-label="Book tickets" style="margin-top: -32px; width: 68px; height: 78px; border-radius: 24px; background: {{accent}}; box-shadow: 0 10px 22px rgba(204,58,14,0.4); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; text-decoration: none; color: #ffffff; font-size: 12px; font-weight: 700"><svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="1.8" stroke-linejoin="round" aria-hidden="true"><path d="M4 6h16v4a2 2 0 0 0 0 4v4H4v-4a2 2 0 0 0 0-4z"></path><path d="M9 10h6M9 14h6"></path></svg>BOOK</a>
<a href="#" style="display: flex; flex-direction: column; align-items: center; gap: 5px; text-decoration: none; color: #141414; font-size: 11px; width: 56px"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#141414" stroke-width="1.8" stroke-linejoin="round" aria-hidden="true"><path d="M6 10h12l-1.5 11h-9z"></path><path d="M7 10a3 3 0 0 1 3-4 3 3 0 0 1 4 0 3 3 0 0 1 3 4"></path></svg>Store</a>
<a href="#" style="display: flex; flex-direction: column; align-items: center; gap: 5px; text-decoration: none; color: #141414; font-size: 11px; width: 56px"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#141414" stroke-width="1.8" aria-hidden="true"><circle cx="7.5" cy="7.5" r="3.5"></circle><circle cx="16.5" cy="7.5" r="3.5"></circle><circle cx="7.5" cy="16.5" r="3.5"></circle><circle cx="16.5" cy="16.5" r="3.5"></circle></svg>More</a>
</div>
<div aria-hidden="true" style="position: absolute; bottom: 8px; left: 50%; transform: translateX(-50%); width: 134px; height: 5px; border-radius: 3px; background: #141414"></div>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#CC3A0E","options":["#CC3A0E","#C2185B","#1E5BD8"]},"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
return { accent: this.props.accent ?? '#CC3A0E' };
}
}
</script>
</body>
</html>
```

### Detail

```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Movie Detail</title>
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&amp;family=Bebas+Neue&amp;display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#ff8a65}a:hover{color:#ffab91}
button{font-family:inherit;cursor:pointer}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; background: #000000; font-family: Inter, system-ui, sans-serif; color: #ffffff; position: relative; overflow: hidden">

<!-- Poster hero -->
<div style="position: absolute; left: 0; top: 0; width: 390px; height: 590px; background: #2a0105">
<img src="https://developermill.com/app-designs/movie-ticket-booking-app-ui-design/assets/18e23cdfc9.svg" alt="" style="position: absolute; left: 0; top: 0; width: 390px; height: 590px; object-fit: cover; object-position: top; display: block">
<div style="position: absolute; left: 0; right: 0; bottom: 0; height: 300px; background: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.6) 45%, #000000 100%)"></div>
</div>

<!-- Top bar -->
<div style="position: absolute; left: 16px; right: 16px; top: 56px; height: 44px; border-radius: 999px; background: rgba(40,0,4,0.55); display: flex; align-items: center; justify-content: space-between; padding: 0 6px">
<a href="Main.dc.html" aria-label="Back" style="width: 36px; height: 36px; 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" stroke-linejoin="round" aria-hidden="true"><path d="M15 5l-7 7 7 7"></path></svg></a>
<span style="font-size: 13px; font-weight: 600">Iron Petal – The Movie: Akane Arc</span>
<button aria-label="Share" style="width: 36px; height: 36px; border: 0; background: none; padding: 0; display: flex; align-items: center; justify-content: center"><svg width="19" height="19" 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 9"></path><path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"></path></svg></button>
</div>

<!-- Trailer pill -->
<button style="position: absolute; left: 50%; top: 300px; transform: translateX(-50%); display: flex; align-items: center; gap: 7px; border: 0; border-radius: 999px; background: rgba(30,30,30,0.6); color: #ffffff; font-size: 13px; padding: 8px 14px 8px 8px"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="1.6" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><path d="M10 8.5l5 3.5-5 3.5z" fill="#ffffff"></path></svg>Trailer (2)</button>

<!-- Title block -->
<div style="position: absolute; left: 0; right: 0; top: 448px; display: flex; flex-direction: column; align-items: center">
<h1 style="margin: 0; font-family: 'Bebas Neue', sans-serif; font-weight: 400; font-size: 64px; line-height: 0.9; letter-spacing: 2px">IRON PETAL</h1>
<span style="font-size: 11px; letter-spacing: 3.5px; color: #ffc9c9; margin-top: 6px">THE MOVIE · AKANE ARC</span>
<span style="font-size: 14px; font-weight: 600; margin-top: 10px">Japanese, Hindi</span>
</div>

<!-- Booking + info -->
<div style="position: absolute; left: 20px; right: 20px; top: 612px; display: flex; flex-direction: column">
<span style="font-size: 13px; color: #e6e6e6">Streaming Now</span>
<a href="Showtimes.dc.html" style="margin-top: 14px; height: 48px; border-radius: 999px; background: {{accent}}; color: #ffffff; display: flex; align-items: center; justify-content: center; text-decoration: none; font-size: 15px; font-weight: 600; box-shadow: 0 10px 24px rgba(204,58,14,0.35)">Book Now</a>
<p style="margin: 16px 0 0; font-size: 12px; color: #e6e6e6">1h 42m • Action, Adventure, Anime, Fantasy • A • 13 Nov, 2026</p>
<p style="margin: 6px 0 0; font-size: 12px; color: #9a9a9a">Japanese • Languages: <span style="color: #ff8a65">Audio(2)</span>, <span style="color: #ff8a65">Subtitles(1)</span></p>
<p style="margin: 10px 0 0; font-size: 12px; line-height: 1.5; color: #d9d9d9">Akane, a sword-for-hire with a blade that blooms, is drawn into a turf war when an old ally resurfaces with a debt she can’t … <a href="#" style="text-decoration: none">Read more…</a></p>
</div>

<div aria-hidden="true" style="position: absolute; bottom: 8px; left: 50%; transform: translateX(-50%); width: 134px; height: 5px; border-radius: 3px; background: #ffffff"></div>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#CC3A0E","options":["#CC3A0E","#C2185B","#1E5BD8"]},"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
return { accent: this.props.accent ?? '#CC3A0E' };
}
}
</script>
</body>
</html>
```

### Showtimes

```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Booking by Theatre</title>
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&amp;family=Bebas+Neue&amp;display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#ffffff}a:hover{color:#ffffff}
button{font-family:inherit;cursor:pointer}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; background: #000000; font-family: Inter, system-ui, sans-serif; color: #ffffff; position: relative; overflow: hidden">

<!-- Header -->
<div style="display: flex; align-items: center; justify-content: space-between; padding: 58px 20px 0">
<div style="font-size: 13px; color: #ffffff">Movies Showing <span style="color: #8a8a8a">|</span> <span style="color: #a6a6a6">Booking by Theatre</span></div>
<a href="Detail.dc.html" aria-label="Close" style="width: 28px; height: 28px; display: flex; align-items: center; justify-content: center"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="1.6" stroke-linecap="round" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><path d="M9 9l6 6M15 9l-6 6"></path></svg></a>
</div>

<!-- Format chips -->
<div style="display: flex; gap: 8px; padding: 18px 20px 0">
<button style="border: 0; border-radius: 999px; background: #ffffff; color: #000000; font-size: 13px; font-weight: 600; padding: 7px 14px">All</button>
<button style="border: 1px solid #4a4a4a; border-radius: 999px; background: none; color: #e0e0e0; font-size: 12px; font-weight: 600; padding: 7px 12px">SCREENX</button>
<button style="border: 1px solid #4a4a4a; border-radius: 999px; background: none; color: #e0e0e0; font-size: 12px; font-weight: 600; padding: 7px 12px">4DX</button>
<button style="border: 1px solid #4a4a4a; border-radius: 999px; background: none; color: #e0e0e0; font-size: 12px; font-weight: 600; padding: 7px 12px">IMAX</button>
<button style="border: 1px solid #4a4a4a; border-radius: 999px; background: none; color: #e0e0e0; font-size: 12px; font-weight: 600; padding: 7px 12px">DOLBY</button>
</div>

<!-- Poster row (placeholders for the three generated posters) -->
<div style="position: relative; height: 170px; margin-top: 22px">
<div aria-hidden="true" style="position: absolute; left: -2px; top: 12px; width: 84px; height: 146px; border-radius: 16px; overflow: hidden"><img src="https://developermill.com/app-designs/movie-ticket-booking-app-ui-design/assets/c27d246b2a.svg" alt="" style="width: 100%; height: 100%; object-fit: cover; display: block"></div>
<div style="position: absolute; left: 50%; top: 0; transform: translateX(-50%); width: 120px; height: 170px; border-radius: 18px; overflow: hidden; background: #6d0610">
<img src="https://developermill.com/app-designs/movie-ticket-booking-app-ui-design/assets/18e23cdfc9.svg" alt="Iron Petal poster" style="width: 100%; height: 100%; object-fit: cover; display: block">
<span style="position: absolute; left: 10px; top: 4px; font-family: 'Bebas Neue', sans-serif; font-size: 30px; font-style: italic">1</span>
</div>
<div aria-hidden="true" style="position: absolute; right: -2px; top: 12px; width: 84px; height: 146px; border-radius: 16px; overflow: hidden"><img src="https://developermill.com/app-designs/movie-ticket-booking-app-ui-design/assets/c84f4e1efb.svg" alt="" style="width: 100%; height: 100%; object-fit: cover; display: block"></div>
</div>

<div style="display: flex; flex-direction: column; align-items: center; padding-top: 20px">
<div style="display: flex; align-items: center; gap: 8px">
<h1 style="margin: 0; font-size: 16px; font-weight: 700">Iron Petal – The Movie: Akane Arc</h1>
<span style="background: #f0a52b; color: #141414; font-size: 11px; font-weight: 800; border-radius: 5px; padding: 3px 5px">16+</span>
</div>
<span style="font-size: 12px; color: #b3b3b3; margin-top: 6px">1h 42m</span>
</div>

<!-- White sheet -->
<div style="position: absolute; left: 0; right: 0; top: 444px; bottom: 0; background: #ffffff; border-radius: 28px 28px 0 0; color: #141414; padding: 18px 16px 0">
<div style="display: flex; gap: 8px">
<button style="width: 50px; height: 56px; border: 0; border-radius: 14px; background: {{accent}}; color: #ffffff; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 11px; font-weight: 700">MON<span style="font-size: 17px; font-weight: 700">16</span></button>
<button style="width: 50px; height: 56px; border: 1px solid #e0e0e0; border-radius: 14px; background: #ffffff; color: #141414; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 11px; font-weight: 600">TUE<span style="font-size: 17px">17</span></button>
<button style="width: 50px; height: 56px; border: 1px solid #e0e0e0; border-radius: 14px; background: #ffffff; color: #141414; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 11px; font-weight: 600">WED<span style="font-size: 17px">18</span></button>
<button style="width: 50px; height: 56px; border: 1px solid #e0e0e0; border-radius: 14px; background: #ffffff; color: #141414; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 11px; font-weight: 600">THU<span style="font-size: 17px">19</span></button>
<button style="width: 50px; height: 56px; border: 1px solid #e0e0e0; border-radius: 14px; background: #ffffff; color: #141414; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 11px; font-weight: 600">FRI<span style="font-size: 17px">20</span></button>
<button style="width: 50px; height: 56px; border: 1px solid #e0e0e0; border-radius: 14px; background: #ffffff; color: #141414; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 11px; font-weight: 600">SAT<span style="font-size: 17px">21</span></button>
</div>

<div style="display: flex; gap: 8px; margin-top: 14px">
<button style="display: flex; align-items: center; gap: 5px; border: 0; border-radius: 999px; background: {{accent}}; color: #ffffff; font-size: 13px; font-weight: 600; padding: 7px 13px"><svg width="13" height="13" viewBox="0 0 24 24" fill="#ffffff" aria-hidden="true"><path d="M12 2a7 7 0 0 0-7 7c0 5 7 13 7 13s7-8 7-13a7 7 0 0 0-7-7zm0 9.5A2.5 2.5 0 1 1 12 6.5a2.5 2.5 0 0 1 0 5z"></path></svg>Mumbai</button>
<button style="border: 1px solid #e0e0e0; border-radius: 999px; background: #ffffff; color: #3d3d3d; font-size: 13px; padding: 7px 14px">All</button>
<button style="border: 1px solid #e0e0e0; border-radius: 999px; background: #ffffff; color: #3d3d3d; font-size: 13px; padding: 7px 14px">Special Theatre</button>
</div>

<!-- Theatre card -->
<div style="margin-top: 14px; border-radius: 18px; box-shadow: 0 4px 18px rgba(0,0,0,0.08); padding: 14px 14px 16px">
<div style="display: flex; align-items: center; gap: 10px">
<div style="width: 34px; height: 34px; border-radius: 10px; background: #fff3d6; color: #b07400; font-size: 11px; font-weight: 800; display: flex; align-items: center; justify-content: center">CV</div>
<div style="flex: 1">
<div style="font-size: 15px; font-weight: 600">Cineverse, Skyline Mall, Borivali</div>
<div style="font-size: 11px; color: #6b6b6b; margin-top: 1px">Non-cancellable.</div>
</div>
<button aria-label="Favourite this cinema" style="width: 36px; height: 36px; border: 0; background: none; padding: 0; display: flex; align-items: center; justify-content: center"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#141414" stroke-width="1.8" aria-hidden="true"><path d="M12 20s-7-4.3-8.8-8.6C1.9 8 4 4.8 7.2 4.8c2 0 3.5 1 4.8 2.7 1.3-1.7 2.8-2.7 4.8-2.7 3.2 0 5.3 3.2 4 6.6C19 15.7 12 20 12 20z"></path></svg></button>
</div>
<div style="display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; margin-top: 14px">
<a href="Seats.dc.html" style="height: 30px; border-radius: 8px; background: #141414; border-left: 5px solid #23a55a; color: #ffffff; text-decoration: none; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 600">4:25 PM</a>
<a href="Seats.dc.html" style="height: 30px; border-radius: 8px; background: #141414; border-left: 5px solid #23a55a; color: #ffffff; text-decoration: none; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 600">4:45 PM</a>
<a href="Seats.dc.html" style="height: 30px; border-radius: 8px; background: linear-gradient(90deg, #f0a52b 0 50%, #141414 50% 100%); color: #ffffff; text-decoration: none; display: flex; align-items: center; justify-content: center; gap: 3px; font-size: 11px; font-weight: 600">7:35 PM<span style="font-size: 7px">· LUX</span></a>
<a href="Seats.dc.html" style="height: 30px; border-radius: 8px; background: linear-gradient(90deg, #f0a52b 0 50%, #141414 50% 100%); color: #ffffff; text-decoration: none; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 600">7:45 PM</a>
<a href="Seats.dc.html" style="height: 30px; border-radius: 8px; background: #141414; border-left: 5px solid #23a55a; color: #ffffff; text-decoration: none; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 600">10:50 PM</a>
<a href="Seats.dc.html" style="position: relative; height: 30px; border-radius: 8px; background: #141414; border-left: 5px solid #23a55a; color: #ffffff; text-decoration: none; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 600">11:00 PM<span aria-label="Late show" style="position: absolute; right: -5px; top: -7px; width: 16px; height: 16px; border-radius: 50%; background: {{accent}}; display: flex; align-items: center; justify-content: center"><svg width="9" height="9" viewBox="0 0 24 24" fill="#ffffff" aria-hidden="true"><path d="M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5z"></path></svg></span></a>
<a href="Seats.dc.html" style="position: relative; height: 30px; border-radius: 8px; background: #141414; border-left: 5px solid #23a55a; color: #ffffff; text-decoration: none; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 600">11:05 PM<span aria-label="Late show" style="position: absolute; right: -5px; top: -7px; width: 16px; height: 16px; border-radius: 50%; background: {{accent}}; display: flex; align-items: center; justify-content: center"><svg width="9" height="9" viewBox="0 0 24 24" fill="#ffffff" aria-hidden="true"><path d="M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5z"></path></svg></span></a>
</div>
</div>

<!-- Next card peek -->
<div aria-hidden="true" style="margin-top: 12px; height: 60px; border-radius: 18px; box-shadow: 0 4px 18px rgba(0,0,0,0.08)"></div>

<!-- Tip toast -->
<div style="position: absolute; left: 12px; right: 12px; bottom: 30px; height: 44px; border-radius: 12px; background: #ffffff; box-shadow: 0 -2px 16px rgba(0,0,0,0.1); display: flex; align-items: center; justify-content: space-between; padding: 0 12px; font-size: 12px">
<span style="display: flex; align-items: center; gap: 4px">Make favourite cinemas by tapping the <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#141414" stroke-width="2" aria-hidden="true"><path d="M12 20s-7-4.3-8.8-8.6C1.9 8 4 4.8 7.2 4.8c2 0 3.5 1 4.8 2.7 1.3-1.7 2.8-2.7 4.8-2.7 3.2 0 5.3 3.2 4 6.6C19 15.7 12 20 12 20z"></path></svg></span>
<span style="display: flex; align-items: center; gap: 6px; color: #3d3d3d">3/3 <button aria-label="Dismiss tip" style="width: 20px; height: 20px; border: 0; border-radius: 50%; background: #ececec; padding: 0; display: flex; align-items: center; justify-content: center"><svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="#3d3d3d" stroke-width="3" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"></path></svg></button></span>
</div>
</div>

<div aria-hidden="true" style="position: absolute; bottom: 8px; left: 50%; transform: translateX(-50%); width: 134px; height: 5px; border-radius: 3px; background: #141414"></div>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#CC3A0E","options":["#CC3A0E","#C2185B","#1E5BD8"]},"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
return { accent: this.props.accent ?? '#CC3A0E' };
}
}
</script>
</body>
</html>
```

### Seats

```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Select Seats</title>
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&amp;display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#141414}a:hover{color:#000000}
button{font-family:inherit;cursor:pointer}
button:disabled{cursor:not-allowed}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; background: #ffffff; font-family: Inter, system-ui, sans-serif; color: #141414; position: relative; overflow: hidden">

<!-- Header -->
<div style="display: flex; align-items: center; justify-content: space-between; padding: 56px 16px 0">
<a href="Showtimes.dc.html" aria-label="Back to showtimes" 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="#141414" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 5l-7 7 7 7"></path></svg></a>
<div style="display: flex; flex-direction: column; align-items: center">
<h1 style="margin: 0; font-size: 15px; font-weight: 700">Iron Petal – The Movie</h1>
<span style="font-size: 11px; color: #5c5c5c; margin-top: 2px">Cineverse, Skyline Mall, Borivali</span>
</div>
<span style="min-width: 40px; height: 26px; border-radius: 999px; background: #fff3d6; color: #8a5a00; font-size: 11px; font-weight: 700; display: flex; align-items: center; justify-content: center; padding: 0 8px; box-sizing: border-box">{{countLabel}}</span>
</div>

<!-- Date + showtimes -->
<div style="padding: 18px 16px 0">
<div style="font-size: 12px; font-weight: 600; color: #3d3d3d">Mon, 16 Nov · 1h 42m · Japanese</div>
<div style="display: flex; gap: 8px; margin-top: 10px">
<button style="height: 32px; padding: 0 11px; border-radius: 9px; border: 1px solid #e0e0e0; background: #ffffff; color: #141414; font-size: 12px; font-weight: 600">4:25 PM</button>
<button style="height: 32px; padding: 0 11px; border-radius: 9px; border: 1px solid #e0e0e0; background: #ffffff; color: #141414; font-size: 12px; font-weight: 600">4:45 PM</button>
<button aria-pressed="true" style="height: 32px; padding: 0 11px; border-radius: 9px; border: 0; background: #141414; color: #ffffff; font-size: 12px; font-weight: 600">7:35 PM <span style="color: #f0a52b; font-size: 10px">LUX</span></button>
<button style="height: 32px; padding: 0 11px; border-radius: 9px; border: 1px solid #e0e0e0; background: #ffffff; color: #141414; font-size: 12px; font-weight: 600">7:45 PM</button>
<button style="height: 32px; padding: 0 11px; border-radius: 9px; border: 1px solid #e0e0e0; background: #ffffff; color: #141414; font-size: 12px; font-weight: 600">10:50 PM</button>
</div>
</div>

<!-- Screen arc -->
<div style="position: relative; margin: 20px 28px 0; height: 40px">
<svg width="334" height="26" viewBox="0 0 334 26" aria-hidden="true" style="display: block"><path d="M4 22 Q167 -8 330 22" fill="none" stroke="{{accent}}" stroke-width="4" stroke-linecap="round"></path><path d="M4 24 Q167 -2 330 24" fill="none" stroke="{{accent}}" stroke-opacity="0.15" stroke-width="10" stroke-linecap="round"></path></svg>
<div style="text-align: center; font-size: 11px; color: #6b6b6b; margin-top: 2px">Screen this way</div>
</div>

<!-- Seat map -->
<div role="group" aria-label="Seat map" style="padding: 8px 20px 0; display: flex; flex-direction: column; gap: 6px">
<div style="display: flex; justify-content: space-between; font-size: 10px; font-weight: 700; letter-spacing: 1px; color: #6b6b6b"><span>CLASSIC</span><span>₹250</span></div>
<sc-for list="{{classicRows}}" as="row" hint-placeholder-count="6">
<div style="display: grid; grid-template-columns: 16px repeat(2, minmax(0, 1fr)) 10px repeat(8, minmax(0, 1fr)) 10px repeat(2, minmax(0, 1fr)) 16px; gap: 4px; align-items: center">
<sc-for list="{{row.cells}}" as="cell" hint-placeholder-count="17">
<sc-if value="{{cell.isLabel}}" hint-placeholder-val="{{false}}"><span style="font-size: 10px; font-weight: 600; color: #6b6b6b; text-align: center">{{cell.text}}</span></sc-if>
<sc-if value="{{cell.isAisle}}" hint-placeholder-val="{{false}}"><span></span></sc-if>
<sc-if value="{{cell.isSeat}}" hint-placeholder-val="{{true}}"><button aria-label="{{cell.aria}}" aria-pressed="{{cell.pressed}}" disabled="{{cell.taken}}" onClick="{{cell.pick}}" style="{{cell.style}}"></button></sc-if>
</sc-for>
</div>
</sc-for>
<div style="display: flex; justify-content: space-between; font-size: 10px; font-weight: 700; letter-spacing: 1px; color: #8a5a00; margin-top: 8px"><span>PREMIUM RECLINER</span><span>₹420</span></div>
<sc-for list="{{premiumRows}}" as="row" hint-placeholder-count="2">
<div style="display: grid; grid-template-columns: 16px repeat(2, minmax(0, 1fr)) 10px repeat(8, minmax(0, 1fr)) 10px repeat(2, minmax(0, 1fr)) 16px; gap: 4px; align-items: center">
<sc-for list="{{row.cells}}" as="cell" hint-placeholder-count="17">
<sc-if value="{{cell.isLabel}}" hint-placeholder-val="{{false}}"><span style="font-size: 10px; font-weight: 600; color: #6b6b6b; text-align: center">{{cell.text}}</span></sc-if>
<sc-if value="{{cell.isAisle}}" hint-placeholder-val="{{false}}"><span></span></sc-if>
<sc-if value="{{cell.isSeat}}" hint-placeholder-val="{{true}}"><button aria-label="{{cell.aria}}" aria-pressed="{{cell.pressed}}" disabled="{{cell.taken}}" onClick="{{cell.pick}}" style="{{cell.style}}"></button></sc-if>
</sc-for>
</div>
</sc-for>
</div>

<!-- Legend -->
<div style="display: flex; gap: 14px; justify-content: center; padding: 16px 16px 0; font-size: 11px; color: #4d4d4d">
<span style="display: flex; align-items: center; gap: 5px"><span style="width: 14px; height: 12px; border-radius: 4px 4px 3px 3px; border: 1.5px solid #9e9e9e; box-sizing: border-box"></span>Classic</span>
<span style="display: flex; align-items: center; gap: 5px"><span style="width: 14px; height: 12px; border-radius: 4px 4px 3px 3px; border: 1.5px solid #d08c14; box-sizing: border-box"></span>Premium</span>
<span style="display: flex; align-items: center; gap: 5px"><span style="width: 14px; height: 12px; border-radius: 4px 4px 3px 3px; background: #dcdcdc"></span>Taken</span>
<span style="display: flex; align-items: center; gap: 5px"><span style="width: 14px; height: 12px; border-radius: 4px 4px 3px 3px; background: {{accent}}"></span>Your pick</span>
</div>

<!-- Ticket stub + CTA -->
<div style="position: absolute; left: 0; right: 0; bottom: 0; background: #141414; border-radius: 28px 28px 0 0; padding: 18px 16px 30px; color: #ffffff">
<div style="display: grid; grid-template-columns: minmax(0, 1fr) auto; border: 1px dashed #4a4a4a; border-radius: 16px">
<dl style="margin: 0; padding: 12px 14px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 14px">
<div><dt style="font-size: 10px; color: #a6a6a6">Seats</dt><dd style="margin: 2px 0 0; font-size: 13px; font-weight: 600">{{seatsText}}</dd></div>
<div><dt style="font-size: 10px; color: #a6a6a6">Show</dt><dd style="margin: 2px 0 0; font-size: 13px; font-weight: 600">Mon · 7:35 PM</dd></div>
</dl>
<div style="border-left: 1px dashed #4a4a4a; padding: 12px 14px; display: flex; flex-direction: column; justify-content: center; align-items: flex-end">
<span style="font-size: 10px; color: #a6a6a6">Total</span>
<span style="font-size: 17px; font-weight: 700">{{totalText}}</span>
</div>
</div>
<sc-if value="{{held}}" hint-placeholder-val="{{false}}">
<p role="status" style="margin: 10px 0 0; font-size: 12px; color: #ffd9c7">Seats held for 10 minutes. Complete payment to confirm your tickets.</p>
</sc-if>
<button disabled="{{noneSelected}}" onClick="{{hold}}" style="{{holdStyle}}">{{holdLabel}}</button>
<div style="display: flex; justify-content: center; margin-top: 8px">
<button onClick="{{clear}}" style="border: 0; background: none; color: #bdbdbd; font-size: 12px; text-decoration: underline; text-underline-offset: 3px; padding: 6px">Clear selection</button>
</div>
</div>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#CC3A0E","options":["#CC3A0E","#C2185B","#1E5BD8"]},"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
constructor(props) {
super(props);
this.state = { picked: ['F6', 'F7'], held: false };
}
toggle(id) {
var picked = this.state.picked.slice();
var i = picked.indexOf(id);
if (i >= 0) { picked.splice(i, 1); }
else if (picked.length < 10) { picked.push(id); }
this.setState({ picked: picked, held: false });
}
renderVals() {
var self = this;
var accent = this.props.accent ?? '#CC3A0E';
var taken = ['A3','A4','B6','B7','B8','C1','D5','D6','E9','E10','F4','G1','G2','H7','H8','H9','C11','F12'];
var picked = this.state.picked;
var base = 'width: 100%; height: 19px; padding: 0; border-radius: 6px 6px 4px 4px; box-sizing: border-box; ';
function buildRow(r, premium) {
var cells = [{ isLabel: true, text: r }];
for (var n = 1; n <= 12; n++) {
var id = r + n;
var isTaken = taken.indexOf(id) >= 0;
var isPicked = picked.indexOf(id) >= 0;
var style;
if (isTaken) style = base + 'border: 0; background: #dcdcdc;';
else if (isPicked) style = base + 'border: 1.5px solid ' + accent + '; background: ' + accent + ';';
else style = base + 'background: #ffffff; border: 1.5px solid ' + (premium ? '#d08c14' : '#9e9e9e') + ';';
cells.push({
isSeat: true,
aria: 'Seat ' + id + (premium ? ', premium' : ', classic') + (isTaken ? ', taken' : ''),
pressed: isPicked ? 'true' : 'false',
taken: isTaken,
style: style,
pick: (function (sid) { return function () { self.toggle(sid); }; })(id)
});
if (n === 2 || n === 10) cells.push({ isAisle: true });
}
cells.push({ isLabel: true, text: r });
return { name: r, cells: cells };
}
var classicRows = ['A','B','C','D','E','F'].map(function (r) { return buildRow(r, false); });
var premiumRows = ['G','H'].map(function (r) { return buildRow(r, true); });
var sorted = picked.slice().sort(function (a, b) {
if (a[0] !== b[0]) return a < b ? -1 : 1;
return parseInt(a.slice(1), 10) - parseInt(b.slice(1), 10);
});
var total = picked.reduce(function (sum, id) { return sum + (id[0] === 'G' || id[0] === 'H' ? 420 : 250); }, 0);
var none = picked.length === 0;
var totalText = '₹' + total.toLocaleString('en-IN');
return {
accent: accent,
classicRows: classicRows,
premiumRows: premiumRows,
seatsText: none ? 'None yet' : sorted.join(', '),
countLabel: picked.length + (picked.length === 1 ? ' Ticket' : ' Tickets'),
totalText: totalText,
noneSelected: none,
held: this.state.held,
holdLabel: none ? 'Select seats' : 'Hold seats · ' + totalText,
holdStyle: 'margin-top: 14px; width: 100%; height: 50px; border: 0; border-radius: 999px; font-size: 15px; font-weight: 700; color: #ffffff; background: ' + (none ? '#4a4a4a' : accent) + ';',
hold: function () { self.setState({ held: true }); },
clear: function () { self.setState({ picked: [], held: false }); }
};
}
}
</script>
</body>
</html>
```

SKILL.md

Save as .claude/skills/movie-ticket-booking-app-ui/SKILL.md

---
name: movie-ticket-booking-app-ui
description: Build the Movie Ticket Booking mobile app UI in Expo React Native. Use when asked to create a movie ticket booking app UI or a new screen in this visual style.
---

# Movie Ticket Booking 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/movie-ticket-booking-app-ui-design

## Visual direction

A cinematic black and white base with a single ember accent, tall poster cards and a dark ticket stub that anchors the checkout.

Keep these signature details:

- Interactive seat map with classic and premium pricing
- Live ticket stub with seats, show time and total
- Peeking poster carousel with ranked overlays
- Date strip, format chips and theatre showtime cards

## Set up

```bash
npx expo install expo-image expo-linear-gradient react-native-svg @expo-google-fonts/bebas-neue @expo-google-fonts/inter expo-font
```

## Tokens

| Token | Hex |
| --- | --- |
| Ember | `#CC3A0E` |
| Ink | `#141414` |
| Screen black | `#000000` |
| Gold rating | `#F0A52B` |
| Available | `#23A55A` |
| Hairline | `#E0E0E0` |

- Typefaces: Inter, Bebas Neue
- Common sizes (px): 10, 11, 12, 13, 14, 15, 16, 17
- Common corner radii (px): 3, 4, 8, 9, 14, 999

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

## Screens

Build one Expo Router route per screen, in this order:

1. **Home and movie chart**: Primary tabs, a peeking poster carousel with chart rank overlays, booking stats and a floating BOOK action in the tab bar.
2. **Movie detail**: A full-bleed poster fades to black behind the title lockup, runtime, languages, synopsis and a single Book Now action.
3. **Booking by theatre**: Format chips and a poster row on black, then a white sheet with a date strip, city filters and showtime chips colour-coded by availability.
4. **Seat selection**: A curved screen, tappable seat grid with aisles and two price tiers, a legend, and a dark ticket stub with a hold action.

## 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 movie-ticket-booking-app --template default
cd movie-ticket-booking-app
rm -rf src
npx expo install expo-image expo-linear-gradient react-native-svg @expo-google-fonts/bebas-neue @expo-google-fonts/inter expo-font

src/app/_layout.tsx

import { BebasNeue_400Regular } from '@expo-google-fonts/bebas-neue';
import {
  Inter_400Regular,
  Inter_600SemiBold,
  Inter_700Bold,
  Inter_800ExtraBold,
} from '@expo-google-fonts/inter';
import { useFonts } from 'expo-font';
import { Stack } from 'expo-router';

export default function RootLayout() {
  const [fontsLoaded] = useFonts({
    BebasNeue_400Regular,
    Inter_400Regular,
    Inter_600SemiBold,
    Inter_700Bold,
    Inter_800ExtraBold,
  });

  if (!fontsLoaded) return null;

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

About this design

The seat picker is real state, not a static mock. Taken seats are disabled, two price tiers total up as you pick, and the ticket stub updates live, so it is a strong starting point for any cinema, theatre or event booking app.

A cinematic black and white base with a single ember accent, tall poster cards and a dark ticket stub that anchors the checkout.

  • Interactive seat map with classic and premium pricing
  • Live ticket stub with seats, show time and total
  • Peeking poster carousel with ranked overlays
  • Date strip, format chips and theatre showtime cards

Colour palette

  • Ember

    #CC3A0E

  • Ink

    #141414

  • Screen black

    #000000

  • Gold rating

    #F0A52B

  • Available

    #23A55A

  • Hairline

    #E0E0E0

How to use this design

  1. 01

    Pick what to copy

    Copy the Movie Ticket Booking 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

Does the seat picker work, or is it a static mockup?

It works. Tapping a seat toggles it, taken seats are disabled, you can pick up to ten seats, and the total recalculates from the classic and premium prices.

Is the Movie Ticket Booking 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