ui icon indicating copy to clipboard operation
ui copied to clipboard

Feature Request: Icon Support for Input Fields

Open towhidstack opened this issue 1 year ago • 9 comments

As a user, I would like to have the ability to display icons within input fields to provide visual cues or additional functionality. Icons could be used for indicating input content (e.g., search icon in a search field) or enhancing user experience. This feature enhancement would greatly improve the versatility and usability of the input fields in our application.

towhidstack avatar Sep 20 '23 04:09 towhidstack

Related to https://github.com/shadcn-ui/ui/discussions/1552

ianschmitz avatar Nov 01 '23 20:11 ianschmitz

I wrapped the input inside a div and placed the icon as a sibling to the input, using position relative (to the parent div) and just fine tune the position. This is my workaround this.

<div className="flex items-center py-4">
        <MagnifyingGlassIcon className="relative left-7 top-2 transform -translate-y-1/2"/>
        <Input
          placeholder="Filter categories..."
          value={(table.getColumn("category")?.getFilterValue() as string) ?? ""}
          onChange={(event) =>
            table.getColumn("category")?.setFilterValue(event.target.value)
          }
          className="max-w-sm pl-10"
        />
</div>

Labastidaa avatar Nov 04 '23 20:11 Labastidaa

I wrapped the input inside a div and placed the icon as a sibling to the input, using position relative (to the parent div) and just fine tune the position. This is my workaround this.

<div className="flex items-center py-4">
        <MagnifyingGlassIcon className="relative left-7 top-2 transform -translate-y-1/2"/>
        <Input
          placeholder="Filter categories..."
          value={(table.getColumn("category")?.getFilterValue() as string) ?? ""}
          onChange={(event) =>
            table.getColumn("category")?.setFilterValue(event.target.value)
          }
          className=" pl-10 max-w-sm"
        />
</div>

Thank you so much @Labastidaa For a reason this solution was messing up with my flex parent container. Here's my workaround for people with the same issue as mine

 <div className="relative flex items-center max-w-2xl ">
    <MagnifyingGlassIcon className="absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2 transform" />
      <Input
        placeholder="Your search..."
        value={search}
        onChange={(event) => setSearch(event.target.value)}
        className=" pl-8"
      />
 </div>

jeromevvb avatar Dec 18 '23 13:12 jeromevvb

This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.

shadcn avatar Feb 27 '24 23:02 shadcn

Not complete Mr Bot!

ianschmitz avatar Feb 27 '24 23:02 ianschmitz

I'll add this as an example.

shadcn avatar Feb 29 '24 05:02 shadcn

Please add this feature as soon as possible! This is such a common thing and it's needed most of the time. The hack of wrapping the input component with a div has many problems.

chinmayghule avatar Mar 05 '24 13:03 chinmayghule

I've been using these as alternatives:

<div class="relative w-full">
  <Input class="pl-9" placeholder="Type something..." />
  <Search class="absolute left-0 top-0 m-2.5 h-4 w-4 text-muted-foreground"/>
</div>

<div class="relative w-full">
  <Input class="pr-9" placeholder="Type something..." />
  <Search class="absolute right-0 top-0 m-2.5 h-4 w-4 text-muted-foreground"/>
</div>

image

helderbarboza avatar Mar 08 '24 18:03 helderbarboza

The hack of wrapping the input component with a div has many problems.

@chinmayghule afaik there is no other way of doing this. other ui libraries do exactly the same to put icons inside input fields.

If you inspect these examples, you'll see all icons are using position: absolute

  • https://nextui.org/docs/components/input#password-input
  • https://mantine.dev/core/input/#left-and-right-sections

flixlix avatar Mar 08 '24 18:03 flixlix

Something like that works pretty good for me:

const SelectItem = React.forwardRef<
  React.ElementRef<typeof SelectPrimitive.Item>,
  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> & {
    className?: string;
    icon?: React.ReactNode;
  }
>(({ className, children, ...props }, ref) => (
  <SelectPrimitive.Item
    ref={ref}
    className={cn(
      'p-3 hover:bg-primary-100 focus:bg-primary-50 data-[state=checked]:bg-primary-50 data-[state=checked]:hover:bg-primary-100',
      'relative flex w-full cursor-default select-none items-center pl-8 outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
      className,
    )}
    {...props}
  >
    <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
      <SelectPrimitive.ItemIndicator>
        <Check className="h-4 w-4" />
      </SelectPrimitive.ItemIndicator>
    </span>

    <SelectPrimitive.ItemText>
      {props.icon ? (
        <span className="flex ">
          <span className="h-9 w-9">{props.icon}</span>
          <span className="ml-4">{children}</span>
        </span>
      ) : (
        children
      )}
    </SelectPrimitive.ItemText>
  </SelectPrimitive.Item>
));
SelectItem.displayName = SelectPrimitive.Item.displayName;

