From 7c5f8ca629f69d186d5680a961eea6eb0c1d1718 Mon Sep 17 00:00:00 2001 From: Szafran Date: Fri, 28 Aug 2020 16:09:07 +0200 Subject: [PATCH 1/5] Moved input, checkbox components --- src/atoms/icon/Icon.stories.js | 2 +- src/atoms/label/Label.css | 2 +- src/molecules/checkbox/Checkbox.css | 93 ++++++++++++++++++ src/molecules/checkbox/Checkbox.html | 28 ++++++ src/molecules/checkbox/Checkbox.js | 39 ++++++++ src/molecules/checkbox/Checkbox.spec.js | 101 +++++++++++++++++++ src/molecules/checkbox/Checkbox.stories.js | 72 ++++++++++++++ src/molecules/checkbox/Checkbox.vue | 15 +++ src/molecules/input/Input.css | 32 ++++++ src/molecules/input/Input.html | 20 ++++ src/molecules/input/Input.js | 35 +++++++ src/molecules/input/Input.selectors.json | 6 ++ src/molecules/input/Input.spec.js | 66 +++++++++++++ src/molecules/input/Input.stories.js | 108 +++++++++++++++++++++ src/molecules/input/Input.vue | 16 +++ 15 files changed, 633 insertions(+), 2 deletions(-) create mode 100644 src/molecules/checkbox/Checkbox.css create mode 100644 src/molecules/checkbox/Checkbox.html create mode 100644 src/molecules/checkbox/Checkbox.js create mode 100644 src/molecules/checkbox/Checkbox.spec.js create mode 100644 src/molecules/checkbox/Checkbox.stories.js create mode 100644 src/molecules/checkbox/Checkbox.vue create mode 100644 src/molecules/input/Input.css create mode 100644 src/molecules/input/Input.html create mode 100644 src/molecules/input/Input.js create mode 100644 src/molecules/input/Input.selectors.json create mode 100644 src/molecules/input/Input.spec.js create mode 100644 src/molecules/input/Input.stories.js create mode 100644 src/molecules/input/Input.vue diff --git a/src/atoms/icon/Icon.stories.js b/src/atoms/icon/Icon.stories.js index 9cda1693f..8fa003d94 100644 --- a/src/atoms/icon/Icon.stories.js +++ b/src/atoms/icon/Icon.stories.js @@ -338,7 +338,7 @@ export const Default = () => ({ - visibility + visibility Off
diff --git a/src/atoms/label/Label.css b/src/atoms/label/Label.css index f76765d48..125db3bbb 100644 --- a/src/atoms/label/Label.css +++ b/src/atoms/label/Label.css @@ -1,7 +1,7 @@ .a-label { @apply block; @apply mb-1; - @apply text-gray-600 leading-relaxed; + @apply text-gray-600 text-sm leading-relaxed; } .a-label--inline { diff --git a/src/molecules/checkbox/Checkbox.css b/src/molecules/checkbox/Checkbox.css new file mode 100644 index 000000000..33f99786d --- /dev/null +++ b/src/molecules/checkbox/Checkbox.css @@ -0,0 +1,93 @@ +/* @import '../../../assets/styles/_variables'; + +$checkbox__icon-size : 14px !default; +$checkbox__icon-fill : $white !default; + +$checkbox__icon-wrapper-margin : 0 $spacer 0 0 !default; +$checkbox__icon-wrapper-border : 2px solid $gray !default; +$checkbox__icon-wrapper-border-radius : 2px !default; + +$checkbox__icon-wrapper-border--checked : 2px solid $color-primary !default; +$checkbox__icon-wrapper-background-color--checked: $color-primary !default; + +.a-checkbox { + position: relative; + display: flex; + + &__field { + position: absolute; + opacity: 0; + + &:checked + .a-checkbox__label { + .a-checkbox__icon-wrapper { + background-color: $checkbox__icon-wrapper-background-color--checked; + border: $checkbox__icon-wrapper-border--checked; + } + + .a-checkbox__icon { + opacity: 1; + } + } + } + + &__label { + display: flex; + align-items: center; + cursor: pointer; + } + + &__icon-wrapper { + margin: $checkbox__icon-wrapper-margin; + border: $checkbox__icon-wrapper-border; + border-radius: $checkbox__icon-wrapper-border-radius; + } + + &__icon { + width: $checkbox__icon-size; + height: $checkbox__icon-size; + cursor: pointer; + opacity: 0; + fill: $checkbox__icon-fill; + } +} */ + +.a-checkbox { + @apply relative; + @apply flex; +} + +.a-checkbox__field { + @apply absolute opacity-0; +} + +.a-checkbox__field:checked + .a-checkbox__label { + @apply text-default; +} + +.a-checkbox__field:checked + .a-checkbox__label .a-checkbox__icon-wrapper { + @apply bg-dark; + @apply border-dark; +} + +.a-checkbox__field:checked + .a-checkbox__label .a-checkbox__icon { + @apply opacity-100; + @apply fill-white; +} + +.a-checkbox__label { + @apply flex items-center; + @apply text-sm text-gray-600; + @apply cursor-pointer; +} + +.a-checkbox__icon-wrapper { + @apply mr-4; + @apply border-2 border-solid border-secondary rounded-sm; +} + +.a-checkbox__icon { + @apply w-5 h-5; + @apply opacity-0; + @apply cursor-pointer; + @apply fill-gray-600; +} diff --git a/src/molecules/checkbox/Checkbox.html b/src/molecules/checkbox/Checkbox.html new file mode 100644 index 000000000..ef2d648c1 --- /dev/null +++ b/src/molecules/checkbox/Checkbox.html @@ -0,0 +1,28 @@ +
+ + + + + +
diff --git a/src/molecules/checkbox/Checkbox.js b/src/molecules/checkbox/Checkbox.js new file mode 100644 index 000000000..56e93400b --- /dev/null +++ b/src/molecules/checkbox/Checkbox.js @@ -0,0 +1,39 @@ +// @vue/component + +export default { + inheritAttrs: false, + model: { + prop: 'checked', + event: 'change' + }, + props: { + /** + * Prop to handle v-model + */ + checked: { + type: Boolean, + default: false + }, + /** + * Input id + */ + id: { + type: String, + required: true + }, + /** + * Class for input + */ + inputClass: { + type: String, + default: null + }, + /** + * Icon title + */ + iconTitle: { + type: String, + default: null + } + } +} diff --git a/src/molecules/checkbox/Checkbox.spec.js b/src/molecules/checkbox/Checkbox.spec.js new file mode 100644 index 000000000..7c0254883 --- /dev/null +++ b/src/molecules/checkbox/Checkbox.spec.js @@ -0,0 +1,101 @@ +import { mount } from '@vue/test-utils' +import ACheckbox from './Checkbox.vue' + +describe('Checkbox', () => { + it('has default structure', () => { + const wrapper = mount(ACheckbox, { + propsData: { + id: '1', + name: 'Checkbox', + value: 'checkbox' + } + }) + + expect(wrapper.is('div')).toBe(true) + expect(wrapper.classes()).toContain('a-checkbox') + expect(wrapper.classes().length).toBe(1) + }) + + it('renders default slots content when passed', () => { + const wrapper = mount(ACheckbox, { + propsData: { + id: '1', + name: 'Checkbox', + value: 'checkbox' + }, + slots: { + default: 'Default slot' + } + }) + + const span = wrapper.find('.a-checkbox__label span[data-test="default"]') + expect(span.exists()).toBe(true) + expect(span.text()).toEqual('Default slot') + }) + + it('renders named slots content when passed', () => { + const wrapper = mount(ACheckbox, { + propsData: { + id: '1', + name: 'Checkbox', + value: 'checkbox' + }, + slots: { + label: '' + } + }) + + const label = wrapper.find('label[data-test="label"]') + expect(label.exists()).toBe(true) + expect(label.text()).toEqual('Label') + }) + + it('default has input type radio', () => { + const wrapper = mount(ACheckbox, { + propsData: { + id: '1', + name: 'Checkbox', + value: 'checkbox' + } + }) + + const input = wrapper.find('.a-checkbox__field') + expect(input.attributes('type')).toBeDefined() + expect(input.attributes('type')).toEqual('checkbox') + }) + + it('default has no disabled attribute on input', () => { + const wrapper = mount(ACheckbox, { + propsData: { + id: '1', + name: 'Checkbox', + value: 'checkbox' + } + }) + + const input = wrapper.find('.a-checkbox__field') + expect(input.attributes('disabled')).not.toBeDefined() + }) + + it('emits a change event when clicked', () => { + const wrapper = mount(ACheckbox, { + propsData: { + id: '1', + name: 'Checkbox', + value: 'checkbox' + } + }) + + const input = wrapper.find('.a-checkbox__field') + expect(input).toBeDefined() + input.trigger('click') + expect(wrapper.emitted('change')).toBeDefined() + expect(wrapper.emitted('change').length).toBe(1) + expect(wrapper.emitted('change')[0][0]).toEqual(true) + + input.trigger('click') + expect(wrapper.emitted('change')).toBeDefined() + expect(wrapper.emitted('change').length).toBe(2) + expect(wrapper.emitted('change')[1][0]).toEqual(false) + }) +}) diff --git a/src/molecules/checkbox/Checkbox.stories.js b/src/molecules/checkbox/Checkbox.stories.js new file mode 100644 index 000000000..a6642dbc9 --- /dev/null +++ b/src/molecules/checkbox/Checkbox.stories.js @@ -0,0 +1,72 @@ +import { storiesOf } from '@storybook/vue' +import { action } from '@storybook/addon-actions' + +import ACheckbox from './Checkbox.vue' +import AIcon from './../../atoms/icon/Icon.vue' +import AIconCheck from './../../atoms/icon/templates/IconCheck.vue' + +const defaultData = { + data: () => { + return { + status: true + } + }, + methods: { + onChange: action('Option changed') + } +} + +storiesOf('Molecules/Checkbox', module) + .addParameters({ info: true }) + .add('Default', () => ({ + ...defaultData, + components: { ACheckbox }, + template: ` + + Checkbox field + + ` + })) + .add('With slot', () => ({ + ...defaultData, + components: { + ACheckbox, + AIcon, + AIconCheck + }, + template: ` + + + + ` + })) diff --git a/src/molecules/checkbox/Checkbox.vue b/src/molecules/checkbox/Checkbox.vue new file mode 100644 index 000000000..5bd2bda41 --- /dev/null +++ b/src/molecules/checkbox/Checkbox.vue @@ -0,0 +1,15 @@ +