diff --git a/doc-app/public/assets/icons/search.svg b/doc-app/public/assets/icons/search.svg index 6bf474ec..9afe31b9 100644 --- a/doc-app/public/assets/icons/search.svg +++ b/doc-app/public/assets/icons/search.svg @@ -1,3 +1,3 @@ - + diff --git a/doc-app/tests/integration/components/ember-input/prefabs/tpk-search-test.gts b/doc-app/tests/integration/components/ember-input/prefabs/tpk-search-test.gts new file mode 100644 index 00000000..3f5614c6 --- /dev/null +++ b/doc-app/tests/integration/components/ember-input/prefabs/tpk-search-test.gts @@ -0,0 +1,54 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render, triggerEvent, waitFor } from '@ember/test-helpers'; +import { setupIntl } from 'ember-intl/test-support'; +import TpkSearch from '@triptyk/ember-input/components/prefabs/tpk-search'; +import tpkSearchPage from '../../../../pages/tpk-search'; +import { a11yAudit } from 'ember-a11y-testing/test-support'; + + +module( + 'Integration | Component | Prefabs | tpk-search', + function (hooks) { + setupRenderingTest(hooks); + setupIntl(hooks, 'fr-fr'); + + async function renderComponent(assert: Assert) { + const mockSearch = () => { + return new Promise((res) => { + assert.step('search'); + setTimeout(() => { + res(null); + }, 500); + }); + }; + + await render( + + ); + } + + test('render search icon by default. Switch to loader icon when onSearch is running', async function (assert) { + await renderComponent(assert); + await tpkSearchPage.input('search'); + triggerEvent('form', 'submit') + await waitFor('.tpk-search-loader'); + assert.dom('.tpk-search-loader').exists(); + await waitFor('[data-test-tpk-search-icon]'); + assert.dom('[data-test-tpk-search-icon]').exists(); + assert.verifySteps(['search']); + }); + + test('Accessibility', async function (assert) { + assert.expect(0); + await renderComponent(assert); + await a11yAudit(); + }); + }, +); diff --git a/doc-app/tests/pages/tpk-search.ts b/doc-app/tests/pages/tpk-search.ts new file mode 100644 index 00000000..8057a37b --- /dev/null +++ b/doc-app/tests/pages/tpk-search.ts @@ -0,0 +1,20 @@ +import { + clickable, + create, + fillable, + focusable, + triggerable, +} from 'ember-cli-page-object'; + +export default create({ + scope: '.tpk-search', + input: fillable('.tpk-search-input'), + focus: focusable('.tpk-search-input'), + button: create({ + scope: '.tpk-search-button', + click: clickable(), + enter: triggerable('keydown', undefined, { + eventProperties: { key: 'Enter' }, + }), + }), +}); diff --git a/packages/ember-input/package.json b/packages/ember-input/package.json index 07a405b2..aaf1895f 100644 --- a/packages/ember-input/package.json +++ b/packages/ember-input/package.json @@ -122,6 +122,7 @@ "app-js": { "./components/base.js": "./dist/_app_/components/base.js", "./components/prefabs/tpk-prefab-button.js": "./dist/_app_/components/prefabs/tpk-prefab-button.js", + "./components/prefabs/tpk-search.js": "./dist/_app_/components/prefabs/tpk-search.js", "./components/prefabs/tpk-toggle.js": "./dist/_app_/components/prefabs/tpk-toggle.js", "./components/tpk-button.js": "./dist/_app_/components/tpk-button.js", "./components/tpk-checkbox-input.js": "./dist/_app_/components/tpk-checkbox-input.js", diff --git a/packages/ember-input/src/app.css b/packages/ember-input/src/app.css index c7fd9ff0..f8367536 100644 --- a/packages/ember-input/src/app.css +++ b/packages/ember-input/src/app.css @@ -1,2 +1,3 @@ @import url('./components/prefabs/tpk-toggle.css'); +@import url('./components/prefabs/tpk-search.css'); @import url('./components/prefabs/tpk-prefab-button.css'); diff --git a/packages/ember-input/src/components/prefabs/tpk-search.css b/packages/ember-input/src/components/prefabs/tpk-search.css new file mode 100644 index 00000000..bf16daa5 --- /dev/null +++ b/packages/ember-input/src/components/prefabs/tpk-search.css @@ -0,0 +1,50 @@ +.tpk-search-label { + @apply flex items-center input; +} + +.tpk-search-input { + @apply w-full; +} + +.tpk-search-icon { + @apply p-1; +} + +.loader { + position: relative; + height: 20px; + width: 20px; + top: 0; + left: 0; + display: inline-block; + animation: around 5.4s infinite; +} + +@keyframes around { + 0% { + transform: rotate(0deg) + } + 100% { + transform: rotate(360deg) + } +} + +.loader::after, .loader::before { + content: ""; + background: white; + position: absolute; + display: inline-block; + width: 100%; + height: 100%; + border-width: 2px; + border-color: #333 #333 transparent transparent; + border-style: solid; + border-radius: 20px; + box-sizing: border-box; + animation: around 0.7s ease-in-out infinite; +} + +.loader::after { + animation: around 0.7s ease-in-out 0.1s infinite; + background: transparent; +} diff --git a/packages/ember-input/src/components/prefabs/tpk-search.gts b/packages/ember-input/src/components/prefabs/tpk-search.gts new file mode 100644 index 00000000..d44c5945 --- /dev/null +++ b/packages/ember-input/src/components/prefabs/tpk-search.gts @@ -0,0 +1,67 @@ +import type { MergeDeep } from 'type-fest'; +import type { BaseUIComponentArgs } from '../base'; +import Component from '@glimmer/component'; +import { task } from 'ember-concurrency'; +import { on } from '@ember/modifier'; +import TpkInputComponent from '../tpk-input.gts'; + +export type TpkSearchPrefabSignature = { + Args: MergeDeep< + BaseUIComponentArgs['Args'], + { + placeholder?: string; + label?: string; + onSearch: (value: string, e: Event) => unknown; + } + >; + Blocks: { + default: []; + }; + Element: HTMLDivElement; +}; + +export default class TpkSearchPrefabComponent extends Component { + performSearch = task(this, { drop: true }, async (value: string, e: Event) => { + e.preventDefault(); + return this.args.onSearch(value, e); + }); + + submitSearch = (e: Event) => { + e.preventDefault(); + const value = (e.target as HTMLInputElement).value; + this.performSearch.perform(value, e); + }; + + get labelOrDefault () { + return this.args.label ?? ''; + } + + + + + +} + diff --git a/packages/ember-input/src/components/prefabs/tpk-toggle.css b/packages/ember-input/src/components/prefabs/tpk-toggle.css index c655d0f4..967f9001 100644 --- a/packages/ember-input/src/components/prefabs/tpk-toggle.css +++ b/packages/ember-input/src/components/prefabs/tpk-toggle.css @@ -3,7 +3,7 @@ } .tpk-toggle-label-container { - @apply label cursor-pointer; + @apply cursor-pointer label; } .tpk-toggle-label {