Skip to content

Commit

Permalink
fix: add required support for labels (#87)
Browse files Browse the repository at this point in the history
for required text-field and selects, the label will automatically get an asterik *
  • Loading branch information
i8ramin authored and adamraider committed May 10, 2019
1 parent ff1fd85 commit 70675de
Show file tree
Hide file tree
Showing 14 changed files with 169 additions and 3 deletions.
25 changes: 25 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
root = true

[*]
indent_style = space
indent_size = 2

end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[{package,bower}.json]
indent_style = space
indent_size = 2

[{.eslintrc,.scss-lint.yml}]
indent_style = space
indent_size = 2

[*.{scss,sass}]
indent_style = space
indent_size = 2
1 change: 1 addition & 0 deletions packages/core/src/components/select/_select.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

@include exports('ray-select') {
.#{$ray-class-prefix}select {
@include required-support('select');
@include icon-support('select');

border: $ray-border-width solid $ray-color-gray-60;
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/components/select/constants.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const CSS_CLASSES = {
ACTIVE: 'ray-select--active',
REQUIRED: 'ray-select--required',
HAS_VALUE: 'ray-select--has-value',
PLACEHOLDER_MODE: 'ray-select--placeholder-mode',
EL__INPUT: 'ray-select__input'
Expand Down
10 changes: 10 additions & 0 deletions packages/core/src/components/select/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ class Select {
this._inputElement.addEventListener('change', this.onChange);
}

isRequired() {
return this._inputElement.required;
}

value() {
// Current value of the Select
return this._inputElement.value;
Expand Down Expand Up @@ -96,6 +100,12 @@ class Select {
this.constructor.cssClasses.HAS_VALUE
);
}

if (this.isRequired()) {
this._root.classList.add(this.constructor.cssClasses.REQUIRED);
} else {
this._root.classList.remove(this.constructor.cssClasses.REQUIRED);
}
}

_getCurrentValueOptionElement = () => {
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/components/text-field/_text-field.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@

@include exports('ray-text-field') {
.#{$ray-class-prefix}text-field {
@include required-support('text-field');
@include icon-support('text-field');
}

.#{$ray-class-prefix}text-area {
@include required-support('text-area');
@include icon-support('text-area');
}

Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/components/text-field/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ export const CSS_CLASSES = {
TEXT_FIELD: {
BASE: 'ray-text-field',
ACTIVE: 'ray-text-field--active',
REQUIRED: 'ray-text-field--required',
EL__INPUT: 'ray-text-field__input',
EL__LABEL: 'ray-text-field__label',
HAS_VALUE: 'ray-text-field--has-value'
},
TEXT_AREA: {
BASE: 'ray-text-area',
ACTIVE: 'ray-text-area--active',
REQUIRED: 'ray-text-area--required',
EL__INPUT: 'ray-text-area__input',
EL__LABEL: 'ray-text-area__label',
HAS_VALUE: 'ray-text-area--has-value'
Expand Down
10 changes: 10 additions & 0 deletions packages/core/src/components/text-field/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ class _InputComponent {
return this._inputElement.value;
}

isRequired() {
return this._inputElement.required;
}

set(value) {
this._inputElement.value = value;
}
Expand All @@ -79,6 +83,12 @@ class _InputComponent {
} else {
this._root.classList.remove(this.constructor.cssClasses.HAS_VALUE);
}

if (this.isRequired()) {
this._root.classList.add(this.constructor.cssClasses.REQUIRED);
} else {
this._root.classList.remove(this.constructor.cssClasses.REQUIRED);
}
}

destroy() {
Expand Down
11 changes: 11 additions & 0 deletions packages/core/src/global/mixins/_form-items.scss
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,14 @@
}
}
}

@mixin required-support($class) {
&--required {
.#{$ray-class-prefix}#{$class}__label {
&::after {
content: '*';
padding-left: 3px;
}
}
}
}
19 changes: 19 additions & 0 deletions packages/core/stories/select.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,25 @@ storiesOf('Select', module)
</div>
);
})
.add('select, required', () => {
setTimeout(init);

return (
<div className="ray-select">
<select className="ray-select__input" required>
<option value="" disabled selected data-ray-placeholder>
{"Hi, I'm a placeholder"}
</option>
<option value="Pikatchu">Pikatchu</option>
<option value="Squirtle">Squirtle</option>
<option value="Charmander">Charmander</option>
</select>
<label className="ray-select__label">
{"What's your favorite Pokémon?"}
</label>
</div>
);
})
.add('select, error', () => {
setTimeout(init);

Expand Down
34 changes: 34 additions & 0 deletions packages/core/stories/text-field.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,23 @@ storiesOf('Text Field', module)
</label>
</div>
))
.add('Text field, required', () => {
setTimeout(initTextField);
return (
<div className="ray-text-field ray-text-field--active">
<input
className="ray-text-field__input"
id="email"
type="email"
placeholder="[email protected]"
required
/>
<label className="ray-text-field__label" htmlFor="email">
Email address
</label>
</div>
);
})
.add('Text field, textarea', () => {
setTimeout(initTextArea);

Expand All @@ -58,6 +75,23 @@ storiesOf('Text Field', module)
</div>
);
})
.add('Text field, textarea - required', () => {
setTimeout(initTextArea);

return (
<div className="ray-text-area">
<textarea
className="ray-text-area__input"
id="textarea"
placeholder="Few people are aware..."
required
/>
<label className="ray-text-area__label" htmlFor="textarea">
Fun fact about Ray Eames
</label>
</div>
);
})
.add('Text field, multi-row textarea', () => {
setTimeout(initTextArea);

Expand Down
13 changes: 11 additions & 2 deletions packages/core/test/components/select.test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import Select from '../../src/components/select';
import { CSS_CLASSES, STRINGS } from '../../src/components/select/constants';
import {
selectFixture,
selectFixtureRequired,
selectFixtureWithPlaceholder,
selectFixtureNoInput
} from '../fixtures/select';

function setupTest(fixture = selectFixture()) {
document.body.innerHTML = null;
document.body.appendChild(fixture);
const selectEl = document.querySelector('.ray-select');
const selectEl = document.querySelector(STRINGS.INIT_SELECTOR);
const select = Select.create(selectEl);
return { select, selectEl };
}
Expand Down Expand Up @@ -76,7 +78,7 @@ describe('Select', () => {

Select.createAll();

const selectEl = document.querySelector('.ray-select');
const selectEl = document.querySelector(STRINGS.INIT_SELECTOR);
expect(Select.instances.get(selectEl)).toBeDefined();
});

Expand Down Expand Up @@ -114,4 +116,11 @@ describe('Select', () => {
expect(selectEl.classList).toContain('ray-select--has-value');
select.destroy();
});

test('it adds `required` class if select is required', () => {
const { select, selectEl } = setupTest(selectFixtureRequired());

expect(selectEl.classList).toContain(CSS_CLASSES.REQUIRED);
select.destroy();
});
});
10 changes: 9 additions & 1 deletion packages/core/test/components/text-field.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from '../../src/components/text-field/constants';
import {
textFieldFixture,
textFieldFixtureRequired,
textFieldFixtureNoInput,
textFieldFixtureWithValue
} from '../fixtures/text-field';
Expand Down Expand Up @@ -32,13 +33,20 @@ describe('TextField', () => {
textField.destroy();
});

