Skip to content

Commit

Permalink
Adds input errors, label errors, and field error messages. Shows some…
Browse files Browse the repository at this point in the history
… contrived examples of how to use with customized novalidate html5 contraints api approach.
  • Loading branch information
roblevintennis committed Oct 3, 2020
1 parent 0d2d7c5 commit 7be8ce5
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 5 deletions.
56 changes: 52 additions & 4 deletions agnosticui-css/input.css
Expand Up @@ -11,17 +11,21 @@
}

.label, .label-base {
box-sizing: border-box;
padding: 0;
font-size: 100%;
font-family: inherit;
border: 0;
box-sizing: border-box;
font-family: inherit;
}

/* Electing to scope these as opposed to doing :root level definitions */
.field-error,
.field-error-large,
.field-error-small,
.label-skin,
.label,
.input-skin,
.input {
--agnosticui-input-error-color: var(--agnosticui-error-color, #ff4351);
--agnosticui-input-font-color: var(--agnosticui-font-color, #333333);
--agnosticui-input-font-weight: var(--agnosticui-font-weight, 300);
--agnosticui-input-font-size: var(--agnosticui-font-size, 16px);
Expand Down Expand Up @@ -80,7 +84,8 @@
vertical-align: initial;
}

/* Reset labels to be 2px less then input font size */
/* Reset labels and field errors to be 2px less then input font size */
.field-error,
.label,
.label-skin {
font-size: var(--agnosticui-input-label-font-size);
Expand Down Expand Up @@ -148,12 +153,47 @@
border-radius: var(--agnosticui-input-radius);
}

/**
* Errors
* We provide a class-based approach to setting errors which means we do
* not support :invalid, so it requires custom use of html4 validation API
* (see https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation
* of the example in corresponding input.html file). The reason I elected to
* not include :invalid, is it seems to result in "shouting" at the user as
* I did not find an easy way to only kick in errors after a certain number
* of characters have been type (blur is actually better but I did not
* implement that in the contrived example).
*/
.label-error {
color: var(--agnosticui-input-error-color);
}
.input-error {
border-color: var(--agnosticui-input-error-color);
}

.label-error,
.field-error,
.field-error-small,
.field-error-large {
color: var(--agnosticui-input-error-color);
}

.field-error,
.field-error-small,
.field-error-large {
display: inline-block;
width: 100%;
margin: var(--agnosticui-input-vertical-pad) 0;
}

/**
* Sizes
*/
.input-large {
font-size: calc(var(--agnosticui-input-font-size) + 4px);
}

.field-error-large,
.label-large {
font-size: calc(var(--agnosticui-input-label-font-size) + 2px);
}
Expand All @@ -167,6 +207,8 @@
.input-small {
font-size: calc(var(--agnosticui-input-font-size) - 4px);
}

.field-error-small,
.label-small {
/* Since labels are already smaller, bringing them down 4px here
just looks too small to my eye. */
Expand All @@ -182,6 +224,12 @@
box-shadow: 0 0 0 3px rgba(55, 149, 225, 0.5);
/* High contrast mode outline */
outline: 3px solid transparent;
transition: box-shadow .25s ease-out;
}
/* Set the focus to transparent when there's an error since we use
borders that visually conflict. */
.input-error:focus {
box-shadow: 0 0 0 3px transparent;
}

/*
Expand Down
99 changes: 98 additions & 1 deletion agnosticui-css/input.html
Expand Up @@ -7,19 +7,28 @@
<title>Inputs</title>

<link rel="stylesheet" href="./input.css">
<link rel="stylesheet" href="./button.css">
<style>
/* these styles are purely demonstration related styles only */
body {
width: 450px;
margin: 40px auto;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Ubuntu", "Fira Sans", Helvetica, "Droid Sans", "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-weight: 200;
line-height: 1.4;
}

h1,
h2,
h3 {
font-weight: 300;
margin-bottom: 40px;
}

p {
font-size: 18px;
}

div,
section {
display: flex;
Expand Down Expand Up @@ -68,7 +77,7 @@ <h3>Text Input</h3>
type="text">
</div>
<div>
<label class="label label-large" for="input-text-large">Input large label</label>
<label class="label label-" for="input-text-large">Input large label</label>
<input placeholder="Placeholder text" class="input input-large" id="input-text-large" name="input-text-large"
type="text">
</div>
Expand Down Expand Up @@ -99,9 +108,97 @@ <h3>Text Input</h3>
id="input-text-underlined-inline" name="input-text-underlined-inline"" type=" text">
</div>
</form>
<h3>Errors</h3>
<p>Block level errors can be achieved declaritively by adding appropriate <i>TYPE-error</i> classes.</p>
<div>
<label class="label label-error" for="input-text-error-block">Block label error</label>
<input placeholder="Placeholder text" class="input input-error" id="input-text-error-block"
name="input-text-error-block" type="text">
<span class="field-error" aria-live="polite">There's an error on this field.</span>
</div>

<p>Inline errors will require you to do some positional styling of your own. The following example shows
one approach to how you might use Flexbox to achieve the desired placeholder of error messages
(please forgive inline styles; this is only meant to show how it could be done)</p>
<div class="row" style="justify-content: flex-start; align-items: flex-start;">
<label style="flex: 1; line-height: 38px;" class="label label-inline label-error"
for="input-text-inlined-error">Inline label
error</label>
<div style="flex: 1; margin-bottom: 0;">
<input placeholder="Placeholder text" class="input input-error input-inline" id="input-text-inlined-error"
name="input-text-inlined" type="text">
<span class="field-error" aria-live="polite">There's an error on this field.</span>
</div>
</div>

<h3>Contraint Validation Example</h3>
<p>Using HTML5's <a href="https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation">constraint
validation with novalidate</a> on the form (custom), you should be able to achieve inlined field level errors.
View source to see the JavaScript snippet that accompanies with the disclaimer that the example is purposely
contrived and simple and not production worthy. Also note, you can use another validation means as AgnosticUI
applies styles in a class-based approach.</p>
<form class="validation-form-example" novalidate>
<label for="mail" class="label validation-form-example-label">Please enter an email address:</label>
<input type="email" class="input" id="mail" name="mail" minlength="8">
<span class="field-error" aria-live="polite"></span>
<button style="margin-top: 6px;" class="btn">Submit</button>
</form>
</section>
</div>

<script>
// Adapted from: https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation
// Note this is just to kick in the html5 validation API for example purposes only!
const form = document.querySelector('.validation-form-example');
const email = document.getElementById('mail')
const label = document.querySelector('.validation-form-example-label')
const emailError = document.querySelector('#mail + span.field-error');

const removeErrors = email => {
emailError.innerHTML = '';
emailError.className = 'field-error';
email.className = "input";
label.className = 'label validation-form-example-label';
}
email.addEventListener('input', function (event) {
// Check validity of input on each character typed in by user
if (email.validity.valid) {
// Reset content of error message and reset corresponding classes
removeErrors(email);
} else {
showError();
}
});

form.addEventListener('submit', function (event) {
if (!email.validity.valid) {
showError();
event.preventDefault();
}
});
function showError() {
// Perhaps naive ux improvement—only shows field error if
// there's at least a few characters to actually validate ¯\_(ツ)_/¯
// It's likely better UX to implement the notion of fields being "touched"
// and only show inline field errors once they've blurred off a field once.
if (email.value && email.value.length < 3) {
removeErrors(email);
return
}

if (email.validity.valueMissing) {
emailError.textContent = 'You need to enter an e-mail address.';
} else if (email.validity.typeMismatch) {
emailError.textContent = 'Entered value needs to be an e-mail address.';
} else if (email.validity.tooShort) {
emailError.textContent = `Email should be at least ${email.minLength} characters; you entered ${email.value.length}.`;
}
emailError.className = 'field-error active';
label.className = 'label label-error validation-form-example-label';
email.className = 'input input-error';
}

</script>
</body>

</html>

0 comments on commit 7be8ce5

Please sign in to comment.