Skip to content

Commit ebb878c

Browse files
committed
Feat(web): ModalHeader hide close button prop DS-1063
- New prop for ModalHeader to hide the close button - New prop for disable escape key to close the modal - Added new demo with those new props
1 parent ebd2b3f commit ebb878c

File tree

4 files changed

+103
-8
lines changed

4 files changed

+103
-8
lines changed

packages/web/src/js/Modal.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
import BaseComponent from './BaseComponent';
22
import { warning } from './common/utilities';
3+
import { EVENT_KEY } from './constants';
34
import EventHandler from './dom/EventHandler';
45
import SelectorEngine from './dom/SelectorEngine';
56
import { enableToggleTrigger, ScrollControl, SpiritConfig } from './utils';
67

8+
// TODO: Remove `handleKeyDown` listener when Chrome fixes the bug,
9+
// right now Chrome is bugged and sends un-cancelable events, so closing modal based on
10+
// `cancel` event is not possible in Chrome.
11+
// Firefox and Safari are working fine.
12+
// @see: https://issues.chromium.org/issues/351867704
13+
714
const NAME = 'modal';
815

916
const MODAL_TOGGLE_SELECTOR = '[data-spirit-toggle="modal"]';
1017

18+
type Config = {
19+
closeOnEscapeKeyDown: boolean;
20+
};
21+
1122
class Modal extends BaseComponent {
1223
isShown: boolean;
1324
isTouchDevice: boolean;
@@ -53,13 +64,31 @@ class Modal extends BaseComponent {
5364
event.preventDefault();
5465
}
5566

67+
handleCancel(event: Event) {
68+
const { closeOnEscapeKeyDown } = this.config as Config;
69+
70+
if (closeOnEscapeKeyDown === false) {
71+
event.preventDefault();
72+
}
73+
}
74+
75+
handleKeyDown(event: KeyboardEvent) {
76+
const { closeOnEscapeKeyDown } = this.config as Config;
77+
78+
if (event.key === EVENT_KEY && closeOnEscapeKeyDown === false && this.isShown) {
79+
event.preventDefault();
80+
}
81+
}
82+
5683
addEventListeners() {
5784
EventHandler.on(this.element, 'close', (event: KeyboardEvent) => this.onDialogClose(event));
5885
if (this.isTouchDevice) {
5986
EventHandler.on(window, 'touchstart', (event: Event & { target: Window }) => this.onClick(event));
6087
} else {
6188
EventHandler.on(window, 'click', (event: Event & { target: Window }) => this.onClick(event));
6289
}
90+
EventHandler.on(this.element, 'cancel', (event: Event) => this.handleCancel(event));
91+
EventHandler.on(document, 'keydown', (event: KeyboardEvent) => this.handleKeyDown(event));
6392
}
6493

6594
removeEventListeners() {
@@ -69,6 +98,8 @@ class Modal extends BaseComponent {
6998
} else {
7099
EventHandler.off(window, 'click', (event: Event & { target: Window }) => this.onClick(event));
71100
}
101+
EventHandler.off(this.element, 'cancel', (event: Event) => this.handleCancel(event));
102+
EventHandler.off(document, 'keydown', (event: KeyboardEvent) => this.handleKeyDown(event));
72103
}
73104

74105
show() {

packages/web/src/js/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ export const CLASS_NAME_LINK_UNDERLINED = 'link-underlined';
1616
export const CLASS_NAME_LINK_DISABLED = 'link-disabled';
1717

1818
export const DEFAULT_TOAST_AUTO_CLOSE_INTERVAL = 3000; // milliseconds
19+
20+
export const EVENT_KEY = 'Escape';

packages/web/src/scss/components/Modal/README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -429,14 +429,15 @@ When you put it all together:
429429

430430
Both trigger and close buttons use `data` attributes to open and close the Modal.
431431

432-
| Name | Type | Default | Required | Description |
433-
| ------------------------------------- | -------- | ------- | -------- | ----------------------------------------------------- |
434-
| `aria-controls` | `string` ||| Aria controls state (auto) |
435-
| `aria-expanded` | `string` ||| Aria expanded state (auto) |
436-
| `data-spirit-close-on-backdrop-click` | `bool` | `true` || Whether the modal will close when backdrop is clicked |
437-
| `data-spirit-dismiss` | `string` | `modal` || Iterable selector |
438-
| `data-spirit-target` | `string` ||| Target selector |
439-
| `data-spirit-toggle` | `string` | `modal` || Iterable selector |
432+
| Name | Type | Default | Required | Description |
433+
| -------------------------------------- | -------- | ------- | -------- | ------------------------------------------------------- |
434+
| `aria-controls` | `string` ||| Aria controls state (auto) |
435+
| `aria-expanded` | `string` ||| Aria expanded state (auto) |
436+
| `data-spirit-close-on-backdrop-click` | `bool` | `true` || Whether the modal will close when backdrop is clicked |
437+
| `data-spirit-close-on-escape-key-down` | `bool` | `true` || Whether the modal will close when escape key is pressed |
438+
| `data-spirit-dismiss` | `string` | `modal` || Iterable selector |
439+
| `data-spirit-target` | `string` ||| Target selector |
440+
| `data-spirit-toggle` | `string` | `modal` || Iterable selector |
440441

441442
## JavaScript Plugin
442443

packages/web/src/scss/components/Modal/index.html

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,4 +1197,65 @@ <h2 id="example-disabled-backdrop-click-title" class="ModalHeader__title">Modal
11971197

11981198
</section>
11991199

1200+
<section class="docs-Section">
1201+
<h2 class="docs-Heading">Hidden Close Button and Disabled Escape Key</h2>
1202+
1203+
<div class="docs-Stack docs-Stack--start">
1204+
1205+
<button
1206+
type="button"
1207+
class="Button Button--primary Button--medium"
1208+
data-spirit-toggle="modal"
1209+
data-spirit-target="#example-hide-close-button"
1210+
aria-controls="example-hide-close-button"
1211+
aria-expanded="false"
1212+
>
1213+
Open Modal
1214+
</button>
1215+
1216+
<dialog id="example-hide-close-button" class="Modal Modal--center" aria-labelledby="example-hide-close-button-title" data-spirit-close-on-backdrop-click="false" data-spirit-close-on-escape-key-down="false">
1217+
1218+
<article class="ModalDialog ModalDialog--expandOnMobile">
1219+
1220+
<header class="ModalHeader">
1221+
<h2 id="example-hide-close-button-title" class="ModalHeader__title">Modal Title</h2>
1222+
</header>
1223+
1224+
<div class="ModalBody">
1225+
<p>
1226+
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia
1227+
perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis
1228+
provident unde. Eveniet, iste, molestiae?
1229+
</p>
1230+
</div>
1231+
1232+
<footer class="ModalFooter ModalFooter--right">
1233+
<div class="ModalFooter__actions">
1234+
<button
1235+
type="button"
1236+
class="Button Button--primary Button--medium"
1237+
data-spirit-dismiss="modal"
1238+
data-spirit-target="#example-hide-close-button"
1239+
>
1240+
Primary action
1241+
</button>
1242+
<button
1243+
type="button"
1244+
class="Button Button--secondary Button--medium"
1245+
data-spirit-dismiss="modal"
1246+
data-spirit-target="#example-hide-close-button"
1247+
>
1248+
Secondary action
1249+
</button>
1250+
</div>
1251+
</footer>
1252+
1253+
</article>
1254+
1255+
</dialog>
1256+
1257+
</div>
1258+
1259+
</section>
1260+
12001261
{{/web/layout/plain }}

0 commit comments

Comments
 (0)