Skip to content

Commit 744ccbc

Browse files
authored
Merge pull request #480 from upfluence/olympelespagnon/vel-5048-create-a-dedicated-osssearchfield-component
Create a dedicated OSS::SearchField component
2 parents e379aa9 + 036f531 commit 744ccbc

File tree

8 files changed

+180
-1
lines changed

8 files changed

+180
-1
lines changed
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<OSS::InputContainer @value={{@value}} @placeholder={{this.placeholder}} @onChange={{this.onChange}} ...attributes>
2+
<:prefix>
3+
<OSS::Icon @icon="fa-search" class="font-color-gray-500" />
4+
</:prefix>
5+
<:suffix>
6+
{{#if (gt @value.length 0)}}
7+
<OSS::Icon @icon="fa-times" class="font-color-gray-500" role="button" {{on "click" this.onClearSearch}} />
8+
{{/if}}
9+
</:suffix>
10+
</OSS::InputContainer>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { hbs } from 'ember-cli-htmlbars';
2+
import { action } from '@storybook/addon-actions';
3+
4+
export default {
5+
title: 'Components/OSS::SearchField',
6+
component: 'search-field',
7+
argTypes: {
8+
value: {
9+
type: { required: true },
10+
description: 'Value of the input',
11+
table: {
12+
type: {
13+
summary: 'string'
14+
},
15+
defaultValue: { summary: 'undefined' }
16+
},
17+
control: { type: 'text' }
18+
},
19+
placeholder: {
20+
description: 'Placeholder of the input',
21+
table: {
22+
type: {
23+
summary: 'string'
24+
},
25+
defaultValue: { summary: 'undefined' }
26+
},
27+
control: { type: 'text' }
28+
},
29+
onChange: {
30+
type: { required: true },
31+
description: 'Method called every time the input is updated',
32+
table: {
33+
category: 'Actions',
34+
type: {
35+
summary: 'onChange(value: string): void'
36+
}
37+
},
38+
control: { type: null }
39+
}
40+
},
41+
parameters: {
42+
docs: {
43+
description: {
44+
component:
45+
'The OSS version of the search-field component. This component encapsulates search field input and allows user to reset the search.'
46+
}
47+
}
48+
}
49+
};
50+
51+
const defaultArgs = {
52+
value: 'John',
53+
placeholder: 'My placeholder',
54+
onChange: action('onChange')
55+
};
56+
57+
const Template = (args) => ({
58+
template: hbs`
59+
<OSS::SearchField @value={{this.value}} @placeholder={{this.placeholder}} @onChange={{this.onChange}} />
60+
`,
61+
context: args
62+
});
63+
export const BasicUsage = Template.bind({});
64+
BasicUsage.args = defaultArgs;
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { action } from '@ember/object';
2+
import { inject as service } from '@ember/service';
3+
import Component from '@glimmer/component';
4+
import type IntlService from 'ember-intl/services/intl';
5+
6+
interface OSSSearchFieldArgs {
7+
value: string;
8+
placeholder?: string;
9+
onChange(value: string): void;
10+
}
11+
12+
export default class OSSSearchFieldComponent extends Component<OSSSearchFieldArgs> {
13+
@service declare intl: IntlService;
14+
15+
get placeholder(): string {
16+
return this.args.placeholder ?? this.intl.t('oss-components.search_field.placeholder');
17+
}
18+
19+
@action
20+
onClearSearch(): void {
21+
this.args.onChange('');
22+
}
23+
24+
@action
25+
onChange(value: string): void {
26+
this.args.onChange(value);
27+
}
28+
}

app/components/o-s-s/search-field.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from '@upfluence/oss-components/components/o-s-s/search-field';

tests/dummy/app/controllers/input.ts

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { countries, type CountryData } from '@upfluence/oss-components/utils/cou
77
export default class Input extends Controller {
88
@tracked shopUrl: string = '';
99
@tracked inputValue: string = '';
10+
@tracked searchFieldValue: string = '';
1011
@tracked textAreaValue: string = '42';
1112
@tracked superHeroes: string[] = ['Iron Man', 'Thor', 'Loki', 'Hulk'];
1213
@tracked items: { name: string; label: string }[] = [
@@ -121,4 +122,9 @@ export default class Input extends Controller {
121122
console.log('onCurrencyOnlyChange', currency);
122123
this.currencyOnly = currency;
123124
}
125+
126+
@action
127+
onSearchFieldChange(value: string): void {
128+
this.searchFieldValue = value;
129+
}
124130
}

tests/dummy/app/templates/input.hbs

+11
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,17 @@
192192
</div>
193193
</div>
194194

195+
<div
196+
class="fx-col fx-1 background-color-white border border-color-default border-radius-md padding-px-12 fx-gap-px-12"
197+
>
198+
<div class="font-size-md font-weight-semibold">
199+
Search Fields
200+
</div>
201+
<div class="fx-row fx-gap-px-24 fx-xalign-start">
202+
<OSS::SearchField @value={{this.searchFieldValue}} @onChange={{this.onSearchFieldChange}} />
203+
</div>
204+
</div>
205+
195206
<div
196207
class="fx-col fx-1 background-color-white border border-color-default border-radius-md padding-px-12 fx-gap-px-12"
197208
>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { module, test } from 'qunit';
2+
import { setupRenderingTest } from 'ember-qunit';
3+
import { render, click, typeIn } from '@ember/test-helpers';
4+
import { hbs } from 'ember-cli-htmlbars';
5+
import { setupIntl } from 'ember-intl/test-support';
6+
import sinon from 'sinon';
7+
8+
module('Integration | Component | o-s-s/search-field', function (hooks) {
9+
setupRenderingTest(hooks);
10+
setupIntl(hooks);
11+
12+
hooks.beforeEach(function () {
13+
this.onChange = (value: string) => {
14+
this.value = value;
15+
};
16+
});
17+
18+
test('Search Field component is rendered with a placeholder', async function (assert) {
19+
this.placeholder = 'This is a placeholder';
20+
this.value = '';
21+
22+
await render(
23+
hbs`<OSS::SearchField @value={{this.value}} @placeholder={{this.placeholder}} @onChange={{this.onChange}} />`
24+
);
25+
26+
assert.dom('input').hasAttribute('placeholder', 'This is a placeholder');
27+
});
28+
29+
test('Input value is reset when the clear button is clicked', async function (assert) {
30+
this.value = 'Test';
31+
32+
await render(hbs`<OSS::SearchField @value={{this.value}} @onChange={{this.onChange}} />`);
33+
34+
assert.dom('[role="button"]').exists();
35+
36+
await click('[role="button"]');
37+
38+
assert.strictEqual(this.value, '');
39+
});
40+
41+
test('onChange function is triggered on input change', async function (assert) {
42+
this.value = '';
43+
this.onChange = sinon.stub();
44+
45+
await render(hbs`<OSS::SearchField @value={{this.value}} @onChange={{this.onChange}} />`);
46+
await typeIn('input', 'Test', { delay: 0 });
47+
48+
assert.true(this.onChange.lastCall.calledWith('Test'));
49+
});
50+
51+
test('Clear button is not displayed when the input is empty', async function (assert) {
52+
this.value = '';
53+
54+
await render(hbs`<OSS::SearchField @value={{this.value}} @onChange={{this.onChange}} />`);
55+
56+
assert.dom('[role="button"]').doesNotExist();
57+
});
58+
});

translations/en-us.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,5 @@ oss-components:
7272
lock_tooltip: Reveal email
7373
removable_text:
7474
remove_tooltip: Remove
75-
75+
search_field:
76+
placeholder: Search

0 commit comments

Comments
 (0)