Skip to content

Commit

Permalink
fix(autocomplete-js): query is reflected in the detached search `bu…
Browse files Browse the repository at this point in the history
…tton` (#1100)

Co-authored-by: Sarah Dayan <5370675+sarahdayan@users.noreply.github.com>
  • Loading branch information
FabienMotte and sarahdayan committed Mar 2, 2023
1 parent 15d9433 commit a41ccc6
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 21 deletions.
104 changes: 99 additions & 5 deletions packages/autocomplete-js/src/__tests__/detached.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@ describe('detached', () => {

const searchButton = container.querySelector<HTMLButtonElement>(
'.aa-DetachedSearchButton'
);
)!;

// Open detached overlay
searchButton.click();

await waitFor(() => {
const input = document.querySelector<HTMLInputElement>('.aa-Input');
const input = document.querySelector<HTMLInputElement>('.aa-Input')!;

expect(document.querySelector('.aa-DetachedOverlay')).toBeInTheDocument();
expect(document.body).toHaveClass('aa-Detached');
Expand All @@ -81,7 +81,7 @@ describe('detached', () => {

const firstItem = document.querySelector<HTMLLIElement>(
'#autocomplete-0-item-0'
);
)!;

// Select the first item
firstItem.click();
Expand All @@ -106,7 +106,7 @@ describe('detached', () => {

const searchButton = container.querySelector<HTMLButtonElement>(
'.aa-DetachedSearchButton'
);
)!;

// Open detached overlay
searchButton.click();
Expand All @@ -118,7 +118,7 @@ describe('detached', () => {

const cancelButton = document.querySelector<HTMLButtonElement>(
'.aa-DetachedCancelButton'
);
)!;

// Prevent `onTouchStart` event from closing detached overlay
const windowTouchStartListener = jest.fn();
Expand Down Expand Up @@ -372,4 +372,98 @@ describe('detached', () => {
);
});
});

test('preserves `query` in the detached search `button` after closing', async () => {
const container = document.createElement('div');
document.body.appendChild(container);
const onStateChange = jest.fn();
autocomplete({
id: 'autocomplete',
detachedMediaQuery: '',
container,
onStateChange,
});

const searchButton = container.querySelector<HTMLButtonElement>(
'.aa-DetachedSearchButton'
)!;

// Open detached overlay
searchButton.click();

// Type a query in the focused input
await waitFor(() => {
const input = document.querySelector<HTMLInputElement>('.aa-Input')!;

expect(document.querySelector('.aa-DetachedOverlay')).toBeInTheDocument();
expect(document.body).toHaveClass('aa-Detached');
expect(input).toHaveFocus();

fireEvent.input(input, { target: { value: 'a' } });
});

// Wait for the panel to open
await waitFor(() => {
expect(
document.querySelector<HTMLElement>('.aa-Panel')
).toBeInTheDocument();
});

const cancelButton = document.querySelector<HTMLButtonElement>(
'.aa-DetachedCancelButton'
)!;

// Close detached overlay
cancelButton.click();

// The detached overlay should close
await waitFor(() => {
expect(
document.querySelector('.aa-DetachedOverlay')
).not.toBeInTheDocument();
expect(document.body).not.toHaveClass('aa-Detached');
});

// The `query` should still be present
expect(onStateChange).toHaveBeenLastCalledWith(
expect.objectContaining({
state: expect.objectContaining({ query: 'a' }),
})
);

// The detached search `button` should contain the `query`
expect(
container.querySelector('.aa-DetachedSearchButtonQuery')
).toHaveTextContent('a');

// The detached search `button` placeholder should be hidden when `query` exists
expect(
container.querySelector('.aa-DetachedSearchButtonPlaceholder')
).toHaveAttribute('hidden');
});

test('reflects the initial `query` in the detached search `button`', async () => {
const container = document.createElement('div');
document.body.appendChild(container);
autocomplete({
id: 'autocomplete',
detachedMediaQuery: '',
container,
initialState: {
query: 'a',
},
});

await waitFor(() => {
// The detached search `button` should have the initial `query`
expect(
container.querySelector('.aa-DetachedSearchButtonQuery')
).toHaveTextContent('a');

// The detached search `button` placeholder should be hidden when `query` exists
expect(
container.querySelector('.aa-DetachedSearchButtonPlaceholder')
).toHaveAttribute('hidden');
});
});
});
2 changes: 0 additions & 2 deletions packages/autocomplete-js/src/autocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,8 +393,6 @@ export function autocomplete<TItem extends BaseItem>(
props.value.core.environment.document.body.classList.remove(
'aa-Detached'
);
autocomplete.value.setQuery('');
autocomplete.value.refresh();
}
});
}
Expand Down
22 changes: 17 additions & 5 deletions packages/autocomplete-js/src/createAutocompleteDom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ export function createAutocompleteDom<TItem extends BaseItem>({
...panelProps,
});

