Skip to content

Commit 7863c02

Browse files
authored
Merge pull request #110 from rackerlabs/SURF-294-build-modals
feat(modal): add modal component
2 parents 55fd87c + 86c3ef0 commit 7863c02

File tree

16 files changed

+393
-1
lines changed

16 files changed

+393
-1
lines changed

docs/_data/nav.json5

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
},
3939
{ label: 'Lists', path: 'lists' },
4040
{ label: 'Menus', path: 'menus' },
41+
{ label: 'Modals', path: 'modals' },
4142
{ label: 'Panels', path: 'panels' },
4243
{ label: 'Popovers', path: 'popovers' },
4344
{ label: 'Reveals', path: 'reveals' },
@@ -64,6 +65,10 @@
6465
{ label: '<hx-menu>', path: 'hx-menu' },
6566
{ label: '<hx-menuitem>', path: 'hx-menuitem' },
6667
{ label: '<hx-menuitem-group>', path: 'hx-menuitem-group' },
68+
{ label: '<hx-modal>', path: 'hx-modal' },
69+
{ label: '<hx-modalbody>', path: 'hx-modalbody' },
70+
{ label: '<hx-modalfoot>', path: 'hx-modalfoot' },
71+
{ label: '<hx-modalhead>', path: 'hx-modalhead' },
6772
{ label: '<hx-panel>', path: 'hx-panel' },
6873
{ label: '<hx-panelbody>', path: 'hx-panelbody' },
6974
{ label: '<hx-panelfoot>', path: 'hx-panelfoot' },

docs/components/modals/index.html

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
title: Modals
3+
also:
4+
elements/hx-disclosure: <hx-disclosure>
5+
elements/hx-modal: <hx-modal>
6+
elements/hx-modalbody: <hx-modalbody>
7+
elements/hx-modalfoot: <hx-modalfoot>
8+
elements/hx-modalhead: <hx-modalhead>
9+
---
10+
{% extends 'component.njk' %}
11+
{% block content %}
12+
<section>
13+
<h2 class="hxSectionTitle" id="demo">Demo</h2>
14+
<div class="demo">
15+
<hx-disclosure aria-controls="demo-modal" class="hxBtn">
16+
Open Modal
17+
</hx-disclosure>
18+
19+
<hx-modal id="demo-modal">
20+
<hx-modalhead>
21+
<h3 class="hxSubSectionTitle">Demo Modal Header</h3>
22+
</hx-modalhead>
23+
<hx-modalbody>
24+
<p>
25+
This is the body of a demo modal. No further actions can happen
26+
on the page until this modal is closed.
27+
</p>
28+
</hx-modalbody>
29+
<hx-modalfoot>
30+
<button class="hxBtn hxBtn--primary">Confirm</button>
31+
<button class="hxBtn">Cancel</button>
32+
</hx-modalfoot>
33+
</hx-modal>
34+
</div>
35+
{% code 'html' %}
36+
<hx-disclosure aria-controls="demo-modal" class="hxBtn">
37+
Open Modal
38+
</hx-disclosure>
39+
40+
<hx-modal id="demo-modal">
41+
<hx-modalhead>
42+
<h3 class="hxSubSectionTitle">Demo Modal Header</h3>
43+
</hx-modalhead>
44+
<hx-modalbody>
45+
<p>
46+
This is the body of a demo modal. No further actions can happen
47+
on the page until this modal is closed.
48+
</p>
49+
</hx-modalbody>
50+
<hx-modalfoot>
51+
<button class="hxBtn hxBtn--primary">Confirm</button>
52+
<button class="hxBtn">Cancel</button>
53+
</hx-modalfoot>
54+
</hx-modal>
55+
{% endcode %}
56+
</section>
57+
{% endblock %}

docs/elements/hx-disclosure/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: <hx-disclosure>
33
also:
4+
components/modals: Modals
45
components/reveals: Reveals
56
elements/hx-reveal: <hx-reveal>
67
---

