@justeattakeaway/pie-notification 0.6.1 → 0.8.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.
@@ -217,7 +217,7 @@
217
217
  "kind": "field",
218
218
  "name": "heading",
219
219
  "type": {
220
- "text": "string"
220
+ "text": "string | undefined"
221
221
  },
222
222
  "privacy": "public",
223
223
  "attribute": "heading"
@@ -261,6 +261,15 @@
261
261
  "privacy": "public",
262
262
  "attribute": "hasStackedActions"
263
263
  },
264
+ {
265
+ "kind": "field",
266
+ "name": "aria",
267
+ "type": {
268
+ "text": "NotificationProps['aria']"
269
+ },
270
+ "privacy": "public",
271
+ "attribute": "aria"
272
+ },
264
273
  {
265
274
  "kind": "field",
266
275
  "name": "_iconSlot",
@@ -536,7 +545,7 @@
536
545
  {
537
546
  "name": "heading",
538
547
  "type": {
539
- "text": "string"
548
+ "text": "string | undefined"
540
549
  },
541
550
  "fieldName": "heading"
542
551
  },
@@ -568,6 +577,13 @@
568
577
  {
569
578
  "name": "hasStackedActions",
570
579
  "fieldName": "hasStackedActions"
580
+ },
581
+ {
582
+ "name": "aria",
583
+ "type": {
584
+ "text": "NotificationProps['aria']"
585
+ },
586
+ "fieldName": "aria"
571
587
  }
572
588
  ],
