From 9f840733ad5e5a5bbeeb555a2bb5e1c101925fe3 Mon Sep 17 00:00:00 2001 From: Callum Axon Date: Tue, 22 Sep 2020 20:51:27 +0100 Subject: [PATCH] feat(VukButton): add button component with primary & secondary variants (#11) * refactor(vukheading): changed template for render function * feat(vukbutton): add button component with primary & secondary variants * build: export button component * Update tailwind.config.js --- package.json | 2 +- src/components/VukButton/VukButton.md | 80 +++++++ src/components/VukButton/VukButton.vue | 101 ++++++++ src/components/VukButton/constants.js | 14 ++ src/components/VukButton/index.ts | 4 + src/components/index.ts | 1 + src/main.ts | 6 + tailwind.config.js | 31 ++- tests/unit/VukButton.spec.ts | 75 ++++++ .../unit/__snapshots__/VukButton.spec.ts.snap | 7 + yarn.lock | 215 +++++++++++++++--- 11 files changed, 494 insertions(+), 42 deletions(-) create mode 100644 src/components/VukButton/VukButton.md create mode 100644 src/components/VukButton/VukButton.vue create mode 100644 src/components/VukButton/constants.js create mode 100644 src/components/VukButton/index.ts create mode 100644 tests/unit/VukButton.spec.ts create mode 100644 tests/unit/__snapshots__/VukButton.spec.ts.snap diff --git a/package.json b/package.json index 37fe142..9b3f8d1 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "node-sass": "^4.13.0", "postcss": "^7.0.21", "sass-loader": "^8.0.0", - "tailwindcss": "^1.1.3", + "tailwindcss": "^1.8.10", "vue": "^2.6.10", "vue-class-component": "^7.2.3", "vue-property-decorator": "^8.4.2" diff --git a/src/components/VukButton/VukButton.md b/src/components/VukButton/VukButton.md new file mode 100644 index 0000000..d5853d6 --- /dev/null +++ b/src/components/VukButton/VukButton.md @@ -0,0 +1,80 @@ +# VukButton + +Consistent button component for usage across VATSIM UK Services. + +## Usage + +Example usage + +```html +Content Goes here +``` + +### Colors + +Per the design guidelines, the following types are defined: + +- blue +- yellow +- purple +- success (green) +- error (red) + +### Variants + +Within these types, two variants are supported + +- primary +- secondary + +### Icons + +An icon can also be used within a button but a directive must be applied to the SVG. +Adding the `v-button-icon` directive will apply the necessary logic to allow the icon to co-exist with text within the button. + +```html + + + + + Testing some long text with an icon + +``` + +### Disabling + +If you need to disable a button, for example within a form, simply use the built in HTML disabled attribute. + +```html +Content Goes here +``` + +This will render the disabled button of the button and disable its usage. This can also be used via a bound property as normal. + +### Events + +To register a click event on the button, you must use the native modifier + +```html +Content Goes here +``` + +### Native Attributes + +Any of the native HTML button attributes can be applied directly to the component e.g. type in a form. + +```html +Content Goes here +``` diff --git a/src/components/VukButton/VukButton.vue b/src/components/VukButton/VukButton.vue new file mode 100644 index 0000000..ecb3f6f --- /dev/null +++ b/src/components/VukButton/VukButton.vue @@ -0,0 +1,101 @@ + diff --git a/src/components/VukButton/constants.js b/src/components/VukButton/constants.js new file mode 100644 index 0000000..64472a1 --- /dev/null +++ b/src/components/VukButton/constants.js @@ -0,0 +1,14 @@ +export const Variants = { + PRIMARY: 'primary', + SECONDARY: 'secondary' +} + +export const Colors = { + BLUE: 'blue', + YELLOW: 'yellow', + PURPLE: 'purple', + SUCCESS: 'success', + ERROR: 'error' +} + +export default { Variants, Colors } diff --git a/src/components/VukButton/index.ts b/src/components/VukButton/index.ts new file mode 100644 index 0000000..386bb76 --- /dev/null +++ b/src/components/VukButton/index.ts @@ -0,0 +1,4 @@ +import VukButton from './VukButton.vue' + +export { VukButton } +export default VukButton diff --git a/src/components/index.ts b/src/components/index.ts index 1620c5f..c462cd4 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,2 +1,3 @@ export * from './VukHeading' export * from './VukLogo' +export * from './VukButton' diff --git a/src/main.ts b/src/main.ts index cb47955..b148e78 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,6 +8,12 @@ const install = function (Vue: VueConstructor, options: Object = {}) { Object.values(components).forEach(component => { Vue.component(component.name, component) }) + + Vue.directive('button-icon', { + inserted(el) { + el.classList.add('h-4', 'mr-2', 'stroke-current') + } + }) } // @ts-ignore diff --git a/tailwind.config.js b/tailwind.config.js index a2a9574..3b2de24 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -9,19 +9,26 @@ module.exports = { light: '#25ADE3' }, grey: { - base: '#1F2122', - secondary: '#F2F2F1', - 100: '#222425', - 200: '#27292A', - 300: '#313334', - 400: '#3B3D3E', - 500: '#585A5A' + base: '#121212', + 100: 'rgba(255,255,255,0.05)', + 200: 'rgba(255,255,255,0.07)', + 300: 'rgba(255,255,255,0.08)', + 400: 'rgba(255,255,255,0.09)', + 500: 'rgba(255,255,255,0.11)', + 600: 'rgba(255,255,255,0.12)', + 700: 'rgba(255,255,255,0.14)', + 800: 'rgba(255,255,255,0.15)', + 900: 'rgba(255,255,255,0.16)', + low: 'rgba(255, 255, 255, 0.38)', + medium: 'rgba(255, 255, 255, 0.60)', + high: 'rgba(255, 255, 255, 0.87)' }, green: '#3BC35A', red: '#E3253B', violet: '#C33B77', yellow: '#E3B725', - white: '#ffffff' + white: 'rgba(255, 255, 255, 0.87)', + transparent: 'transparent' }, fontFamily: { display: 'Roboto' @@ -42,6 +49,12 @@ module.exports = { '4xl': '6rem' } }, - variants: {}, + variants: { + backgroundColor: ({ after }) => after(['disabled']), + cursor: ({ after }) => after(['disabled']), + textColor: ({ after }) => after(['disabled']), + borderWidth: ({ after }) => after(['disabled']), + borderColor: ({ after }) => after(['disabled']) + }, plugins: [] } diff --git a/tests/unit/VukButton.spec.ts b/tests/unit/VukButton.spec.ts new file mode 100644 index 0000000..a68b460 --- /dev/null +++ b/tests/unit/VukButton.spec.ts @@ -0,0 +1,75 @@ +import VukButton from '@/components/VukButton/VukButton.vue' +import { Colors } from '@/components/VukButton/constants' +import { shallowMount } from '@vue/test-utils' + +describe('VukButton', () => { + let cmp: any + + const propsData = { + color: 'blue', + variant: 'primary' + } + beforeEach(() => { + cmp = shallowMount(VukButton, { + propsData + }) + }) + + describe('snapshot', () => { + it('should match the snapshot', () => { + expect(cmp.vm.$el).toMatchSnapshot() + }) + }) + describe('props', () => { + describe('type', () => { + it('should pass the validator when it is a valid type', () => { + expect(cmp.vm.$options.props.color.validator(Colors.BLUE)).toEqual(true) + }) + it('should not pass the validator when it is not a valid type', () => { + expect(cmp.vm.$options.props.color.validator('not-valid')).toEqual( + false + ) + }) + }) + }) + + describe('computed', () => { + describe('background', () => { + it('should resolve a value based upon a valid type', () => { + expect(cmp.vm.$options.computed.background.call(cmp.vm)).toEqual( + 'bg-primary' + ) + }) + it('should resolve a transparent background value when the variant is secondary', () => { + cmp.setProps({ variant: 'secondary' }) + expect(cmp.vm.$options.computed.background.call(cmp.vm)).toEqual( + 'bg-transparent' + ) + }) + }) + describe('borderColor', () => { + it('should resolve a value based upon a valid type', () => { + cmp.setProps({ type: 'blue' }) + expect(cmp.vm.$options.computed.borderColor.call(cmp.vm)).toEqual( + 'border-primary' + ) + }) + }) + describe('textColor', () => { + it('should resolve a text value based upon a valid type', () => { + cmp.setProps({ type: 'blue' }) + expect(cmp.vm.$options.computed.textColor.call(cmp.vm)).toEqual( + 'text-white' + ) + }) + }) + describe('hoverStyles', () => { + it('should resolve a hover value based upon a valid type', () => { + cmp.setProps({ variant: 'primary' }) + expect(cmp.vm.$options.computed.hoverStyles.call(cmp.vm)).toEqual( + 'hover:bg-opacity-25' + ) + }) + }) + }) +}) diff --git a/tests/unit/__snapshots__/VukButton.spec.ts.snap b/tests/unit/__snapshots__/VukButton.spec.ts.snap new file mode 100644 index 0000000..3584f7b --- /dev/null +++ b/tests/unit/__snapshots__/VukButton.spec.ts.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`VukButton snapshot should match the snapshot 1`] = ` +