docs/elements/hx-modal/index.html

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
title: <hx-modal>
3+
also:
4+
components/modals: Modals
5+
elements/hx-modalhead: <hx-modalhead>
6+
elements/hx-modalbody: <hx-modalbody>
7+
elements/hx-modalfoot: <hx-modalfoot>
8+
---
9+
{% extends 'element.njk' %}
10+
{% block content %}
11+
<section>
12+
<p>
13+
The custom <code>&lt;hx-modal&gt;</code> element defines a section of
14+
floating content that needs a forced action from the user.
15+
</p>
16+
17+
<hx-dl class="hxBox-md metadata">
18+
<hx-def>
19+
<hx-dt>Permitted Parents</hx-dt>
20+
<hx-dd>any</hx-dd>
21+
</hx-def>
22+
<hx-def>
23+
<hx-dt>Permitted Children</hx-dt>
24+
<hx-dd>
25+
in this order:
26+
<ol>
27+
<li>an optional <a href="elements/hx-modalhead">&lt;hx-modalhead&gt;</a> element</li>
28+
<li>an <a href="elements/hx-modalbody">&lt;hx-modalbody&gt;</a> element</li>
29+
<li>an optional <a href="elements/hx-modalfoot">&lt;hx-modalfoot&gt;</a> element</li>
30+
</ol>
31+
</hx-dd>
32+
</hx-def>
33+
</hx-dl>
34+
</section>
35+
{% endblock %}
36+
37+
{% block attributes %}
38+
<dl>
39+
<dt>open</dt>
40+
<dd>Opens the modal</dd>
41+
</dl>
42+
{% endblock %}
43+
44+
{% block properties %}
45+
<dl>
46+
<dt>open <small>(Boolean [false])</small></dt>
47+
<dd>Determines if modal is open.</dd>
48+
</dl>
49+
{% endblock %}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
title: <hx-modalbody>
3+
also:
4+
components/modals: Modals
5+
elements/hx-modal: <hx-modal>
6+
elements/hx-modalhead: <hx-modalhead>
7+
elements/hx-modalfoot: <hx-modalfoot>
8+
---
9+
{% extends 'element.njk' %}
10+
{% block content %}
11+
<section>
12+
<p>
13+
The custom <code>&lt;hx-modalbody&gt;</code> element wraps flow content
14+
within a modal.
15+
</p>
16+
17+
<hx-dl class="hxBox-md metadata">
18+
<hx-def>
19+
<hx-dt>Permitted Parents</hx-dt>
20+
<hx-dd>
21+
an <a href="elements/hx-modal">&lt;hx-modal&gt;</a> element
22+
</hx-dd>
23+
</hx-def>
24+
<hx-def>
25+
<hx-dt>Permitted Children</hx-dt>
26+
<hx-dd>flow content</hx-dd>
27+
</hx-def>
28+
</hx-dl>
29+
</section>
30+
{% endblock %}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
title: <hx-modalfoot>
3+
also:
4+
components/modals: Modals
5+
elements/hx-modal: <hx-modal>
6+
elements/hx-modalhead: <hx-modalhead>
7+
elements/hx-modalbody: <hx-modalbody>
8+
---
9+
{% extends 'element.njk' %}
10+
{% block content %}
11+
<section>
12+
<p>
13+
The custom <code>&lt;hx-modalfoot&gt;</code> element centers buttons at the
14+
bottom of the modal.
15+
</p>
16+
17+
<hx-dl class="hxBox-md metadata">
18+
<hx-def>
19+
<hx-dt>Permitted Parents</hx-dt>
20+
<hx-dd>
21+
an <a href="elements/hx-modal">&lt;hx-modal&gt;</a> element
22+
</hx-dd>
23+
</hx-def>
24+
<hx-def>
25+
<hx-dt>Permitted Children</hx-dt>
26+
<hx-dd>flow content</hx-dd>
27+
</hx-def>
28+
</hx-dl>
29+
</section>
30+
{% endblock %}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
title: <hx-modalhead>
3+
also:
4+
components/modals: Modals
5+
elements/hx-modal: <hx-modal>
6+
elements/hx-modalbody: <hx-modalbody>
7+
elements/hx-modalfoot: <hx-modalfoot>
8+
---
9+
{% extends 'element.njk' %}
10+
{% block content %}
11+
<section>
12+
<p>
13+
The custom <code>&lt;hx-modalhead&gt;</code> element ensures proper spacing
14+
and margins for modal headings.
15+
</p>
16+
17+
<hx-dl class="hxBox-md metadata">
18+
<hx-def>
19+
<hx-dt>Permitted Parents</hx-dt>
20+
<hx-dd>
21+
an <a href="elements/hx-modal">&lt;hx-modal&gt;</a> element
22+
</hx-dd>
23+
</hx-def>
24+
<hx-def>
25+
<hx-dt>Permitted Children</hx-dt>
26+
<hx-dd>flow content</hx-dd>
27+
</hx-def>
28+
</hx-dl>
29+
</section>
30+
{% endblock %}

