BelkacemYerfa / shadcn-extension

An open source component collection , that extends your ui library , built using shadcn component
https://shadcn-extension.vercel.app/
MIT License
460 stars 15 forks source link

Feedback #50

Open lenocin opened 2 months ago

lenocin commented 2 months ago

Since my "key" is a database Id, it wasn't feasable to use the component as is (I certainly did not want to display db ids as the selected items)

So made this change which does the trick for me:

interface Option {
  value: string;
  label: string; 
}
interface MultiSelectorTriggerProps
  extends React.HTMLAttributes<HTMLDivElement> {
  options: Option[];
}
const MultiSelectorTrigger = forwardRef<
  HTMLDivElement,
  MultiSelectorTriggerProps
>(({ className, children, options, ...props }, ref) => {
  const { value, onValueChange, activeIndex } = useMultiSelect();

  const mousePreventDefault = useCallback((e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
  }, []);

  return (
    <div
      ref={ref}
      className={cn(
        'flex flex-wrap gap-1 p-1 py-2 border border-muted rounded-lg bg-background',
        className
      )}
      {...props}
    >
      {value.map((item, index) => (
        <Badge
          key={item}
          className={cn(
            'px-1 rounded-xl flex items-center gap-1',
            activeIndex === index && 'ring-2 ring-muted-foreground '
          )}
          variant={'secondary'}
        >
          <span className="text-xs">
            {options.find((option) => option.value === item)?.label}
          </span>
          <button
            aria-label={`Remove ${item} option`}
            aria-roledescription="button to remove option"
            type="button"
            onMouseDown={mousePreventDefault}
            onClick={() => onValueChange(item)}
          >
            <span className="sr-only">Remove {item} option</span>
            <RemoveIcon className="h-4 w-4 hover:stroke-destructive" />
          </button>
        </Badge>
      ))}
      {children}
    </div>
  );
});
BelkacemYerfa commented 2 months ago

Hi @lenocin .

Thanks for you feedback, if I understand correctly you want a way to support a type of Options[] instead of having the string[].

But I wanted to ask you of why like you want to use it like that , you can totally use the id for db as a key and the value gonna be whatever value you have in the returned array that you have.

jakubjenis commented 2 weeks ago

@BelkacemYerfa I had exactly the same problem. If I want to change both the label inside the dropdown when selecting new elements and label inside the Badge, I need to modify the component like @lenocin suggests.

It does not make much sense to not have the text inside the appear in the Badge after click. Very common use case is binding to { "value":id, "label": name} but the id not appearing anywhere visually, only as a form value. Don't know how to achieve this in your version of the component.

Otherwise, I like it the best from all the shadcn based multiselect components, good job!

BelkacemYerfa commented 2 weeks ago

Hi @jakubjenis

Thanks for your feedback, i understand the current issue that you're facing now. We gonna introduce the fix in the upcoming release.

jakubjenis commented 2 weeks ago

Great stuff!