Skip to content

Commit

Permalink
refactor: refactor search highlighting
Browse files Browse the repository at this point in the history
  • Loading branch information
adriansberg committed Sep 26, 2023
1 parent 1e87ca3 commit 8f60307
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 39 deletions.
94 changes: 55 additions & 39 deletions src/components/search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import Downshift from 'downshift';
import { useState } from 'react';
import { useAutocomplete } from '@atb/page-modules/departures/client';
import style from './search.module.css';
import { debounce, split } from 'lodash';
import { MonoIcon } from '@atb/assets/mono-icon';
import VenueIcon from '@atb/components/venue-icon';
import { andIf } from '@atb/utils/css';
Expand All @@ -16,17 +15,11 @@ type SearchProps = {
export default function Search({
label,
onChange,
initialQuery = '',
initialQuery = 'No',
}: SearchProps) {
const [query, setQuery] = useState(initialQuery);
const { data } = useAutocomplete(query);

const highlight = (name: string, inputValue: string | null) => {
if (!inputValue) return [name];

return split(name, new RegExp(`(${inputValue})`, 'gi'));
};

return (
<Downshift
initialInputValue={query}
Expand Down Expand Up @@ -66,40 +59,63 @@ export default function Search({
</button>

<ul className={style.menu} {...getMenuProps()}>
{isOpen && data
? data.map((item, index) => (
<li
className={andIf({
[style.item]: true,
[style.itemHighlighted]: highlightedIndex === index,
})}
{...getItemProps({
index,
item,
})}
key={item.id}
>
<div className={style.itemIcon} aria-hidden>
<VenueIcon category={item.category} />
</div>
<span className={style.itemName}>
{highlight(item.name, inputValue).map((part, index) => {
if (!part.length || !inputValue) return;
return part.toLowerCase() ===
inputValue.toLowerCase() ? (
<strong key={index}>{part}</strong>
) : (
<span key={index}>{part}</span>
);
})}
</span>
<span className={style.itemLocality}>{item.locality}</span>
</li>
))
: null}
{isOpen &&
data?.map((item, index) => (
<li
className={andIf({
[style.item]: true,
[style.itemHighlighted]: highlightedIndex === index,
})}
key={item.id}
{...getItemProps({
index,
item,
})}
>
<div className={style.itemIcon} aria-hidden>
<VenueIcon category={item.category} />
</div>
<span className={style.itemName}>
{highlightSearchText(inputValue, item.name).map(
({ part, highlight }) => {
if (highlight)
return <strong key={item.id + part}>{part}</strong>;
else return <span key={item.id + part}>{part}</span>;
},
)}
</span>
<span className={style.itemLocality}>{item.locality}</span>
</li>
))}
</ul>
</div>
)}
</Downshift>
);
}

function highlightSearchText(input: string | null, name: string) {
if (!input) return [{ part: name, highlight: false }];

let startIndex = name.toLowerCase().indexOf(input.toLowerCase());

if (startIndex !== -1) {
let endIndex = startIndex + input.length;
return [
{
part: name.substring(0, startIndex),
highlight: false,
},
{
part: name.substring(startIndex, endIndex),
highlight: true,
},
{
part: name.substring(endIndex),
highlight: false,
},
];
} else {
return [{ part: name, highlight: false }];
}
}
2 changes: 2 additions & 0 deletions src/components/search/search.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
}

.itemIcon {
display: flex;
align-items: center;
padding: var(--spacings-small);
padding-right: var(--spacings-xLarge);
}
Expand Down

0 comments on commit 8f60307

Please sign in to comment.