Component

Input

A single-line field, with optional adornments inside it.

stablev0.2.0 Chromium 103 ui-scale safe

Install

Copies the file into components/ds/, with its registry dependencies and npm packages. See Installation for the one-time setup.
bunx shadcn@3 add @fastrp/input

Examples

Default

Open alone

Bu Discord hesabı zaten bağlı.

API

<Input />
PropTypeDefaultNotes
containerClassNamestring—Styles the wrapper that `start` / `end` add. `className` always reaches the `<input>`, so width and flex sizing belong here when adornments are present.
endReactNode—A suffix, unit or button inside the field, after the text.
startReactNode—An icon or prefix inside the field, before the text.

Dependencies

npm

  • None

Registry

  • @fastrp/utils

Source

components/ds/input.tsxShow
import type * as React from 'react';
import { cn } from '@/lib/utils';

// @fast-ds [email protected]

/** Shared with `Textarea`, so the two fields always match. */
export const fieldClassName =
  'w-full min-w-0 rounded-md border border-foreground/10 bg-ink/60 px-3 text-sm text-foreground shadow-[inset_0_1px_2px_rgb(0_0_0/0.35)] transition-[border-color,box-shadow,background-color] duration-fast placeholder:text-muted-foreground hover:border-foreground/20 focus-visible:border-primary/70 focus-visible:bg-ink/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/25 disabled:cursor-not-allowed disabled:opacity-50 aria-[invalid=true]:border-danger aria-[invalid=true]:focus-visible:ring-danger/30';

export type InputProps = React.ComponentProps<'input'> & {
  /** An icon or prefix inside the field, before the text. */
  start?: React.ReactNode;
  /** A suffix, unit or button inside the field, after the text. */
  end?: React.ReactNode;
  /**
   * Styles the wrapper that `start` / `end` add. `className` always reaches the `<input>`, so width
   * and flex sizing belong here when adornments are present.
   */
  containerClassName?: string;
};

function Input({ className, containerClassName, type = 'text', start, end, ...props }: InputProps) {
  const input = (
    <input
      data-slot="input"
      type={type}
      className={cn(
        fieldClassName,
        'h-10 file:mr-3 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground',
        start && 'pl-10',
        end && 'pr-10',
        className,
      )}
      {...props}
    />
  );

  if (!start && !end) return input;

  return (
    <div className={cn('relative flex w-full items-center', containerClassName)}>
      {start && (
        <span className="pointer-events-none absolute left-3 flex items-center text-muted-foreground [&_svg]:size-4">
          {start}
        </span>
      )}
      {input}
      {end && (
        <span className="absolute right-2 flex items-center text-muted-foreground [&_svg]:size-4">
          {end}
        </span>
      )}
    </div>
  );
}

export { Input };