diff --git a/src/atoms/blockquote/Blockquote.css b/src/atoms/blockquote/Blockquote.css
index 00c348255..cd57f7fe5 100644
--- a/src/atoms/blockquote/Blockquote.css
+++ b/src/atoms/blockquote/Blockquote.css
@@ -1,6 +1,6 @@
.a-blockquote {
@apply my-2;
@apply py-2 pr-2 pl-4;
- @apply border-l-4 border-solid border-light;
+ @apply border-l-4 border-solid border-gray-300;
@apply leading-relaxed;
}
diff --git a/src/molecules/input/Input.html b/src/molecules/input/Input.html
new file mode 100644
index 000000000..a2b9d65c1
--- /dev/null
+++ b/src/molecules/input/Input.html
@@ -0,0 +1,21 @@
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
diff --git a/src/molecules/input/Input.js b/src/molecules/input/Input.js
new file mode 100644
index 000000000..394199da2
--- /dev/null
+++ b/src/molecules/input/Input.js
@@ -0,0 +1,68 @@
+// @vue/component
+import getClass from '../../../utils/helpers/get-class.js'
+
+export default {
+ mixins: [getClass],
+ inheritAttrs: false,
+ props: {
+ /**
+ * Prop to handle v-model
+ */
+ value: {
+ type: String,
+ default: null
+ },
+ /**
+ * Input id
+ */
+ id: {
+ type: String,
+ required: true
+ },
+ /**
+ * Label text
+ */
+ label: {
+ type: String,
+ default: null
+ }
+ },
+ computed: {
+ listeners () {
+ return {
+ ...this.$listeners,
+ input: event => this.$emit('input', event.target.value)
+ }
+ }
+ },
+ data () {
+ return {
+ config: {
+ base: {
+ input: [
+ 'relative'
+ ],
+ input__field: [
+ 'w-full', 'h-12',
+ 'px-4'
+ ]
+ },
+ primary: {
+ input__field: [
+ 'border', 'border-solid', 'border-form',
+ 'placeholder-primary'
+ ]
+ },
+ inline: {
+ input: [
+ 'flex', 'items-center'
+ ],
+ input__label: [
+ 'flex-shrink-0',
+ 'm-4', 'mb-4'
+ ]
+ }
+ }
+ }
+ }
+}
diff --git a/src/molecules/input/Input.scss b/src/molecules/input/Input.scss
new file mode 100644
index 000000000..c755d3d85
--- /dev/null
+++ b/src/molecules/input/Input.scss
@@ -0,0 +1,50 @@
+@import '../../../assets/styles/_globals.scss';
+
+$input__margin : 0 0 $spacer--medium 0 !default;
+$input-wrapper__label-margin : 0 $spacer--medium 0 0 !default;
+
+$input__field-padding : 0 $spacer--large 0 $spacer--medium !default;
+$input__field-width : 100% !default;
+$input__field-height : 40px !default;
+$input__field-border : 1px solid $form-elements-border-color !default;
+$input__field-border-radius : $form-elements-radius !default;
+$input__field-placeholder-color: $gray !default;
+
+$input__icon-top : 20px !default;
+$input__icon-right : 8px !default;
+
+.a-input {
+ // position: relative;
+ // margin: $input__margin;
+
+ // &--inline {
+ // display: flex;
+ // align-items: center;
+
+ // .a-label {
+ // flex-shrink: 0;
+ // margin: $input-wrapper__label-margin;
+ // }
+ // }
+
+ // &__field {
+ // // width: $input__field-width;
+ // // height: $input__field-height;
+ // // padding: $input__field-padding;
+ // // border: $input__field-border;
+ // // border-radius: $input__field-border-radius;
+
+ // // &[type='search'] {
+ // // -webkit-appearance: textfield;
+
+ // // &::-webkit-search-decoration,
+ // // &::-webkit-search-cancel-button {
+ // // -webkit-appearance: none;
+ // // }
+ // // }
+
+ // // &::placeholder {
+ // // color: $input__field-placeholder-color;
+ // // }
+ // }
+}
diff --git a/src/molecules/input/Input.spec.js b/src/molecules/input/Input.spec.js
new file mode 100644
index 000000000..922a5bdcb
--- /dev/null
+++ b/src/molecules/input/Input.spec.js
@@ -0,0 +1,66 @@
+import { mount } from '@vue/test-utils'
+import AInput from './Input.vue'
+
+describe('Input', () => {
+ it('has default structure', () => {
+ const wrapper = mount(AInput, {
+ propsData: {
+ id: 'input-id'
+ }
+ })
+ const input = wrapper.find('.a-input__field')
+
+ expect(wrapper.is('div')).toBe(true)
+ expect(wrapper.classes()).toContain('a-input')
+ expect(wrapper.classes().length).toBe(1)
+
+ expect(input.is('input')).toBe(true)
+ expect(input.classes()).toContain('a-input__field')
+ expect(input.classes().length).toBe(1)
+ expect(input.attributes().id).toBeDefined()
+ expect(input.attributes().id).toBe('input-id')
+ })
+
+ it('renders email input when type set to email', () => {
+ const wrapper = mount(AInput, {
+ propsData: {
+ id: 'input-id',
+ type: 'email'
+ }
+ })
+
+ const input = wrapper.find('.a-input__field')
+ expect(input.attributes('type')).toBe('email')
+ })
+
+ it('renders slots content when passed', () => {
+ const wrapper = mount(AInput, {
+ propsData: {
+ id: 'input-id'
+ },
+ slots: {
+ label: ''
+ }
+ })
+
+ const label = wrapper.find('.a-input > label')
+
+ expect(label.exists()).toBe(true)
+ expect(label.text()).toEqual('Alpaca UI')
+ })
+
+ it('emits an input event', () => {
+ const wrapper = mount(AInput, {
+ propsData: {
+ id: 'input-id'
+ }
+ })
+
+ const textInput = wrapper.find('input')
+ textInput.setValue('Sample text')
+
+ expect(wrapper.emitted('input')).toBeTruthy()
+ expect(wrapper.emitted().input[0].length).toBe(1)
+ expect(wrapper.emitted().input[0][0]).toEqual('Sample text')
+ })
+})
diff --git a/src/molecules/input/Input.stories.js b/src/molecules/input/Input.stories.js
new file mode 100644
index 000000000..cf0890702
--- /dev/null
+++ b/src/molecules/input/Input.stories.js
@@ -0,0 +1,110 @@
+import AInput from './Input.vue'
+import AIcon from '../../atoms/icon/Icon.vue'
+import AIconPerson from '../../atoms/icon/templates/IconPerson.vue'
+
+export default {
+ title: 'Molecules/Input',
+ component: AInput,
+ argTypes: {
+ type: {
+ control: {
+ type: 'text'
+ }
+ },
+ placeholder: {
+ control: {
+ type: 'text'
+ }
+ },
+ label: {
+ control: {
+ type: 'text'
+ }
+ }
+ }
+}
+
+const args = {
+ type: 'text',
+ placeholder: 'Placeholder text...',
+ label: 'Label text'
+}
+
+const Template = (args, { argTypes }) => ({
+ components: { AInput },
+ props: Object.keys(argTypes),
+ data: () => {
+ return {
+ inputValue: ''
+ }
+ },
+ template: `
+
+
+
+ Model: {{ inputValue }}
+
+
+ `
+})
+
+export const Default = Template.bind({})
+
+export const Inline = Template.bind({})
+
+export const WithSlots = (args, { argTypes }) => ({
+ components: { AInput, AIcon, AIconPerson },
+ props: Object.keys(argTypes),
+ data: () => {
+ return {
+ inputValue: '',
+ iconStyles: {
+ top: '29px',
+ right: '8px',
+ cursor: 'pointer'
+ }
+ }
+ },
+ template: `
+
+
+
+
+
+
+
+ Model: {{ inputValue }}
+
+
+ `
+})
+
+Default.args = args
+Inline.args = {
+ ...args,
+ variant: ['primary', 'inline']
+}
+WithSlots.args = args
diff --git a/src/molecules/input/Input.vue b/src/molecules/input/Input.vue
new file mode 100644
index 000000000..da87a9054
--- /dev/null
+++ b/src/molecules/input/Input.vue
@@ -0,0 +1,14 @@
+
+
+
diff --git a/tailwind.config.js b/tailwind.config.js
index 9dd79059c..7ddbfca40 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -4,8 +4,8 @@ module.exports = {
],
theme: {
extend: {
- minHeight: {
- 24: '24px'
+ maxWidth: {
+ content: '1328px'
}
},
screens: {
@@ -52,18 +52,24 @@ module.exports = {
}),
borderColor: theme => ({
...theme('colors'),
- default: theme('colors.gray.500'),
- primary: theme('colors.gray.500'),
- secondary: theme('colors.gray.600'),
- dark: theme('colors.gray.800'),
- light: theme('colors.gray.300')
+ // primary: theme('colors.gray.500'),
+ // secondary: theme('colors.gray.600'),
+ form: theme('colors.gray.500')
+ // default: theme('colors.gray.500'),
+ // dark: theme('colors.gray.800'),
+ // light: theme('colors.gray.300'),
+
}),
textColor: theme => ({
...theme('colors'),
- default: theme('colors.gray.800'),
+ // default: theme('colors.gray.800'),
primary: theme('colors.gray.800'),
secondary: theme('colors.gray.600')
}),
+ placeholderColor: theme => ({
+ primary: theme('colors.gray.600'),
+ // secondary: theme('colors.gray.300')
+ }),
fill: theme => ({
...theme('colors'),
dark: theme('colors.gray.800'),
@@ -71,10 +77,7 @@ module.exports = {
}),
outline: theme => ({
focus: [`2px solid ${theme('colors.bright-sky-blue')}`, '-1px']
- }),
- maxWidth: {
- content: '1328px'
- }
+ })
},
variants: {},
plugins: [],
diff --git a/utils/helpers/get-class.js b/utils/helpers/get-class.js
index 3a55a2228..05bd7babe 100644
--- a/utils/helpers/get-class.js
+++ b/utils/helpers/get-class.js
@@ -13,7 +13,7 @@ export default {
let variantStyles
let classes = []
- if (baseStyles) {
+ if (baseStyles?.[el]) {
classes = [...baseStyles[el]]
}