<div class="a-select ">
<label for="some-id" class="a-select__label a-select__label--required">
Select your choice
</label>
<div class="a-select__background">
<select id="some-id" class="a-select__field" name="select" required>
<option value=""> </option>
<option value="bern">Bern</option>
<option value="zuerich">Zürich</option>
<option value="vaud">Vaud</option>
</select>
</div>
<div class="a-select__helptext">Where do you live?</div>
</div>
<div class="a-select {{ modifiers_classes }}">
<label for="{{ id }}" class="a-select__label {{#if required}}a-select__label--required{{/if}}">
{{ label }}
</label>
<div class="a-select__background">
<select id="{{ id }}"
class="a-select__field"
name="{{ name }}"
{{ required }}>
<option value=""> </option>
{{#each options}}
<option value="{{this.value}}"{{#if selected}} selected{{/if}}>{{this.label}}</option>
{{/each}}
</select>
</div>
{{#if helptext}}
<div class="a-select__helptext">{{ helptext }}</div>
{{/if}}
</div>
.a-select {
position: relative;
width: 100%;
&__label {
position: absolute;
z-index: 2;
left: 0.75rem;
top: -1rem;
text-transform: uppercase;
font-size: 0.625rem;
font-weight: $font-weight-bold;
transition-timing-function: $transition-ease;
transition-duration: $transition-fast;
transition-property: font-size, top, font-weight;
max-width: calc(100% - 2.5rem);
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
&.is-empty {
font-size: 1em;
font-weight: $font-weight-normal;
text-transform: none;
top: 0.75rem;
}
&--required:after {
content: "*";
}
}
&__background {
background: $color-grey-1;
border-bottom: 2px solid $color-grey-2;
margin-top: 1.4rem;
padding-left: 0.75rem;
transition: border-bottom-color $transition-fast $transition-ease;
position: relative;
border-radius: 2px;
height: calc(2.5rem + 2px);
&.is-valid {
border-bottom-color: $color-primary;
}
&.is-invalid.is-touched {
border-bottom-color: $color-red;
}
&.has-focus-within, &:focus-within {
border-bottom: 2px solid $color-grey-3;
}
&:before {
content: ' ';
width: 0.6em;
height: 0.6em;
display: block;
position: absolute;
right: 0;
top: 0.875em;
border-bottom: 0.1666666667em solid; // 2/12
border-right: 0.1666666667em solid; // 2/12
transform: translateX(-100%) rotate(45deg);
}
@include hover {
&:before {
border-color: $color-primary;
@include high-contrast {
border-color: $color-primary-dark;
}
}
}
}
&__field {
width: 100%;
position: absolute;
padding-left: 0.75rem;
top: 0;
right: 0;
z-index: 3;
border: none;
height: 2.5rem;
color: $color-text;
font-size: 1rem;
border-radius: 0;
box-shadow: none;
background: transparent none;
-webkit-appearance: none;
&:focus {
outline: none;
}
}
&--invers &__background {
background-color: $color-white;
}
&__helptext {
font-size: 0.75em;
color: $color-grey-3;
margin-top: 0.4em;
}
}
import BaseView from 'base-view';
const INPUT_SELECTOR = '.a-select__field';
const BACKGROUND_SELECTOR = '.a-select__background';
const LABEL_SELECTOR = '.a-select__label';
const FOCUS_WITHIN_STATE = 'has-focus-within';
const EMPTY_STATE = 'is-empty';
const TOUCHED_STATE = 'is-touched';
const VALID_STATE = 'is-valid';
const INVALID_STATE = 'is-invalid';
export default class ASelect extends BaseView {
initialize() {
this.select = this.getScopedElement( INPUT_SELECTOR );
this.background = this.getScopedElement( BACKGROUND_SELECTOR );
this.label = this.getScopedElement( LABEL_SELECTOR );
this.manageEmptyState();
}
bind() {
super.bind();
this.on( 'focus', INPUT_SELECTOR, () => this.onSetFocus() );
this.on( 'blur', INPUT_SELECTOR, () => this.onRemoveFocus() );
this.on( 'change', INPUT_SELECTOR, () => this.onChange(), false, false );
this.on( 'click', LABEL_SELECTOR, () => {
this.select.focus();
} );
}
onChange() {
this.manageEmptyState();
this.setTouchedState();
this.manageValidState();
}
onSetFocus() {
this.setTouchedState();
this.addClass( this.background, FOCUS_WITHIN_STATE );
this.manageEmptyState();
}
onRemoveFocus() {
this.removeClass( this.background, FOCUS_WITHIN_STATE );
this.manageEmptyState();
this.manageValidState();
}
manageEmptyState() {
if (this.isEmpty()) {
this.setEmptyState();
} else {
this.removeEmptyState();
}
}
isEmpty() {
return ! this.select.value;
}
setEmptyState() {
this.addClass( this.label, EMPTY_STATE );
}
removeEmptyState() {
this.removeClass( this.label, EMPTY_STATE );
}
setTouchedState() {
this.addClass( this.background, TOUCHED_STATE );
}
manageValidState() {
if (! this.select.hasAttribute( 'required' )) {
return;
}
if (! this.isEmpty()) {
this.addClass( this.background, VALID_STATE );
this.removeClass( this.background, INVALID_STATE );
}
if (this.select.hasAttribute( 'required' ) && this.isEmpty()) {
this.removeClass( this.background, VALID_STATE );
this.addClass( this.background, INVALID_STATE );
}
}
}
{
"id": "some-id",
"required": "required",
"label": "Select your choice",
"name": "select",
"helptext": "Where do you live?",
"options": [
{
"label": "Bern",
"value": "bern"
},
{
"label": "Zürich",
"value": "zuerich"
},
{
"label": "Vaud",
"value": "vaud"
}
]
}
No notes defined.