test('#create can add has-value class if there is a prefilled value', () => {
test('#create can add `has-value` class if there is a prefilled value', () => {
const { textField, textFieldEl } = setupTest(textFieldFixtureWithValue());

expect(textFieldEl.classList).toContain(CSS_CLASSES.TEXT_FIELD.HAS_VALUE);
textField.destroy();
});

test('#create can add `required` class if the input is required', () => {
const { textField, textFieldEl } = setupTest(textFieldFixtureRequired());

expect(textFieldEl.classList).toContain(CSS_CLASSES.TEXT_FIELD.REQUIRED);
textField.destroy();
});

test('#constructor throws an error if text-field contains no text input', () => {
expect(() => setupTest(textFieldFixtureNoInput())).toThrow(
`TextField must have an input element with a class of `
Expand Down
17 changes: 17 additions & 0 deletions packages/core/test/fixtures/select/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,23 @@ export function selectFixture() {
`;
}

export function selectFixtureRequired() {
return html`
<div class="ray-select">
<select class="ray-select__input" required>
<option value="" disabled selected data-ray-placeholder></option>
<option value="Pikatchu">Pikatchu</option>
<option value="Squirtle">Squirtle</option>
<option value="Charmander">Charmander</option>
</select>
<label class="ray-select__label">
What's your favorite Pokémon?
</label>
</div>
`;
}

export function selectFixtureNoInput() {
return html`
<div class="ray-select">
Expand Down
17 changes: 17 additions & 0 deletions packages/core/test/fixtures/text-field/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ export function textFieldFixture() {
`;
}

export function textFieldFixtureRequired() {
return html`
<div class="${baseClass}">
<input
class="${baseClass}__input"
id="email"
type="email"
placeholder="[email protected]"
required
/>
<label class="${baseClass}__label" for="email">
Email address
</label>
</div>
`;
}

export function textFieldFixtureNoInput() {
return html`
<div class="${baseClass}">
Expand Down

0 comments on commit 70675de

Please sign in to comment.