ui
ui copied to clipboard
feat: added icon support for input fields
This pull request addresses issue #1562 and introduces the feature of icon support for input fields. Users can now include icons within input fields to enhance visual representation or provide context. Icons can be positioned on the left or right of the input field, providing flexibility for various use cases.
Best regards,
Towhid Hasan
@TowhidBD is attempting to deploy a commit to the shadcn-pro Team on Vercel.
A member of the Team first needs to authorize it.
One thing I would change: Instead of an icon property it is better to have a startIcon and endIcon property. Use case would be a "lock icon" and "eye icon" for password fields.
Generalization: Even better is to have input adornments where you can specify start and end as ReactNodes. With adornments you can also add prefix and suffix easily like for example a "minutes" suffix.
I wonder if there is any way to hide icons on smaller screen, i.e. to provide min width (or screen size) beyond which the icon is visible. Smaller screens can get more width for text.
Somebody will fix? :D
I think this "icons" can be something like toggle show password that it's a button, so i think it's better call adornment, and in some cases people would like to use in left and in right position, and following the @kachkaev recomendation i add the border classes to the outer div and some disabled handle too:
import * as React from "react";
import { cn } from "~/lib/utils";
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {
startAdornment?: JSX.Element;
endAdornment?: JSX.Element;
}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, startAdornment, endAdornment, ...props }, ref) => {
const hasAdornment = Boolean(startAdornment) || Boolean(endAdornment);
return (
<>
{hasAdornment ? (
<div
className="flex items-center justify-center gap-2 px-3 h-10 rounded-md border border-input bg-transparent ring-offset-background focus-within:ring-1 focus-within:ring-ring focus-within:ring-offset-2 data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50"
data-disabled={props.disabled}
>
{startAdornment && (
<div className={cn("text-muted-foreground")}>
{startAdornment}
</div>
)}
<input
type={type}
className={cn(
"flex h-full w-full rounded-md bg-transparent py-2 text-sm file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground shadow-none outline-none border-none focus-visible:outline-none focus-visible:border-none focus-visible:shadow-none",
className
)}
ref={ref}
{...props}
/>
{endAdornment && (
<div className={cn("text-muted-foreground")}>{endAdornment}</div>
)}
</div>
) : (
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-input bg-transparent px-4 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
ref={ref}
{...props}
/>
)}
</>
);
}
);
Input.displayName = "Input";
export { Input };
usage:
<FormField
control={methods.control}
name="sequentialCode"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Sequential Code</FormLabel>
<FormControl>
<Input
{...field}
placeholder="Sequential Code"
endAdornment={
<Tooltip>
<TooltipTrigger asChild>
<HelpCircle className="h-4 w-4 cursor-pointer" />
</TooltipTrigger>
<TooltipContent>
<p>
Sequential Code is something cool
</p>
</TooltipContent>
</Tooltip>
}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
@victorcesae - This is fantastic and exactly what I was hoping for. I really hope this is merged, it works excellently. Thank you so much.
Another utility is to add text adornments, doing some simple typechecking so if a string is passed you can style a background, else render the react node.
{prefix && (
<div className={cn('flex justify-center items-center text-muted-foreground pl-3 select-none', typeof prefix === 'string' && 'bg-muted/70 pr-3 border-r border-input')}>{prefix}</div>
)}
Another utility is to add text adornments, doing some simple typechecking so if a string is passed you can style a background, else render the react node.
{prefix && ( <div className={cn('flex justify-center items-center text-muted-foreground pl-3 select-none', typeof prefix === 'string' && 'bg-muted/70 pr-3 border-r border-input')}>{prefix}</div> )}
Perhaps this should be left to the developer to decide? ReactNode should already cover this use case, no?
Just wanted to +1 and bump this, it'd be super useful to have.
wanted +1
Cursor helped me 😂
code in below
<div className="flex">
<div className="flex items-center justify-center px-3 border border-r-0 rounded-l bg-gray-50">
{payment.pay_due_currency}
</div>
<Input className="rounded-l-none" readOnly type="text" value={payment.pay_due_amount} />
</div>
Cursor helped me 😂
code in below
<div className="flex"> <div className="flex items-center justify-center px-3 border border-r-0 rounded-l bg-gray-50"> {payment.pay_due_currency} </div> <Input className="rounded-l-none" readOnly type="text" value={payment.pay_due_amount} /> </div>
Does this do something different to the proposed solution? What's the motivation for sharing? Looks kind of based in your specific implementation.
Hi everyone! 👋
I’m excited to share an extension library I’ve built for shadcn/ui, which includes an InputBase component. The API adheres to Radix UI and shadcn/ui conventions, ensuring it’s both intuitive and easy to integrate into your projects.
You can check it out here: https://ui-x.junwen-k.dev/docs/components/input-base
The library also includes other handy components designed to enhance developer productivity. If you find it helpful, I’d be thrilled if you could leave a star—it really helps others discover the project. I’d love to hear your feedback or suggestions, so feel free to share your thoughts! 😊
Wanted + 1
This is now available as InputGroup. Thanks for your work on this PR @towhidstack. Appreciate it.
Thank you legend 🙏
