krishna_sales/src/components/reusable/Input.tsx
Bhanu Prakash Sai Potteri d5e4ebee5d Build app-434 field-sales console
API layer for sandbox app 434 (three workflows: Order Booking, Store,
Daily Reports) — ZinoClient, per-workflow client singletons, config ids,
types, and the source API docs.

Component library (Tailwind v4 + design tokens): buttons, reusable
(Card/Badge/Input/Select/Pagination/Modal/Spinner/EmptyState), generic +
wired record views (rv) and detail views (dv).

Screens + routing (react-router v7): login gate, auth-guarded console
shell with tab nav, and deep-linkable record/detail routes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 15:16:34 +05:30

61 lines
1.9 KiB
TypeScript

import type { InputHTMLAttributes, ReactNode } from 'react';
import { cn } from '../../lib/cn';
export interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'prefix'> {
label?: string;
hint?: string;
error?: string;
/** Leading adornment, e.g. "₹". */
prefix?: ReactNode;
/** Trailing adornment, e.g. "/ year". */
suffix?: ReactNode;
/** Class for the outer label wrapper. */
className?: string;
}
/** Labeled text/number input with optional prefix, suffix, hint and error. */
export function Input({
label,
hint,
error,
prefix,
suffix,
required,
className,
disabled,
...rest
}: InputProps) {
return (
<label className={cn('flex flex-col gap-1.5 font-sans', disabled && 'cursor-not-allowed', className)}>
{label && (
<span className="text-sm font-medium text-muted">
{label}
{required && <span className="text-ruby-600"> *</span>}
</span>
)}
<div
className={cn(
'flex items-center gap-2 rounded-md px-3 h-[42px] border transition-[border-color,box-shadow] duration-150',
disabled ? 'bg-sunk border-border-subtle' : 'bg-card',
error ? 'border-ruby-600' : !disabled && 'border-border-default focus-ring',
)}
>
{prefix && <span className="text-base font-semibold text-faint">{prefix}</span>}
<input
required={required}
disabled={disabled}
className={cn(
'flex-1 w-full border-none outline-none bg-transparent font-sans text-base',
disabled ? 'text-muted cursor-not-allowed' : 'text-strong',
)}
{...rest}
/>
{suffix && <span className="text-faint text-sm">{suffix}</span>}
</div>
{(hint || error) && (
<span className={cn('text-xs', error ? 'text-ruby-600' : 'text-faint')}>{error || hint}</span>
)}
</label>
);
}