const detachedSearchButtonQuery = createDomElement('div', {
class: classNames.detachedSearchButtonQuery,
textContent: state.query,
});
const detachedSearchButtonPlaceholder = createDomElement('div', {
class: classNames.detachedSearchButtonPlaceholder,
hidden: Boolean(state.query),
textContent: placeholder,
});

if (__TEST__) {
setProperties(panel, {
'data-testid': 'panel',
Expand All @@ -148,17 +158,17 @@ export function createAutocompleteDom<TItem extends BaseItem>({
class: classNames.detachedSearchButtonIcon,
children: [SearchIcon({ environment })],
});
const detachedSearchButtonPlaceholder = createDomElement('div', {
class: classNames.detachedSearchButtonPlaceholder,
textContent: placeholder,
});
const detachedSearchButton = createDomElement('button', {
type: 'button',
class: classNames.detachedSearchButton,
onClick() {
setIsModalOpen(true);
},
children: [detachedSearchButtonIcon, detachedSearchButtonPlaceholder],
children: [
detachedSearchButtonIcon,
detachedSearchButtonPlaceholder,
detachedSearchButtonQuery,
],
});
const detachedCancelButton = createDomElement('button', {
type: 'button',
Expand Down Expand Up @@ -188,6 +198,8 @@ export function createAutocompleteDom<TItem extends BaseItem>({
return {
detachedContainer,
detachedOverlay,
detachedSearchButtonQuery,
detachedSearchButtonPlaceholder,
inputWrapper,
input,
root,
Expand Down
1 change: 1 addition & 0 deletions packages/autocomplete-js/src/getDefaultOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const defaultClassNames: AutocompleteClassNames = {
detachedSearchButton: 'aa-DetachedSearchButton',
detachedSearchButtonIcon: 'aa-DetachedSearchButtonIcon',
detachedSearchButtonPlaceholder: 'aa-DetachedSearchButtonPlaceholder',
detachedSearchButtonQuery: 'aa-DetachedSearchButtonQuery',
form: 'aa-Form',
input: 'aa-Input',
inputWrapper: 'aa-InputWrapper',
Expand Down
6 changes: 6 additions & 0 deletions packages/autocomplete-js/src/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ export function renderSearchBox<TItem extends BaseItem>({
setProperties(dom.label, { hidden: state.status === 'stalled' });
setProperties(dom.loadingIndicator, { hidden: state.status !== 'stalled' });
setProperties(dom.clearButton, { hidden: !state.query });
setProperties(dom.detachedSearchButtonQuery, {
textContent: state.query,
});
setProperties(dom.detachedSearchButtonPlaceholder, {
hidden: Boolean(state.query),
});
}

export function renderPanel<TItem extends BaseItem>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export type AutocompleteClassNames = {
detachedSearchButton: string;
detachedSearchButtonIcon: string;
detachedSearchButtonPlaceholder: string;
detachedSearchButtonQuery: string;
form: string;
input: string;
inputWrapper: string;
Expand Down
2 changes: 2 additions & 0 deletions packages/autocomplete-js/src/types/AutocompleteDom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ export type AutocompleteDom = {
panel: HTMLDivElement;
detachedContainer: HTMLDivElement;
detachedOverlay: HTMLDivElement;
detachedSearchButtonQuery: HTMLDivElement;
detachedSearchButtonPlaceholder: HTMLDivElement;
};
13 changes: 13 additions & 0 deletions packages/autocomplete-theme-classic/src/theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -930,10 +930,23 @@ body {
color: rgba(var(--aa-primary-color-rgb), 1);
cursor: initial;
display: flex;
flex-shrink: 0;
height: 100%;
justify-content: center;
width: calc(var(--aa-icon-size) + var(--aa-spacing));
}
@at-root .aa-DetachedSearchButtonQuery {
color: rgba(var(--aa-text-color-rgb), 1);
line-height: 1.25em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
@at-root .aa-DetachedSearchButtonPlaceholder {
&[hidden] {
display: none;
}
}
}

// Remove scroll on `body`
Expand Down
13 changes: 4 additions & 9 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7554,15 +7554,10 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"

caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001179, caniuse-lite@^1.0.30001286:
version "1.0.30001303"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001303.tgz#9b168e4f43ccfc372b86f4bc5a551d9b909c95c9"
integrity sha512-/Mqc1oESndUNszJP0kx0UaQU9kEv9nNtJ7Kn8AdA0mNnH8eR1cj0kG+NbNuC1Wq/b21eA8prhKRA3bbkjONegQ==

caniuse-lite@^1.0.30001161, caniuse-lite@^1.0.30001400:
version "1.0.30001439"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz#ab7371faeb4adff4b74dad1718a6fd122e45d9cb"
integrity sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A==
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001161, caniuse-lite@^1.0.30001179, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001400:
version "1.0.30001458"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001458.tgz"
integrity sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w==

capital-case@^1.0.3, capital-case@^1.0.4:
version "1.0.4"
Expand Down

0 comments on commit a41ccc6

Please sign in to comment.