Skip to content

Commit

Permalink
fix(ie11): make text field and text area active states work (#4)
Browse files Browse the repository at this point in the history
* fix(ie11): make text field and text area active states work

* trigger deploy
  • Loading branch information
adamraider authored Feb 28, 2019
1 parent d25aa29 commit 9b67d33
Show file tree
Hide file tree
Showing 13 changed files with 543 additions and 90 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module.exports = {
env: {
browser: true,
es6: true
es6: true,
jest: true
},
extends: [
'airbnb-base',
Expand Down
2 changes: 1 addition & 1 deletion packages/core/lib/components/select/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CSS_CLASSES, STRINGS } from './constants';
import { validateNodeType, isTargetingItself } from './util';
import { validateNodeType, isTargetingItself } from '../../global/js/util';

class Select {
static instances = new WeakMap();
Expand Down
32 changes: 32 additions & 0 deletions packages/core/lib/components/text-field/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## Modifiers

Use these modifiers with `.ray-text-field` or `.ray-text-area` class.

| Selector | Description |
| --------------------------------- | --------------------------------------------------- |
| .ray-text-field--compact | Selector for applying compact styles |
| .ray-text-field--active | Selector for applying active/focus styles |
| .ray-text-field--has-value | Selector for applying styles when field has value |
| .ray-text-field--placeholder-mode | Selector for applying placeholder styles (no value) |
| .ray-text-field--disabled | Selector for applying disabled styles |
| .ray-text-field--error | Selector for applying error styles |

## JavaScript

Text fields:

```javascript
import { TextField } from '@wework/ray';
TextField.createAll();
// or
TextField.create(document.querySelector('.ray-text-field'));
```

Textareas:

```javascript
import { TextArea } from '@wework/ray';
TextArea.createAll();
// or
TextArea.create(document.querySelector('.ray-text-area'));
```
74 changes: 36 additions & 38 deletions packages/core/lib/components/text-field/_text-field.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,39 @@
font-size: $ray-field-label-size;
display: block;
background-color: transparent;
padding: 0 $ray-field-h-spacing;
padding: 0 $ray-field-h-spacing - $ray-border-width;
outline: 0;
border: 0;
cursor: pointer;

&:focus,
&:not(:placeholder-shown) {
+ label {
@include label--active;
&::-ms-clear {
display: none;
}

&:not(:focus) {
@include placeholder {
color: transparent;
}
}

&::placeholder {
transition: color 0.125s ease-in;
@include no-select;
// separate selector from :not(:placeholder-shown) to support IE11
&:focus {
@include input--active;

@include placeholder {
transition: color 0.125s ease-in;
@include no-select;
text-overflow: ellipsis;
color: $ray-color-text-medium !important;
}
}

&:not(:focus)::placeholder {
color: transparent;
&:not(:placeholder-shown) {
@include input--active;
}

&:focus::placeholder,
[placeholder] {
text-overflow: ellipsis;
color: $ray-color-text-medium;
}
}

Expand All @@ -55,30 +63,18 @@
}

// :focus-within is only supported in modern browsers (https://caniuse.com/#search=focus-within), --active should be used as a backup
&--active,
&:focus-within {
border-color: $ray-color-blue-50;

.#{$ray-class-prefix}text-field__label,
.#{$ray-class-prefix}text-area__label {
@include label--active;
color: $ray-color-blue-50;
}
@include text-field--has-value;
@include text-field--focus;
}

.#{$ray-class-prefix}text-field__input,
.#{$ray-class-prefix}text-area__input {
&::placeholder {
color: $ray-color-text-light !important;
}
}
&--active,
&--has-value {
@include text-field--has-value;
}

&.#{$ray-class-prefix}text-field--compact,
&.#{$ray-class-prefix}text-area--compact {
.#{$ray-class-prefix}text-field__label,
.#{$ray-class-prefix}text-area__label {
padding-top: 0;
}
}
&--active {
@include text-field--focus;
}

&--disabled {
Expand Down Expand Up @@ -117,12 +113,13 @@
.#{$ray-class-prefix}text-area__input {
padding-top: 0;

&:focus,
// separate selector to support IE11
&:focus {
@include compact-label--active;
}

&:not(:placeholder-shown) {
+ label {
padding-top: 0;
pointer-events: none;
}
@include compact-label--active;
}
}
}
Expand All @@ -138,6 +135,7 @@
}

