@justeattakeaway/pie-modal 0.11.0 → 0.13.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,18 @@
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
+ &[open] {
41
+ // We only apply this when the modal is open,
42
+ // otherwise it interferes with the native
43
+ // `display: none;` on the dialog element.
44
+ display: flex;
45
+ flex-direction: column;
46
+ }
47
+
18
48
  border-radius: var(--modal-border-radius);
19
49
  border: none;
20
50
  box-shadow: var(--modal-elevation);
@@ -23,31 +53,60 @@
23
53
 
24
54
  padding: 0;
25
55
 
26
- --modal-max-inline-size: var(--modal-size-m);
56
+ --modal-margin-none: var(--dt-spacing-none);
57
+ --modal-margin-small: var(--dt-spacing-g);
58
+ --modal-margin-large: var(--dt-spacing-j);
59
+ --modal-margin-block: var(--modal-margin-small);
60
+
61
+ @media (min-width: $breakpoint-wide) {
62
+ --modal-margin-block: var(--modal-margin-large);
63
+ }
64
+
65
+ // The initial values for these variables apply to the medium-sized modal
66
+ // Other sizes will update the variables as needed
67
+ --modal-block-size: fit-content;
27
68
  --modal-inline-size: 75%;
69
+ --modal-max-block-size: calc(100vh - calc(var(--modal-margin-block) * 2));
70
+ --modal-max-inline-size: var(--modal-size-m);
28
71
 
29
- max-inline-size: var(--modal-max-inline-size);
72
+ block-size: var(--modal-block-size);
30
73
  inline-size: var(--modal-inline-size);
74
+ max-block-size: var(--modal-max-block-size);
75
+ max-inline-size: var(--modal-max-inline-size);
31
76
 
32
77
  &[size='small'] {
33
78
  --modal-max-inline-size: var(--modal-size-s);
79
+
80
+ @media (min-width: $breakpoint-wide) {
81
+ --modal-margin-block: var(--modal-margin-large);
82
+ }
34
83
  }
35
84
 
36
85
  &[size='medium'] {
37
86
  /* Same as default styles */
38
87
  &[isfullwidthbelowmid] {
39
- @media (max-width: $breakpoint-wide) {
88
+ @media (max-width: calc($breakpoint-wide - 1px)) {
89
+ --modal-margin-block: var(--modal-margin-none);
90
+ --modal-border-radius: var(--dt-radius-rounded-none);
91
+ --modal-block-size: 100%;
40
92
  --modal-inline-size: 100%;
93
+
94
+ // In this case, the modal must exceed the previous maximum width
95
+ --modal-max-inline-size: 100%;
41
96
  }
42
97
  }
43
98
  }
44
99
 
45
100
  &[size='large'] {
101
+ --modal-inline-size: 75%;
46
102
  --modal-max-inline-size: var(--modal-size-l);
47
- --modal-inline-size: 100%;
103
+ --modal-margin-block: var(--modal-margin-large);
48
104
 
49
- @media (min-width: $breakpoint-wide) {
50
- --modal-inline-size: 75%;
105
+ @media (max-width: calc($breakpoint-wide - 1px)) {
106
+ --modal-margin-block: var(--modal-margin-none);
107
+ --modal-border-radius: var(--dt-radius-rounded-none);
108
+ --modal-block-size: 100%;
109
+ --modal-inline-size: 100%;
51
110
  }
52
111
  }
53
112
 
@@ -57,21 +116,60 @@
57
116
  background: #{dt.$color-overlay};
58
117
  }
59
118
 
119
+ & .c-modal-footer {
120
+ --modal-button-spacing: var(--dt-spacing-d);
121
+ --modal-footer-padding: var(--dt-spacing-d);
122
+
123
+ display: flex;
124
+ flex-flow: row-reverse;
125
+ flex-wrap: wrap;
126
+ gap: var(--modal-button-spacing);
127
+ padding: var(--modal-footer-padding);
128
+
129
+ @media (min-width: $breakpoint-wide) {
130
+ --modal-footer-padding: var(--dt-spacing-e);
131
+ }
132
+ }
133
+
134
+ & .c-modal-header {
135
+ --modal-header-padding: var(--dt-spacing-e);
136
+
137
+ padding-inline: var(--modal-header-padding);
138
+ padding-block: var(--modal-header-padding);
139
+ align-items: center;
140
+ display: flex;
141
+ }
142
+
143
+ &[hasbackbutton] .c-modal-header {
144
+ padding-block: var(--dt-spacing-c);
145
+ padding-inline-start: var(--dt-spacing-c);
146
+ }
147
+
148
+ &[isdismissible] .c-modal-header {
149
+ justify-content: space-between;
150
+ padding-block: var(--dt-spacing-c);
151
+ padding-inline-end: var(--dt-spacing-c);
152
+ }
153
+
60
154
  & .c-modal-heading {
61
- // Modal header Custom Props
62
155
  --modal-header-font-size: calc(var(--dt-font-heading-m-size--wide) * 1px);
63
156
  --modal-header-font-line-height: calc(var(--dt-font-heading-m-line-height--wide) * 1px);
64
157
  --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
158
 
68
159
  font-size: var(--modal-header-font-size);
69
160
  line-height: var(--modal-header-font-line-height);
70
161
  font-weight: var(--modal-header-font-weight);
71
-
72
162
  margin: 0;
73
- padding-block: var(--modal-header-padding) var(--modal-header-padding-block-end);
74
- padding-inline: var(--modal-header-padding);
163
+ }
164
+
165
+ // Ensure correct padding when there is a back button in front of the heading
166
+ &[hasbackbutton] .c-modal-heading {
167
+ margin-inline-start: var(--dt-spacing-c);
168
+ }
169
+
170
+ // Ensure correct padding when there is a close button behind the heading
171
+ &[isdismissible] .c-modal-heading {
172
+ margin-inline-end: var(--dt-spacing-e);
75
173
  }
76
174
 
77
175
  & .c-modal-content {
@@ -80,22 +178,88 @@
80
178
  --modal-content-font-weight: var(--dt-font-weight-regular);
81
179
  --modal-content-line-height: calc(var(--dt-font-size-16-line-height) * 1px);
82
180
  --modal-content-padding: var(--dt-spacing-e);
83
- --modal-content-padding-block-start: var(--dt-spacing-a);
181
+ --modal-content-padding-block: var(--dt-spacing-a);
182
+
183
+ // Spinner sizes defaults
184
+ --spinner-size: 48px;
185
+ --spinner-border-width: 6px;
186
+
187
+ // Spinner colors - currently set for the primary button styles
188
+ --spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);
189
+ --spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);
190
+ --spinner-base-color-l: var(--dt-color-content-interactive-secondary-l);
191
+ --spinner-left-color-opacity: 0.35;
192
+ --spinner-left-color: hsl(var(--spinner-base-color-h), var(--spinner-base-color-s), var(--spinner-base-color-l), var(--spinner-left-color-opacity));
193
+ --spinner-right-color: hsl(var(--spinner-base-color-h), var(--spinner-base-color-s), var(--spinner-base-color-l), 1);
194
+
195
+ // Spinner animations
196
+ --spinner-animation-duration: 1.15s;
197
+ --spinner-animation-timing-function: linear;
198
+ --spinner-animation-iteration-count: infinite;
199
+
200
+ position: relative;
201
+ min-block-size: 60px;
84
202
 
