Input
Labelled text input with hint and error states, sized to match Button.
ui
$
npx shadcn@latest add @storekit/inputinput
Live and interactive. Switch the brand in the frame header to see the same source under another token file.
Installation
$
npx shadcn@latest add @storekit/input$
pnpm dlx shadcn@latest add @storekit/input$
yarn dlx shadcn@latest add @storekit/input$
bunx --bun shadcn@latest add @storekit/inputSource
components/storekit/ui/input.tsx
37 lines
import * as React from "react"
import { cn } from "@/components/storekit/lib/cn"
/* Text input with an optional label and hint. 44px tall so it matches Button. */
export const Input = React.forwardRef<
HTMLInputElement,
React.InputHTMLAttributes<HTMLInputElement> & { label?: string; hint?: string; error?: string }
>(function Input({ className, label, hint, error, id, ...props }, ref) {
const autoId = React.useId()
const inputId = id || autoId
const noteId = `${inputId}-note`
return (
<label htmlFor={inputId} className="block">
{label ? <span className="mb-1.5 block text-[13px] font-medium text-sk-ink">{label}</span> : null}
<input
ref={ref}
id={inputId}
aria-invalid={!!error || undefined}
aria-describedby={error || hint ? noteId : undefined}
className={cn(
"h-11 w-full rounded-sk-btn border bg-sk-card px-3.5 text-base text-sk-ink sm:text-sm outline-none transition-[border-color,box-shadow] duration-200 placeholder:text-sk-muted/70",
"focus:border-sk-accent focus:ring-[3px] focus:ring-sk-accent/15",
error ? "border-sk-sale" : "border-sk-line",
className
)}
{...props}
/>
{error ? (
<span id={noteId} role="alert" className="mt-1.5 block text-xs text-sk-sale">{error}</span>
) : hint ? (
<span id={noteId} className="mt-1.5 block text-xs text-sk-muted">{hint}</span>
) : null}
</label>
)
})
Usage
Import from "@/components/storekit/ui/input" and pass your product data. The demo above exercises the full prop surface with sample values.