ICU-62 -Add checkbox rose component
This commit is contained in:
9 files changed
+288
-1
No files matched your search
@@ -0,0 +1,19 @@
|
||||
import Component from '@ember/component';
|
||||
import layout from '../../templates/components/rose/checkbox';
|
||||
|
||||
/**
|
||||
A simple HTML `<input type="checkbox">` element wrapped in `<label>`.
|
||||
|
||||
@example
|
||||
<Rose::Checkbox />
|
||||
<Rose::Checkbox>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" />
|
||||
**/
|
||||
|
||||
export default Component.extend({
|
||||
layout,
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
@use '../utilities/checkbox';
|
||||
|
||||
@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),
|
||||
)
|
||||
);
|
||||
@@ -1,2 +1,3 @@
|
||||
@import 'button';
|
||||
@import 'form';
|
||||
@import 'checkbox';
|
||||
@@ -0,0 +1,130 @@
|
||||
@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');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<label class={{concat "rose-checkbox-" (if @style @style "default")}}>
|
||||
<input type="checkbox"
|
||||
...attributes
|
||||
checked={{if @checked "checked"}}
|
||||
disabled={{if @disabled "disabled"}}
|
||||
class="{{if @error "error"}}"
|
||||
/>
|
||||
{{yield}}
|
||||
</label>
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'rose/components/rose/checkbox';
|
||||
@@ -10,7 +10,6 @@ Dummy app index template
|
||||
<Rose::Button @style="secondary" @disabled={{true}}>Secondary</Rose::Button>
|
||||
<br>
|
||||
|
||||
|
||||
<Rose::Form::Input
|
||||
@label="Label"
|
||||
@value="Read only"
|
||||
@@ -63,3 +62,12 @@ Dummy app index template
|
||||
@value="Text"
|
||||
disabled={{true}}
|
||||
/>
|
||||
|
||||
<h1>Checkbox</h1>
|
||||
<Rose::Checkbox></Rose::Checkbox>
|
||||
<Rose::Checkbox>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>
|
||||
@@ -0,0 +1,26 @@
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
import { text, boolean, select } from '@storybook/addon-knobs';
|
||||
|
||||
export default {
|
||||
title: 'Rose::Checkbox',
|
||||
};
|
||||
|
||||
export const Normal = () => ({
|
||||
template: hbs`
|
||||
<Rose::Checkbox
|
||||
@checked={{checked}}
|
||||
@disabled={{disabled}}
|
||||
@error={{error}}
|
||||
@style={{style}}
|
||||
>
|
||||
{{text}}
|
||||
</Rose::Checkbox>
|
||||
`,
|
||||
context: {
|
||||
text: text('text', 'Checkbox 🛎'),
|
||||
checked: boolean('checked', false),
|
||||
disabled: boolean('disabled', false),
|
||||
error: boolean('error', false),
|
||||
style: select('style', { default: 'default'}, 'default')
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
|
||||
module('Integration | Component | rose/checkbox', function (hooks) {
|
||||
setupRenderingTest(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) {
|
||||
await render(hbs`<Rose::Checkbox />`);
|
||||
assert.equal(this.element.querySelector('input').type, 'checkbox');
|
||||
});
|
||||
|
||||
test('it renders with label', async function (assert) {
|
||||
await render(hbs`<Rose::Checkbox>Label</Rose::Checkbox>`);
|
||||
assert.equal(this.element.textContent.trim(), 'Label');
|
||||
});
|
||||
|
||||
test('it is not checked', async function (assert) {
|
||||
await render(hbs`<Rose::Checkbox />`);
|
||||
assert.equal(this.element.querySelector('input').checked, false);
|
||||
});
|
||||
|
||||
test('it is not disabled', async function (assert) {
|
||||
await render(hbs`<Rose::Checkbox />`);
|
||||
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);
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
|
||||
test('it is disabled when @disabled={{true}}', async function (assert) {
|
||||
await render(hbs`<Rose::Checkbox @disabled={{true}} />`);
|
||||
assert.equal(this.element.querySelector('input').disabled, true);
|
||||
});
|
||||
|
||||
test('it is disabled and checked when @disabled={{true}} and @checked={{true}}', async function (assert) {
|
||||
await render(
|
||||
hbs`<Rose::Checkbox @disabled={{true}} @checked={{true}}></Rose::Checkbox>`
|
||||
);
|
||||
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');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user