rodrigocipriani avatar Mar 27 '24 02:03 rodrigocipriani

I've been using these as alternatives:

<div class="relative w-full">
  <Input class="pl-9" placeholder="Type something..." />
  <Search class="absolute left-0 top-0 m-2.5 h-4 w-4 text-muted-foreground"/>
</div>

<div class="relative w-full">
  <Input class="pr-9" placeholder="Type something..." />
  <Search class="absolute right-0 top-0 m-2.5 h-4 w-4 text-muted-foreground"/>
</div>

image

thanks bro.

RinNguyens avatar May 20 '24 08:05 RinNguyens

Hack with position:absolute this is a bad way for number type input, as example

position-absolute-bug

Dmitry-Titov-K avatar May 24 '24 06:05 Dmitry-Titov-K

Hack with position:absolute this is a bad way for number type input, as example

position-absolute-bug

You can easily fix this by adding a right-padding to the input.

I would be interested in knowing how you would implement it if not with position absolute

flixlix avatar May 24 '24 06:05 flixlix

Hack with position:absolute this is a bad way for number type input, as example position-absolute-bug

You can easily fix this by adding a right-padding to the input.

I would be interested in knowing how you would implement it if not with position absolute

For example, like in Next UI, which you mentioned earlier https://nextui.org/docs/components/input#start--end-content

Dmitry-Titov-K avatar May 24 '24 07:05 Dmitry-Titov-K

image

I see they are using a surrounding div to "simulate" the input background. For me personally, this would require too many changes in the input component, i.e. changing the background of the div and handling focus & hover states etc. to be feasible.

I don't see why using the position absolute variant wouldn't be enough; It just keeps things simpler.

Again, this is just personal preference, feel free to implement it like NextUI did

flixlix avatar May 24 '24 07:05 flixlix

image I see they are using a surrounding div to "simulate" the input background. For me personally, this would require too many changes in the input component, i.e. changing the background of the div and handling focus & hover states etc. to be feasible.

I don't see why using the position absolute variant wouldn't be enough; It just keeps things simpler.

Again, this is just personal preference, feel free to implement it like NextUI did

Thank you for your time yes, the essence of my message was that position:absolute in my opinion, is not an ideal solution, rather for some cases

Dmitry-Titov-K avatar May 24 '24 08:05 Dmitry-Titov-K

This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.

shadcn avatar Jun 16 '24 23:06 shadcn

I was having a problem with adding a icon inside a shadcn form input, so here it is

type Props = {
  control: any;
  label?: string;
  hint?: string;
  placeholder?: string;
  name: string;
  type?: string;
  secureTextEntry?: boolean;
  rightIcon?: any;
};

const FormInput = ({
  control,
  label,
  hint,
  placeholder,
  name,
  type = "text",
  secureTextEntry,
  rightIcon,
}: Props) => {
  const secureEntry = useBoolean(true);
  const IconComponent = rightIcon;
  const iconClassName =
    "w-5 absolute right-0 top-0 m-2.5 h-4 w-4 text-muted-foreground user-select-none cursor-pointer";
  return (
    <FormField
      control={control}
      name={name}
      render={({ field }) => (
        <FormItem>
          <FormLabel>{label}</FormLabel>
          <div className="relative w-full">
            <FormControl>
              <Input
                className="pr-9"
                type={secureTextEntry && secureEntry.value ? "password" : type}
                placeholder={placeholder}
                {...field}
              />
            </FormControl>
            {secureTextEntry &&
              (secureEntry.value ? (
                <Eye onClick={secureEntry.toggle} className={iconClassName} />
              ) : (
                <EyeOff
                  onClick={secureEntry.toggle}
                  className={iconClassName}
                />
              ))}
            {!secureTextEntry && rightIcon && (
              <IconComponent className={iconClassName} />
            )}
          </div>
          <FormDescription>{hint}</FormDescription>
          <FormMessage />
        </FormItem>
      )}
    />
  );
};

Shaxadhere avatar Jul 26 '24 08:07 Shaxadhere

So is there an official example for this? 😇

MartinCura avatar Aug 03 '24 12:08 MartinCura