input.tsx 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import { Input as TaroInput, InputProps as TaroInputProps } from '@tarojs/components'
  2. import { cn } from '@/utils/cn'
  3. import { cva, type VariantProps } from 'class-variance-authority'
  4. import { forwardRef } from 'react'
  5. const inputVariants = cva(
  6. 'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base 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',
  7. {
  8. variants: {
  9. variant: {
  10. default: 'border-gray-300 focus:border-blue-500 focus:ring-blue-500',
  11. outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
  12. filled: 'border-none bg-gray-50 hover:bg-gray-100',
  13. },
  14. size: {
  15. default: 'h-10 px-3 py-2',
  16. sm: 'h-9 px-2 text-sm',
  17. lg: 'h-11 px-4 text-lg',
  18. icon: 'h-10 w-10',
  19. },
  20. },
  21. defaultVariants: {
  22. variant: 'default',
  23. size: 'default',
  24. },
  25. }
  26. )
  27. export interface InputProps extends Omit<TaroInputProps, 'className'>, VariantProps<typeof inputVariants> {
  28. className?: string
  29. leftIcon?: string
  30. rightIcon?: string
  31. error?: boolean
  32. errorMessage?: string
  33. }
  34. const Input = forwardRef<HTMLInputElement, InputProps>(
  35. ({ className, variant, size, leftIcon, rightIcon, error, errorMessage, ...props }, ref) => {
  36. return (
  37. <div className="w-full">
  38. <div className="relative">
  39. {leftIcon && (
  40. <div className="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none">
  41. <div className={cn('w-5 h-5 text-gray-400', leftIcon)} />
  42. </div>
  43. )}
  44. <TaroInput
  45. ref={ref}
  46. className={cn(
  47. inputVariants({ variant, size, className }),
  48. error && 'border-red-500 focus:border-red-500 focus:ring-red-500',
  49. leftIcon && 'pl-10',
  50. rightIcon && 'pr-10',
  51. )}
  52. {...props}
  53. />
  54. {rightIcon && (
  55. <div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none">
  56. <div className={cn('w-5 h-5 text-gray-400', rightIcon)} />
  57. </div>
  58. )}
  59. </div>
  60. {error && errorMessage && (
  61. <p className="mt-1 text-sm text-red-600">{errorMessage}</p>
  62. )}
  63. </div>
  64. )
  65. }
  66. )
  67. Input.displayName = 'Input'
  68. export { Input, inputVariants }