Skip to content

Commit

Permalink
feat(Select): conditional validation styles
Browse files Browse the repository at this point in the history
- add <hx-select-control>
  - [hx-changed] when 'change' happens on first <select> descendant
  - [hx-touched] when 'blur' happens on first <select> descendant
- <hx-select> and <select> styled invalid if:
  - hx-select-control[hx-changed] and select:invalid
  - hx-select-control[hx-touched] and select:invalid
  - hx-select-control.hxInvalid (forced styling by app author)
  • Loading branch information
Ryan A. Johnson committed Mar 8, 2019
1 parent 85592b9 commit 37ac482
Show file tree
Hide file tree
Showing 12 changed files with 873 additions and 987 deletions.
5 changes: 3 additions & 2 deletions docs/_data/nav.json5
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@
label: 'Custom Elements',
path: 'elements',
children: [
{ label: '<hx-accordion>', path: 'hx-accordion' },
{ label: '<hx-accordion-panel>', path: 'hx-accordion-panel' },
{ label: '<hx-accordion>', path: 'hx-accordion' },
{ label: '<hx-alert>', path: 'hx-alert' },
{ label: '<hx-busy>', path: 'hx-busy' },
{ label: '<hx-checkbox>', path: 'hx-checkbox' },
Expand All @@ -85,8 +85,9 @@
{ label: '<hx-progress>', path: 'hx-progress' },
{ label: '<hx-radio>', path: 'hx-radio' },
{ label: '<hx-reveal>', path: 'hx-reveal' },
{ label: '<hx-search>', path: 'hx-search' },
{ label: '<hx-search-assistance>', path: 'hx-search-assistance' },
{ label: '<hx-search>', path: 'hx-search' },
{ label: '<hx-select-control>', path: 'hx-select-control' },
{ label: '<hx-select>', path: 'hx-select' },
{ label: '<hx-status>', path: 'hx-status' },
{ label: '<hx-tab>', path: 'hx-tab' },
Expand Down
71 changes: 20 additions & 51 deletions docs/components/dropdown-select/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
minver: 0.16.0
also:
components/dropdown-select/test.html: Testing - Dropdown Select
elements/hx-select-control: <hx-select-control>
elements/hx-select: <hx-select>
---
{% extends 'component.njk' %}
{% block content %}
Expand All @@ -18,36 +20,33 @@ <h2 id="basic-select">Basic Select</h2>
<form class="beta-hxForm">
<fieldset>
<legend class="beta-hxFieldName">Options</legend>
<div class="hxCheckbox">
<div>
<input id="chkRequired" type="checkbox" v-model="isRequired" />
<hx-checkbox></hx-checkbox>
<label for="chkRequired">Required</label>
</div>
<div class="hxCheckbox">
<div>
<input id="chkDisabled" type="checkbox" v-model="isDisabled" />
<hx-checkbox></hx-checkbox>
<label for="chkDisabled">Disabled</label>
</div>
</fieldset>
</form>
</header>

<div>
<div class="hxSelect">
<hx-select-control>
<select
id="selDemo"
:disabled="isDisabled"
:required="isRequired"
@change.once="onChange"
@change="onChange"
@blur="onBlur"
>
<option value="">-- Please Select --</option>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
<hx-select></hx-select>
<label for="selDemo">Choose an Option</label>
</div>
</hx-select-control>
</div>

<footer>
Expand All @@ -58,58 +57,28 @@ <h2 id="basic-select">Basic Select</h2>
<hx-busy></hx-busy>
<p>Loading...</p>
</div>

<p class="hxSubBody hxSubdued">
<hx-icon type="info-circle"></hx-icon>
<code>&lt;select&gt;</code> must be defined before
<code>&lt;hx-select&gt;</code> and <code>&lt;label&gt;</code>
for styles to be effective.
</p>
<p class="hxSubBody hxSubdued">
<hx-icon type="info-circle"></hx-icon>
Extra elements will be hidden.
</p>
</section>

<!--
TODO:
Need centralized documentation of HelixUI form control validation behavior.
-->
<section>
<h2 id="validation">Validation</h2>
<p class="comfortable">
A {{page.title}} is designed to take advantage of standardized
<a href="https://mzl.la/2SuKTmv">HTML form validation</a> capabilities.
Error styles will be applied as long as the <code>&lt;select&gt;</code>
element matches the <code>:invalid</code> CSS pseudo-class.
</p>
<p>
There are two ways to modify validity of the
<code>&lt;select&gt;</code> element.
By default, a {{page.title}} is styled as if it were valid.
Otherwise, any form control that is invalid on initial render
would display as invalid before the user has had a chance to
interact with the form.
</p>
<p>
As the user interacts with a {{page.title}}, it will automatically update
itself in order to communicate when it is appropriate for the browser
to apply invalid control styles.
</p>
<ol class="hxList">
<li>
add or remove the <code>required</code> attribute
</li>
<li>
calling its
<a href="https://mzl.la/2MQYTkd">
<code>setCustomValidity()</code>
</a> method
</li>
</ol>
<ul class="hxList">
<li>
By default, dropdown selects are styled as if they are valid.
Invalid styles are only applied when their <code>select</code>
<code>.hxSelect.hx-dirty &gt; select:invalid</code> matches.
Otherwise, any required control without a value would display as invalid as soon as they are rendered.
</li>
<li>
The first time <code>&lt;select&gt;</code> changes value,
<code>&lt;hx-select&gt;</code> will automatically add the
<code>.hx-dirty</code> CSS class to the
<code>.hxSelect</code> wrapper.
</li>
</ul>
</section>
-->
{% endblock %}
39 changes: 24 additions & 15 deletions docs/components/dropdown-select/select-demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,47 @@ if (document.getElementById('vue-selectDemo')) {
new Vue({
el: '#vue-selectDemo',
data: {
isDirty: false,
isChanged: false,
isDisabled: false,
isRequired: false,
isTouched: false,
},
methods: {
onChange: function () {
this.isDirty = true;
this.isChanged = true;
},
onBlur: function () {
this.isTouched = true;
},
},
computed: {
classes: function () {
let _classes = 'hxSelect';
if (this.isDirty) {
_classes += ' hx-dirty';
}
return _classes;
attrChanged: function () {
return (this.isChanged ? 'hx-changed' : '');
},
attrTouched: function () {
return (this.isTouched ? 'hx-touched' : '');
},
attrDisabled: function () {
return (this.isDisabled ? 'disabled' : '');
},
attrRequired: function () {
return (this.isRequired ? 'required' : '');
},
snippet: function () {
return Util.snippet(`
<div class="${this.classes}">
<hx-select-control
${this.attrChanged}
${this.attrTouched}
>
<select
${this.isDisabled ? 'disabled' : ''}
id="demoSelect"
${this.isRequired ? 'required' : ''}
${this.attrDisabled}
${this.attrRequired}
>
...
</select>
<hx-select></hx-select>
<label for="demoSelect">...</label>
</div>
</hx-select-control>
`);
},
},
Expand Down
Loading

0 comments on commit 37ac482

Please sign in to comment.