diff --git a/apps/storybook/stories/typeahead.stories.tsx b/apps/storybook/stories/typeahead.stories.tsx index bd0c0a1f..defffbf4 100644 --- a/apps/storybook/stories/typeahead.stories.tsx +++ b/apps/storybook/stories/typeahead.stories.tsx @@ -20,6 +20,9 @@ export default { placeholder: { control: 'text', }, + required: { + control: 'boolean', + }, }, component: Typeahead, parameters: { @@ -80,3 +83,39 @@ Basic.args = { isLabelHidden: false, label: 'Author', }; + +export function Required() { + const people = [ + { id: '1', label: 'Wade Cooper', value: '1' }, + { id: '2', label: 'Arlene Mccoy', value: '2' }, + { id: '3', label: 'Devon Webb', value: '3' }, + { id: '4', label: 'Tom Cook', value: '4' }, + { id: '5', label: 'Tanya Fox', value: '5' }, + { id: '6', label: 'Hellen Schmidt', value: '6' }, + ]; + const [selectedEntry, setSelectedEntry] = useState( + people[0], + ); + const [query, setQuery] = useState(''); + + const filteredPeople = + query === '' + ? people + : people.filter((person) => + person.label + .toLowerCase() + .replace(/\s+/g, '') + .includes(query.toLowerCase().replace(/\s+/g, '')), + ); + + return ( + + ); +} diff --git a/packages/ui/src/Typeahead/Typeahead.tsx b/packages/ui/src/Typeahead/Typeahead.tsx index 0eb4b257..e84d03a3 100644 --- a/packages/ui/src/Typeahead/Typeahead.tsx +++ b/packages/ui/src/Typeahead/Typeahead.tsx @@ -1,4 +1,5 @@ import clsx from 'clsx'; +import type { InputHTMLAttributes } from 'react'; import { Fragment, useState } from 'react'; import { Combobox, Transition } from '@headlessui/react'; import { ChevronDownIcon } from '@heroicons/react/20/solid'; @@ -10,8 +11,18 @@ export type TypeaheadOption = Readonly<{ value: string; }>; +type Attributes = Pick< + InputHTMLAttributes, + | 'disabled' + | 'name' + | 'onBlur' + | 'onFocus' + | 'pattern' + | 'placeholder' + | 'required' +>; + type Props = Readonly<{ - disabled?: boolean; isLabelHidden?: boolean; label: string; noResultsMessage?: string; @@ -22,9 +33,9 @@ type Props = Readonly<{ ) => void; onSelect: (option: TypeaheadOption) => void; options: ReadonlyArray; - placeholder?: string; value?: TypeaheadOption; -}>; +}> & + Readonly; export default function Typeahead({ disabled = false, @@ -34,9 +45,10 @@ export default function Typeahead({ nullable = false, options, onQueryChange, + required, value, onSelect, - placeholder, + ...props }: Props) { const [query, setQuery] = useState(''); return ( @@ -68,6 +80,12 @@ export default function Typeahead({ : 'mb-1 block text-sm font-medium text-slate-700', )}> {label} + {required && ( + + )}
@@ -79,11 +97,12 @@ export default function Typeahead({ displayValue={(option) => (option as unknown as TypeaheadOption)?.label } - placeholder={placeholder} + required={required} onChange={(event) => { setQuery(event.target.value); onQueryChange(event.target.value, event); }} + {...props} />