SPB Git

Repository Public

input.tsx 1.8 KB 32 lines tsx

1'use client';2import * as React from 'react';3import { cn } from '@/lib/cn';45const base =6  'w-full rounded-sm border border-line-2 bg-surface px-3 text-[13px] text-text placeholder:text-muted transition-colors duration-150 hover:border-line-3 focus:border-accent focus:outline-none focus:ring-[3px] focus:ring-accent/15 focus-visible:outline-none disabled:opacity-50 aria-[invalid=true]:border-error';78export const Input = React.forwardRef<HTMLInputElement, React.InputHTMLAttributes<HTMLInputElement>>(function Input({ className, ...props }, ref) {9  return <input ref={ref} className={cn(base, 'h-8 pointer-coarse:h-12 pointer-coarse:rounded-[14px]', className)} {...props} />;10});11export const Textarea = React.forwardRef<HTMLTextAreaElement, React.TextareaHTMLAttributes<HTMLTextAreaElement>>(function Textarea({ className, ...props }, ref) {12  return <textarea ref={ref} className={cn(base, 'min-h-20 py-2', className)} {...props} />;13});1415export function Field({ label, hint, error, children, className }: { label: string; hint?: React.ReactNode; error?: string | null; children: React.ReactElement<{ id?: string; 'aria-invalid'?: boolean; 'aria-describedby'?: string }>; className?: string }) {16  const id = React.useId();17  const descId = `${id}-d`;18  return (19    <div className={cn('flex flex-col gap-1.5', className)}>20      <label htmlFor={id} className="text-xs font-medium text-text-2">21        {label}22      </label>23      {React.cloneElement(children, { id, 'aria-invalid': error ? true : undefined, 'aria-describedby': hint || error ? descId : undefined })}24      {(error || hint) && (25        <p id={descId} className={cn('text-xs', error ? 'text-error' : 'text-muted')} role={error ? 'alert' : undefined}>26          {error || hint}27        </p>28      )}29    </div>30  );31}32
Files main
Menu

Theme