Skip to content

Commit

Permalink
Clean up SelectList a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
jessepinho committed Apr 3, 2024
1 parent a0378fe commit 82b4c69
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const SetRpcEndpoint = () => {
<SelectList.Option
key={rpcEndpoint.url}
label={rpcEndpoint.name}
secondaryText={rpcEndpoint.url}
secondary={rpcEndpoint.url}
onSelect={setGrpcEndpoint}
value={rpcEndpoint.url}
isSelected={rpcEndpoint.url === grpcEndpoint}
Expand All @@ -53,7 +53,7 @@ export const SetRpcEndpoint = () => {

<SelectList.Option
label='Custom RPC'
secondaryText={
secondary={
<input
type='url'
ref={customRpcEndpointInput}
Expand All @@ -67,7 +67,6 @@ export const SetRpcEndpoint = () => {
customRpcEndpointInput.current?.focus();
}}
isSelected={isCustomRpcEndpoint}
value={''}
image={<Network />}
/>
</SelectList>
Expand Down
8 changes: 4 additions & 4 deletions packages/ui/components/ui/select-list.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ export const Basic: Story = {
const onChange = (value: unknown) => updateArgs({ value });

const options = [
{ value: 'one', label: 'One', secondaryText: 'AKA, 1' },
{ value: 'two', label: 'Two', secondaryText: 'AKA, 2' },
{ value: 'three', label: 'Three', secondaryText: 'AKA, 3' },
{ value: 'one', label: 'One', secondary: 'AKA, 1' },
{ value: 'two', label: 'Two', secondary: 'AKA, 2' },
{ value: 'three', label: 'Three', secondary: 'AKA, 3' },
];

return (
Expand All @@ -32,7 +32,7 @@ export const Basic: Story = {
key={option.value}
value={option.value}
label={option.label}
secondaryText={option.secondaryText}
secondary={option.secondary}
isSelected={!args.value ? option.value === 'one' : args.value === option.value}
onSelect={onChange}
/>
Expand Down
45 changes: 31 additions & 14 deletions packages/ui/components/ui/select-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,52 @@ export const SelectList = ({ children }: { children: ReactNode }) => (
<div className='flex flex-col gap-2'>{children}</div>
);

const Option = <T,>({
label,
secondaryText,
value,
onSelect,
isSelected,
image,
}: {
interface BaseOptionProps {
label: string;
secondaryText?: ReactNode;
secondary?: ReactNode;
isSelected?: boolean;
image?: ReactNode;
}

interface OptionPropsWithValue<T> extends BaseOptionProps {
value: T;
onSelect: (value: T) => void;
isSelected: boolean;
image?: ReactNode;
}) => (
}

interface OptionPropsWithoutValue extends BaseOptionProps {
onSelect?: () => void;
}

type OptionProps<T = never> = OptionPropsWithValue<T> | OptionPropsWithoutValue;

/**
* `SelectList.Option` can be used to render either a selectable option in a
* `SelectList`, or a bit of UI (via the `secondary` prop) for e.g., adding a
* custom item to a list.
*
* In the latter case, leave `value` undefined. `onSelect` is also optional, but
* you can define it if it's useful for, e.g., focusing on a text field on
* click.
*/
const Option = <T,>({ label, secondary, isSelected, image, ...rest }: OptionProps<T>) => (
<div
className={cn(
'flex items-center cursor-pointer gap-2 rounded-[6px] border-[1px] border-DEFAULT border-solid border-border bg-charcoal p-4 transition-colors',
isSelected && 'border-teal',
)}
role='button'
onClick={() => onSelect(value)}
aria-selected={isSelected}
onClick={() => {
if ('value' in rest && 'onSelect' in rest) rest.onSelect(rest.value);
else if (rest.onSelect) rest.onSelect();
}}
>
<div className='flex size-10 shrink-0 items-center justify-center'>{image}</div>

<div className='flex grow flex-col gap-1'>
<div>{label}</div>

{!!secondaryText && <span className='text-xs text-muted-foreground'>{secondaryText}</span>}
{!!secondary && <span className='text-xs text-muted-foreground'>{secondary}</span>}
</div>
</div>
);
Expand Down

0 comments on commit 82b4c69

Please sign in to comment.