85
203
  font-size: var(--modal-content-font-size);
86
204
  line-height: var(--modal-content-line-height);
87
205
  font-weight: var(--modal-content-font-weight);
88
206
 
89
- padding-block: var(--modal-content-padding-block-start) var(--modal-content-padding);
90
207
  padding-inline: var(--modal-content-padding);
208
+ padding-block: var(--modal-content-padding-block);
209
+
210
+ overflow-y: auto;
211
+
212
+ &--scrollable {
213
+ background:
214
+ // Scroll shadow cover
215
+ // A top-to-bottom opacity gradient from transparent to the component background colour
216
+ linear-gradient(to bottom, transparent, var(--dt-color-container-default) 75%) center bottom,
217
+ // Scroll shadow
218
+ linear-gradient(transparent, var(--dt-color-border-strong)) center bottom;
219
+ background-repeat: no-repeat;
220
+ background-size: 100% 48px, 100% 12px;
221
+
222
+ // The shadow cover is an opacity gradient which is attached to the bottom of the scrollable element
223
+ // and scrolls with it, so as you reach the bottom of the content the more opaque portion covers
224
+ // (and therefore hides) the shadow. This gives the effect of the shadow fading away.
225
+ // The shadow itself does not move as you scroll.
226
+ background-attachment: local, scroll;
227
+ }
228
+
229
+ &:before {
230
+ content: '';
91
231
 
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
232
+ // Centre the spinner over the top of the button text
233
+ position: absolute;
234
+ left: 50%;
235
+ top: 50%;
236
+ translate: -50% -50%;
237
+
238
+ height: var(--spinner-size);
239
+ width: var(--spinner-size);
240
+ display: block;
241
+ background-color: transparent;
242
+ border-radius: 50%;
243
+ border-color: var(--spinner-left-color) var(--spinner-right-color) var(--spinner-right-color) var(--spinner-left-color);
244
+ border-width: var(--spinner-border-width);
245
+ border-style: solid;
246
+ will-change: transform;
247
+ opacity: 0;
248
+ }
249
+ }
250
+
251
+ &[isLoading] .c-modal-content {
252
+ &:before {
253
+ animation: rotate360 var(--spinner-animation-duration) var(--spinner-animation-timing-function) var(--spinner-animation-iteration-count);
254
+ opacity: 1;
255
+ }
256
+
257
+ & .c-modal-contentInner {
258
+ opacity: 0;
259
+ }
94
260
  }
95
261
 
96
262
  & .c-modal-closeBtn {
97
- position: absolute;
98
- inset-inline-end: var(--dt-spacing-d);
99
- inset-block-start: var(--dt-spacing-d);
263
+ margin-inline-start: auto;
100
264
  }
101
265
  }