573
589
  "superclass": {
package/dist/index.d.ts CHANGED
@@ -16,6 +16,11 @@ export declare type ActionProps = {
16
16
  ariaLabel?: string;
17
17
  };
18
18
 
19
+ export declare type AriaProps = {
20
+ close?: string;
21
+ label?: string;
22
+ };
23
+
19
24
  export declare const componentClass = "c-notification";
20
25
 
21
26
  export declare const componentSelector = "pie-notification";
@@ -28,11 +33,11 @@ export declare const headingLevels: readonly ["h2", "h3", "h4", "h5", "h6"];
28
33
 
29
34
  export declare interface NotificationProps {
30
35
  /**
31
- * Set the variant of the notification.
36
+ * Sets the variant of the notification.
32
37
  */
33
38
  variant?: typeof variants[number];
34
39
  /**
35
- * The position of the notification defining proper styles if the component appear within the content or at the top of the interface.
40
+ * Defines the proper styles, whether the component appears within the content or at the top of the interface
36
41
  */
37
42
  position?: typeof positions[number];
38
43
  /**
@@ -40,7 +45,7 @@ export declare interface NotificationProps {
40
45
  */
41
46
  isDismissible?: boolean;
42
47
  /**
43
- * When true, the footer aligns to the header and icons which makes the component compact.
48
+ * When true, aligns the footer with the header and icons, making the component compact.
44
49
  */
45
50
  isCompact?: boolean;
46
51
  /**
@@ -52,7 +57,7 @@ export declare interface NotificationProps {
52
57
  */
53
58
  headingLevel?: typeof headingLevels[number];
54
59
  /**
55
- * Option to hide the icon regardless its variant or if user provided an icon.
60
+ * When true, the icon will be hidden.
56
61
  */
57
62
  hideIcon?: boolean;
58
63
  /**
@@ -68,9 +73,14 @@ export declare interface NotificationProps {
68
73
  */
69
74
  supportingAction?: ActionProps;
70
75
  /**
71
- * When true, the notification will stack the action buttons on narrow screens.
76
+ * When true, action buttons will stack on narrow screens.
72
77
  */
73
78
  hasStackedActions?: boolean;
79
+ /**
80
+ * The ARIA labels used for various parts of the notification.
81
+ * Only pass label if there is no heading to ensure the region is announced with a title
82
+ */
83
+ aria?: AriaProps;
74
84
  }
75
85
 
76
86
  /**
@@ -114,12 +124,13 @@ export declare class PieNotification extends LitElement implements NotificationP
114
124
  position: NonNullable<NotificationProps['position']>;
115
125
  isDismissible: boolean;
116
126
  isCompact: boolean;
117
- heading: string;
127
+ heading?: string;
118
128
  headingLevel: NonNullable<NotificationProps['headingLevel']>;
119
129
  hideIcon: boolean;
120
130
  leadingAction: NotificationProps['leadingAction'];
121
131
  supportingAction: NotificationProps['supportingAction'];
122
132
  hasStackedActions: boolean;
133
+ aria: NotificationProps['aria'];
123
134
  _iconSlot: Array<HTMLElement>;
124
135
  protected _hasExternalIcon: boolean;
125
136
  protected _hasIconClass: boolean;
@@ -132,7 +143,6 @@ export declare class PieNotification extends LitElement implements NotificationP
132
143
  /**
133
144
  * Lifecycle method executed when component is updated.
134
145
  * It dispatches an event if notification is opened.
135
- * It applies a gutter if there's no heading content in order to avoid the close button overlap the content.
136
146
  */
137
147
  protected updated(_changedProperties: PropertyValues<this>): void;
138
148
  /**
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
- import { unsafeCSS as O, LitElement as x, nothing as c } from "lit";
2
- import { html as d, unsafeStatic as E } from "lit/static-html.js";
3
- import { validPropertyValues as v, defineCustomElement as k, dispatchCustomEvent as g } from "@justeattakeaway/pie-webc-core";
4
- import { property as l, queryAssignedElements as w, state as $ } from "lit/decorators.js";
1
+ import { unsafeCSS as E, LitElement as k, nothing as c } from "lit";
2
+ import { html as d, unsafeStatic as w } from "lit/static-html.js";
3
+ import { validPropertyValues as m, defineCustomElement as A, dispatchCustomEvent as v } from "@justeattakeaway/pie-webc-core";
4
+ import { property as r, queryAssignedElements as z, state as C } from "lit/decorators.js";
5
+ import { ifDefined as I } from "lit/directives/if-defined.js";
5
6
  import "@justeattakeaway/pie-button";
6
7
  import "@justeattakeaway/pie-icon-button";
7
8
  import "@justeattakeaway/pie-icons-webc/dist/IconAlertCircle.js";
@@ -9,7 +10,7 @@ import "@justeattakeaway/pie-icons-webc/dist/IconAlertTriangle.js";
9
10
  import "@justeattakeaway/pie-icons-webc/dist/IconCheckCircle.js";
10
11
  import "@justeattakeaway/pie-icons-webc/dist/IconClose.js";
11
12
  import "@justeattakeaway/pie-icons-webc/dist/IconInfoCircle.js";
12
- const A = ["neutral", "neutral-alternative", "info", "success", "warning", "error"], z = ["h2", "h3", "h4", "h5", "h6"], S = ["inline-content", "full-width"], o = "pie-notification", h = "c-notification", D = `${o}-close`, V = `${o}-open`, T = `${o}-leading-action-click`, B = `${o}-supporting-action-click`, r = {
13
+ const S = ["neutral", "neutral-alternative", "info", "success", "warning", "error"], D = ["h2", "h3", "h4", "h5", "h6"], V = ["inline-content", "full-width"], t = "pie-notification", h = "c-notification", T = `${t}-close`, B = `${t}-open`, L = `${t}-leading-action-click`, P = `${t}-supporting-action-click`, l = {
13
14
  isOpen: !0,
14
15
  variant: "neutral",
15
16
  position: "inline-content",
@@ -18,16 +19,16 @@ const A = ["neutral", "neutral-alternative", "info", "success", "warning", "erro
18
19
  headingLevel: "h2",
19
20
  hideIcon: !1,
20
21
  hasStackedActions: !1
21
- }, L = `*,*:after,*:before{box-sizing:inherit}.c-notification{--notification-border-radius: var(--dt-radius-rounded-c);--notification-background-color: var(--dt-color-container-subtle);--notification-direction: column;--notification-heading-font-size: calc(var(--dt-font-heading-s-size--narrow) * 1px);--notification-heading-line-height: calc(var(--dt-font-heading-s-line-height--narrow) * 1px);--notification-font-size: calc(var(--dt-font-body-l-size) * 1px);--notification-line-height: calc(var(--dt-font-body-l-line-height) * 1px);--notification-icon-fill: var(--dt-color-content-default);--notification-close-icon-offset: var(--dt-spacing-b);--notification-heading-icon-offset: 2px;padding:var(--dt-spacing-d);border-radius:var(--notification-border-radius);background-color:var(--notification-background-color);position:relative;display:flex;flex-direction:var(--notification-direction);gap:var(--dt-spacing-d);font-size:var(--notification-font-size);line-height:var(--notification-line-height)}.c-notification[isCompact]{--notification-direction: row}.c-notification[position=full-width]{--notification-border-radius: var(--dt-radius-rounded-none)}.c-notification[variant=neutral-alternative]{--notification-background-color: var(--dt-color-container-default)}.c-notification[variant=info]{--notification-background-color: var(--dt-color-support-info-02);--notification-icon-fill: var(--dt-color-blue)}.c-notification[variant=success]{--notification-background-color: var(--dt-color-support-positive-02)}.c-notification[variant=warning]{--notification-background-color: var(--dt-color-support-warning-02)}.c-notification[variant=error]{--notification-background-color: var(--dt-color-support-error-02);--notification-icon-fill: var(--dt-color-red)}.c-notification-heading{margin:0;margin-block-end:var(--dt-spacing-a);font-size:var(--notification-heading-font-size);line-height:var(--notification-heading-line-height)}@media (min-width: 768px){.c-notification-heading{--notification-heading-font-size: calc(var(--dt-font-heading-s-size--wide) * 1px);--notification-heading-line-height: calc(var(--dt-font-heading-s-line-height--wide) * 1px)}}.c-notification-content-section{display:flex;flex-direction:row}.c-notification-content-section .has-icon{display:block ruby;margin-inline-end:var(--dt-spacing-c)}.c-notification-content-section[isDismissible]{max-width:calc(100% - var(--notification-close-icon-offset) - 40px)}.c-notification-heading-icon{padding-block-start:var(--notification-heading-icon-offset);color:var(--notification-icon-fill)}.c-notification-icon-close{position:absolute;inset-block-start:var(--notification-close-icon-offset);inset-inline-end:var(--notification-close-icon-offset)}.c-notification-footer{display:flex;flex-direction:row;justify-content:flex-end;gap:var(--dt-spacing-d)}.c-notification-footer[isCompact]{align-self:flex-end}@media (max-width: 768px){.c-notification-footer[isStacked]{flex-direction:column-reverse}}
22
+ }, F = `*,*:after,*:before{box-sizing:inherit}.c-notification{--notification-border-radius: var(--dt-radius-rounded-c);--notification-background-color: var(--dt-color-container-subtle);--notification-direction: column;--notification-heading-font-size: calc(var(--dt-font-heading-s-size--narrow) * 1px);--notification-heading-line-height: calc(var(--dt-font-heading-s-line-height--narrow) * 1px);--notification-font-size: calc(var(--dt-font-body-l-size) * 1px);--notification-line-height: calc(var(--dt-font-body-l-line-height) * 1px);--notification-icon-fill: var(--dt-color-content-default);--notification-close-icon-offset: var(--dt-spacing-b);--notification-heading-icon-offset: 2px;padding:var(--dt-spacing-d);border-radius:var(--notification-border-radius);background-color:var(--notification-background-color);position:relative;display:flex;flex-direction:var(--notification-direction);gap:var(--dt-spacing-d);font-size:var(--notification-font-size);line-height:var(--notification-line-height)}.c-notification[isCompact]{--notification-direction: row}.c-notification[position=full-width]{--notification-border-radius: var(--dt-radius-rounded-none)}.c-notification[variant=neutral-alternative]{--notification-background-color: var(--dt-color-container-default)}.c-notification[variant=info]{--notification-background-color: var(--dt-color-support-info-02);--notification-icon-fill: var(--dt-color-blue)}.c-notification[variant=success]{--notification-background-color: var(--dt-color-support-positive-02)}.c-notification[variant=warning]{--notification-background-color: var(--dt-color-support-warning-02)}.c-notification[variant=error]{--notification-background-color: var(--dt-color-support-error-02);--notification-icon-fill: var(--dt-color-red)}.c-notification-heading{margin:0;margin-block-end:var(--dt-spacing-a);font-size:var(--notification-heading-font-size);line-height:var(--notification-heading-line-height)}@media (min-width: 768px){.c-notification-heading{--notification-heading-font-size: calc(var(--dt-font-heading-s-size--wide) * 1px);--notification-heading-line-height: calc(var(--dt-font-heading-s-line-height--wide) * 1px)}}.c-notification-content-section{display:flex;flex-direction:row}.c-notification-content-section .has-icon{display:block ruby;margin-inline-end:var(--dt-spacing-c)}.c-notification-content-section[isDismissible]{max-width:calc(100% - var(--notification-close-icon-offset) - 40px)}.c-notification-heading-icon{padding-block-start:var(--notification-heading-icon-offset);color:var(--notification-icon-fill)}.c-notification-icon-close{position:absolute;inset-block-start:var(--notification-close-icon-offset);inset-inline-end:var(--notification-close-icon-offset)}.c-notification-footer{display:flex;flex-direction:row;justify-content:flex-end;gap:var(--dt-spacing-d)}.c-notification-footer[isCompact]{align-self:flex-end}@media (max-width: 768px){.c-notification-footer[isStacked]{flex-direction:column-reverse}}
22
23
  `;
23
- var P = Object.defineProperty, F = Object.getOwnPropertyDescriptor, e = (u, i, t, a) => {
24
- for (var s = a > 1 ? void 0 : a ? F(i, t) : i, f = u.length - 1, p; f >= 0; f--)
25
- (p = u[f]) && (s = (a ? p(i, t, s) : p(s)) || s);
26
- return a && s && P(i, t, s), s;
24
+ var j = Object.defineProperty, H = Object.getOwnPropertyDescriptor, e = (u, i, o, a) => {
25
+ for (var s = a > 1 ? void 0 : a ? H(i, o) : i, f = u.length - 1, p; f >= 0; f--)
26
+ (p = u[f]) && (s = (a ? p(i, o, s) : p(s)) || s);
27
+ return a && s && j(i, o, s), s;
27
28
  };
28
- class n extends x {
29
+ class n extends k {
29
30
  constructor() {
30
- super(...arguments), this.isOpen = r.isOpen, this.variant = r.variant, this.position = r.position, this.isDismissible = r.isDismissible, this.isCompact = r.isCompact, this.headingLevel = r.headingLevel, this.hideIcon = r.hideIcon, this.hasStackedActions = r.hasStackedActions, this._hasExternalIcon = !1, this._hasIconClass = !1;
31
+ super(...arguments), this.isOpen = l.isOpen, this.variant = l.variant, this.position = l.position, this.isDismissible = l.isDismissible, this.isCompact = l.isCompact, this.headingLevel = l.headingLevel, this.hideIcon = l.hideIcon, this.hasStackedActions = l.hasStackedActions, this._hasExternalIcon = !1, this._hasIconClass = !1;
31
32
  }
32
33
  /**
33
34
  * Lifecycle method executed when component is about to update.
@@ -39,10 +40,9 @@ class n extends x {
39
40
  /**
40
41
  * Lifecycle method executed when component is updated.
41
42
  * It dispatches an event if notification is opened.
42
- * It applies a gutter if there's no heading content in order to avoid the close button overlap the content.
43
43
  */
44
44
  updated(i) {
45
- i.has("isOpen") && this.isOpen && g(this, V, { targetNotification: this });
45
+ i.has("isOpen") && this.isOpen && v(this, B, { targetNotification: this });
46
46
  }
47
47
  /**
48
48
  * Method responsible to check if an external icon has been provided.
@@ -59,10 +59,10 @@ class n extends x {
59
59
  *
60
60
  * @private
61
61
  */
62
- renderFooter(i, t) {
62
+ renderFooter(i, o) {
63
63
  return d`
64
- <footer class="${h}-footer" data-test-id="${o}-footer" ?isCompact="${this.isCompact}" ?isStacked="${this.hasStackedActions && !this.isCompact}">
65
- ${t ? this.renderActionButton(t, "supporting") : c}
64
+ <footer class="${h}-footer" data-test-id="${t}-footer" ?isCompact="${this.isCompact}" ?isStacked="${this.hasStackedActions && !this.isCompact}">
65
+ ${o ? this.renderActionButton(o, "supporting") : c}
66
66
  ${i ? this.renderActionButton(i, "leading") : c}
67
67
  </footer>
68
68
  `;
@@ -76,8 +76,13 @@ class n extends x {
76
76
  *
77
77
  * @private
78
78
  */
79
- renderNotificationHeading(i, t) {
80
- return d`<${t} class="${h}-heading" data-test-id="${o}-heading">${i}</${t}>`;
79
+ renderNotificationHeading(i, o) {
80
+ return d`<${o}
81
+ id="${t}-heading"
82
+ class="${h}-heading"
83
+ data-test-id="${t}-heading">
84
+ ${i}
85
+ </${o}>`;
81
86
  }
82
87
  /**
83
88
  * Util method that returns a boolean if variant has a default icon.
@@ -99,13 +104,13 @@ class n extends x {
99
104
  getDefaultVariantIcon(i) {
100
105
  switch (i) {
101
106
  case "info":
102
- return d`<icon-info-circle size="m" data-test-id="${o}-heading-icon-info"></icon-info-circle>`;
107
+ return d`<icon-info-circle size="m" data-test-id="${t}-heading-icon-info"></icon-info-circle>`;
103
108
  case "success":
104
- return d`<icon-check-circle size="m" data-test-id="${o}-heading-icon-success"></icon-check-circle>`;
109
+ return d`<icon-check-circle size="m" data-test-id="${t}-heading-icon-success"></icon-check-circle>`;
105
110
  case "warning":
106
- return d`<icon-alert-triangle size="m" data-test-id="${o}-heading-icon-warning"></icon-alert-triangle>`;
111
+ return d`<icon-alert-triangle size="m" data-test-id="${t}-heading-icon-warning"></icon-alert-triangle>`;
107
112
  case "error":
108
- return d`<icon-alert-circle size="m" data-test-id="${o}-heading-icon-error"></icon-alert-circle>`;
113
+ return d`<icon-alert-circle size="m" data-test-id="${t}-heading-icon-error"></icon-alert-circle>`;
109
114
  default:
110
115
  return c;
111
116
  }
@@ -131,10 +136,10 @@ class n extends x {
131
136
  *
132
137
  * @private
133
138
  */
134
- renderIcon(i, t, a) {
139
+ renderIcon(i, o, a) {
135
140
  return d`
136
- <div data-test-id="${o}-icon-area" class="${a ? "has-icon " : ""}${h}-heading-icon">
137
- ${t ? c : this.renderIconVariant(i)}
141
+ <div data-test-id="${t}-icon-area" class="${a ? "has-icon " : ""}${h}-heading-icon">
142
+ ${o ? c : this.renderIconVariant(i)}
138
143
  <slot name="icon"></slot>
139
144
  </div>
140
145
  `;
@@ -146,13 +151,15 @@ class n extends x {
146
151
  * @private
147
152
  */
148
153
  renderCloseButton() {
154
+ var i;
149
155
  return d`
150
156
  <pie-icon-button
151
157
  variant="ghost-secondary"
152
158
  size="small"
153
159
  class="${h}-icon-close"
154
- data-test-id="${o}-icon-close"
160
+ data-test-id="${t}-icon-close"
155
161
  @click="${this.handleCloseButton}"
162
+ aria-label="${I((i = this.aria) == null ? void 0 : i.close)}"
156
163
  >
157
164
  <icon-close></icon-close>
158
165
  </pie-icon-button>`;
@@ -164,7 +171,7 @@ class n extends x {
164
171
  * @private
165
172
  */
166
173
  handleCloseButton() {
167
- this.closeNotificationComponent(), g(this, D, { targetNotification: this });
174
+ this.closeNotificationComponent(), v(this, T, { targetNotification: this });
168
175
  }
169
176
  /**
170
177
  * Util method responsible to close the component.
@@ -183,7 +190,7 @@ class n extends x {
183
190
  * @private
184
191
  */
185
192
  handleActionClick(i) {
186
- g(this, i === "leading" ? T : B, { targetNotification: this });
193
+ v(this, i === "leading" ? L : P, { targetNotification: this });
187
194
  }
188
195
  /**
189
196
  * Render the action button depending on action type and its action.
@@ -194,15 +201,15 @@ class n extends x {
194
201
  * @returns {TemplateResult | typeof nothing} - The rendered action button or nothing if the action text is not defined.
195
202
  * @private
196
203
  */
197
- renderActionButton(i, t) {
204
+ renderActionButton(i, o) {
198
205
  const { text: a, ariaLabel: s } = i;
199
206
  return a ? d`
200
207
  <pie-button
201
- variant="${t === "leading" ? "primary" : "ghost"}"
208
+ variant="${o === "leading" ? "primary" : "ghost"}"
202
209
  size="small-productive"
203
210
  aria-label="${s || c}"
204
- @click="${() => this.handleActionClick(t)}"
205
- data-test-id="${o}-${t}-action"
211
+ @click="${() => this.handleActionClick(o)}"
212
+ data-test-id="${t}-${o}-action"
206
213
  ?isFullWidth="${this.hasStackedActions}"
207
214
  type="button">
208
215
  ${a}
@@ -212,99 +219,107 @@ class n extends x {
212
219
  render() {
213
220
  const {
214
221
  variant: i,
215
- position: t,
222
+ position: o,
216
223
  heading: a,
217
224
  headingLevel: s,
218
225
  isDismissible: f,
219
226
  isCompact: p,
220
- _hasExternalIcon: I,
221
- hideIcon: C,
222
- _hasIconClass: y,
223
- leadingAction: m,
224
- supportingAction: _,
225
- isOpen: N
227
+ _hasExternalIcon: y,
228
+ hideIcon: _,
229
+ _hasIconClass: O,
230
+ leadingAction: b,
231
+ supportingAction: N,
232
+ isOpen: x,
233
+ aria: g
226
234
  } = this;
227
- if (!N)
235
+ if (!x)
228
236
  return c;
229
- const b = f && !p;
237
+ const $ = f && !p;
230
238
  return d`
231
239
  <div
232
- data-test-id="${o}"
240
+ data-test-id="${t}"
233
241
  class="${h}"
234
242
  variant="${i}"
235
- position="${t}"
236
- ?isCompact="${p}">
237
- ${b ? this.renderCloseButton() : c}
243
+ position="${o}"
244
+ ?isCompact="${p}"
245
+ role="region"
246
+ aria-live="${i === "error" ? "assertive" : "polite"}"
247
+ aria-labelledby="${a ? `${t}-heading` : c}"
248
+ aria-label="${!a && I(g == null ? void 0 : g.label)}">
249
+ ${$ ? this.renderCloseButton() : c}
238
250
 
239
- <section class="${h}-content-section" ?isDismissible="${b}">
240
- ${C ? c : this.renderIcon(i, I, y)}
251
+ <section class="${h}-content-section" ?isDismissible="${$}">
252
+ ${_ ? c : this.renderIcon(i, y, O)}
241
253
  <article>
242
- ${a ? this.renderNotificationHeading(a, E(s)) : c}
254
+ ${a ? this.renderNotificationHeading(a, w(s)) : c}
243
255
  <slot></slot>
244
256
  </article>
245
257
  </section>
246
258
 
247
- ${m ? this.renderFooter(m, _) : c}
259
+ ${b ? this.renderFooter(b, N) : c}
248
260
  </div>`;
249
261
  }
250
262
  }
251
- n.styles = O(L);
263
+ n.styles = E(F);
252
264
  e([
253
- l({ type: Boolean })
265
+ r({ type: Boolean })
254
266
  ], n.prototype, "isOpen", 2);
255
267
  e([
256
- l(),
257
- v(o, A, r.variant)
268
+ r(),
269
+ m(t, S, l.variant)
258
270
  ], n.prototype, "variant", 2);
259
271
  e([
260
- l(),
261
- v(o, S, r.position)
272
+ r(),
273
+ m(t, V, l.position)
262
274
  ], n.prototype, "position", 2);
263
275
  e([
264
- l({ type: Boolean })
276
+ r({ type: Boolean })
265
277
  ], n.prototype, "isDismissible", 2);
266
278
  e([
267
- l({ type: Boolean })
279
+ r({ type: Boolean })
268
280
  ], n.prototype, "isCompact", 2);
269
281
  e([
270
- l({ type: String })
282
+ r({ type: String })
271
283
  ], n.prototype, "heading", 2);
272
284
  e([
273
- l(),
274
- v(o, z, r.headingLevel)
285
+ r(),
286
+ m(t, D, l.headingLevel)
275
287
  ], n.prototype, "headingLevel", 2);
276
288
  e([
277
- l({ type: Boolean })
289
+ r({ type: Boolean })
278
290
  ], n.prototype, "hideIcon", 2);
279
291
  e([
280
- l({ type: Object })
292
+ r({ type: Object })
281
293
  ], n.prototype, "leadingAction", 2);
282
294
  e([
283
- l({ type: Object })
295
+ r({ type: Object })
284
296
  ], n.prototype, "supportingAction", 2);
285
297
  e([
286
- l({ type: Boolean })
298
+ r({ type: Boolean })
287
299
  ], n.prototype, "hasStackedActions", 2);
288
300
  e([
289
- w({ slot: "icon" })
301
+ r({ type: Object })
302
+ ], n.prototype, "aria", 2);
303
+ e([
304
+ z({ slot: "icon" })
290
305
  ], n.prototype, "_iconSlot", 2);
291
306
  e([
292
- $()
307
+ C()
293
308
  ], n.prototype, "_hasExternalIcon", 2);
294
309
  e([
295
- $()
310
+ C()
296
311
  ], n.prototype, "_hasIconClass", 2);
297
- k(o, n);
312
+ A(t, n);
298
313
  export {
299
- D as ON_NOTIFICATION_CLOSE_EVENT,
300
- T as ON_NOTIFICATION_LEADING_ACTION_CLICK_EVENT,
301
- V as ON_NOTIFICATION_OPEN_EVENT,
302
- B as ON_NOTIFICATION_SUPPORTING_ACTION_CLICK_EVENT,
314
+ T as ON_NOTIFICATION_CLOSE_EVENT,
315
+ L as ON_NOTIFICATION_LEADING_ACTION_CLICK_EVENT,
316
+ B as ON_NOTIFICATION_OPEN_EVENT,
317
+ P as ON_NOTIFICATION_SUPPORTING_ACTION_CLICK_EVENT,
303
318
  n as PieNotification,
304
319
  h as componentClass,
305
- o as componentSelector,
306
- r as defaultProps,
307
- z as headingLevels,
308
- S as positions,
309
- A as variants
320
+ t as componentSelector,
321
+ l as defaultProps,
322
+ D as headingLevels,
323
+ V as positions,
324
+ S as variants
310
325
  };
package/dist/react.d.ts CHANGED
@@ -17,6 +17,11 @@ export declare type ActionProps = {
17
17
  ariaLabel?: string;
18
18
  };
19
19
 
20
+ export declare type AriaProps = {
21
+ close?: string;
22
+ label?: string;
23
+ };
24
+
20
25
  export declare const componentClass = "c-notification";
21
26
 
22
27
  export declare const componentSelector = "pie-notification";
@@ -29,11 +34,11 @@ export declare const headingLevels: readonly ["h2", "h3", "h4", "h5", "h6"];
29
34
 
30
35
  export declare interface NotificationProps {
31
36
  /**
32
- * Set the variant of the notification.
37
+ * Sets the variant of the notification.
33
38
  */
34
39
  variant?: typeof variants[number];
35
40
  /**
36
- * The position of the notification defining proper styles if the component appear within the content or at the top of the interface.
41
+ * Defines the proper styles, whether the component appears within the content or at the top of the interface
37
42
  */
38
43
  position?: typeof positions[number];
39
44
  /**
@@ -41,7 +46,7 @@ export declare interface NotificationProps {
41
46
  */
42
47
  isDismissible?: boolean;
43
48
  /**
44
- * When true, the footer aligns to the header and icons which makes the component compact.
49
+ * When true, aligns the footer with the header and icons, making the component compact.
45
50
  */
46
51
  isCompact?: boolean;
47
52
  /**
@@ -53,7 +58,7 @@ export declare interface NotificationProps {
53
58
  */
54
59
  headingLevel?: typeof headingLevels[number];
55
60
  /**
56
- * Option to hide the icon regardless its variant or if user provided an icon.
61
+ * When true, the icon will be hidden.
57
62
  */
58
63
  hideIcon?: boolean;
59
64
  /**
@@ -69,9 +74,14 @@ export declare interface NotificationProps {
69
74
  */
70
75
  supportingAction?: ActionProps;
71
76
  /**
72
- * When true, the notification will stack the action buttons on narrow screens.
77
+ * When true, action buttons will stack on narrow screens.
73
78
  */
74
79
  hasStackedActions?: boolean;
80
+ /**
81
+ * The ARIA labels used for various parts of the notification.
82
+ * Only pass label if there is no heading to ensure the region is announced with a title
83
+ */
84
+ aria?: AriaProps;
75
85
  }
76
86
 
77
87
  /**
@@ -117,12 +127,13 @@ declare class PieNotification_2 extends LitElement implements NotificationProps
117
127
  position: NonNullable<NotificationProps['position']>;
118
128
  isDismissible: boolean;
119
129
  isCompact: boolean;
120
- heading: string;
130
+ heading?: string;
121
131
  headingLevel: NonNullable<NotificationProps['headingLevel']>;
122
132
  hideIcon: boolean;
123
133
  leadingAction: NotificationProps['leadingAction'];
124
134
  supportingAction: NotificationProps['supportingAction'];
125
135
  hasStackedActions: boolean;
136
+ aria: NotificationProps['aria'];
126
137
  _iconSlot: Array<HTMLElement>;
127
138
  protected _hasExternalIcon: boolean;
128
139
  protected _hasIconClass: boolean;
@@ -135,7 +146,6 @@ declare class PieNotification_2 extends LitElement implements NotificationProps
135
146
  /**
136
147
  * Lifecycle method executed when component is updated.
137
148
  * It dispatches an event if notification is opened.
138
- * It applies a gutter if there's no heading content in order to avoid the close button overlap the content.
139
149
  */
140
150
  protected updated(_changedProperties: PropertyValues<this>): void;
141
151
  /**
package/dist/react.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import * as i from "react";
2
2
  import { createComponent as o } from "@lit/react";
3
3
  import { PieNotification as t } from "./index.js";
4
- import { ON_NOTIFICATION_CLOSE_EVENT as E, ON_NOTIFICATION_LEADING_ACTION_CLICK_EVENT as A, ON_NOTIFICATION_OPEN_EVENT as g, ON_NOTIFICATION_SUPPORTING_ACTION_CLICK_EVENT as L, componentClass as d, componentSelector as k, defaultProps as F, headingLevels as S, positions as V, variants as u } from "./index.js";
4
+ import { ON_NOTIFICATION_CLOSE_EVENT as A, ON_NOTIFICATION_LEADING_ACTION_CLICK_EVENT as g, ON_NOTIFICATION_OPEN_EVENT as L, ON_NOTIFICATION_SUPPORTING_ACTION_CLICK_EVENT as d, componentClass as k, componentSelector as F, defaultProps as S, headingLevels as V, positions as u, variants as v } from "./index.js";
5
5
  import "lit";
6
6
  import "lit/static-html.js";
7
7
  import "@justeattakeaway/pie-webc-core";
8
8
  import "lit/decorators.js";
9
+ import "lit/directives/if-defined.js";
9
10
  import "@justeattakeaway/pie-button";
10
11
  import "@justeattakeaway/pie-icon-button";
11
12
  import "@justeattakeaway/pie-icons-webc/dist/IconAlertCircle.js";
@@ -28,17 +29,17 @@ const n = o({
28
29
  onPieNotificationOpen: "pie-notification-open"
29
30
  // When the notification is opened.
30
31
  }
31
- }), T = n;
32
+ }), l = n;
32
33
  export {
33
- E as ON_NOTIFICATION_CLOSE_EVENT,
34
- A as ON_NOTIFICATION_LEADING_ACTION_CLICK_EVENT,
35
- g as ON_NOTIFICATION_OPEN_EVENT,
36
- L as ON_NOTIFICATION_SUPPORTING_ACTION_CLICK_EVENT,
37
- T as PieNotification,
38
- d as componentClass,
39
- k as componentSelector,
40
- F as defaultProps,
41
- S as headingLevels,
42
- V as positions,
43
- u as variants
34
+ A as ON_NOTIFICATION_CLOSE_EVENT,
35
+ g as ON_NOTIFICATION_LEADING_ACTION_CLICK_EVENT,
36
+ L as ON_NOTIFICATION_OPEN_EVENT,
37
+ d as ON_NOTIFICATION_SUPPORTING_ACTION_CLICK_EVENT,
38
+ l as PieNotification,
39
+ k as componentClass,
40
+ F as componentSelector,
41
+ S as defaultProps,
42
+ V as headingLevels,
43
+ u as positions,
44
+ v as variants
44
45
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-notification",
3
3
  "description": "PIE Design System Notification built using Web Components",
4
- "version": "0.6.1",
4
+ "version": "0.8.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
package/src/defs.ts CHANGED
@@ -4,6 +4,11 @@ export const variants = ['neutral', 'neutral-alternative', 'info', 'success', 'w
4
4
  export const headingLevels = ['h2', 'h3', 'h4', 'h5', 'h6'] as const;
5
5
  export const positions = ['inline-content', 'full-width'] as const;
6
6
 
7
+ export type AriaProps = {
8
+ close?: string;
9
+ label?: string;
10
+ };
11
+
7
12
  export type ActionProps = {
8
13
  /**
9
14
  * The text to display inside the button.
@@ -18,12 +23,12 @@ export type ActionProps = {
18
23
 
19
24
  export interface NotificationProps {
20
25
  /**
21
- * Set the variant of the notification.
26
+ * Sets the variant of the notification.
22
27
  */
23
28
  variant?: typeof variants[number];
24
29
 
25
30
  /**
26
- * The position of the notification defining proper styles if the component appear within the content or at the top of the interface.
31
+ * Defines the proper styles, whether the component appears within the content or at the top of the interface
27
32
  */
28
33
  position?: typeof positions[number];
29
34
 
@@ -33,7 +38,7 @@ export interface NotificationProps {
33
38
  isDismissible?: boolean;
34
39
 
35
40
  /**
36
- * When true, the footer aligns to the header and icons which makes the component compact.
41
+ * When true, aligns the footer with the header and icons, making the component compact.
37
42
  */
38
43
  isCompact?: boolean;
39
44
 
@@ -48,7 +53,7 @@ export interface NotificationProps {
48
53
  headingLevel?: typeof headingLevels[number];
49
54
 
50
55
  /**
51
- * Option to hide the icon regardless its variant or if user provided an icon.
56
+ * When true, the icon will be hidden.
52
57
  */
53
58
  hideIcon?: boolean;
54
59
 
@@ -68,9 +73,15 @@ export interface NotificationProps {
68
73
  supportingAction?: ActionProps;
69
74
 
70
75
  /**
71
- * When true, the notification will stack the action buttons on narrow screens.
76
+ * When true, action buttons will stack on narrow screens.
72
77
  */
73
78
  hasStackedActions?: boolean;
79
+
80
+ /**
81
+ * The ARIA labels used for various parts of the notification.
82
+ * Only pass label if there is no heading to ensure the region is announced with a title
83
+ */
84
+ aria?: AriaProps;
74
85
  }
75
86
 
76
87
  export const componentSelector = 'pie-notification';
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  import { type StaticValue, html, unsafeStatic } from 'lit/static-html.js';
9
9
  import { defineCustomElement, validPropertyValues, dispatchCustomEvent } from '@justeattakeaway/pie-webc-core';
10
10
  import { property, queryAssignedElements, state } from 'lit/decorators.js';
11
+ import { ifDefined } from 'lit/directives/if-defined.js';
11
12
  import {
12
13
  type NotificationProps,
13
14
  type ActionProps,
@@ -61,7 +62,7 @@ export class PieNotification extends LitElement implements NotificationProps {
61
62
  public isCompact = defaultProps.isCompact;
62
63
 
63
64
  @property({ type: String })
64
- public heading!: string;
65
+ public heading?: string;
65
66
 
66
67
  @property()
67
68
  @validPropertyValues(componentSelector, headingLevels, defaultProps.headingLevel)
@@ -79,6 +80,9 @@ export class PieNotification extends LitElement implements NotificationProps {
79
80
  @property({ type: Boolean })
80
81
  public hasStackedActions = defaultProps.hasStackedActions;
81
82
 
83
+ @property({ type: Object })
84
+ public aria: NotificationProps['aria'];
85
+
82
86
  @queryAssignedElements({ slot: 'icon' }) _iconSlot!: Array<HTMLElement>;
83
87
 
84
88
  @state()
@@ -103,7 +107,6 @@ export class PieNotification extends LitElement implements NotificationProps {
103
107
  /**
104
108
  * Lifecycle method executed when component is updated.
105
109
  * It dispatches an event if notification is opened.
106
- * It applies a gutter if there's no heading content in order to avoid the close button overlap the content.
107
110
  */
108
111
  protected updated (_changedProperties: PropertyValues<this>): void {
109
112
  if (_changedProperties.has('isOpen') && this.isOpen) {
@@ -147,7 +150,12 @@ export class PieNotification extends LitElement implements NotificationProps {
147
150
  * @private
148
151
  */
149
152
  private renderNotificationHeading (heading: NotificationProps['heading'], headingTag: StaticValue): TemplateResult {
150
- return html`<${headingTag} class="${componentClass}-heading" data-test-id="${componentSelector}-heading">${heading}</${headingTag}>`;
153
+ return html`<${headingTag}
154
+ id="${componentSelector}-heading"
155
+ class="${componentClass}-heading"
156
+ data-test-id="${componentSelector}-heading">
157
+ ${heading}
158
+ </${headingTag}>`;
151
159
  }
152
160
 
153
161
  /**
@@ -234,6 +242,7 @@ export class PieNotification extends LitElement implements NotificationProps {
234
242
  class="${componentClass}-icon-close"
235
243
  data-test-id="${componentSelector}-icon-close"
236
244
  @click="${this.handleCloseButton}"
245
+ aria-label="${ifDefined(this.aria?.close)}"
237
246
  >
238
247
  <icon-close></icon-close>
239
248
  </pie-icon-button>`;
@@ -319,6 +328,7 @@ export class PieNotification extends LitElement implements NotificationProps {
319
328
  leadingAction,
320
329
  supportingAction,
321
330
  isOpen,
331
+ aria,
322
332
  } = this;
323
333
 
324
334
  if (!isOpen) {
@@ -333,7 +343,11 @@ export class PieNotification extends LitElement implements NotificationProps {
333
343
  class="${componentClass}"
334
344
  variant="${variant}"
335
345
  position="${position}"
336
- ?isCompact="${isCompact}">
346
+ ?isCompact="${isCompact}"
347
+ role="region"
348
+ aria-live="${variant === 'error' ? 'assertive' : 'polite'}"
349
+ aria-labelledby="${heading ? `${componentSelector}-heading` : nothing}"
350
+ aria-label="${!heading && ifDefined(aria?.label)}">
337
351
  ${showCloseButton ? this.renderCloseButton() : nothing}
338
352
 
339
353
  <section class="${componentClass}-content-section" ?isDismissible="${showCloseButton}">