Skip to content

Commit

Permalink
feature(unlock-app): Implement combobox Component for improved UX (#…
Browse files Browse the repository at this point in the history
…14815)

* utilise combobox in event creation form

* utilise combobox in event addition to collection drawer

* update form

* use updated prop

* update combobox serach behaviour
  • Loading branch information
0xTxbi authored Oct 28, 2024
1 parent f1840f5 commit 6175837
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 73 deletions.
69 changes: 38 additions & 31 deletions packages/ui/lib/components/Form/Combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,20 @@ export function Combobox({
[query, allOptions]
)

// Determine which options to display based on showMoreOptions state
// Determine which options to display based on showMoreOptions state and search query
const displayedOptions = useMemo(() => {
// When searching, show all filtered results
if (query !== '') {
return filteredOptions
}
// When not searching, respect showMoreOptions state
if (showMoreOptions) {
return filteredOptions
}
return filteredOptions.filter((option) =>
options.some((initialOption) => initialOption.value === option.value)
)
}, [filteredOptions, showMoreOptions, options])
}, [filteredOptions, showMoreOptions, options, query])

const handleSelect = (value: Option) => {
setSelected(value)
Expand Down Expand Up @@ -260,36 +265,38 @@ export function Combobox({
{option.label}
</li>
))}
{/* Show "More options" button if there are more options available */}
{!showMoreOptions && moreOptions.length > 0 && (
<li
ref={(el) =>
(optionsRef.current[displayedOptions.length] = el)
}
className={clsx(
'flex cursor-pointer mx-2 rounded-sm items-center justify-center gap-2 py-3 px-3 text-base font-semibold',
'hover:bg-ui-main-50 text-brand-ui-primary',
'border-t border-gray-200',
focusedIndex === displayedOptions.length &&
'bg-ui-main-50'
)}
onClick={handleShowMore}
onKeyDown={(e) => {
if (e.key === 'Enter') {
handleShowMore()
} else {
handleKeyDown(e)
{/* Show "More options" button only when not searching and there are more options available */}
{!showMoreOptions &&
query === '' &&
moreOptions.length > 0 && (
<li
ref={(el) =>
(optionsRef.current[displayedOptions.length] = el)
}
}}
role="option"
tabIndex={
focusedIndex === displayedOptions.length ? 0 : -1
}
>
<MoreIcon className="size-4" />
More options
</li>
)}
className={clsx(
'flex cursor-pointer mx-2 rounded-sm items-center justify-center gap-2 py-3 px-3 text-base font-semibold',
'hover:bg-ui-main-50 text-brand-ui-primary',
'border-t border-gray-200',
focusedIndex === displayedOptions.length &&
'bg-ui-main-50'
)}
onClick={handleShowMore}
onKeyDown={(e) => {
if (e.key === 'Enter') {
handleShowMore()
} else {
handleKeyDown(e)
}
}}
role="option"
tabIndex={
focusedIndex === displayedOptions.length ? 0 : -1
}
>
<MoreIcon className="size-4" />
More options
</li>
)}
</>
) : (
<li className="px-3 py-2 text-base text-gray-500">
Expand Down
79 changes: 46 additions & 33 deletions unlock-app/src/components/content/event/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
ToggleSwitch,
ImageUpload,
Checkbox,
Combobox,
} from '@unlock-protocol/ui'
import { useConfig } from '~/utils/withConfig'
import { NetworkDescription } from '~/components/interface/locks/Create/elements/CreateLockForm'
Expand Down Expand Up @@ -325,40 +326,52 @@ export const Form = ({ onSubmit, compact = false }: FormProps) => {
error={errors.metadata?.description?.message as string}
/>

<Select
onChange={(newValue) => {
setValue('network', Number(newValue))
setValue('lock.currencyContractAddress', null)
setValue(
'currencySymbol',
networks[newValue].nativeCurrency.symbol
)
setCurrencyNetwork(networks[newValue].name)
setKickBackSupported(!!networks[newValue].kickbackAddress)
}}
options={networkOptions}
moreOptions={moreNetworkOptions}
label="Network"
defaultValue={network}
description={
<div className="flex flex-col gap-2">
{details.network && (
<NetworkDescription network={details.network} />
<Controller
name="network"
control={control}
render={({ field: { onChange, value } }) => (
<Combobox
options={networkOptions}
moreOptions={moreNetworkOptions}
initialSelected={networkOptions.find(
(option) => option.value === value
)}
<p>
This is the network on which your ticketing contract
will be deployed.{' '}
<Link
className="underline text-brand-ui-primary "
target="_blank"
href="https://unlock-protocol.com/guides/how-to-choose-a-network-for-your-smart-contract-deployment/"
>
Read our guide
</Link>{' '}
on how to chose the right network.
</p>
</div>
}
onSelect={(option) => {
const newValue = Number(option.value)
onChange(newValue)
setValue('network', newValue)
setValue('lock.currencyContractAddress', null)
setValue(
'currencySymbol',
networks[newValue].nativeCurrency.symbol
)
setCurrencyNetwork(networks[newValue].name)
setKickBackSupported(
!!networks[newValue].kickbackAddress
)
}}
label="Network"
description={
<div className="flex flex-col gap-2">
{details.network && (
<NetworkDescription network={details.network} />
)}
<p>
This is the network on which your ticketing contract
will be deployed.{' '}
<Link
className="underline text-brand-ui-primary "
target="_blank"
href="https://unlock-protocol.com/guides/how-to-choose-a-network-for-your-smart-contract-deployment/"
>
Read our guide
</Link>{' '}
on how to chose the right network.
</p>
</div>
}
/>
)}
/>
<NetworkWarning network={details.network} />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import {
Button,
Combobox,
Disclosure,
Drawer,
Input,
Placeholder,
Select,
} from '@unlock-protocol/ui'
import { useUserEvents } from '~/hooks/useUserEvents'
import { Form as EventCreationForm, NewEventForm } from '../event/Form'
Expand Down Expand Up @@ -348,16 +348,15 @@ export default function AddEventsToCollectionDrawer({
<Placeholder.Card />
</Placeholder.Root>
) : filteredUserEvents && filteredUserEvents.length > 0 ? (
<Select
onChange={(newValue) => {
setEventSlug(newValue?.toString() || '')
setIsEventSelected(newValue !== undefined && newValue !== '')
}}
<Combobox
options={userEventsOptions}
onSelect={(selected) => {
setEventSlug(selected.value.toString())
setIsEventSelected(true)
}}
placeholder="Select an event"
searchPlaceholder="Search events..."
label="Your Existing Events"
defaultValue={
userEventsOptions.length > 0 ? userEventsOptions[0].value : ''
}
description="Select an event from your existing events."
disabled={isSubmitting}
/>
Expand Down

0 comments on commit 6175837

Please sign in to comment.