Skip to content

Commit 18a3115

Browse files
authored
Merge pull request #215 from rackerlabs/SURF-1038-add-progressbar
feat(Progress): Add Progress component
2 parents 7a12832 + a16e9df commit 18a3115

File tree

12 files changed

+274
-2
lines changed

12 files changed

+274
-2
lines changed

docs/_data/nav.json5

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
{ label: 'Panels', path: 'panels' },
4646
{ label: 'Pagination', path: 'pagination' },
4747
{ label: 'Popovers', path: 'popovers' },
48+
{ label: 'Progress', path: 'progress' },
4849
{ label: 'Reveals', path: 'reveals' },
4950
{ label: 'Search', path: 'search' },
5051
{ label: 'Status Pills', path: 'status-pills' },
@@ -87,6 +88,7 @@
8788
{ label: '<hx-popover-body>', path: 'hx-popover-body' },
8889
{ label: '<hx-popover-foot>', path: 'hx-popover-foot' },
8990
{ label: '<hx-popover-head>', path: 'hx-popover-head' },
91+
{ label: '<hx-progress>', path: 'hx-progress' },
9092
{ label: '<hx-reveal>', path: 'hx-reveal' },
9193
{ label: '<hx-search>', path: 'hx-search' },
9294
{ label: '<hx-search-assistance>', path: 'hx-search-assistance' },
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
title: Progress
3+
also:
4+
elements/hx-progress: <hx-progress>
5+
---
6+
{% extends 'component.njk' %}
7+
{% block content %}
8+
<section>
9+
<h2 id="basic-progress">Basic Progress</h2>
10+
<div id="vue-progressDemo" class="hxRow" v-cloak>
11+
{% raw %}
12+
<div class="hxCol hxSpan-12-xs hxSpan-3-lg hxOrder-2-lg">
13+
<p>
14+
<b>Value ({{pct}}%)</b><br>
15+
<input type="range" min="0" max="100" step="1" v-model="pct" />
16+
</p>
17+
</div>
18+
<div class="hxCol hxSpan-12-xs hxSpan-9-lg hxOrder-1-lg">
19+
<section>
20+
<div class="demo">
21+
<hx-progress :value="pct"></hx-progress>
22+
</div>
23+
<pre><code>{{snippet}}</code></pre>
24+
</section>
25+
</div>
26+
{% endraw %}
27+
</div>
28+
</section>
29+
{% endblock %}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import Util from '../../_util';
2+
3+
if (document.getElementById('vue-progressDemo')) {
4+
new Vue({
5+
el: '#vue-progressDemo',
6+
data: {
7+
pct: 42,
8+
},
9+
computed: {
10+
snippet: function () {
11+
return Util.snippet(`
12+
<hx-progress
13+
value="${this.pct}">
14+
</hx-progress>
15+
`);
16+
},
17+
},
18+
});
19+
}

docs/docs.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import './components/icons/icon-demo';
1111
import './components/lists/list-demo';
1212
import './components/panels/panel-demo';
1313
import './components/popovers/popover-demo';
14+
import './components/progress/progress-demo';
1415
import './components/reveals/reveal-demo';
1516
import './components/search/search-demo';
1617
import './components/status-pills/status-demo';
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
title: <hx-progress>
3+
also:
4+
components/progress: Progress
5+
---
6+
{% extends 'element.njk' %}
7+
{% block content %}
8+
<section>
9+
<p>
10+
The custom <code>{{page.title}}</code> element renders a progress bar
11+
indicator to communicate the completion progress of a task.
12+
</p>
13+
14+
<hx-dl class="hxBox-md metadata">
15+
<hx-def>
16+
<hx-dt>Permitted Parents</hx-dt>
17+
<hx-dd>Any element that accepts flow content</hx-dd>
18+
</hx-def>
19+
<hx-def>
20+
<hx-dt>Permitted Children</hx-dt>
21+
<hx-dd>none (content will be removed upon element upgrade)</hx-dd>
22+
</hx-def>
23+
<hx-def>
24+
<hx-dt>Events</hx-dt>
25+
<hx-dd><em>none</em></hx-dd>
26+
</hx-def>
27+
</hx-dl>
28+
</section>
29+
{% endblock %}
30+
31+
{% block attributes %}
32+
<dl>
33+
<dt>value {Integer=0}</dt>
34+
<dd>
35+
<p>Value representing completion percentage.</p>
36+
</dd>
37+
</dl>
38+
{% endblock %}
39+
40+
{% block properties %}
41+
<dl>
42+
<dt>value {Integer=0}</dt>
43+
<dd>
44+
<p>
45+
Manipulates the <code>value</code> attribute.
46+
</p>
47+
</dd>
48+
</dl>
49+
{% endblock %}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
title: Testing <hx-progress>
3+
---
4+
{% extends 'test.njk' %}
5+
{% block content %}
6+
<section>
7+
<h2>No Attributes</h2>
8+
<div data-visreg="hxProgress-no-attrs">
9+
<hx-progress></hx-progress>
10+
</div>
11+
</section>
12+
13+
<section>
14+
<h2>Written DOM with children</h2>
15+
<div data-visreg="hxProgress-written-dom-children">
16+
<hx-progress>Hello!</hx-progress>
17+
</div>
18+
</section>
19+
20+
<section>
21+
<h2>Value = "foobar" (String type)</h2>
22+
<div data-visreg="hxProgress-text-value">
23+
<hx-progress value="foobar"></hx-progress>
24+
</div>
25+
</section>
26+
27+
<section>
28+
<h2>Value = 12.5 (Float type)</h2>
29+
<div data-visreg="hxProgress-float-value">
30+
<hx-progress value="12.5"></hx-progress>
31+
</div>
32+
</section>
33+
34+
<section>
35+
<h2>Value = 0 (min value)</h2>
36+
<div data-visreg="hxProgress-min-value">
37+
<hx-progress value="0"></hx-progress>
38+
</div>
39+
</section>
40+
41+
<section>
42+
<h2>Value = 42 (middle value)</h2>
43+
<div data-visreg="hxProgress-mid-value">
44+
<hx-progress value="42"></hx-progress>
45+
</div>
46+
</section>
47+
48+
<section>
49+
<h2>Value = 100 (max value)</h2>
50+
<div data-visreg="hxProgress-max-value">
51+
<hx-progress value="100"></hx-progress>
52+
</div>
53+
</section>
54+
55+
<section>
56+
<h2>Value = 9000 (over max)</h2>
57+
<div data-visreg="hxProgress-over-max">
58+
<hx-progress value="9000"></hx-progress>
59+
</div>
60+
</section>
61+
62+
<section>
63+
<h2>Value = -25 (under min)</h2>
64+
<div data-visreg="hxProgress-under-min">
65+
<hx-progress value="-25"></hx-progress>
66+
</div>
67+
</section>
68+
{% endblock %}