&__input {
overflow-y: scroll;
display: inline-block;
padding-top: 1rem;
resize: vertical;
Expand Down
23 changes: 23 additions & 0 deletions packages/core/lib/components/text-field/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export const CSS_CLASSES = {
TEXT_FIELD: {
BASE: 'ray-text-field',
ACTIVE: 'ray-text-field--active',
EL__INPUT: 'ray-text-field__input',
HAS_VALUE: 'ray-text-field--has-value'
},
TEXT_AREA: {
BASE: 'ray-text-area',
ACTIVE: 'ray-text-area--active',
EL__INPUT: 'ray-text-area__input',
HAS_VALUE: 'ray-text-area--has-value'
}
};

export const STRINGS = {
TEXT_FIELD: {
INIT_SELECTOR: `.${CSS_CLASSES.TEXT_FIELD.BASE}`
},
TEXT_AREA: {
INIT_SELECTOR: `.${CSS_CLASSES.TEXT_AREA.BASE}`
}
};
107 changes: 107 additions & 0 deletions packages/core/lib/components/text-field/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { CSS_CLASSES, STRINGS } from './constants';
import { validateNodeType, isTargetingItself } from '../../global/js/util';

class _InputComponent {
static create(element, options) {
return this.instances.get(element) || new this(element, options);
}

static createAll(target = document, _options = {}) {
// Finds all instances of init selector on the document or within a given element and instantiates them.
const options = {
initSelector: this.strings.INIT_SELECTOR,
..._options
};

validateNodeType(target);

if (isTargetingItself(target, options)) {
this.create(target, options);
} else {
const textFields = [...target.querySelectorAll(options.initSelector)];
textFields.forEach(textField => this.create(textField, options));
}
}

constructor(root) {
this._root = root;
this._inputElement = this._root.querySelector(
`.${this.constructor.cssClasses.EL__INPUT}`
);

if (!this._inputElement) {
throw new Error(
`TextField must have an input element with a class of .${
this.constructor.cssClasses.EL__INPUT
}`
);
}

this._bindEventListeners();

this.constructor.instances.set(this._root, this);
}

_bindEventListeners() {
this._inputElement.addEventListener('focus', this.onFocus);
this._inputElement.addEventListener('blur', this.onBlur);
}

value() {
// Current value of the TextField
return this._inputElement.value;
}

set(value) {
this._inputElement.value = value;
}

onFocus = () => {
this._root.classList.add(this.constructor.cssClasses.ACTIVE);
};

onBlur = () => {
this._root.classList.remove(this.constructor.cssClasses.ACTIVE);

if (this.value()) {
this._root.classList.add(this.constructor.cssClasses.HAS_VALUE);
} else {
this._root.classList.remove(this.constructor.cssClasses.HAS_VALUE);
}
};

destroy() {
// Implement this method to release any resources / deregister any listeners they have
// attached. An example of this might be deregistering a resize event from the window object.
this._inputElement.removeEventListener('focus', this.onFocus);
this._inputElement.removeEventListener('blur', this.onBlur);

this.constructor.instances.delete(this._root);
}
}

class TextField extends _InputComponent {
static instances = new WeakMap();

static get cssClasses() {
return CSS_CLASSES.TEXT_FIELD;
}

static get strings() {
return STRINGS.TEXT_FIELD;
}
}

class TextArea extends _InputComponent {
static instances = new WeakMap();

static get cssClasses() {
return CSS_CLASSES.TEXT_AREA;
}

static get strings() {
return STRINGS.TEXT_AREA;
}
}

export { TextField, TextArea };
File renamed without changes.
66 changes: 65 additions & 1 deletion packages/core/lib/global/mixins/_form-items.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
padding-top: 0;
pointer-events: none;

top: -$ray-field-h-spacing / 2;
top: -1 * $ray-field-h-spacing / 2;
left: $ray-field-h-spacing / 2;
padding-left: $ray-field-h-spacing / 2;
padding-right: $ray-field-h-spacing / 2;
Expand All @@ -39,6 +39,70 @@
background: $ray-color-white;
}

@mixin text-field--has-value {
.#{$ray-class-prefix}text-field__label,
.#{$ray-class-prefix}text-area__label {
@include label--active;
}

.#{$ray-class-prefix}text-field__input,
.#{$ray-class-prefix}text-area__input {
&::placeholder {
color: $ray-color-text-light !important;
}
}

&.#{$ray-class-prefix}text-field--compact,
&.#{$ray-class-prefix}text-area--compact {
.#{$ray-class-prefix}text-field__label,
.#{$ray-class-prefix}text-area__label {
padding-top: 0;
}
}
}

@mixin text-field--focus {
border-color: $ray-color-blue-50;

.#{$ray-class-prefix}text-field__label,
.#{$ray-class-prefix}text-area__label {
color: $ray-color-blue-50;
}
}

@mixin compact-label--active {
+ .#{$ray-class-prefix}text-field__label,
+ .#{$ray-class-prefix}text-area__label {
padding-top: 0;
pointer-events: none;
}
}

@mixin input--active {
+ .#{$ray-class-prefix}text-field__label,
+ .#{$ray-class-prefix}text-area__label {
@include label--active;
}
}

@mixin placeholder {
&::-webkit-input-placeholder {
@content;
}

&:-moz-placeholder {
@content;
}

&::-moz-placeholder {
@content;
}

&:-ms-input-placeholder {
@content;
}
}

@keyframes wipe-in {
from {
height: 100%;
Expand Down
3 changes: 2 additions & 1 deletion packages/core/lib/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Select from './components/select';
import { TextField, TextArea } from './components/text-field';

export { Select }; // eslint-disable-line import/prefer-default-export
export { Select, TextField, TextArea };
Loading

0 comments on commit 9b67d33

Please sign in to comment.