Text Inputs
Icon-leading email, URL, and phone fields built on shadcn Input—each installs with a shared icon-leading-input module.
Email, URL, and phone fields each ship as their own registry item; inputs-internals provides the shared icon-leading-input shell. For empty read-only values (tables, readouts), use Empty Value Placeholder—it has its own registry item and documentation page.
Email Input
Installation
Registry item email-input — pulls input and inputs-internals from the registry and declares lucide-react. Files land under components/f-ui/email-input/ and components/f-ui/inputs-internals/ (see the registry manifest).
pnpm dlx shadcn@latest add https://ui.isaacfei.com/r/email-input.jsonnpx shadcn@latest add https://ui.isaacfei.com/r/email-input.jsonyarn dlx shadcn@latest add https://ui.isaacfei.com/r/email-input.jsonbun x shadcn@latest add https://ui.isaacfei.com/r/email-input.jsonWith a namespace: npx shadcn@latest add @f-ui/email-input.
Usage
import { EmailInput } from '@/components/f-ui/email-input/email-input';
<EmailInput value={email} onChange={(e) => setEmail(e.target.value)} />Example
Value:—
"use client";
import { useState } from "react";
import { EmailInput } from "@/components/f-ui/email-input/email-input";
import {
EmptyValuePlaceholder,
isEmptyDisplayValue,
} from "@/components/f-ui/empty-value-placeholder";
export function EmailInputDemo() {
const [value, setValue] = useState("");
return (
<div className="max-w-sm space-y-3">
<EmailInput
value={value}
onChange={(e) => setValue(e.target.value)}
aria-label="Email"
/>
<p className="text-muted-foreground flex flex-wrap items-center gap-x-1 gap-y-0.5 text-xs">
<span>Value:</span>
{isEmptyDisplayValue(value) ? (
<EmptyValuePlaceholder />
) : (
<span className="text-foreground font-medium tabular-nums">{value}</span>
)}
</p>
</div>
);
}API Reference
- Thin wrapper around
IconLeadingInput(EmailInputexport) withtype="email"and a default mail icon inleadingSlot. leadingSlot: optional override for the leading icon.- Default
placeholder:email@example.com. - Inherits standard controlled
Inputprops (value,onChange,disabled,className,aria-*, etc.).
URL Input
Installation
Registry item url-input.
pnpm dlx shadcn@latest add https://ui.isaacfei.com/r/url-input.jsonnpx shadcn@latest add https://ui.isaacfei.com/r/url-input.jsonyarn dlx shadcn@latest add https://ui.isaacfei.com/r/url-input.jsonbun x shadcn@latest add https://ui.isaacfei.com/r/url-input.jsonNamespace: npx shadcn@latest add @f-ui/url-input.
Usage
import { UrlInput } from '@/components/f-ui/url-input/url-input';
<UrlInput value={url} onChange={(e) => setUrl(e.target.value)} />Example
Value:—
"use client";
import { useState } from "react";
import { UrlInput } from "@/components/f-ui/url-input/url-input";
import {
EmptyValuePlaceholder,
isEmptyDisplayValue,
} from "@/components/f-ui/empty-value-placeholder";
export function UrlInputDemo() {
const [value, setValue] = useState("");
return (
<div className="max-w-sm space-y-3">
<UrlInput
value={value}
onChange={(e) => setValue(e.target.value)}
aria-label="URL"
/>
<p className="text-muted-foreground flex flex-wrap items-center gap-x-1 gap-y-0.5 text-xs">
<span>Value:</span>
{isEmptyDisplayValue(value) ? (
<EmptyValuePlaceholder />
) : (
<span className="text-foreground max-w-full break-all font-medium">
{value}
</span>
)}
</p>
</div>
);
}API Reference
- Same pattern as EmailInput with
type="url"and a default link icon. - Default
placeholder:https://.
Phone Input
Installation
Registry item phone-input.
pnpm dlx shadcn@latest add https://ui.isaacfei.com/r/phone-input.jsonnpx shadcn@latest add https://ui.isaacfei.com/r/phone-input.jsonyarn dlx shadcn@latest add https://ui.isaacfei.com/r/phone-input.jsonbun x shadcn@latest add https://ui.isaacfei.com/r/phone-input.jsonNamespace: npx shadcn@latest add @f-ui/phone-input.
Usage
import { PhoneInput } from '@/components/f-ui/phone-input/phone-input';
<PhoneInput value={phone} onChange={(e) => setPhone(e.target.value)} />Example
Value:—
"use client";
import { useState } from "react";
import { PhoneInput } from "@/components/f-ui/phone-input/phone-input";
import {
EmptyValuePlaceholder,
isEmptyDisplayValue,
} from "@/components/f-ui/empty-value-placeholder";
export function PhoneInputDemo() {
const [value, setValue] = useState("");
return (
<div className="max-w-sm space-y-3">
<PhoneInput
value={value}
onChange={(e) => setValue(e.target.value)}
aria-label="Phone"
/>
<p className="text-muted-foreground flex flex-wrap items-center gap-x-1 gap-y-0.5 text-xs">
<span>Value:</span>
{isEmptyDisplayValue(value) ? (
<EmptyValuePlaceholder />
) : (
<span className="text-foreground font-medium tabular-nums">{value}</span>
)}
</p>
</div>
);
}API Reference
- Same pattern with
type="tel"and a default phone icon. - Default
placeholder:+1 (555) 000-0000.