Components
Loading preview...
Here is advanced phone input component
@ui-layouts
npx shadcn@latest add https://21st.dev/r/uilayout.contact/phone-input'use client';
import React, { useState } from 'react';
import { useForm, Controller } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { isValidPhoneNumber } from 'react-phone-number-input';
import { z } from 'zod';
import PhoneInput from '@/components/ui/phone-input';
const FormSchema = z.object({
phone: z
.string()
.min(1, 'Phone number is required')
.refine((value) => value && isValidPhoneNumber(value), {
message: 'Invalid phone number',
}),
});
type FormData = z.infer<typeof FormSchema>;
const PhoneInputDemo = () => {
const {
control,
handleSubmit,
formState: { errors },
reset,
} = useForm<FormData>({
resolver: zodResolver(FormSchema),
defaultValues: { phone: '' },
});
const [submittedData, setSubmittedData] = useState<FormData | null>(null);
const onSubmit = (data: FormData) => {
setSubmittedData(data);
};
const handleReset = () => {
reset();
setSubmittedData(null);
};
return (
<div className='flex flex-col items-center justify-center p-8 min-h-screen bg-gray-50 dark:bg-gray-950 text-gray-900 dark:text-gray-50'>
<div className='w-full max-w-md bg-white dark:bg-gray-800 p-8 rounded-lg shadow-xl space-y-8'>
<h2 className='text-2xl font-semibold text-center'>Basic Usage & Validation</h2>
<form onSubmit={handleSubmit(onSubmit)} className='flex flex-col items-stretch space-y-4'>
<div className='flex flex-col space-y-2'>
<label htmlFor='phone-field' className='text-sm font-medium'>
Phone Number
</label>
<Controller
name='phone'
control={control}
render={({ field }) => (
<PhoneInput
{...field}
id='phone-field'
placeholder='Enter a phone number'
className='border rounded-lg h-10 w-full'
value={field.value || undefined}
onChange={(val) => field.onChange(val || '')}
onBlur={field.onBlur}
/>
)}
/>
{errors.phone && (
<p className='text-red-500 text-sm'>{errors.phone.message}</p>
)}
</div>
<div className="flex gap-4 justify-end">
<button
type='button'
onClick={handleReset}
className='p-2 px-4 bg-gray-200 text-gray-800 dark:bg-gray-700 dark:text-gray-200 rounded-md text-sm font-medium hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors'
>
Reset
</button>
<button
type='submit'
className='p-2 px-4 bg-blue-600 text-white rounded-md text-sm font-medium hover:bg-blue-700 transition-colors'
>
Submit
</button>
</div>
</form>
{submittedData && (
<div className='mt-6 p-4 bg-gray-100 dark:bg-gray-700 rounded-md text-sm'>
<h3 className='font-semibold mb-2'>Submitted Data:</h3>
<pre className='whitespace-pre-wrap break-all text-gray-900 dark:text-gray-100'>
{JSON.stringify(submittedData, null, 2)}
</pre>
</div>
)}
</div>
</div>
);
};
export { PhoneInputDemo as DemoOne };