refactor: 💡 Update html checkbox to use ember component

Refactor to use ember provided input element with checkbox type. Removed
unnecessary sass mixin for checkbox.
This commit is contained in:
Susmitha Girumala committed 2020-05-04 21:38:21 -04:00
1 parent a2d6c1e900
commit 31e70eebfb
7 files changed
+125 -190

No files matched your search

@@ -2,16 +2,18 @@ import Component from '@ember/component';
import layout from '../../templates/components/rose/checkbox';
/**
A simple HTML `<input type="checkbox">` element wrapped in `<label>`.
A simple ember input `<Input @type="checkbox">` element with associated `label`.
@example
<Rose::Checkbox />
<Rose::Checkbox>Label</Rose::Checkbox>
<Rose::Checkbox @id="fancy">Label</Rose::Checkbox>
<Rose::Checkbox @name={{define-me}}>Name</Rose::Checkbox>
<Rose::Checkbox @form={{@form}}>Form</Rose::Checkbox>
<Rose::Checkbox @value={{@value}}>Value</Rose::Checkbox>
<Rose::Checkbox @error={{true}}>Error</Rose::Checkbox>
<Rose::Checkbox @checked={{true}}>Checked</Rose::Checkbox>
<Rose::Checkbox @disabled={{true}}>Disabled</Rose::Checkbox>
<Rose::Checkbox @disabled={{true}} @checked={{true}}>Disabled + Checked</Rose::Checkbox>
<Rose::Checkbox @style="default" />
**/
export default Component.extend({
@@ -1,26 +1,78 @@
@use '../utilities/checkbox';
@use '../utilities/type' as typography;
@include checkbox.checkbox-style(
'default',
(
color: var(--stark),
border-color: var(--ui-border),
background-color: var(--subtle),
),
(
border-color: var(--ui-gray),
),
(
border-color: var(--info),
),
(
border-color: var(--failure),
),
(
border-color: var(--info),
),
(
border-color: var(--ui-border),
background-color: var(--ui-gray-subtler-4),
)
);
.rose-checkbox {
color: var(--stark);
background-color: var(--subtle);
.rose-checkbox-input {
-webkit-appearance: none;
appearance: none;
display: inline-block;
position: relative;
padding: 0;
margin: 0;
border: 1px solid var(--ui-border);
border-radius: 2px;
width: 16px;
height: 16px;
vertical-align: -1px;
background-color: var(--subtle);
&::before {
content: '';
position: absolute;
left: 4px;
top: 1px;
width: 3px;
height: 8px;
border: solid;
border-width: 0 2px 2px 0;
border-color: var(--info);
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
visibility: hidden;
}
&:checked {
border-color: var(--info);
}
&:disabled {
cursor: not-allowed;
border-color: var(--ui-border);
background-color: var(--ui-gray-subtler-4);
&::before {
border-color: var(--ui-border);
}
}
&:checked::before {
visibility: visible;
}
&:focus {
outline: none;
border-color: var(--info);
}
&:hover {
border-color: var(--ui-gray);
}
}
&.error {
.rose-checkbox-input {
border-color: var(--failure);
&:focus {
outline: none;
border-color: var(--info);
}
&:disabled {
border-color: var(--ui-border);
}
}
}
}
@@ -1,130 +0,0 @@
@use 'sass:map';
@mixin checkbox {
color: var(--stark);
margin: 0;
padding: 0;
input[type='checkbox'] {
-webkit-appearance: none;
appearance: none;
}
input[type='checkbox'] {
display: inline-block;
position: relative;
padding: 0;
margin: 0;
margin-right: 10px;
border: 1px solid;
border-radius: 2px;
width: 16px;
height: 16px;
background: var(--subtle);
vertical-align: -1px;
}
input[type='checkbox']::before {
content: '';
position: absolute;
top: 4px;
left: 1px;
border-left: 2px solid;
border-bottom: 2px solid;
height: 3px;
width: 10px;
transform: rotate(-45deg);
visibility: hidden;
border-color: black;
}
input[type='checkbox']:checked::before {
visibility: visible;
}
input[type='checkbox']:focus {
outline: none;
}
}
@mixin checkbox-style(
$name,
$default,
$hover: &,
$focus: &,
$error: &,
$checked: &,
$disabled: &
) {
input[type='checkbox'] {
-webkit-appearance: none;
appearance: none;
}
.rose-checkbox-#{$name} {
@include checkbox;
border-color: map.get($default, border-color);
color: map.get($default, color);
& input[type='checkbox'] {
border-color: map.get($default, border-color);
background-color: map.get($default, background-color);
}
& input[type='checkbox']:hover {
@if map.get($hover, 'border-color') {
border-color: map.get($hover, 'border-color');
}
}
& input[type='checkbox']:focus {
@if map.get($focus, 'border-color') {
border-color: map.get($focus, 'border-color');
}
}
@if $checked {
& input[type='checkbox']:checked {
@if map.get($checked, 'border-color') {
border-color: map.get($checked, 'border-color');
}
}
& input[type='checkbox']:checked::before {
@if map.get($checked, 'border-color') {
border-color: map.get($checked, 'border-color');
}
}
}
& input[type='checkbox']:disabled {
cursor: not-allowed;
@if map.get($disabled, 'border-color') {
border-color: map.get($disabled, 'border-color');
}
@if map.get($disabled, 'background-color') {
background-color: map.get($disabled, 'background-color');
}
&:checked {
@if map.get($disabled, 'border-color') {
border-color: map.get($disabled, 'border-color');
}
}
&:checked::before {
@if map.get($disabled, 'border-color') {
border-color: map.get($disabled, 'border-color');
}
}
}
@if $error {
& input[type='checkbox'].error {
@if map.get($error, 'border-color') {
border-color: map.get($error, 'border-color');
}
}
}
}
}
@@ -1,9 +1,15 @@
<label class={{concat "rose-checkbox-" (if @style @style "default")}}>
<input type="checkbox"
<div class="rose-checkbox{{if @error " error"}}">
<Input @type="checkbox"
id={{if @id (concat @id "-checkbox")}}
...attributes
checked={{if @checked "checked"}}
disabled={{if @disabled "disabled"}}
class="{{if @error "error"}}"
/>
{{yield}}
</label>
name={{@name}}
disabled={{@disabled}}
form={{@form}}
class="rose-checkbox-input"
value={{@value}}
@checked={{@checked}} />
<label class="rose-checkbox-label" for={{if @id (concat @id "-checkbox")}}>
{{yield}}
</label>
</div>
+3 -6
View File
@@ -1,5 +1,4 @@
Dummy app index template
<h2>Button</h2>
<Rose::Button @style="primary">Primary</Rose::Button>
<br>
<Rose::Button @style="primary" @disabled={{true}}>Primary</Rose::Button>
@@ -63,11 +62,9 @@ Dummy app index template
disabled={{true}}
/>
<h1>Checkbox</h1>
<Rose::Checkbox></Rose::Checkbox>
<Rose::Checkbox>Label</Rose::Checkbox>
<h2>Checkbox</h2>
<Rose::Checkbox @id="default">Label</Rose::Checkbox>
<Rose::Checkbox @error={{true}}>Error</Rose::Checkbox>
<Rose::Checkbox @checked={{true}}>Checked</Rose::Checkbox>
<Rose::Checkbox @disabled={{true}}>Disabled</Rose::Checkbox>
<Rose::Checkbox @disabled={{true}} @checked={{true}}>Disabled + Checked</Rose::Checkbox>
<Rose::Checkbox @style="default">Default style</Rose::Checkbox>
+10 -6
View File
@@ -1,5 +1,5 @@
import { hbs } from 'ember-cli-htmlbars';
import { text, boolean, select } from '@storybook/addon-knobs';
import { text, boolean } from '@storybook/addon-knobs';
export default {
title: 'Rose::Checkbox',
@@ -8,19 +8,23 @@ export default {
export const Normal = () => ({
template: hbs`
<Rose::Checkbox
@id={{id}}
@name={{name}}
@form={{form}}
@checked={{checked}}
@disabled={{disabled}}
@error={{error}}
@style={{style}}
>
{{text}}
{{label}}
</Rose::Checkbox>
`,
context: {
text: text('text', 'Checkbox 🛎'),
label: text('text', 'Checkbox 🛎'),
id: text('text', 'Identifier'),
name: text('text', 'name'),
form: text('text', 'form'),
checked: boolean('checked', false),
disabled: boolean('disabled', false),
error: boolean('error', false),
style: select('style', { default: 'default'}, 'default')
error: boolean('error', false)
},
});
@@ -9,7 +9,6 @@ module('Integration | Component | rose/checkbox', function (hooks) {
test('it renders without label', async function (assert) {
await render(hbs`<Rose::Checkbox />`);
assert.equal(this.element.textContent.trim(), '');
assert.equal(this.element.querySelector('input').type, 'checkbox');
});
test('it renders a checkbox', async function (assert) {
@@ -22,6 +21,21 @@ module('Integration | Component | rose/checkbox', function (hooks) {
assert.equal(this.element.textContent.trim(), 'Label');
});
test('it renders in a div wrapper', async function (assert) {
await render(hbs`<Rose::Checkbox />`);
assert.ok(this.element.querySelector('div.rose-checkbox'));
});
test('it renders a checkbox class', async function (assert) {
await render(hbs`<Rose::Checkbox />`);
assert.ok(this.element.querySelector('input.rose-checkbox-input'));
});
test('it renders a label class', async function (assert) {
await render(hbs`<Rose::Checkbox />`);
assert.ok(this.element.querySelector('label.rose-checkbox-label'));
});
test('it is not checked', async function (assert) {
await render(hbs`<Rose::Checkbox />`);
assert.equal(this.element.querySelector('input').checked, false);
@@ -32,11 +46,6 @@ module('Integration | Component | rose/checkbox', function (hooks) {
assert.equal(this.element.querySelector('input').disabled, false);
});
test('it renders with default style', async function (assert) {
await render(hbs`<Rose::Checkbox />`);
assert.equal(this.element.querySelector('label').className, 'rose-checkbox-default');
});
test('it is checked when @checked={{true}}', async function (assert) {
await render(hbs`<Rose::Checkbox @checked={{true}} />`);
assert.equal(this.element.querySelector('input').checked, true);
@@ -44,7 +53,7 @@ module('Integration | Component | rose/checkbox', function (hooks) {
test('it marks error when @error={{true}}', async function (assert) {
await render(hbs`<Rose::Checkbox @error={{true}} />`);
assert.equal(this.element.querySelector('input').className, 'error');
assert.ok(this.element.querySelector('div.error'));
});
test('it is disabled when @disabled={{true}}', async function (assert) {
@@ -59,9 +68,4 @@ module('Integration | Component | rose/checkbox', function (hooks) {
assert.equal(this.element.querySelector('input').checked, true);
assert.equal(this.element.querySelector('input').disabled, true);
});
test('it adds a style class when @style defines it', async function (assert) {
await render(hbs`<Rose::Checkbox @style="primary" />`);
assert.equal(this.element.querySelector('label').className, 'rose-checkbox-primary');
});
});