hlarcher HF Staff commited on
Commit
878012f
·
unverified ·
1 Parent(s): f457ce6

Mobile optimizations and Safran logo

Browse files

- Reduce timeline padding on mobile
- Hide timeline tooltips on mobile
- Move event card to top of map on mobile
- Zoom out to show all France during playback on mobile
- Add embedded Safran Aircraft Engines logo to header

index.html CHANGED
@@ -1,31 +1,62 @@
1
  <!DOCTYPE html>
2
  <html lang="fr">
3
  <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Patrouille de France - Airshow Tracker</title>
7
- <link href="https://api.mapbox.com/mapbox-gl-js/v3.9.4/mapbox-gl.css" rel="stylesheet">
8
- <link rel="stylesheet" href="/src/styles/main.css">
9
- <link rel="stylesheet" href="/src/styles/timeline.css">
10
  </head>
11
  <body>
12
- <div id="app">
13
  <header class="header">
14
- <h1>Patrouille de France</h1>
15
- <span class="subtitle">Airshow Tracker</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  </header>
17
 
18
  <main class="main">
19
- <div id="map" class="map"></div>
20
- <div id="countdown" class="countdown-container"></div>
21
- <div id="event-card" class="event-card hidden"></div>
22
  </main>
23
 
24
  <footer class="footer">
25
- <div id="timeline" class="timeline"></div>
26
  </footer>
27
- </div>
28
 
29
- <script type="module" src="/src/main.js"></script>
30
  </body>
31
  </html>
 
1
  <!DOCTYPE html>
2
  <html lang="fr">
3
  <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Patrouille de France - Airshow Tracker</title>
7
+ <link href="https://api.mapbox.com/mapbox-gl-js/v3.9.4/mapbox-gl.css" rel="stylesheet">
8
+ <link rel="stylesheet" href="/src/styles/main.css">
9
+ <link rel="stylesheet" href="/src/styles/timeline.css">
10
  </head>
11
  <body>
12
+ <div id="app">
13
  <header class="header">