src/helix-ui/elements.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ export { HXMenuElement } from './elements/HXMenuElement.js';
1010
export { HXMenuitemElement } from './elements/HXMenuitemElement.js';
1111
export { HXModalElement } from './elements/HXModalElement.js';
1212
export { HXPopoverElement } from './elements/HXPopoverElement.js';
13+
export { HXProgressElement } from './elements/HXProgressElement.js';
1314
export { HXRevealElement } from './elements/HXRevealElement.js';
14-
export { HXSearchElement } from './elements/HXSearchElement.js';
1515
export { HXSearchAssistanceElement } from './elements/HXSearchAssistanceElement.js';
16-
export { HXTabcontentElement } from './elements/HXTabcontentElement.js';
16+
export { HXSearchElement } from './elements/HXSearchElement.js';
1717
export { HXTabElement } from './elements/HXTabElement.js';
18+
export { HXTabcontentElement } from './elements/HXTabcontentElement.js';
1819
export { HXTablistElement } from './elements/HXTablistElement.js';
1920
export { HXTabpanelElement } from './elements/HXTabpanelElement.js';
2021
export { HXTabsetElement } from './elements/HXTabsetElement.js';
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { HXElement } from './HXElement';
2+
3+
const MIN = 0;
4+
const MAX = 100;
5+
6+
const tagName = 'hx-progress';
7+
const template = document.createElement('template');
8+
template.innerHTML = `
9+
<style>
10+
#fill {
11+
background-color: currentColor;
12+
box-sizing: border-box;
13+
height: 100%;
14+
width: 0%;
15+
}
16+
</style>
17+
<div id="fill"></div>
18+
`;
19+
20+
/**
21+
* @private
22+
* @param {*} val - Value to coerce into an Integer
23+
* @returns {Integer} Integer value between hard-coded MIN and MAX
24+
*/
25+
function _parseValue (val) {
26+
// coerce into an Integer
27+
let safeVal = Math.round(Number(val) || MIN);
28+
// guard upper bound
29+
safeVal = safeVal > MAX ? MAX : safeVal;
30+
// guard lower bound
31+
safeVal = safeVal < MIN ? MIN : safeVal;
32+
33+
return safeVal;
34+
}
35+
36+
/**
37+
* Defines behavior for the `<hx-progress>` custom element.
38+
* @class
39+
* @extends HXElement
40+
*/
41+
export class HXProgressElement extends HXElement {
42+
static get is () {
43+
return tagName;
44+
}
45+
46+
constructor () {
47+
super(tagName, template);
48+
}
49+
50+
connectedCallback () {
51+
this.$upgradeProperty('value');
52+
this.$defaultAttribute('role', 'progressbar');
53+
this.$defaultAttribute('aria-valuemin', MIN);
54+
this.$defaultAttribute('aria-valuemax', MAX);
55+
this.value = this.value;
56+
}
57+
58+
static get observedAttributes () {
59+
return [ 'value' ];
60+
}
61+
62+
attributeChangedCallback (attr, oldVal, newVal) {
63+
if (newVal !== oldVal) {
64+
if (attr === 'value') {
65+
let safeVal = _parseValue(newVal);
66+
this._elFill.style.width = `${safeVal}%`;
67+
this.setAttribute('aria-valuenow', safeVal);
68+
}
69+
}
70+
}
71+
72+
/**
73+
* Completion percentage
74+
* @type {Integer}
75+
*/
76+
get value () {
77+
return _parseValue(this.getAttribute('value'));
78+
}
79+
set value (newVal) {
80+
let safeVal = _parseValue(newVal);
81+
this.setAttribute('value', safeVal);
82+
}
83+
84+
/**
85+
* @private
86+
* @type {HTMLElement}
87+
*/
88+
get _elFill () {
89+
return this.shadowRoot.getElementById('fill');
90+
}
91+
}//HXBusyElement

src/helix-ui/styles/components.less

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
@import 'components/lists';
1313
@import 'components/navigation';
1414
@import 'components/pagination';
15+
@import 'components/progress';
1516
@import 'components/search';
1617
@import 'components/stepper'; // BETA
1718
@import 'components/tables';
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
hx-progress {
2+
background-color: @gray-400;
3+
border-radius: 1em;
4+
color: @cyan-500;
5+
overflow: hidden;
6+
}

0 commit comments

Comments
 (0)