forked from OurHike/OurHike
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathonboarding.css
More file actions
154 lines (149 loc) · 5.24 KB
/
Copy pathonboarding.css
File metadata and controls
154 lines (149 loc) · 5.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/* First run, as a card over the map (screens/Onboarding.tsx).
*
* The rule this file exists to keep: the map behind the steps stays visible.
* That is not decoration - every one of the three steps is a claim about the
* map, so a stylesheet that covered it would quietly undo the reason the map
* is drawn behind them at all.
*
* So there is no page background here, and the card is capped short of the
* viewport rather than sized by its contents. Both are asserted in
* test/entryLayout.test.ts, because jsdom does no layout and "you can still
* see the map" is exactly the kind of property that decays under a later
* well-meaning `min-height: 100svh`.
*
* The file header used to say the shell "pays for a whole extra MapLibre build
* to have it there". It no longer does - #721 made the map screen itself the
* backdrop, hidden down to its canvas - which is also why the block below is
* an overlay rather than a child of a frame that no longer exists.
*/
.onboarding {
/* Over the map screen, which is a sibling in App.tsx's fragment rather than
a parent (#721). Fixed rather than absolute because there is no positioned
ancestor to resolve against any more, and the steps want the viewport:
.map-screen is 100svh, so this covers exactly it. */
position: fixed;
inset: 0;
z-index: 1;
display: flex;
flex-direction: column;
/* The card sits at the bottom - the thumb end of a phone, and the end of
the screen a map is least often read from. */
justify-content: flex-end;
/* Deliberately no background. See the file header - and note that being a
full-viewport overlay makes this line load-bearing rather than merely
tidy: a background here would hide the map completely. */
pointer-events: none;
}
/* The steps themselves.
*
* `max-height` is the load-bearing line: it is what guarantees the map is
* visible above the card on a short screen as well as a tall one. The card
* scrolls its own contents past that point rather than growing, so the way
* forward is never pushed off the bottom of the screen. */
.onboarding__card {
position: relative;
display: flex;
flex-direction: column;
gap: var(--space-4, 16px);
max-height: 78%;
overflow-y: auto;
/* Only the card takes taps - the overlay around it is `pointer-events: none`
so the empty region is a window onto the map rather than a modal scrim,
which is the one thing the design says it is not. */
pointer-events: auto;
padding: var(--space-5, 20px);
padding-bottom: max(var(--space-5, 20px), env(safe-area-inset-bottom, 0));
background: var(--bg-page);
/* A sheet over the map, shaped like the one this app already has: the same
14px top corners and the same upward shadow as the legend (chrome.css),
which is the other thing that rises over this map from the bottom edge.
No scrim over the map behind it, for the same reason the legend has none -
dimming the map to introduce the map is a strange way to introduce it. */
border-radius: var(--radius-l, 14px) var(--radius-l, 14px) 0 0;
box-shadow: 0 -6px 24px rgb(0 0 0 / 12%);
animation: onboarding-rise var(--duration-slow, 320ms) var(--ease-out, ease-out) both;
}
/* Emergent rather than instant: the card lifts into place over the map, and
each step lifts again as it replaces the last (the element is keyed by step
in Onboarding.tsx, so React remounts it and the animation re-runs).
Transform and opacity only - both are compositor properties, so this costs
no layout on a phone that is also building a map. */
@keyframes onboarding-rise {
from {
opacity: 0;
transform: translateY(12px);
}
to {
opacity: 1;
transform: none;
}
}
/* Motion is the part of this that is optional, and the only part. Someone who
has asked their phone for less of it still gets the card, the map behind it
and every step in the same place - it simply arrives rather than rises. */
@media (prefers-reduced-motion: reduce) {
.onboarding__card {
animation: none;
}
}
.onboarding__progress {
margin: 0;
font-family: var(--font-mono, ui-monospace, monospace);
font-size: 11px;
color: var(--fg-3);
}
.onboarding__step {
display: flex;
flex-direction: column;
gap: var(--space-3, 12px);
}
.onboarding__title {
margin: 0;
font-size: 24px;
color: var(--fg-1);
}
/* One line on the sheet whose tab is open, in the same voice the download
window uses under its own tabs (downloads.css .downloads__item-summary). */
.onboarding__sheet-summary {
margin: 0;
color: var(--fg-2);
font-size: 13px;
}
.onboarding__reassurance {
font-weight: 600;
color: var(--brand-primary);
}
.onboarding__actions,
.onboarding__nav {
display: flex;
flex-direction: column;
gap: var(--space-2, 8px);
}
.onboarding__primary,
.onboarding__secondary,
.onboarding__skip {
min-height: var(--min-touch-target, 44px);
border-radius: 10px;
cursor: pointer;
font-size: 15px;
font-weight: 600;
transition:
background-color 160ms ease,
color 160ms ease;
}
.onboarding__primary {
color: var(--fg-on-brand);
background: var(--brand-primary);
border: 0;
}
.onboarding__secondary {
color: var(--fg-1);
background: var(--bg-surface);
border: 1px solid var(--border-2);
}
.onboarding__skip {
color: var(--fg-3);
background: none;
border: 0;
font-weight: 500;
}