src/helix-ui.less

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ fieldset label {
9393
@import 'core/hx-disclosure';
9494
@import 'core/hx-dl';
9595
@import 'core/hx-icon';
96+
@import 'core/hx-modal';
97+
@import 'core/hx-modalbody';
98+
@import 'core/hx-modalfoot';
99+
@import 'core/hx-modalhead';
96100
@import 'core/hx-panel';
97101
@import 'core/hx-popover';
98102
@import 'core/hx-reveal';

src/helix-ui/elements.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
export { HXCheckboxElement } from './elements/HXCheckboxElement.js';
22
export { HXDisclosureElement } from './elements/HXDisclosureElement.js';
3-
export { HXMenuElement } from './elements/HXMenuElement.js';
43
export { HXIconElement } from './elements/HXIconElement.js';
4+
export { HXMenuElement } from './elements/HXMenuElement.js';
5+
export { HXModalElement } from './elements/HXModalElement.js';
56
export { HXPopoverElement } from './elements/HXPopoverElement.js';
67
export { HXRevealElement } from './elements/HXRevealElement.js';
78
export { HXTabcontentElement } from './elements/HXTabcontentElement.js';
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { HXElement } from './HXElement';
2+
import { KEYS } from '../util';
3+
import shadowStyles from './_hx-modal.less';
4+
5+
const tagName = 'hx-modal';
6+
const template = document.createElement('template');
7+
8+
template.innerHTML = `
9+
<style>${shadowStyles}</style>
10+
<div id="container">
11+
<button id="close">
12+
<hx-icon type="times"></hx-icon>
13+
</button>
14+
<slot></slot>
15+
</div>
16+
`;
17+
18+
export class HXModalElement extends HXElement {
19+
static get is () {
20+
return tagName;
21+
}
22+
23+
static get observedAttributes () {
24+
return [ 'open' ];
25+
}
26+
27+
constructor () {
28+
super(tagName, template);
29+
this._close = this._close.bind(this);
30+
this._keyUp = this._keyUp.bind(this);
31+
}
32+
33+
connectedCallback () {
34+
this.$upgradeProperty('open');
35+
this._btnClose = this.shadowRoot.querySelector("#close");
36+
37+
this._btnClose.addEventListener('click', this._close);
38+
document.addEventListener('keyup', this._keyUp);
39+
}
40+
41+
disconnectedCallback () {
42+
this._btnClose.removeEventListener('click', this._close);
43+
document.removeEventListener('keyup', this._keyUp);
44+
}
45+
46+
attributeChangedCallback (attr, oldValue, newValue) {
47+
this.setAttribute('aria-hidden', newValue !== '');
48+
}
49+
50+
_close () {
51+
this.open = false;
52+
}
53+
54+
_keyUp (event) {
55+
if (event.keyCode === KEYS.Escape) {
56+
this._close();
57+
}
58+
}
59+
60+
set open (value) {
61+
if (value) {
62+
this.setAttribute('open', '');
63+
this.$emit('open');
64+
} else {
65+
this.removeAttribute('open');
66+
this.$emit('close');
67+
}
68+
}
69+
70+
get open () {
71+
return this.hasAttribute('open');
72+
}
73+
}

0 commit comments

Comments
 (0)