@justeattakeaway/pie-toast 0.2.0 → 0.3.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.
@@ -12,6 +12,14 @@
12
12
  "kind": "javascript-module",
13
13
  "path": "src/defs.js",
14
14
  "declarations": [
15
+ {
16
+ "kind": "variable",
17
+ "name": "variants",
18
+ "type": {
19
+ "text": "['neutral', 'info', 'warning', 'success', 'error']"
20
+ },
21
+ "default": "['neutral', 'info', 'warning', 'success', 'error']"
22
+ },
15
23
  {
16
24
  "kind": "variable",
17
25
  "name": "componentSelector",
@@ -52,10 +60,18 @@
52
60
  "type": {
53
61
  "text": "DefaultProps"
54
62
  },
55
- "default": "{\n isOpen: true,\n isDismissible: true,\n isMultiline: false,\n}"
63
+ "default": "{\n isOpen: true,\n variant: 'neutral',\n isStrong: false,\n isDismissible: true,\n isMultiline: false,\n}"
56
64
  }
57
65
  ],
58
66
  "exports": [
67
+ {
68
+ "kind": "js",
69
+ "name": "variants",
70
+ "declaration": {
71
+ "name": "variants",
72
+ "module": "src/defs.js"
73
+ }
74
+ },
59
75
  {
60
76
  "kind": "js",
61
77
  "name": "componentSelector",
@@ -131,6 +147,18 @@
131
147
  "privacy": "public",
132
148
  "attribute": "isOpen"
133
149
  },
150
+ {
151
+ "kind": "field",
152
+ "name": "variant",
153
+ "privacy": "public",
154
+ "attribute": "variant"
155
+ },
156
+ {
157
+ "kind": "field",
158
+ "name": "isStrong",
159
+ "privacy": "public",
160
+ "attribute": "isStrong"
161
+ },
134
162
  {
135
163
  "kind": "field",
136
164
  "name": "isDismissible",
@@ -293,6 +321,33 @@
293
321
  "name": "closeToastComponent",
294
322
  "privacy": "private",
295
323
  "description": "Util method responsible to close the component.\nIt handles the action when user clicks in the close button and triggers an event when is executed."
324
+ },
325
+ {
326
+ "kind": "method",
327
+ "name": "getVariantIcon",
328
+ "privacy": "private",
329
+ "description": "Util method that returns an icon from a variant that has default icon."
330
+ },
331
+ {
332
+ "kind": "method",
333
+ "name": "variantHasIcon",
334
+ "privacy": "private",
335
+ "parameters": [
336
+ {
337
+ "name": "variant",
338
+ "type": {
339
+ "text": "typeof variants[number]"
340
+ },
341
+ "description": "The variant to check if has icon."
342
+ }
343
+ ],
344
+ "description": "Util method that returns true if the variant has an icon."
345
+ },
346
+ {
347
+ "kind": "method",
348
+ "name": "shouldNotUseInverseBtnVariant",
349
+ "privacy": "private",
350
+ "description": "util method that returns true if the variant is warning and is strong."
296
351
  }
297
352
  ],
298
353
  "attributes": [
@@ -308,6 +363,14 @@
308
363
  "name": "isOpen",
309
364
  "fieldName": "isOpen"
310
365
  },
