Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion components/src/stories/TextField.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ export const Component = {
},
template: '<ui-textfield v-bind="args"></ui-textfield>',
}),

args: {
label: 'Label text',
value: '',
placeholder: 'Placeholder text',
suffix: '',
},
};

Expand All @@ -25,5 +28,8 @@ export default {
},
argTypes: {
label: 'text',
value: 'text',
placeholder: 'text',
suffix: 'text',
},
};
89 changes: 41 additions & 48 deletions components/src/widgets/textfield/widget.spec.js
Original file line number Diff line number Diff line change
@@ -1,67 +1,60 @@
import { mount } from '@vue/test-utils';
import Textfield from './widget';


describe('Textfield widget', () => {
let context;
let result;

describe('#data', () => {
it('returns the initial data', () => {
result = Textfield.data();

expect(result).toEqual({
focused: false,
localValue: '',
});
let wrapper;

describe('render', () => {
it('renders the base component without any prop', () => {
wrapper = mount(Textfield);

expect(wrapper.get('.text-field').exists()).toBeTruthy();
expect(wrapper.get('.text-field label').text()).toEqual('');
expect(wrapper.get('.text-field__input').exists()).toBeTruthy();
expect(wrapper.get('.text-field__input').element.value).toEqual('');
expect(wrapper.get('.text-field__input').attributes('placeholder')).toEqual('');
expect(wrapper.find('.text-field__suffix').exists()).toBeFalsy();
expect(wrapper.find('.text-field_focused').exists()).toBeFalsy();
expect(wrapper.find('.text-field__input_right').exists()).toBeFalsy();
});
});

describe('methods', () => {
describe('#onInput', () => {

beforeEach(() => {
context = {
localValue: 'my value',
$emit: jest.fn(),
e: {
stopPropagation: jest.fn(),
},
};

Textfield.methods.onInput.call(context, context.e);
});

it('calls stop propagation from event', () => {
expect(context.e.stopPropagation).toHaveBeenCalled();
it('renders the base component with the props set', () => {
wrapper = mount(Textfield, {
props: {
value: 'Foo',
label: 'My text input',
placeholder: 'Insert text here',
suffix: 'hh:mm:ssss.csv',
},
});

it('emits input event with localValue', () => {
expect(context.$emit).toHaveBeenCalledWith('input', context.localValue);
});
expect(wrapper.get('.text-field').exists()).toBeTruthy();
expect(wrapper.get('.text-field label').text()).toEqual('My text input');
expect(wrapper.get('.text-field__input').exists()).toBeTruthy();
expect(wrapper.get('.text-field__input').element.value).toEqual('Foo');
expect(wrapper.get('.text-field__input').attributes('placeholder')).toEqual('Insert text here');
expect(wrapper.get('.text-field__suffix').text()).toEqual('hh:mm:ssss.csv');
expect(wrapper.get('.text-field__input_right').exists()).toBeTruthy();
expect(wrapper.find('.text-field_focused').exists()).toBeFalsy();
});

describe('#removeFocus', () => {
it('sets focused to false if focused is true', () => {
context = {
focused: true,
}
it('sets the "text-field_focused" class when focused', async () => {
wrapper = mount(Textfield);

Textfield.methods.removeFocus.call(context);
await wrapper.find('.text-field').trigger('focusin');

expect(context.focused).toEqual(false);
})
expect(wrapper.get('.text-field_focused').exists()).toBeTruthy();
});
});

describe('#setFocus', () => {
it('sets focused to false if focused is true', () => {
context = {
focused: false,
}
describe('events', () => {
it('emits the "input" event when the input element value changes', async () => {
wrapper = mount(Textfield);

Textfield.methods.setFocus.call(context);
await wrapper.find('.text-field__input').setValue('lorem ipsum');

expect(context.focused).toEqual(true);
})
expect(wrapper.emitted().input[0]).toEqual(['lorem ipsum']);
});
});
});
104 changes: 62 additions & 42 deletions components/src/widgets/textfield/widget.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<!-- eslint-disable vue/no-v-html -->
<template>
<div
:class="[
{'text-field_focused': focused},
'text-field',
]"
class="text-field"
:class="{ 'text-field_focused': isFocused }"
@focusin="setFocus"
@focusout="removeFocus"
>
Expand All @@ -13,51 +10,66 @@
<div class="text-field__body">
<input
v-model="localValue"
name="textfield"
class="text-field__input"
:class="{ 'text-field__input_right': suffix }"
:placeholder="placeholder"
name="textfield"
type="text"
@input="onInput"
@input.stop
>
<span
v-if="suffix"
class="text-field__suffix"
>{{ suffix }}</span>
</div>
</div>
</div>
</template>

<script>
export default {
props: {
label: {
type: String,
default: '',
},
<script setup>
import { ref, watch } from 'vue';

const props = defineProps({
value: {
type: String,
default: '',
},
emits: ['input'],
data() {
return {
focused: false,
localValue: '',
}
label: {
type: String,
default: '',
},
placeholder: {
type: String,
default: '',
},
suffix: {
type: String,
default: '',
},
});

methods: {
onInput(e) {
e.stopPropagation();
this.$emit('input', this.localValue );
},
const localValue = ref('');

removeFocus() {
if (this.focused) {
this.focused = false;
}
},
const isFocused = ref(false);
const emit = defineEmits(['input']);

setFocus() {
if (this.focused) return;
const removeFocus = () => (isFocused.value = false);
const setFocus = () => (isFocused.value = true);

this.focused = true;
},
watch(
() => props.value,
newValue => {
localValue.value = newValue;
},
}
{ immediate: true },
);

watch(
localValue,
(newValue) => {
emit('input', newValue);
},
);
</script>

<style lang="stylus">
Expand All @@ -77,12 +89,6 @@ export default {
font-size: 14px;
}

&___r {
display: flex;
flex-flow: row nowrap;
align-items: center;
}

&__body {
flex-grow: 1;

Expand Down Expand Up @@ -115,6 +121,10 @@ export default {
outline: none;
border-style: none;
background-color: transparent;
font-size: 14px;
font-weight: 400;
line-height: 20px;
color: #212121;

&:hover,
&:focus {
Expand All @@ -135,7 +145,17 @@ export default {
.text-field_disabled & {
color: #BDBDBD;
}

&_right {
text-align: right;
}
}

&__suffix {
font-size: 14px;
font-weight: 400;
line-height: 20px;
color: #707070;
}
}
</style>