14
+ <h1>Patrouille de France</h1>
15
+ <span class="subtitle">Airshow Tracker</span>
16
+ <span class="header-spacer"></span>
17
+ <svg xmlns="http://www.w3.org/2000/svg" class="header-logo"
18
+ x="0px" y="0px" viewBox="0 0 922 200">
19
+ <g>
20
+ <path class="st0" d="M488.8,70.9v25l56.7,0l-3.4,16.2h-53.2v35.8H463V54.6h91.3l-3.5,16.3H488.8z M803,147.9h-29.7l-8.9-18.9h-49.8
21
+ l-8.6,18.9h-18.7l43.9-93.3c0,0,11.7,0,17.5,0c6.6,0,9.1,2.7,12.5,9.7C764.4,70.9,803,147.9,803,147.9z M756.7,112.8l-17.6-37.2
22
+ l-17,37.2H756.7z M450.2,147.9h-29.7l-8.9-18.9h-49.8l-8.6,18.9h-18.7l44-93.3c0,0,11.7,0,17.5,0c6.6,0,9.1,2.7,12.5,9.7
23
+ C411.5,70.9,450.2,147.9,450.2,147.9z M403.8,112.8l-17.6-37.2l-17,37.2H403.8z M280,150.9c33.4,0,48.8-12.2,48.8-30
24
+ c0-15.5-14-23.4-44.7-31.8c-18.3-5-29.7-6-29.7-12.2c0-5.9,10.7-9.1,27.1-8.3c20.6,1,33.7,9.7,33.7,9.7l8.1-12.9
25
+ c0,0-18.5-13.7-47.9-13.7c-32.1,0-49,9.8-49,27.8c0,17.8,19.2,23.9,47.2,31.9c17.2,4.9,27.2,5.8,27.2,12.4
26
+ c0,5.1-5.2,11.4-28.1,10.3c-22-1.1-41.1-13.8-41.1-13.8l-9.8,11.9C221.9,132.1,242.8,150.9,280,150.9z M902.5,54.6v55.7
27
+ c0,0-54.7-43.6-59.2-47.2c-8.1-6.4-11.8-8.5-20.8-8.5c-3.8,0-6.7,0-6.7,0v93.3H835V93.1c0,0,54.2,43.3,58.7,46.8
28
+ c8.1,6.4,12.2,8,21.2,8c3.8,0,6.7,0,6.7,0V54.6H902.5z M677.4,147.9c0,0-6.7,0-17.5,0c-10.4,0-16.7-7.2-20.5-12.2
29
+ c-4.2-5.5-14.7-19.4-14.7-19.4s-1.2,0-1.8,0c-7,0-26.3,0-26.3,0h-0.3v31.6h-25.9V54.6h26.2c0,0,19.2,0,26.3,0
30
+ c20.1,0,49,2.1,49,30.9v0c0,16.7-9.8,24.4-21.9,27.9L677.4,147.9z M643.8,85.5L643.8,85.5c0-9.8-6.2-14.6-19.9-14.6h-27.3l-0.3-0.2
31
+ v29.6l0.3-0.2h27.3C637.6,100.1,643.8,95.3,643.8,85.5z">
32
+ </path>
33
+ <path class="st0" d="M175,141.5h-2.1c-19.2,26.3-50.2,43.4-85.2,43.4c-35,0-66.1-17.1-85.2-43.4H0.4c15.5,32.6,48.8,55.2,87.3,55.2
34
+ C126.2,196.6,159.5,174.1,175,141.5z">
35
+ </path>
36
+ <path id="_x3C_Tracé_x3E__7_" class="st0" d="M156.9,151.9c4.7-5.2,8.9-12.4,9.8-17.6c4.5-23.8-17.6-35.9-43.7-45
37
+ c-20.4-7.1-37.2-12-51.5-16.4c-22.7-7-26.6-13.7-26.4-20.9c0.2-8.4,9.1-19,19.2-25.3c0,0-19-0.1-38.3,14.3
38
+ C14.7,49.5,10,58.3,8.3,66.3c-8.1,39.8,70.5,55.6,100.7,65.4c16.5,5.4,18.7,12.6,18.6,18.3c-0.3,13.3-19.1,25.3-19.2,25.3
39
+ C123.7,175,144.4,165.9,156.9,151.9">
40
+ </path>
41
+ <path class="st0" d="M175,58.5h-2.1c-19.2-26.3-50.2-43.4-85.2-43.4c-35,0-66.1,17.1-85.2,43.4H0.4C15.9,25.9,49.2,3.4,87.7,3.4
42
+ C126.2,3.4,159.5,25.9,175,58.5z">
43
+ </path>
44
+ </g>
45
+ </svg>
46
+
47
  </header>
48
 
49
  <main class="main">
50
+ <div id="map" class="map"></div>
51
+ <div id="countdown" class="countdown-container"></div>
52
+ <div id="event-card" class="event-card hidden"></div>
53
  </main>
54
 
55
  <footer class="footer">
56
+ <div id="timeline" class="timeline"></div>
57
  </footer>
58
+ </div>
59
 
60
+ <script type="module" src="/src/main.js"></script>
61
  </body>
62
  </html>
src/components/Map.js CHANGED
@@ -136,6 +136,14 @@ export class MapView {
136
  this.hideFlightPath();
137
  }
138
 
 
 
 
 
 
 
 
 
139
  getMap() {
140
  return this.map;
141
  }
 
136
  this.hideFlightPath();
137
  }
138
 
139
+ zoomToFrance() {
140
+ this.map.flyTo({
141
+ center: MAP_CONFIG.center,
142
+ zoom: 4.3,
143
+ duration: 800
144
+ });
145
+ }
146
+
147
  getMap() {
148
  return this.map;
149
  }
src/main.js CHANGED
@@ -6,6 +6,9 @@ import { HOME_BASE } from './config.js';
6
  import airshowData from './data/airshows.json';
7
 
8
  const FLIGHT_ANIMATION_DURATION = 2000; // ms
 
 
 
9
 