366
+ {
367
+ "name": "variant",
368
+ "fieldName": "variant"
369
+ },
370
+ {
371
+ "name": "isStrong",
372
+ "fieldName": "isStrong"
373
+ },
311
374
  {
312
375
  "name": "isDismissible",
313
376
  "fieldName": "isDismissible"
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ComponentDefaultPropsGeneric } from '@justeattakeaway/pie-webc-core';
1
+ import { ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
2
2
  import type { CSSResult } from 'lit';
3
3
  import type { GenericConstructor } from '@justeattakeaway/pie-webc-core';
4
4
  import type { LitElement } from 'lit';
@@ -22,7 +22,7 @@ export declare const componentClass = "c-toast";
22
22
 
23
23
  export declare const componentSelector = "pie-toast";
24
24
 
25
- export declare type DefaultProps = ComponentDefaultPropsGeneric<ToastProps, 'isOpen' | 'isDismissible' | 'isMultiline'>;
25
+ export declare type DefaultProps = ComponentDefaultProps<ToastProps, keyof Omit<ToastProps, 'message' | 'leadingAction'>>;
26
26
 
27
27
  export declare const defaultProps: DefaultProps;
28
28
 
@@ -52,9 +52,11 @@ export declare const ON_TOAST_OPEN_EVENT: string;
52
52
  */
53
53
  export declare class PieToast extends PieToast_base implements ToastProps {
54
54
  message: ToastProps['message'];
55
- isOpen: any;
56
- isDismissible: any;
57
- isMultiline: any;
55
+ isOpen: boolean;
56
+ variant: "neutral" | "info" | "warning" | "success" | "error";
57
+ isStrong: boolean;
58
+ isDismissible: boolean;
59
+ isMultiline: boolean;
58
60
  leadingAction: ToastProps['leadingAction'];
59
61
  actionButton?: HTMLElement;
60
62
  private _actionButtonOffset;
@@ -124,6 +126,26 @@ export declare class PieToast extends PieToast_base implements ToastProps {
124
126
  * @private
125
127
  */
126
128
  private closeToastComponent;
129
+ /**
130
+ * Util method that returns an icon from a variant that has default icon.
131
+ *
132
+ * @private
133
+ */
134
+ private getVariantIcon;
135
+ /**
136
+ * Util method that returns true if the variant has an icon.
137
+ *
138
+ * @param {typeof variants[number]} variant - The variant to check if has icon.
139
+ *
140
+ * @private
141
+ */
142
+ private variantHasIcon;
143
+ /**
144
+ * util method that returns true if the variant is warning and is strong.
145
+ *
146
+ * @private
147
+ */
148
+ private shouldNotUseInverseBtnVariant;
127
149
  render(): TemplateResult<1> | typeof nothing;
128
150
  }
129
151
 
@@ -134,6 +156,14 @@ export declare interface ToastProps {
134
156
  * When true, the toast is set to be open and visible.
135
157
  */
136
158
  isOpen?: boolean;
159
+ /**
160
+ * Sets the variant of the toast.
161
+ */
162
+ variant?: typeof variants[number];
163
+ /**
164
+ * When true, the toast is displayed with a strong visual style.
165
+ */
166
+ isStrong?: boolean;
137
167
  /**
138
168
  * When true, allows dismissing the toast by clicking on the close button.
139
169
  */
@@ -152,4 +182,6 @@ export declare interface ToastProps {
152
182
  leadingAction?: ActionProps;
153
183
  }
154
184
 
185
+ export declare const variants: readonly ["neutral", "info", "warning", "success", "error"];
186
+
155
187
  export { }
package/dist/index.js CHANGED
@@ -1,25 +1,30 @@
1
- import { LitElement as x, html as p, nothing as r, unsafeCSS as b } from "lit";
1
+ import { LitElement as y, html as c, nothing as l, unsafeCSS as w } from "lit";
2
2
  import { property as h, query as O } from "lit/decorators.js";
3
- import { classMap as y } from "lit/directives/class-map.js";
4
- import { RtlMixin as $, dispatchCustomEvent as g, defineCustomElement as A } from "@justeattakeaway/pie-webc-core";
3
+ import { classMap as b } from "lit/directives/class-map.js";
4
+ import { RtlMixin as A, dispatchCustomEvent as v, validPropertyValues as M, defineCustomElement as B } from "@justeattakeaway/pie-webc-core";
5
5
  import "@justeattakeaway/pie-icon-button";
6
6
  import "@justeattakeaway/pie-icons-webc/dist/IconClose.js";
7
- import "@justeattakeaway/pie-icons-webc/dist/IconPlaceholder.js";
7
+ import "@justeattakeaway/pie-icons-webc/dist/IconInfoCircle.js";
8
+ import "@justeattakeaway/pie-icons-webc/dist/IconAlertCircle.js";
9
+ import "@justeattakeaway/pie-icons-webc/dist/IconAlertTriangle.js";
10
+ import "@justeattakeaway/pie-icons-webc/dist/IconCheckCircle.js";
8
11
  import "@justeattakeaway/pie-button";
9
- const M = `*,*:after,*:before{box-sizing:inherit}.c-toast{--toast-border-radius: var(--dt-radius-rounded-b);--toast-background-color: var(--dt-color-container-inverse);--toast-font-color: var(--dt-color-content-inverse);--toast-font-size: calc(var(--dt-font-body-s-size) * 1px);--toast-line-height: calc(var(--dt-font-body-s-line-height) * 1px);display:flex;flex-direction:column;justify-content:center;min-height:48px;max-height:122px;min-width:300px;max-width:420px;padding:var(--dt-spacing-a) var(--dt-spacing-c) var(--dt-spacing-a) var(--dt-spacing-d);border-radius:var(--toast-border-radius);gap:var(--dt-spacing-a);background-color:var(--toast-background-color);box-shadow:var(--dt-elevation-03);color:var(--toast-font-color);font-size:var(--toast-font-size);line-height:var(--toast-line-height)}.c-toast-contentArea{display:flex;gap:var(--dt-spacing-b);justify-content:space-between}.c-toast-messageArea{display:flex;align-items:center;gap:var(--dt-spacing-b);padding:calc(var(--dt-spacing-03) / 2) 0}.c-toast-messageArea span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.c-toast-messageArea.is-multiline{align-items:flex-start}.c-toast-messageArea.is-multiline span{max-height:60px;white-space:inherit;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical}.c-toast-actionsArea{display:flex;gap:var(--dt-spacing-b)}.c-toast-footer{display:flex;justify-content:flex-end}
10
- `, o = "pie-toast", d = "c-toast", _ = `${o}-close`, C = `${o}-open`, w = `${o}-leading-action-click`, m = {
12
+ const C = `*,*:after,*:before{box-sizing:inherit}.c-toast{--toast-border-radius: var(--dt-radius-rounded-b);--toast-background-color: var(--dt-color-container-inverse);--toast-font-color: var(--dt-color-content-inverse);--toast-font-size: calc(var(--dt-font-body-s-size) * 1px);--toast-line-height: calc(var(--dt-font-body-s-line-height) * 1px);--toast-icon-fill: var(--dt-color-content-default);--toast-message-max-width: 100%;display:flex;flex-direction:column;justify-content:center;min-height:48px;max-height:122px;min-width:300px;max-width:420px;padding:var(--dt-spacing-a) var(--dt-spacing-c) var(--dt-spacing-a) var(--dt-spacing-d);border-radius:var(--toast-border-radius);gap:var(--dt-spacing-a);background-color:var(--toast-background-color);box-shadow:var(--dt-elevation-03);color:var(--toast-font-color);font-size:var(--toast-font-size);line-height:var(--toast-line-height)}.c-toast--info{--toast-icon-fill: var(--dt-color-support-info-inverse)}.c-toast--info.c-toast--strong{--toast-background-color: var(--dt-color-support-info);--toast-icon-fill: var(--dt-color-content-inverse)}.c-toast--warning{--toast-icon-fill: var(--dt-color-support-warning-inverse)}.c-toast--warning.c-toast--strong{--toast-background-color: var(--dt-color-support-warning);--toast-icon-fill: var(--dt-color-content-dark);--toast-font-color: var(--dt-color-content-dark)}.c-toast--success{--toast-icon-fill: var(--dt-color-support-positive-inverse)}.c-toast--success.c-toast--strong{--toast-background-color: var(--dt-color-support-positive);--toast-icon-fill: var(--dt-color-content-inverse)}.c-toast--error{--toast-icon-fill: var(--dt-color-support-error-inverse)}.c-toast--error.c-toast--strong{--toast-background-color: var(--dt-color-support-error);--toast-icon-fill: var(--dt-color-content-inverse)}.c-toast-contentArea{display:flex;gap:var(--dt-spacing-b);justify-content:space-between}.c-toast-messageArea{display:flex;align-items:center;gap:var(--dt-spacing-b);padding:calc(var(--dt-spacing-03) / 2) 0}.c-toast-messageArea span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden;max-width:var(--toast-message-max-width)}.c-toast-messageArea.c-toast--multiline{align-items:flex-start}.c-toast-messageArea.c-toast--multiline span{max-height:60px;white-space:inherit;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical}.c-toast-actionsArea{display:flex;gap:var(--dt-spacing-b)}.c-toast-footer{display:flex;justify-content:flex-end}.c-toast-icon{color:var(--toast-icon-fill)}
13
+ `, _ = ["neutral", "info", "warning", "success", "error"], i = "pie-toast", a = "c-toast", N = `${i}-close`, k = `${i}-open`, I = `${i}-leading-action-click`, g = {
11
14
  isOpen: !0,
15
+ variant: "neutral",
16
+ isStrong: !1,
12
17
  isDismissible: !0,
13
18
  isMultiline: !1
14
19
  };
15
- var B = Object.defineProperty, T = Object.getOwnPropertyDescriptor, l = (u, t, s, i) => {
16
- for (var e = i > 1 ? void 0 : i ? T(t, s) : t, a = u.length - 1, c; a >= 0; a--)
17
- (c = u[a]) && (e = (i ? c(t, s, e) : c(e)) || e);
18
- return i && e && B(t, s, e), e;
20
+ var S = Object.defineProperty, T = Object.getOwnPropertyDescriptor, p = (f, t, s, o) => {
21
+ for (var n = o > 1 ? void 0 : o ? T(t, s) : t, e = f.length - 1, d; e >= 0; e--)
22
+ (d = f[e]) && (n = (o ? d(t, s, n) : d(n)) || n);
23
+ return o && n && S(t, s, n), n;
19
24
  };
20
- class n extends $(x) {
25
+ class r extends A(y) {
21
26
  constructor() {
22
- super(...arguments), this.message = "", this.isOpen = m.isOpen, this.isDismissible = m.isDismissible, this.isMultiline = m.isMultiline, this._actionButtonOffset = 0, this._messageAreaMaxWidth = 0;
27
+ super(...arguments), this.message = "", this.isOpen = g.isOpen, this.variant = g.variant, this.isStrong = g.isStrong, this.isDismissible = g.isDismissible, this.isMultiline = g.isMultiline, this._actionButtonOffset = 0, this._messageAreaMaxWidth = 0;
23
28
  }
24
29
  /**
25
30
  * Calculates and returns the width of the message based on the toast properties.
@@ -31,9 +36,9 @@ class n extends $(x) {
31
36
  *
32
37
  * @returns {number} - The width of the message in pixels.
33
38
  */
34
- getMessageMaxWidth(t, s, i, e) {
35
- let f = 0;
36
- return t && (f += 20 + 8), !s && i && (f += this._actionButtonOffset + 8), e && (f += 32 + 8), 392 - f;
39
+ getMessageMaxWidth(t, s, o, n) {
40
+ let u = 0;
41
+ return t && (u += 20 + 8), !s && o && (u += this._actionButtonOffset + 8), n && (u += 32 + 8), 392 - u;
37
42
  }
38
43
  /**
39
44
  * Lifecycle method executed when component is updated.
@@ -41,10 +46,10 @@ class n extends $(x) {
41
46
  * It calculates _messageAreaMaxWidth
42
47
  */
43
48
  async updated(t) {
44
- var i;
45
- t.has("isOpen") && this.isOpen && g(this, C, { targetNotification: this }), await this.updateComplete, this.actionButton && (this._actionButtonOffset = this.actionButton.offsetWidth);
46
- const s = !0;
47
- this._messageAreaMaxWidth = this.getMessageMaxWidth(s, this.isMultiline, !!((i = this.leadingAction) != null && i.text), this.isDismissible), (t.has("message") || t.has("isDismissible") || t.has("isMultiline") || t.has("leadingAction")) && this.requestUpdate();
49
+ var o;
50
+ t.has("isOpen") && this.isOpen && v(this, k, { targetNotification: this }), await this.updateComplete, this.actionButton && (this._actionButtonOffset = this.actionButton.offsetWidth);
51
+ const s = this.variantHasIcon(this.variant);
52
+ this._messageAreaMaxWidth = this.getMessageMaxWidth(s, this.isMultiline, !!((o = this.leadingAction) != null && o.text), this.isDismissible), (t.has("variant") || t.has("isStrong") || t.has("message") || t.has("isDismissible") || t.has("isMultiline") || t.has("leadingAction")) && this.requestUpdate();
48
53
  }
49
54
  /**
50
55
  * It handle the action button action.
@@ -52,7 +57,7 @@ class n extends $(x) {
52
57
  * @private
53
58
  */
54
59
  handleActionClick() {
55
- g(this, w, { targetNotification: this });
60
+ v(this, I, { targetNotification: this });
56
61
  }
57
62
  /**
58
63
  * Render the action button depending on action type and its action.
@@ -63,14 +68,14 @@ class n extends $(x) {
63
68
  * @private
64
69
  */
65
70
  renderActionButton(t) {
66
- const { text: s, ariaLabel: i } = t;
67
- return p`
71
+ const { text: s, ariaLabel: o } = t;
72
+ return c`
68
73
  <pie-button
69
- variant="ghost-inverse"
74
+ variant="${this.shouldNotUseInverseBtnVariant() ? "ghost" : "ghost-inverse"}"
70
75
  size="xsmall"
71
- aria-label="${i || r}"
76
+ aria-label="${o || l}"
72
77
  @click="${() => this.handleActionClick()}"
73
- data-test-id="${o}-leading-action"
78
+ data-test-id="${i}-leading-action"
74
79
  type="button">
75
80
  ${s}
76
81
  </pie-button>
@@ -85,9 +90,9 @@ class n extends $(x) {
85
90
  */
86
91
  renderFooter() {
87
92
  const { leadingAction: t } = this;
88
- return p`
89
- <footer class="${d}-footer" data-test-id="${o}-footer" >
90
- ${t ? this.renderActionButton(t) : r}
93
+ return c`
94
+ <footer class="${a}-footer" data-test-id="${i}-footer" >
95
+ ${t ? this.renderActionButton(t) : l}
91
96
  </footer>
92
97
  `;
93
98
  }
@@ -98,11 +103,11 @@ class n extends $(x) {
98
103
  * @private
99
104
  */
100
105
  renderCloseButton() {
101
- return p`
106
+ return c`
102
107
  <pie-icon-button
103
- variant="ghost-inverse"
108
+ variant="${this.shouldNotUseInverseBtnVariant() ? "ghost-secondary" : "ghost-inverse"}"
104
109
  size="xsmall"
105
- data-test-id="${o}-close"
110
+ data-test-id="${i}-close"
106
111
  @click="${this.closeToastComponent}">
107
112
  <icon-close></icon-close>
108
113
  </pie-icon-button>`;
@@ -117,8 +122,8 @@ class n extends $(x) {
117
122
  * @private
118
123
  */
119
124
  renderMessage(t, s) {
120
- return p`
121
- <span style="max-width: ${s}px" data-test-id="${o}-message">
125
+ return c`
126
+ <span style="--toast-message-max-width: ${s}px" data-test-id="${i}-message">
122
127
  ${t}
123
128
  </span>
124
129
  `;
@@ -130,65 +135,116 @@ class n extends $(x) {
130
135
  * @private
131
136
  */
132
137
  closeToastComponent() {
133
- this.isOpen = !1, g(this, _, { targetNotification: this });
138
+ this.isOpen = !1, v(this, N, { targetNotification: this });
139
+ }
140
+ /**
141
+ * Util method that returns an icon from a variant that has default icon.
142
+ *
143
+ * @private
144
+ */
145
+ getVariantIcon() {
146
+ switch (this.variant) {
147
+ case "info":
148
+ return c`<icon-info-circle class="${a}-icon" size="s" data-test-id="${i}-heading-icon-info"></icon-info-circle>`;
149
+ case "success":
150
+ return c`<icon-check-circle class="${a}-icon" size="s" data-test-id="${i}-heading-icon-success"></icon-check-circle>`;
151
+ case "warning":
152
+ return c`<icon-alert-triangle class="${a}-icon" size="s" data-test-id="${i}-heading-icon-warning"></icon-alert-triangle>`;
153
+ case "error":
154
+ return c`<icon-alert-circle class="${a}-icon" size="s" data-test-id="${i}-heading-icon-error"></icon-alert-circle>`;
155
+ default:
156
+ return l;
157
+ }
158
+ }
159
+ /**
160
+ * Util method that returns true if the variant has an icon.
161
+ *
162
+ * @param {typeof variants[number]} variant - The variant to check if has icon.
163
+ *
164
+ * @private
165
+ */
166
+ variantHasIcon(t) {
167
+ return ["info", "success", "warning", "error"].includes(t);
168
+ }
169
+ /**
170
+ * util method that returns true if the variant is warning and is strong.
171
+ *
172
+ * @private
173
+ */
174
+ shouldNotUseInverseBtnVariant() {
175
+ return this.variant === "warning" && this.isStrong;
134
176
  }
135
177
  render() {
136
178
  const {
137
179
  isOpen: t,
138
- message: s,
139
- isDismissible: i,
180
+ variant: s,
181
+ message: o,
182
+ isDismissible: n,
140
183
  leadingAction: e,
141
- isMultiline: a,
142
- _messageAreaMaxWidth: c
184
+ isMultiline: d,
185
+ isStrong: m,
186
+ _messageAreaMaxWidth: x
143
187
  } = this;
144
188
  if (!t)
145
- return r;
146
- const v = {
147
- [`${d}-messageArea`]: !0,
148
- "is-multiline": a
189
+ return l;
190
+ const u = {
191
+ [a]: !0,
192
+ [`${a}--${s}`]: !0,
193
+ [`${a}--strong`]: m
194
+ }, $ = {
195
+ [`${a}-messageArea`]: !0,
196
+ [`${a}--multiline`]: d
149
197
  };
150
- return p`
151
- <div data-test-id="${o}" class="${d}">
152
- <div class="${d}-contentArea">
153
- <div class="${y(v)}">
154
- <icon-placeholder size="s"></icon-placeholder>
155
- ${s === "" ? r : this.renderMessage(s, c)}
198
+ return c`
199
+ <div data-test-id="${i}" class="${b(u)}">
200
+ <div class="${a}-contentArea">
201
+ <div class="${b($)}">
202
+ ${this.variantHasIcon(s) ? this.getVariantIcon() : l}
203
+ ${o === "" ? l : this.renderMessage(o, x)}
156
204
  </div>
157
- <div class="${d}-actionsArea">
158
- ${!a && (e != null && e.text) ? this.renderActionButton(e) : r}
159
- ${i ? this.renderCloseButton() : r}
205
+ <div class="${a}-actionsArea">
206
+ ${!d && (e != null && e.text) ? this.renderActionButton(e) : l}
207
+ ${n ? this.renderCloseButton() : l}
160
208
  </div>
161
209
  </div>
162
- ${a && (e != null && e.text) ? this.renderFooter() : r}
210
+ ${d && (e != null && e.text) ? this.renderFooter() : l}
163
211
  </div>`;
164
212
  }
165
213
  }
166
- n.styles = b(M);
167
- l([
214
+ r.styles = w(C);
215
+ p([
168
216
  h()
169
- ], n.prototype, "message", 2);
170
- l([
217
+ ], r.prototype, "message", 2);
218
+ p([
219
+ h({ type: Boolean })
220
+ ], r.prototype, "isOpen", 2);
221
+ p([
222
+ h(),
223
+ M(i, _, g.variant)
224
+ ], r.prototype, "variant", 2);
225
+ p([
171
226
  h({ type: Boolean })
172
- ], n.prototype, "isOpen", 2);
173
- l([
227
+ ], r.prototype, "isStrong", 2);
228
+ p([
174
229
  h({ type: Boolean })
175
- ], n.prototype, "isDismissible", 2);
176
- l([
230
+ ], r.prototype, "isDismissible", 2);
231
+ p([
177
232
  h({ type: Boolean })
178
- ], n.prototype, "isMultiline", 2);
179
- l([
233
+ ], r.prototype, "isMultiline", 2);
234
+ p([
180
235
  h({ type: Object })
181
- ], n.prototype, "leadingAction", 2);
182
- l([
236
+ ], r.prototype, "leadingAction", 2);
237
+ p([
183
238
  O("pie-button")
184
- ], n.prototype, "actionButton", 2);
185
- A(o, n);
239
+ ], r.prototype, "actionButton", 2);
240
+ B(i, r);
186
241
  export {
187
- _ as ON_TOAST_CLOSE_EVENT,
188
- w as ON_TOAST_LEADING_ACTION_CLICK_EVENT,
189
- C as ON_TOAST_OPEN_EVENT,
190
- n as PieToast,
191
- d as componentClass,
192
- o as componentSelector,
193
- m as defaultProps
242
+ N as ON_TOAST_CLOSE_EVENT,
243
+ I as ON_TOAST_LEADING_ACTION_CLICK_EVENT,
244
+ k as ON_TOAST_OPEN_EVENT,
245
+ r as PieToast,
246
+ a as componentClass,
247
+ i as componentSelector,
248
+ g as defaultProps,
249
+ _ as variants
194
250
  };
package/dist/react.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ComponentDefaultPropsGeneric } from '@justeattakeaway/pie-webc-core';
1
+ import { ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
2
2
  import type { CSSResult } from 'lit';
3
3
  import type { GenericConstructor } from '@justeattakeaway/pie-webc-core';
4
4
  import type { LitElement } from 'lit';
@@ -23,7 +23,7 @@ export declare const componentClass = "c-toast";
23
23
 
24
24
  export declare const componentSelector = "pie-toast";
25
25
 
26
- export declare type DefaultProps = ComponentDefaultPropsGeneric<ToastProps, 'isOpen' | 'isDismissible' | 'isMultiline'>;
26
+ export declare type DefaultProps = ComponentDefaultProps<ToastProps, keyof Omit<ToastProps, 'message' | 'leadingAction'>>;
27
27
 
28
28
  export declare const defaultProps: DefaultProps;
29
29
 
@@ -55,9 +55,11 @@ export declare const PieToast: React_2.ForwardRefExoticComponent<ToastProps & Re
55
55
  */
56
56
  declare class PieToast_2 extends PieToast_base implements ToastProps {
57
57
  message: ToastProps['message'];
58
- isOpen: any;
59
- isDismissible: any;
60
- isMultiline: any;
58
+ isOpen: boolean;
59
+ variant: "neutral" | "info" | "warning" | "success" | "error";
60
+ isStrong: boolean;
61
+ isDismissible: boolean;
62
+ isMultiline: boolean;
61
63
  leadingAction: ToastProps['leadingAction'];
62
64
  actionButton?: HTMLElement;
63
65
  private _actionButtonOffset;
@@ -127,6 +129,26 @@ declare class PieToast_2 extends PieToast_base implements ToastProps {
127
129
  * @private
128
130
  */
129
131
  private closeToastComponent;
132
+ /**
133
+ * Util method that returns an icon from a variant that has default icon.
134
+ *
135
+ * @private
136
+ */
137
+ private getVariantIcon;
138
+ /**
139
+ * Util method that returns true if the variant has an icon.
140
+ *
141
+ * @param {typeof variants[number]} variant - The variant to check if has icon.
142
+ *
143
+ * @private
144
+ */
145
+ private variantHasIcon;
146
+ /**
147
+ * util method that returns true if the variant is warning and is strong.
148
+ *
149
+ * @private
150
+ */
151
+ private shouldNotUseInverseBtnVariant;
130
152
  render(): TemplateResult<1> | typeof nothing;
131
153
  }
132
154
 
@@ -139,6 +161,14 @@ export declare interface ToastProps {
139
161
  * When true, the toast is set to be open and visible.
140
162
  */
141
163
  isOpen?: boolean;
164
+ /**
165
+ * Sets the variant of the toast.
166
+ */
167
+ variant?: typeof variants[number];
168
+ /**
169
+ * When true, the toast is displayed with a strong visual style.
170
+ */
171
+ isStrong?: boolean;
142
172
  /**
143
173
  * When true, allows dismissing the toast by clicking on the close button.
144
174
  */
@@ -157,4 +187,6 @@ export declare interface ToastProps {
157
187
  leadingAction?: ActionProps;
158
188
  }
159
189
 
190
+ export declare const variants: readonly ["neutral", "info", "warning", "success", "error"];
191
+
160
192
  export { }
package/dist/react.js CHANGED
@@ -1,28 +1,32 @@
1
1
  import * as t from "react";
2
2
  import { createComponent as o } from "@lit/react";
3
3
  import { PieToast as e } from "./index.js";
4
- import { ON_TOAST_CLOSE_EVENT as P, ON_TOAST_LEADING_ACTION_CLICK_EVENT as l, ON_TOAST_OPEN_EVENT as f, componentClass as A, componentSelector as S, defaultProps as I } from "./index.js";
4
+ import { ON_TOAST_CLOSE_EVENT as A, ON_TOAST_LEADING_ACTION_CLICK_EVENT as S, ON_TOAST_OPEN_EVENT as I, componentClass as L, componentSelector as V, defaultProps as d, variants as v } from "./index.js";
5
5
  import "lit";
6
6
  import "lit/decorators.js";
7
7
  import "lit/directives/class-map.js";
8
8
  import "@justeattakeaway/pie-webc-core";
9
9
  import "@justeattakeaway/pie-icon-button";
10
10
  import "@justeattakeaway/pie-icons-webc/dist/IconClose.js";
11
- import "@justeattakeaway/pie-icons-webc/dist/IconPlaceholder.js";
11
+ import "@justeattakeaway/pie-icons-webc/dist/IconInfoCircle.js";
12
+ import "@justeattakeaway/pie-icons-webc/dist/IconAlertCircle.js";
13
+ import "@justeattakeaway/pie-icons-webc/dist/IconAlertTriangle.js";
14
+ import "@justeattakeaway/pie-icons-webc/dist/IconCheckCircle.js";
12
15
  import "@justeattakeaway/pie-button";
13
- const m = o({
16
+ const r = o({
14
17
  displayName: "PieToast",
15
18
  elementClass: e,
16
19
  react: t,
17
20
  tagName: "pie-toast",
18
21
  events: {}
19
- }), E = m;
22
+ }), P = r;
20
23
  export {
21
- P as ON_TOAST_CLOSE_EVENT,
22
- l as ON_TOAST_LEADING_ACTION_CLICK_EVENT,
23
- f as ON_TOAST_OPEN_EVENT,
24
- E as PieToast,
25
- A as componentClass,
26
- S as componentSelector,
27
- I as defaultProps
24
+ A as ON_TOAST_CLOSE_EVENT,
25
+ S as ON_TOAST_LEADING_ACTION_CLICK_EVENT,
26
+ I as ON_TOAST_OPEN_EVENT,
27
+ P as PieToast,
28
+ L as componentClass,
29
+ V as componentSelector,
30
+ d as defaultProps,
31
+ v as variants
28
32
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-toast",
3
3
  "description": "PIE Design System Toast built using Web Components",
4
- "version": "0.2.0",
4
+ "version": "0.3.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -40,6 +40,9 @@
40
40
  "cem-plugin-module-file-extensions": "0.0.5"
41
41
  },
42
42
  "dependencies": {
43
+ "@justeattakeaway/pie-button": "0.48.0",
44
+ "@justeattakeaway/pie-icon-button": "0.28.9",
45
+ "@justeattakeaway/pie-icons-webc": "0.24.2",
43
46
  "@justeattakeaway/pie-webc-core": "0.24.0"
44
47
  },
45
48
  "volta": {
package/src/defs.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { type ComponentDefaultPropsGeneric } from '@justeattakeaway/pie-webc-core';
1
+ import { type ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
2
+
3
+ export const variants = ['neutral', 'info', 'warning', 'success', 'error'] as const;
2
4
 
3
- // TODO - please remove the eslint disable comment below when you add props to this interface
4
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
5
5
  export type ActionProps = {
6
6
  /**
7
7
  * The text to display inside the button.
@@ -19,6 +19,15 @@ export interface ToastProps {
19
19
  * When true, the toast is set to be open and visible.
20
20
  */
21
21
  isOpen?: boolean;
22
+ /**
23
+ * Sets the variant of the toast.
24
+ */
25
+ variant?: typeof variants[number];
26
+
27
+ /**
28
+ * When true, the toast is displayed with a strong visual style.
29
+ */
30
+ isStrong?: boolean;
22
31
  /**
23
32
  * When true, allows dismissing the toast by clicking on the close button.
24
33
  */
@@ -61,10 +70,12 @@ export const ON_TOAST_OPEN_EVENT = `${componentSelector}-open`;
61
70
  */
62
71
  export const ON_TOAST_LEADING_ACTION_CLICK_EVENT = `${componentSelector}-leading-action-click`;
63
72
 
64
- export type DefaultProps = ComponentDefaultPropsGeneric<ToastProps, 'isOpen' | 'isDismissible' | 'isMultiline'>;
73
+ export type DefaultProps = ComponentDefaultProps<ToastProps, keyof Omit<ToastProps, 'message' | 'leadingAction'>>;
65
74
 
66
75
  export const defaultProps: DefaultProps = {
67
76
  isOpen: true,
77
+ variant: 'neutral',
78
+ isStrong: false,
68
79
  isDismissible: true,
69
80
  isMultiline: false,
70
81
  };
package/src/index.ts CHANGED
@@ -8,10 +8,18 @@ import {
8
8
  } from 'lit';
9
9
  import { property, query } from 'lit/decorators.js';
10
10
  import { classMap } from 'lit/directives/class-map.js';
11
- import { RtlMixin, defineCustomElement, dispatchCustomEvent } from '@justeattakeaway/pie-webc-core';
11
+ import {
12
+ RtlMixin,
13
+ defineCustomElement,
14
+ dispatchCustomEvent,
15
+ validPropertyValues,
16
+ } from '@justeattakeaway/pie-webc-core';
12
17
  import '@justeattakeaway/pie-icon-button';
13
18
  import '@justeattakeaway/pie-icons-webc/dist/IconClose.js';
14
- import '@justeattakeaway/pie-icons-webc/dist/IconPlaceholder.js';
19
+ import '@justeattakeaway/pie-icons-webc/dist/IconInfoCircle.js';
20
+ import '@justeattakeaway/pie-icons-webc/dist/IconAlertCircle.js';
21
+ import '@justeattakeaway/pie-icons-webc/dist/IconAlertTriangle.js';
22
+ import '@justeattakeaway/pie-icons-webc/dist/IconCheckCircle.js';
15
23
  import '@justeattakeaway/pie-button';
16
24
 
17
25
  import styles from './toast.scss?inline';
@@ -24,6 +32,7 @@ import {
24
32
  ON_TOAST_OPEN_EVENT,
25
33
  ON_TOAST_LEADING_ACTION_CLICK_EVENT,
26
34
  defaultProps,
35
+ variants,
27
36
  } from './defs';
28
37
 
29
38
  // Valid values available to consumers
@@ -39,6 +48,13 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
39
48
  @property({ type: Boolean })
40
49
  public isOpen = defaultProps.isOpen;
41
50
 
51
+ @property()
52
+ @validPropertyValues(componentSelector, variants, defaultProps.variant)
53
+ public variant = defaultProps.variant;
54
+
55
+ @property({ type: Boolean })
56
+ public isStrong = defaultProps.isStrong;
57
+
42
58
  @property({ type: Boolean })
43
59
  public isDismissible = defaultProps.isDismissible;
44
60
 
@@ -111,12 +127,13 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
111
127
  this._actionButtonOffset = this.actionButton.offsetWidth;
112
128
  }
113
129
 
114
- // Temporary const. This will be removed when we implement variants.
115
- const hasIcon = true;
130
+ const hasIcon = this.variantHasIcon(this.variant);
116
131
 
117
132
  this._messageAreaMaxWidth = this.getMessageMaxWidth(hasIcon, this.isMultiline, !!this.leadingAction?.text, this.isDismissible);
118
133
 
119
134
  if (
135
+ _changedProperties.has('variant') ||
136
+ _changedProperties.has('isStrong') ||
120
137
  _changedProperties.has('message') ||
121
138
  _changedProperties.has('isDismissible') ||
122
139
  _changedProperties.has('isMultiline') ||
@@ -147,7 +164,7 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
147
164
 
148
165
  return html`
149
166
  <pie-button
150
- variant="ghost-inverse"
167
+ variant="${this.shouldNotUseInverseBtnVariant() ? 'ghost' : 'ghost-inverse'}"
151
168
  size="xsmall"
152
169
  aria-label="${ariaLabel || nothing}"
153
170
  @click="${() => this.handleActionClick()}"
@@ -183,7 +200,7 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
183
200
  private renderCloseButton (): TemplateResult {
184
201
  return html`
185
202
  <pie-icon-button
186
- variant="ghost-inverse"
203
+ variant="${this.shouldNotUseInverseBtnVariant() ? 'ghost-secondary' : 'ghost-inverse'}"
187
204
  size="xsmall"
188
205
  data-test-id="${componentSelector}-close"
189
206
  @click="${this.closeToastComponent}">
@@ -202,7 +219,7 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
202
219
  */
203
220
  private renderMessage (message: string, messageAreaMaxWidth: number): TemplateResult {
204
221
  return html`
205
- <span style="max-width: ${messageAreaMaxWidth}px" data-test-id="${componentSelector}-message">
222
+ <span style="--toast-message-max-width: ${messageAreaMaxWidth}px" data-test-id="${componentSelector}-message">
206
223
  ${message}
207
224
  </span>
208
225
  `;
@@ -219,13 +236,55 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
219
236
  dispatchCustomEvent(this, ON_TOAST_CLOSE_EVENT, { targetNotification: this });
220
237
  }
221
238
 
239
+ /**
240
+ * Util method that returns an icon from a variant that has default icon.
241
+ *
242
+ * @private
243
+ */
244
+ private getVariantIcon () {
245
+ switch (this.variant) {
246
+ case 'info':
247
+ return html`<icon-info-circle class="${componentClass}-icon" size="s" data-test-id="${componentSelector}-heading-icon-info"></icon-info-circle>`;
248
+ case 'success':
249
+ return html`<icon-check-circle class="${componentClass}-icon" size="s" data-test-id="${componentSelector}-heading-icon-success"></icon-check-circle>`;
250
+ case 'warning':
251
+ return html`<icon-alert-triangle class="${componentClass}-icon" size="s" data-test-id="${componentSelector}-heading-icon-warning"></icon-alert-triangle>`;
252
+ case 'error':
253
+ return html`<icon-alert-circle class="${componentClass}-icon" size="s" data-test-id="${componentSelector}-heading-icon-error"></icon-alert-circle>`;
254
+ default:
255
+ return nothing as never;
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Util method that returns true if the variant has an icon.
261
+ *
262
+ * @param {typeof variants[number]} variant - The variant to check if has icon.
263
+ *
264
+ * @private
265
+ */
266
+ private variantHasIcon (variant: typeof variants[number]) {
267
+ return ['info', 'success', 'warning', 'error'].includes(variant);
268
+ }
269
+
270
+ /**
271
+ * util method that returns true if the variant is warning and is strong.
272
+ *
273
+ * @private
274
+ */
275
+ private shouldNotUseInverseBtnVariant () {
276
+ return this.variant === 'warning' && this.isStrong;
277
+ }
278
+
222
279
  render () {
223
280
  const {
224
281
  isOpen,
282
+ variant,
225
283
  message,
226
284
  isDismissible,
227
285
  leadingAction,
228
286
  isMultiline,
287
+ isStrong,
229
288
  _messageAreaMaxWidth,
230
289
  } = this;
231
290
 
@@ -233,16 +292,22 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
233
292
  return nothing;
234
293
  }
235
294
 
295
+ const componentWrapperClasses = {
296
+ [componentClass]: true,
297
+ [`${componentClass}--${variant}`]: true,
298
+ [`${componentClass}--strong`]: isStrong,
299
+ };
300
+
236
301
  const messageAreaClasses = {
237
302
  [`${componentClass}-messageArea`]: true,
238
- 'is-multiline': isMultiline,
303
+ [`${componentClass}--multiline`]: isMultiline,
239
304
  };
240
305
 
241
306
  return html`
242
- <div data-test-id="${componentSelector}" class="${componentClass}">
307
+ <div data-test-id="${componentSelector}" class="${classMap(componentWrapperClasses)}">
243
308
  <div class="${componentClass}-contentArea">
244
309
  <div class="${classMap(messageAreaClasses)}">
245
- <icon-placeholder size="s"></icon-placeholder>
310
+ ${this.variantHasIcon(variant) ? this.getVariantIcon() : nothing}
246
311
  ${message === '' ? nothing : this.renderMessage(message, _messageAreaMaxWidth)}
247
312
  </div>
248
313
  <div class="${componentClass}-actionsArea">
package/src/toast.scss CHANGED
@@ -6,6 +6,8 @@
6
6
  --toast-font-color: var(--dt-color-content-inverse);
7
7
  --toast-font-size: #{p.font-size(--dt-font-body-s-size)};
8
8
  --toast-line-height: #{p.line-height(--dt-font-body-s-line-height)};
9
+ --toast-icon-fill: var(--dt-color-content-default);
10
+ --toast-message-max-width: 100%;
9
11
 
10
12
  display: flex;
11
13
  flex-direction: column;
@@ -25,6 +27,43 @@
25
27
  line-height: var(--toast-line-height);
26
28
  }
27
29
 
30
+ .c-toast--info {
31
+ --toast-icon-fill: var(--dt-color-support-info-inverse);
32
+
33
+ &.c-toast--strong {
34
+ --toast-background-color: var(--dt-color-support-info);
35
+ --toast-icon-fill: var(--dt-color-content-inverse);
36
+ }
37
+ }
38
+
39
+ .c-toast--warning {
40
+ --toast-icon-fill: var(--dt-color-support-warning-inverse);
41
+
42
+ &.c-toast--strong {
43
+ --toast-background-color: var(--dt-color-support-warning);
44
+ --toast-icon-fill: var(--dt-color-content-dark);
45
+ --toast-font-color: var(--dt-color-content-dark);
46
+ }
47
+ }
48
+
49
+ .c-toast--success {
50
+ --toast-icon-fill: var(--dt-color-support-positive-inverse);
51
+
52
+ &.c-toast--strong {
53
+ --toast-background-color: var(--dt-color-support-positive);
54
+ --toast-icon-fill: var(--dt-color-content-inverse);
55
+ }
56
+ }
57
+
58
+ .c-toast--error {
59
+ --toast-icon-fill: var(--dt-color-support-error-inverse);
60
+
61
+ &.c-toast--strong {
62
+ --toast-background-color: var(--dt-color-support-error);
63
+ --toast-icon-fill: var(--dt-color-content-inverse);
64
+ }
65
+ }
66
+
28
67
  .c-toast-contentArea {
29
68
  display: flex;
30
69
  gap: var(--dt-spacing-b);
@@ -41,11 +80,12 @@
41
80
  text-overflow: ellipsis;
42
81
  white-space: nowrap;
43
82
  overflow: hidden;
83
+ max-width: var(--toast-message-max-width);
44
84
  }
45
85
 
46
- &.is-multiline {
86
+ &.c-toast--multiline {
47
87
  align-items: flex-start;
48
-
88
+
49
89
  span {
50
90
  max-height: 60px;
51
91
  white-space: inherit;
@@ -69,3 +109,8 @@
69
109
  display: flex;
70
110
  justify-content: flex-end;
71
111
  }
112
+
113
+ .c-toast-icon {
114
+ color: var(--toast-icon-fill);
115
+ }
116
+