forked from jordanlambrecht/tracker-tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInput.tsx
More file actions
79 lines (72 loc) · 1.93 KB
/
Copy pathInput.tsx
File metadata and controls
79 lines (72 loc) · 1.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// src/components/ui/Input.tsx
import clsx from "clsx"
import { type InputHTMLAttributes, type Ref, useId } from "react"
type HintVariant = "default" | "danger"
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
label?: string
error?: string
hint?: string
hintVariant?: HintVariant
ref?: Ref<HTMLInputElement>
}
const HINT_COLORS: Record<HintVariant, string> = {
default: "text-muted",
danger: "text-danger/80",
}
function Input({
label,
error,
hint,
hintVariant = "default",
className,
id,
ref,
...props
}: InputProps) {
const generatedId = useId()
const inputId = id ?? generatedId
const hintId = hint ? `${inputId}-hint` : undefined
const describedBy = [error && `${inputId}-error`, hintId].filter(Boolean).join(" ") || undefined
return (
<div className="flex flex-col gap-1 w-full">
{label && (
<label
htmlFor={inputId}
className="text-xs font-sans font-medium text-secondary uppercase tracking-wider"
>
{label}
</label>
)}
<input
ref={ref}
id={inputId}
className={clsx(
"w-full font-mono text-sm text-primary",
"bg-control-bg rounded-nm-md",
"px-4 py-3 placeholder:text-muted",
"transition-all duration-150",
"nm-inset",
"focus:outline-none focus:nm-inset",
"disabled:opacity-40 disabled:cursor-not-allowed",
"border-0",
className
)}
aria-invalid={error ? "true" : undefined}
aria-describedby={describedBy}
{...props}
/>
{error && (
<p id={`${inputId}-error`} className="text-xs font-sans text-danger" role="alert">
{error}
</p>
)}
{hint && (
<p id={hintId} className={clsx("text-xs font-sans", HINT_COLORS[hintVariant])}>
{hint}
</p>
)}
</div>
)
}
export type { InputProps }
export { Input }