shadimage
motokoui
uiinputsource: ok · hit

Input

A text field with Motoko surface styles, hover and focus borders.

npx shadcn add "https://www.motokoui.com/r/input.json"
free

No selection tags yet — empty means no evidence, not lack of support.

Dependencies

Bundle weight · light

Registry dependencies

utils

Files1 · source cached 10/9/2026, 7:21:29 AM

registry/motokoui/input.tsx
import * as React from "react"

import { cn } from "@/lib/utils"

export interface InputProps {
  /** Leading icon inside the field (left side). */
  icon?: React.ReactNode
  /** Label rendered above the field. Linked to the input via `htmlFor` / `id`. */
  label?: string
  /** Minimum text length. */
  minLength?: number
  /** Maximum text length. */
  maxLength?: number
  /** Controlled value. */
  value?: string
  /** Placeholder text shown when the field is empty. */
  placeholder?: string
  /** Disables the field and skips hover border styles. */
  disabled?: boolean
  /** Field name for form submission. */
  name?: string
  /** Extra classes for the container. */
  className?: string
  /** Extra classes on the `<input>`. */
  classNameInput?: string
  /** Extra classes on the `<label>`. */
  classNameLabel?: string
  /** Called when the value changes. Required when using controlled `value`. */
  onChange?: React.ChangeEventHandler<HTMLInputElement>
}

const Input = React.forwardRef<HTMLInputElement, InputProps>(
  (
    {
      icon,
      label,
      minLength,
      maxLength,
      value,
      placeholder,
      disabled,
      name,
      className,
      classNameInput,
      classNameLabel,
      onChange,
    },
    ref
  ) => {
    const inputId = React.useId()

    return (
      <div className={cn("flex w-full flex-col gap-2", className)}>
        {label ? (
          <label
            htmlFor={inputId}
            className={cn(
              "text-t-primary text-sm font-semibold tracking-tight",
              classNameLabel
            )}
          >
            {label}
          </label>
        ) : null}
        <div className="relative w-full">
          {icon ? (
            <span
              aria-hidden
              className="text-t-secondary pointer-events-none absolute top-1/2 left-3.5 z-10 flex size-4 -translate-y-1/2 items-center justify-center [&_svg]:size-4 [&_svg]:shrink-0"
            >
              {icon}
            </span>
          ) : null}
          <input
            id={inputId}
            ref={ref}
            data-slot="input"
            type="text"
            name={name}
            value={value}
            placeholder={placeholder}
            disabled={disabled}
            minLength={minLength}
            maxLength={maxLength}
            onChange={onChange}
            className={cn(
              "bg-b-surface2 placeholder:text-t-secondary/50 focus:border-s-highlight enabled:hover:border-s-highlight h-12 w-full rounded-2xl border-2 px-3 transition-colors outline-none disabled:cursor-not-allowed disabled:opacity-50",
              icon && "pl-10",
              classNameInput
            )}
          />
        </div>
      </div>
    )
  }
)

Input.displayName = "Input"

export { Input }

More from motokoui

Browse all components in this library →