@justeattakeaway/pie-modal 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/modal.scss CHANGED
@@ -1,5 +1,23 @@
1
1
  @use '@justeat/pie-design-tokens/dist/jet.scss' as dt;
2
2
 
3
+ // TODO - add to CSS lib once created
4
+ *,
5
+ *:before,
6
+ *:after {
7
+ box-sizing: border-box;
8
+ }
9
+
10
+ // Spin animation for loading state
11
+ @keyframes rotate360 {
12
+ from {
13
+ transform: rotate(0deg);
14
+ }
15
+
16
+ to {
17
+ transform: rotate(360deg);
18
+ }
19
+ }
20
+
3
21
  .c-modal {
4
22
  // Custom Property Declarations
5
23
  // These are defined here instead of :host to encapsulate them inside Shadow DOM
@@ -15,6 +33,25 @@
15
33
  --modal-bg-color: var(--dt-color-container-default);
16
34
  --modal-elevation: var(--dt-elevation-04);
17
35
 
36
+ &:focus-visible {
37
+ outline: none;
38
+ }
39
+
40
+ // We need to override the icon sizes at different screen sizes regardless of size prop passed in
41
+ pie-icon-button {
42
+ @media (max-width: $breakpoint-wide) {
43
+ --btn-dimension: 40px;
44
+ }
45
+ }
46
+
47
+ &[open] {
48
+ // We only apply this when the modal is open,
49
+ // otherwise it interferes with the native
50
+ // `display: none;` on the dialog element.
51
+ display: flex;
52
+ flex-direction: column;
53
+ }
54
+
18
55
  border-radius: var(--modal-border-radius);
19
56
  border: none;
20
57
  box-shadow: var(--modal-elevation);
@@ -23,31 +60,70 @@
23
60
 
24
61
  padding: 0;
25
62
 
26
- --modal-max-inline-size: var(--modal-size-m);
63
+ --modal-margin-none: var(--dt-spacing-none);
64
+ --modal-margin-small: var(--dt-spacing-g);
65
+ --modal-margin-large: var(--dt-spacing-j);
66
+ --modal-margin-block: var(--modal-margin-small);
67
+
68
+ @media (min-width: $breakpoint-wide) {
69
+ --modal-margin-block: var(--modal-margin-large);
70
+ }
71
+
72
+ // The initial values for these variables apply to the medium-sized modal
73
+ // Other sizes will update the variables as needed
74
+ --modal-block-size: fit-content;
27
75
  --modal-inline-size: 75%;
76
+ --modal-max-block-size: calc(100vh - calc(var(--modal-margin-block) * 2));
77
+ --modal-max-inline-size: var(--modal-size-m);
28
78
 
29
- max-inline-size: var(--modal-max-inline-size);
79
+ block-size: var(--modal-block-size);
30
80
  inline-size: var(--modal-inline-size);
81
+ max-block-size: var(--modal-max-block-size);
82
+ max-inline-size: var(--modal-max-inline-size);
31
83
 
32
84
  &[size='small'] {
33
85
  --modal-max-inline-size: var(--modal-size-s);
86
+
87
+ @media (min-width: $breakpoint-wide) {
88
+ --modal-margin-block: var(--modal-margin-large);
89
+ }
34
90
  }
35
91
 
36
92
  &[size='medium'] {
37
93
  /* Same as default styles */
38
94
  &[isfullwidthbelowmid] {
39
- @media (max-width: $breakpoint-wide) {
95
+ @media (max-width: calc($breakpoint-wide - 1px)) {
96
+ --modal-margin-block: var(--modal-margin-none);
97
+ --modal-border-radius: var(--dt-radius-rounded-none);
98
+ --modal-block-size: 100%;
40
99
  --modal-inline-size: 100%;
100
+
101
+ // In this case, the modal must exceed the previous maximum width
102
+ --modal-max-inline-size: 100%;
41
103
  }
42
104
  }
43
105
  }
44
106
 
45
107
  &[size='large'] {
108
+ --modal-inline-size: 75%;
46
109
  --modal-max-inline-size: var(--modal-size-l);
47
- --modal-inline-size: 100%;
110
+ --modal-margin-block: var(--modal-margin-large);
48
111
 
49
- @media (min-width: $breakpoint-wide) {
50
- --modal-inline-size: 75%;
112
+ @media (max-width: calc($breakpoint-wide - 1px)) {
113
+ --modal-margin-block: var(--modal-margin-none);
114
+ --modal-border-radius: var(--dt-radius-rounded-none);
115
+ --modal-block-size: 100%;
116
+ --modal-inline-size: 100%;
117
+ }
118
+ }
119
+
120
+ &[position='top'] {
121
+ margin-block-start: var(--dt-spacing-j);
122
+
123
+ &[isfullwidthbelowmid] {
124
+ @media (max-width: calc($breakpoint-wide - 1px)) {
125
+ margin-block-start: var(--dt-spacing-none);
126
+ }
51
127
  }
52
128
  }
53
129
 
@@ -57,21 +133,93 @@
57
133
  background: #{dt.$color-overlay};
58
134
  }
59
135
 
136
+ & .c-modal-footer {
137
+ --modal-button-spacing: var(--dt-spacing-d);
138
+ --modal-footer-padding: var(--dt-spacing-d);
139
+
140
+ display: flex;
141
+ flex-flow: row-reverse;
142
+ flex-wrap: wrap;
143
+ gap: var(--modal-button-spacing);
144
+ padding: var(--modal-footer-padding);
145
+
146
+ @media (min-width: $breakpoint-wide) {
147
+ --modal-footer-padding: var(--dt-spacing-e);
148
+ }
149
+ }
150
+
151
+ & .c-modal-header {
152
+ padding-inline: var(--dt-spacing-d);
153
+ padding-block: 14px; // This is deliberately not a custom property
154
+ display: grid;
155
+ grid-template-areas:
156
+ 'back heading close'
157
+ '. heading .';
158
+ grid-template-columns: minmax(0, max-content) minmax(0, 1fr) minmax(0, max-content);
159
+ align-items: center;
160
+
161
+ @media (min-width: $breakpoint-wide) {
162
+ padding-inline: var(--dt-spacing-e);
163
+ padding-block: 20px; // This is deliberately not a custom property
164
+ }
165
+ }
166
+
167
+ &[hasbackbutton] .c-modal-header {
168
+ padding-block: var(--dt-spacing-b);
169
+ padding-inline-start: var(--dt-spacing-b);
170
+
171
+ @media (min-width: $breakpoint-wide) {
172
+ padding-block: var(--dt-spacing-c);
173
+ padding-inline-start: var(--dt-spacing-c);
174
+ }
175
+ }
176
+
177
+ &[isdismissible] .c-modal-header {
178
+ padding-block: var(--dt-spacing-b);
179
+ padding-inline-end: var(--dt-spacing-b);
180
+
181
+ @media (min-width: $breakpoint-wide) {
182
+ padding-block: var(--dt-spacing-c);
183
+ padding-inline-end: var(--dt-spacing-c);
184
+ }
185
+ }
186
+
60
187
  & .c-modal-heading {
61
- // Modal header Custom Props
62
188
  --modal-header-font-size: calc(var(--dt-font-heading-m-size--wide) * 1px);
63
189
  --modal-header-font-line-height: calc(var(--dt-font-heading-m-line-height--wide) * 1px);
64
190
  --modal-header-font-weight: var(--dt-font-heading-m-weight);
65
- --modal-header-padding: var(--dt-spacing-e);
66
- --modal-header-padding-block-end: var(--dt-spacing-d);
67
191
 
68
192
  font-size: var(--modal-header-font-size);
69
193
  line-height: var(--modal-header-font-line-height);
70
194
  font-weight: var(--modal-header-font-weight);
71
-
72
195
  margin: 0;
73
- padding-block: var(--modal-header-padding) var(--modal-header-padding-block-end);
74
- padding-inline: var(--modal-header-padding);
196
+ grid-area: heading;
197
+ }
198
+
199
+ // Ensure correct padding when there is a back button in front of the heading
200
+ &[hasbackbutton] .c-modal-heading {
201
+ padding-inline-start: var(--dt-spacing-b);
202
+
203
+ @media (min-width: $breakpoint-wide) {
204
+ padding-inline-start: var(--dt-spacing-c);
205
+ }
206
+ }
207
+
208
+ // Ensure correct padding when there is a close button behind the heading
209
+ &[isdismissible] .c-modal-heading {
210
+ padding-inline-end: var(--dt-spacing-d);
211
+
212
+ @media (min-width: $breakpoint-wide) {
213
+ padding-inline-end: var(--dt-spacing-e);
214
+ }
215
+ }
216
+
217
+ & .c-modal-backBtn {
218
+ grid-area: back;
219
+ }
220
+
221
+ & .c-modal-closeBtn {
222
+ grid-area: close;
75
223
  }
76
224
 
77
225
  & .c-modal-content {
@@ -80,22 +228,84 @@
80
228
  --modal-content-font-weight: var(--dt-font-weight-regular);
81
229
  --modal-content-line-height: calc(var(--dt-font-size-16-line-height) * 1px);
82
230
  --modal-content-padding: var(--dt-spacing-e);
83
- --modal-content-padding-block-start: var(--dt-spacing-a);
231
+ --modal-content-padding-block: var(--dt-spacing-a);
232
+
233
+ // Spinner sizes defaults
234
+ --spinner-size: 48px;
235
+ --spinner-border-width: 6px;
236
+
237
+ // Spinner colors - currently set for the primary button styles
238
+ --spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);
239
+ --spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);
240
+ --spinner-base-color-l: var(--dt-color-content-interactive-secondary-l);
241
+ --spinner-left-color-opacity: 0.35;
242
+ --spinner-left-color: hsl(var(--spinner-base-color-h), var(--spinner-base-color-s), var(--spinner-base-color-l), var(--spinner-left-color-opacity));
243
+ --spinner-right-color: hsl(var(--spinner-base-color-h), var(--spinner-base-color-s), var(--spinner-base-color-l), 1);
244
+
245
+ // Spinner animations
246
+ --spinner-animation-duration: 1.15s;
247
+ --spinner-animation-timing-function: linear;
248
+ --spinner-animation-iteration-count: infinite;
249
+
250
+ position: relative;
251
+ min-block-size: var(--dt-spacing-j);
84
252
 
85
253
  font-size: var(--modal-content-font-size);
86
254
  line-height: var(--modal-content-line-height);
87
255
  font-weight: var(--modal-content-font-weight);
88
256
 
89
- padding-block: var(--modal-content-padding-block-start) var(--modal-content-padding);
90
257
  padding-inline: var(--modal-content-padding);
258
+ padding-block: var(--modal-content-padding-block);
259
+
260
+ overflow-y: auto;
91
261
 
92
- overflow-y: scroll;
93
- max-block-size: 300px; // This is just a placeholder before we add the proper container styles to slotted content to demonstrate scrollable slot content
262
+ &--scrollable {
263
+ background:
264
+ // Scroll shadow cover
265
+ // A top-to-bottom opacity gradient from transparent to the component background colour
266
+ linear-gradient(to bottom, transparent, var(--dt-color-container-default) 75%) center bottom,
267
+ // Scroll shadow
268
+ linear-gradient(transparent, var(--dt-color-border-strong)) center bottom;
269
+ background-repeat: no-repeat;
270
+ background-size: 100% 48px, 100% 12px;
271
+
272
+ // The shadow cover is an opacity gradient which is attached to the bottom of the scrollable element
273
+ // and scrolls with it, so as you reach the bottom of the content the more opaque portion covers
274
+ // (and therefore hides) the shadow. This gives the effect of the shadow fading away.
275
+ // The shadow itself does not move as you scroll.
276
+ background-attachment: local, scroll;
277
+ }
278
+
279
+ &:before {
280
+ content: '';
281
+
282
+ // Centre the spinner over the top of the button text
283
+ position: absolute;
284
+ left: 50%;
285
+ top: 50%;
286
+ translate: -50% -50%;
287
+
288
+ height: var(--spinner-size);
289
+ width: var(--spinner-size);
290
+ display: block;
291
+ background-color: transparent;
292
+ border-radius: 50%;
293
+ border-color: var(--spinner-left-color) var(--spinner-right-color) var(--spinner-right-color) var(--spinner-left-color);
294
+ border-width: var(--spinner-border-width);
295
+ border-style: solid;
296
+ will-change: transform;
297
+ opacity: 0;
298
+ }
94
299
  }
95
300
 
96
- & .c-modal-closeBtn {
97
- position: absolute;
98
- inset-inline-end: var(--dt-spacing-d);
99
- inset-block-start: var(--dt-spacing-d);
301
+ &[isLoading] .c-modal-content {
302
+ &:before {
303
+ animation: rotate360 var(--spinner-animation-duration) var(--spinner-animation-timing-function) var(--spinner-animation-iteration-count);
304
+ opacity: 1;
305
+ }
306
+
307
+ & .c-modal-contentInner {
308
+ opacity: 0;
309
+ }
100
310
  }
101
311
  }