10
  class App {
11
  constructor() {
@@ -103,6 +106,11 @@ class App {
103
  this.isPlaying = playing;
104
 
105
  if (playing) {
 
 
 
 
 
106
  // Start playback
107
  if (this.timeline.selectedIndex < 0) {
108
  // No event selected, start from first
 
6
  import airshowData from './data/airshows.json';
7
 
8
  const FLIGHT_ANIMATION_DURATION = 2000; // ms
9
+ const MOBILE_BREAKPOINT = 768;
10
+
11
+ const isMobile = () => window.innerWidth <= MOBILE_BREAKPOINT;
12
 
13
  class App {
14
  constructor() {
 
106
  this.isPlaying = playing;
107
 
108
  if (playing) {
109
+ // On mobile, zoom out to show all of France during playback
110
+ if (isMobile()) {
111
+ this.map.zoomToFrance();
112
+ }
113
+
114
  // Start playback
115
  if (this.timeline.selectedIndex < 0) {
116
  // No event selected, start from first
src/styles/main.css CHANGED
@@ -67,6 +67,16 @@ body {
67
  color: var(--color-text-muted);
68
  }
69
 
 
 
 
 
 
 
 
 
 
 
70
  /* Main content */
71
  .main {
72
  flex: 1;
@@ -340,20 +350,21 @@ body {
340
  display: none;
341
  }
342
 
343
- /* Event card - bottom sheet style */
344
  .event-card {
345
- top: auto;
346
- bottom: var(--timeline-height);
347
- left: 0;
348
- right: 0;
349
- width: 100%;
350
- border-radius: 12px 12px 0 0;
351
- padding: 16px;
352
  transform: translateY(0);
353
  }
354
 
355
  .event-card.hidden {
356
- transform: translateY(100%);
 
357
  }
358
 
359
  .event-card h2 {
@@ -381,4 +392,8 @@ body {
381
  .header .subtitle {
382
  display: none;
383
  }
 
 
 
 
384
  }
 
67
  color: var(--color-text-muted);
68
  }
69
 
70
+ .header-spacer {
71
+ flex: 1;
72
+ }
73
+
74
+ .header-logo {
75
+ height: 24px;
76
+ opacity: 0.6;
77
+ filter: brightness(0) invert(1);
78
+ }
79
+
80
  /* Main content */
81
  .main {
82
  flex: 1;
 
350
  display: none;
351
  }
352
 
353
+ /* Event card - top position on mobile */
354
  .event-card {
355
+ top: 8px;
356
+ bottom: auto;
357
+ left: 8px;
358
+ right: 8px;
359
+ width: auto;
360
+ border-radius: 8px;
361
+ padding: 12px;
362
  transform: translateY(0);
363
  }
364
 
365
  .event-card.hidden {
366
+ transform: translateY(-100%);
367
+ opacity: 0;
368
  }
369
 
370
  .event-card h2 {
 
392
  .header .subtitle {
393
  display: none;
394
  }
395
+
396
+ .header-logo {
397
+ height: 18px;
398
+ }
399
  }
src/styles/timeline.css CHANGED
@@ -198,7 +198,7 @@
198
  /* Mobile: horizontal scrolling timeline */
199
  @media (max-width: 768px) {
200
  .timeline {
201
- padding: 12px 16px;
202
  gap: 12px;
203
  }
204
 
@@ -214,7 +214,7 @@
214
 
215
  .timeline-months {
216
  gap: 16px;
217
- padding: 8px 16px 8px 0;
218
  }
219
 
220
  .timeline-year {
@@ -239,7 +239,8 @@
239
  height: 14px;
240
  }
241
 
 
242
  .timeline-event-tooltip {
243
- font-size: 0.6rem;
244
  }
245
  }
 
198
  /* Mobile: horizontal scrolling timeline */
199
  @media (max-width: 768px) {
200
  .timeline {
201
+ padding: 4px 16px;
202
  gap: 12px;
203
  }
204
 
 
214
 
215
  .timeline-months {
216
  gap: 16px;
217
+ padding: 4px 16px 4px 0;
218
  }
219
 
220
  .timeline-year {
 
239
  height: 14px;
240
  }
241
 
242
+ /* Hide tooltip on mobile */
243
  .timeline-event-tooltip {
244
+ display: none;
245
  }
246
  }