Displays a form input field or a component that looks like an input field.
Installation
npx shadcn@latest add @caprice/inputnpm install @caprice-ui/reactInstall the following dependencies:
npm install @base-ui/react lucide-reactAdd a cn helper
import { defineConfig, type VariantProps } from 'cva';import { twMerge } from 'tailwind-merge';export const { compose, cva, cx: cn,} = defineConfig({ hooks: { onComplete: (className: string) => twMerge(className), },});export type { VariantProps };Copy and paste the following code into your project.
'use client';import { mergeProps } from '@base-ui/react';import { Input as InputPrimitive } from '@base-ui/react/input';import type * as React from 'react';import { type PressEvents, useFocusRing, usePress } from 'react-aria';import { cva, type VariantProps } from '@/lib/utils';export const inputVariants = cva({ base: [ 'w-full min-w-0 rounded-md border border-input py-1 shadow-xs outline-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground dark:bg-input/30', // Transition 'transition-[color,background-color,border-color,box-shadow]', // File 'file:inline-flex file:border-0 file:bg-transparent file:font-medium file:text-foreground', // Focus state, using focus instead of focus-visible to avoid confusion with data-focus-visible 'focus:border-ring focus:ring-[3px] focus:ring-ring/50 focus:placeholder:text-current', // Real "focus-visible", only visible when interacting with a keyboard. // ref: https://react-spectrum.adobe.com/react-aria/useFocusRing.html 'data-focus-visible:outline-2 data-focus-visible:outline-primary data-focus-visible:outline-solid data-focus-visible:outline-offset-2 data-focus-visible:ring-transparent dark:data-focus-visible:outline-primary/64', // Disabled state 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50', // Invalid state 'aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-invalid:data-focus-visible:outline-destructive/80 dark:aria-invalid:data-focus-visible:outline-destructive/48', ], variants: { variant: { outline: [ 'bg-transparent', // Hover state 'not-disabled:hover:not-focus-within:bg-input/32 not-disabled:hover:not-focus-within:placeholder:text-current dark:not-disabled:hover:not-focus-within:bg-input/72', // Pressed state 'data-pressed:bg-input/48 dark:data-pressed:bg-input/84', ], }, size: { md: 'h-9 px-3 text-base file:h-7 md:text-sm', lg: 'h-12 px-4 text-base file:h-10', xl: 'h-14 px-4 text-xl file:h-12', }, }, defaultVariants: { size: 'md', variant: 'outline', },});/** * A native input element that automatically works with [Field](https://base-ui.com/react/components/field). * Renders an `<input>` element. * * Documentation: [Caprice UI Input](https://caprice-ui.com/docs/components/input) * * API Reference: [Base UI Input](https://base-ui.com/react/components/input) */export namespace Input { export type State = InputPrimitive.State; export type Variants = { /** * Size * @default 'md' */ size?: VariantProps<typeof inputVariants>['size'] | number; /** * Variant * @default 'outline' */ variant?: VariantProps<typeof inputVariants>['variant']; }; export type Props = Omit<React.ComponentProps<typeof InputPrimitive>, 'size'> & PressEvents & Input.Variants; export type ChangeEventDetails = InputPrimitive.ChangeEventDetails; export type ChangeEventReason = InputPrimitive.ChangeEventReason;}export function Input({ className, size, variant, // PressEvents onPress, onPressStart, onPressChange, onPressEnd, onPressUp, onClick, ...props}: Input.Props) { const { isFocusVisible, focusProps } = useFocusRing({ isTextInput: true }); const { pressProps, isPressed } = usePress({ onPress, onPressStart, onPressChange, onPressEnd, onPressUp, onClick, isDisabled: props.disabled, }); const defaultProps: React.ComponentProps<'input'> & { 'data-slot'?: string } = { 'data-slot': 'input', className: inputVariants({ variant, size: typeof size === 'string' ? size : undefined, className, }), }; const inputProps = mergeProps<'input'>(defaultProps, focusProps, pressProps, props); return ( <InputPrimitive data-focus-visible={isFocusVisible ? '' : undefined} data-pressed={isPressed ? '' : undefined} size={typeof size === 'number' ? size : undefined} {...inputProps} /> );}Update the import paths to match your project setup.
Usage
import { Input } from "@/components/caprice-ui/input"import { Input } from "@caprice-ui/react/input"<Input />Examples
Sizes
File
Disabled
Invalid
With Label
With Button
Variants
Prop
Type