title | description | navigation | github | prev | next | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Tailwind CSS Input Number for React - Material Tailwind |
Discover Tailwind CSS and React input number examples that allow users to enter and adjust numeric values easily. They come in different styles and colors, allowing you to easily adapt them to your needs. |
|
input-number |
icon-button |
form |
The input number component allows users to enter and adjust numeric values easily, and it is usually found in forms and applications.
Compared to a basic input, it restricts entries to numbers only, often includes increment/decrement buttons, and can enforce minimum and maximum limits to ensure valid data entry.
This component improves user experience, ensures data consistency, and supports accessibility. See our Tailwind CSS input number examples below. They come in different styles and colors, allowing you to easily adapt them to your needs.
## Basic Input Number with Select
Use this example of a basic number input to allow users to choose a number with select.
<CodePreview component={<InputNumberExamples.InputNumberWithSelect />}>
import { Select, Option, Typography } from "@material-tailwind/react";
export function InputNumberWithSelect() {
return (
<div className="w-72">
<Select label="Number Input" defaultValue="1">
<Option value="1">1</Option>
<Option value="2">2</Option>
<Option value="3">3</Option>
<Option value="3">4</Option>
</Select>
</div>
);
}
## Input Zip Code
This example features a zip code input field where users can enter their postal code. The helper text below the input field explains the purpose of the zip code, ensuring accurate data entry.
<CodePreview component={<InputNumberExamples.InputZipCode />}>
import { Input, Typography } from "@material-tailwind/react";
export function InputZipCode() {
return (
<div className="w-96">
<Input
type="number"
inputMode="numeric"
label="Enter Zip Code"
className="appearance-none [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
/>
<Typography
variant="small"
color="gray"
className="mt-2 flex items-center gap-1 font-normal"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="-mt-px h-4 w-4"
>
<path
fillRule="evenodd"
d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm8.706-1.442c1.146-.573 2.437.463 2.126 1.706l-.709 2.836.042-.02a.75.75 0 01.67 1.34l-.04.022c-1.147.573-2.438-.463-2.127-1.706l.71-2.836-.042.02a.75.75 0 11-.671-1.34l.041-.022zM12 9a.75.75 0 100-1.5.75.75 0 000 1.5z"
clipRule="evenodd"
/>
</svg>
Your text helps us to provide location-specific services.
</Typography>
</div>
);
}
## Input Phone Number
Use this example of a phone number input with a country code selector. Users can choose their country from a dropdown menu, which automatically updates the country code.
<CodePreview component={<InputNumberExamples.InputPhoneNumber />}>
import React from "react";
import {
Input,
Menu,
MenuHandler,
MenuList,
MenuItem,
Button,
Typography,
} from "@material-tailwind/react";
const COUNTRIES = ["France (+33)", "Germany (+49)", "Spain (+34)", "USA (+1)"];
const CODES = ["+33", "+49", "+34", "+1"];
export function InputPhoneNumber() {
const [country, setCountry] = React.useState(0);
return (
<div className="w-full max-w-[24rem]">
<Typography
variant="small"
color="blue-gray"
className="mb-1 font-medium"
>
Enter Phone Number
</Typography>
<div className="relative flex w-full">
<Menu placement="bottom-start">
<MenuHandler>
<Button
ripple={false}
variant="text"
color="blue-gray"
className="h-10 w-14 shrink-0 rounded-r-none border border-r-0 border-blue-gray-200 bg-transparent px-3"
>
{CODES[country]}
</Button>
</MenuHandler>
<MenuList className="max-h-[20rem] max-w-[18rem]">
{COUNTRIES.map((country, index) => {
return (
<MenuItem
key={country}
value={country}
onClick={() => setCountry(index)}
>
{country}
</MenuItem>
);
})}
</MenuList>
</Menu>
<Input
type="tel"
pattern="[0-9]*"
inputMode="numeric"
maxLength={12}
placeholder="324-456-2323"
className="rounded-l-none !border-t-blue-gray-200 placeholder:text-blue-gray-300 placeholder:opacity-100 focus:!border-t-gray-900 appearance-none [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
labelProps={{
className: "before:content-none after:content-none",
}}
containerProps={{
className: "min-w-0",
}}
/>
</div>
</div>
);
}
## Input with Amount Control Buttons
This example showcases an input field with "+" and "-" buttons for adjusting the amount. Users can easily increase or decrease the number by clicking the buttons, providing a straightforward way to control quantities.
<CodePreview component={<InputNumberExamples.InputAmountButtons />}>
import React from "react";
import { Input, IconButton, Typography } from "@material-tailwind/react";
export function InputAmountButtons() {
const [value, setValue] = React.useState(0);
return (
<div className="w-80">
<Typography
variant="small"
color="blue-gray"
className="mb-1 font-medium"
>
Select Amount
</Typography>
<div className="relative w-full">
<Input
type="number"
value={value}
onChange={(e) => setValue(Number(e.target.value))}
className="!border-t-blue-gray-200 placeholder:text-blue-gray-300 placeholder:opacity-100 focus:!border-t-gray-900 appearance-none [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
labelProps={{
className: "before:content-none after:content-none",
}}
containerProps={{
className: "min-w-0",
}}
/>
<div className="absolute right-1 top-1 flex gap-0.5">
<IconButton
size="sm"
className="rounded"
onClick={() => setValue((cur) => (cur === 0 ? 0 : cur - 1))}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
className="h-4 w-4"
>
<path d="M3.75 7.25a.75.75 0 0 0 0 1.5h8.5a.75.75 0 0 0 0-1.5h-8.5Z" />
</svg>
</IconButton>
<IconButton
size="sm"
className="rounded"
onClick={() => setValue((cur) => cur + 1)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
className="h-4 w-4"
>
<path d="M8.75 3.75a.75.75 0 0 0-1.5 0v3.5h-3.5a.75.75 0 0 0 0 1.5h3.5v3.5a.75.75 0 0 0 1.5 0v-3.5h3.5a.75.75 0 0 0 0-1.5h-3.5v-3.5Z" />
</svg>
</IconButton>
</div>
</div>
<Typography variant="small" color="gray" className="mt-2 font-normal">
Adjust the number using the + and - controls.
</Typography>
</div>
);
}
## Input with Control Buttons and Icon
Use this example of an input field with control buttons that include icons. The "+" and "-" buttons are accompanied by relevant icons, such as a group icon for adding or removing members, making the controls more intuitive.
<CodePreview component={<InputNumberExamples.InputControlWithIcon />}>
import React from "react";
import { Input, IconButton, Typography } from "@material-tailwind/react";
export function InputControlWithIcon() {
const [value, setValue] = React.useState(0);
return (
<div className="w-80">
<Typography
variant="small"
color="blue-gray"
className="mb-1 font-medium"
>
Select Amount
</Typography>
<div className="relative w-full">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="absolute left-2.5 top-2.5 h-5 w-5 text-slate-600"
>
<path d="M4.5 6.375a4.125 4.125 0 1 1 8.25 0 4.125 4.125 0 0 1-8.25 0ZM14.25 8.625a3.375 3.375 0 1 1 6.75 0 3.375 3.375 0 0 1-6.75 0ZM1.5 19.125a7.125 7.125 0 0 1 14.25 0v.003l-.001.119a.75.75 0 0 1-.363.63 13.067 13.067 0 0 1-6.761 1.873c-2.472 0-4.786-.684-6.76-1.873a.75.75 0 0 1-.364-.63l-.001-.122ZM17.25 19.128l-.001.144a2.25 2.25 0 0 1-.233.96 10.088 10.088 0 0 0 5.06-1.01.75.75 0 0 0 .42-.643 4.875 4.875 0 0 0-6.957-4.611 8.586 8.586 0 0 1 1.71 5.157v.003Z"></path>
</svg>
<Input
type="number"
value={value}
onChange={(e) => setValue(Number(e.target.value))}
className="!border-t-blue-gray-200 pl-10 placeholder:text-blue-gray-300 placeholder:opacity-100 focus:!border-t-gray-900 appearance-none [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
labelProps={{
className: "before:content-none after:content-none",
}}
containerProps={{
className: "min-w-0",
}}
/>
<div className="absolute right-1 top-1 flex gap-0.5">
<IconButton
size="sm"
className="rounded"
onClick={() => setValue((cur) => (cur === 0 ? 0 : cur - 1))}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
className="h-4 w-4"
>
<path d="M3.75 7.25a.75.75 0 0 0 0 1.5h8.5a.75.75 0 0 0 0-1.5h-8.5Z" />
</svg>
</IconButton>
<IconButton
size="sm"
className="rounded"
onClick={() => setValue((cur) => cur + 1)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
className="h-4 w-4"
>
<path d="M8.75 3.75a.75.75 0 0 0-1.5 0v3.5h-3.5a.75.75 0 0 0 0 1.5h3.5v3.5a.75.75 0 0 0 1.5 0v-3.5h3.5a.75.75 0 0 0 0-1.5h-3.5v-3.5Z" />
</svg>
</IconButton>
</div>
</div>
<Typography variant="small" color="gray" className="mt-2 font-normal">
Adjust the number using the + and - controls.
</Typography>
</div>
);
}
## Input with Plain Control Buttons
This example features a counter input with "+" and "-" buttons for adjusting the number of items. Users can quickly modify the quantity by clicking the buttons, making it ideal for ecommerce or inventory management applications.
<CodePreview component={<InputNumberExamples.InputCounterPlainButtons />}>
import React from "react";
import { Input, IconButton, Typography } from "@material-tailwind/react";
export function InputCounterPlainButtons() {
const [value, setValue] = React.useState(0);
return (
<div className="w-80">
<Typography
variant="small"
color="blue-gray"
className="mb-1 font-medium"
>
Select Amount
</Typography>
<div className="relative w-full">
<Input
type="number"
value={value}
onChange={(e) => setValue(Number(e.target.value))}
className="!border-t-blue-gray-200 placeholder:text-blue-gray-300 placeholder:opacity-100 focus:!border-t-gray-900 appearance-none [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
labelProps={{
className: "before:content-none after:content-none",
}}
containerProps={{
className: "min-w-0",
}}
/>
<div className="absolute right-1 top-1 flex gap-0.5">
<IconButton
size="sm"
variant="text"
className="rounded"
onClick={() => setValue((cur) => (cur === 0 ? 0 : cur - 1))}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
className="h-4 w-4"
>
<path d="M3.75 7.25a.75.75 0 0 0 0 1.5h8.5a.75.75 0 0 0 0-1.5h-8.5Z" />
</svg>
</IconButton>
<IconButton
size="sm"
variant="text"
className="rounded"
onClick={() => setValue((cur) => cur + 1)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
className="h-4 w-4"
>
<path d="M8.75 3.75a.75.75 0 0 0-1.5 0v3.5h-3.5a.75.75 0 0 0 0 1.5h3.5v3.5a.75.75 0 0 0 1.5 0v-3.5h3.5a.75.75 0 0 0 0-1.5h-3.5v-3.5Z" />
</svg>
</IconButton>
</div>
</div>
<Typography variant="small" color="gray" className="mt-2 font-normal">
Adjust the number using the + and - controls.
</Typography>
</div>
);
}
## Input with Currency
Use this example of a currency input to allow users to enter an amount of money along with selecting the currency type. The input field includes a dropdown menu for selecting currencies like USD, EUR, and CHF, ensuring clarity and preventing errors in financial transactions.
<CodePreview component={<InputNumberExamples.InputCurrency />}>
import React from "react";
import { Input, IconButton, Typography } from "@material-tailwind/react";
export function InputCounterPlainButtons() {
const [value, setValue] = React.useState(0);
return (
<div className="w-80">
<Typography
variant="small"
color="blue-gray"
className="mb-1 font-medium"
>
Select Amount
</Typography>
<div className="relative w-full">
<Input
type="number"
value={value}
onChange={(e) => setValue(Number(e.target.value))}
className="!border-t-blue-gray-200 placeholder:text-blue-gray-300 placeholder:opacity-100 focus:!border-t-gray-900 appearance-none [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
labelProps={{
className: "before:content-none after:content-none",
}}
containerProps={{
className: "min-w-0",
}}
/>
<div className="absolute right-1 top-1 flex gap-0.5">
<IconButton
size="sm"
variant="text"
className="rounded"
onClick={() => setValue((cur) => (cur === 0 ? 0 : cur - 1))}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
className="h-4 w-4"
>
<path d="M3.75 7.25a.75.75 0 0 0 0 1.5h8.5a.75.75 0 0 0 0-1.5h-8.5Z" />
</svg>
</IconButton>
<IconButton
size="sm"
variant="text"
className="rounded"
onClick={() => setValue((cur) => cur + 1)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
className="h-4 w-4"
>
<path d="M8.75 3.75a.75.75 0 0 0-1.5 0v3.5h-3.5a.75.75 0 0 0 0 1.5h3.5v3.5a.75.75 0 0 0 1.5 0v-3.5h3.5a.75.75 0 0 0 0-1.5h-3.5v-3.5Z" />
</svg>
</IconButton>
</div>
</div>
<Typography variant="small" color="gray" className="mt-2 font-normal">
Adjust the number using the + and - controls.
</Typography>
</div>
);
}
## Input Credit Card
This Tailwind component example features input fields for entering credit card information, including cardholder name, card number, expiration date, and CVV. The "Purchase Now" button is prominently displayed, providing a clear call-to-action for completing transactions.
<CodePreview component={<InputNumberExamples.InputCreditCard />}>
import React from "react";
import { Input, Typography, Button } from "@material-tailwind/react";
export function InputCreditCard() {
const [cvv, setCvv] = React.useState("");
const [cardNumber, setCardNumber] = React.useState("");
const [expirationDate, setExpirationDate] = React.useState("");
const [cardholderName, setCardholderName] = React.useState("");
return (
<div className="w-full max-w-sm">
<Typography
variant="small"
color="blue-gray"
className="mb-1 block font-medium"
>
Cardholder Name
</Typography>
<Input
placeholder="e.g John Doe"
className="appearance-none !border-t-blue-gray-200 placeholder:text-blue-gray-300 placeholder:opacity-100 focus:!border-t-gray-900 [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
labelProps={{
className: "before:content-none after:content-none",
}}
containerProps={{
className: "min-w-0",
}}
value={cardholderName}
onChange={(e) => setCardholderName(e.target.value)}
/>
<Typography
variant="small"
color="blue-gray"
className="mb-1 mt-4 block font-medium"
>
Card Number
</Typography>
<Input
placeholder="1234 5678 9012 3456"
maxLength={19}
className="appearance-none !border-t-blue-gray-200 placeholder:text-blue-gray-300 placeholder:opacity-100 focus:!border-t-gray-900 [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
labelProps={{
className: "before:content-none after:content-none",
}}
containerProps={{
className: "min-w-0",
}}
value={cardNumber
.replace(/\s/g, "")
.replace(/(\d{4})/g, "$1 ")
.trim()}
onChange={(e) => setCardNumber(e.target.value)}
/>
<div className="mt-4 flex">
<div className="mr-4 w-full md:w-8/12">
<Typography
variant="small"
color="blue-gray"
className="mb-1 block font-medium"
>
Expiration Date
</Typography>
<Input
placeholder="MM/YY"
maxLength={5}
pattern="\d{2}/\d{2}"
className="appearance-none !border-t-blue-gray-200 placeholder:text-blue-gray-300 placeholder:opacity-100 focus:!border-t-gray-900 [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
labelProps={{
className: "before:content-none after:content-none",
}}
containerProps={{
className: "!min-w-0",
}}
value={expirationDate
.replace(/[^0-9]/g, "")
.replace(/(\d{2})(\d{1,2})/, "$1/$2")
.substring(0, 5)}
onChange={(e) => setExpirationDate(e.target.value)}
/>
</div>
<div className="w-full md:w-4/12">
<Typography
variant="small"
color="blue-gray"
className="mb-1 block font-medium"
>
CVV
</Typography>
<Input
placeholder="123"
maxLength={3}
pattern="\d{3}"
className="appearance-none !border-t-blue-gray-200 placeholder:text-blue-gray-300 placeholder:opacity-100 focus:!border-t-gray-900 [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
labelProps={{
className: "before:content-none after:content-none",
}}
containerProps={{
className: "!min-w-0",
}}
value={cvv.replace(/[^0-9]/g, "").replace(/(\..*)\./g, "$1")}
onChange={(e) => setCvv(e.target.value)}
/>
</div>
</div>
<Button className="mt-4" fullWidth>
Purchase Now
</Button>
</div>
);
}
## Input One-Time Password
Use this example of a one-time password (OTP) input to improve security. Users enter a 6-digit OTP sent to their registered phone number or email. This input field is designed for secure verification processes, ensuring that only authorized users can complete transactions or access sensitive information.
<CodePreview component={<InputNumberExamples.InputOneTimePassword />}>
import React from "react";
import { Input, Typography, Button } from "@material-tailwind/react";
export function InputOneTimePassword() {
const inputRefs = React.useRef([]);
const [otp, setOtp] = React.useState(Array(6).fill(""));
const handleChange = (index, value) => {
const newOtp = [...otp];
newOtp[index] = value.replace(/[^0-9]/g, "");
setOtp(newOtp);
if (value && index < inputRefs.current.length - 1) {
inputRefs.current[index + 1].focus();
}
};
function handleBackspace(event, index) {
if (event.key === "Backspace" && !event.target.value && index > 0) {
console.log(inputRefs.current[index - 1]);
inputRefs.current[index - 1].focus();
}
}
return (
<div className="w-full max-w-sm">
<Typography
variant="small"
color="blue-gray"
className="flex items-center justify-center gap-1 text-center font-medium"
>
Enter the 6-digit OTP sent to{" "}
<span className="font-bold">+1 123-456-7890</span>
</Typography>
<div className="my-4 flex items-center justify-center gap-2">
{otp.map((digit, index) => (
<React.Fragment key={index}>
<Input
type="text"
maxLength={1}
className="!w-10 appearance-none !border-t-blue-gray-200 text-center !text-lg placeholder:text-blue-gray-300 placeholder:opacity-100 focus:!border-t-gray-900"
labelProps={{
className: "before:content-none after:content-none",
}}
containerProps={{
className: "!min-w-0 !w-10 !shrink-0",
}}
value={digit}
onChange={(e) => handleChange(index, e.target.value)}
onKeyDown={(e) => handleBackspace(e, index)}
inputRef={(el) => (inputRefs.current[index] = el)}
/>
{index === 2 && <span className="text-2xl text-slate-700">-</span>}
</React.Fragment>
))}
</div>
<Typography
variant="small"
className="text-center font-normal text-blue-gray-500"
>
Did not receive the code? <span className="font-bold">Resend</span>
</Typography>
</div>
);
}
## Input Currency Conversion
Use this example to enter amounts for currency conversion. Users can input the amount to convert and select the desired currencies from dropdown menus. A visual swap button allows users to easily switch between "From" and "To" currencies.
<CodePreview component={<InputNumberExamples.InputCurrencyConversion />}>
import React from "react";
import {
Input,
Menu,
MenuHandler,
MenuList,
MenuItem,
Button,
IconButton,
Typography,
} from "@material-tailwind/react";
export function InputCurrencyConversion() {
const [fromCurrency, setFromCurrency] = React.useState("USD");
const [toCurrency, setToCurrency] = React.useState("EUR");
const [fromAmount, setFromAmount] = React.useState("");
const [toAmount, setToAmount] = React.useState("");
const currencies = ["USD", "EUR", "CAD", "RON"];
const handleCurrencyChange = (type: "from" | "to", currency: string) => {
if (type === "from") {
setFromCurrency(currency);
} else {
setToCurrency(currency);
}
};
const handleSwap = () => {
setFromCurrency(toCurrency);
setToCurrency(fromCurrency);
setFromAmount(toAmount);
setToAmount(fromAmount);
};
return (
<div className="mx-auto mt-4 w-full max-w-xl">
<Typography className="mb-4 font-normal text-blue-gray-500">
Enter the amount you wish to convert and select the desired currency.
</Typography>
<div className="flex flex-col items-center justify-between">
<div className="mt-4 w-full max-w-sm">
<Typography
variant="small"
color="blue-gray"
className="mb-1 font-medium"
>
From
</Typography>
<div className="relative flex w-full max-w-sm">
<Input
type="number"
placeholder="1,000"
className="appearance-none rounded-r-none !border-t-blue-gray-200 placeholder:text-blue-gray-300 placeholder:opacity-100 focus:!border-t-gray-900 [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
labelProps={{
className: "before:content-none after:content-none",
}}
containerProps={{
className: "min-w-0",
}}
value={fromAmount}
onChange={(e) => setFromAmount(e.target.value)}
/>
<Menu placement="bottom-start">
<MenuHandler>
<Button
ripple={false}
variant="text"
color="blue-gray"
className="h-10 w-14 shrink-0 rounded-l-none border border-l-0 border-blue-gray-200 bg-transparent px-3"
>
{fromCurrency}
</Button>
</MenuHandler>
<MenuList className="max-h-[20rem] max-w-[18rem]">
{currencies.map((currency, index) => {
return (
<MenuItem
key={currency}
value={currency}
onClick={() => handleCurrencyChange("from", currency)}
>
{currency}
</MenuItem>
);
})}
</MenuList>
</Menu>
</div>
</div>
<div className="mb-4 mt-8 flex items-center justify-center">
<IconButton
variant="outlined"
color="blue-gray"
onClick={handleSwap}
className="rounded-full"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
className="h-4 w-4"
>
<path
fillRule="evenodd"
d="M13.78 10.47a.75.75 0 0 1 0 1.06l-2.25 2.25a.75.75 0 0 1-1.06 0l-2.25-2.25a.75.75 0 1 1 1.06-1.06l.97.97V5.75a.75.75 0 0 1 1.5 0v5.69l.97-.97a.75.75 0 0 1 1.06 0ZM2.22 5.53a.75.75 0 0 1 0-1.06l2.25-2.25a.75.75 0 0 1 1.06 0l2.25 2.25a.75.75 0 0 1-1.06 1.06l-.97-.97v5.69a.75.75 0 0 1-1.5 0V4.56l-.97.97a.75.75 0 0 1-1.06 0Z"
clipRule="evenodd"
/>
</svg>
</IconButton>
</div>
<div className="w-full max-w-sm">
<Typography
variant="small"
color="blue-gray"
className="mb-1 font-medium"
>
To
</Typography>
<div className="relative flex w-full">
<Input
type="number"
placeholder="1,000"
className="appearance-none rounded-r-none !border-t-blue-gray-200 placeholder:text-blue-gray-300 placeholder:opacity-100 focus:!border-t-gray-900 [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
labelProps={{
className: "before:content-none after:content-none",
}}
containerProps={{
className: "min-w-0",
}}
value={toAmount}
onChange={(e) => setToAmount(e.target.value)}
/>
<Menu placement="bottom-start">
<MenuHandler>
<Button
ripple={false}
variant="text"
color="blue-gray"
className="h-10 w-14 shrink-0 rounded-l-none border border-l-0 border-blue-gray-200 bg-transparent px-3"
>
{fromCurrency}
</Button>
</MenuHandler>
<MenuList className="max-h-[20rem] max-w-[18rem]">
{currencies.map((currency, index) => {
return (
<MenuItem
key={currency}
value={currency}
onClick={() => handleCurrencyChange("from", currency)}
>
{currency}
</MenuItem>
);
})}
</MenuList>
</Menu>
</div>
</div>
</div>
<div className="mt-8 text-sm text-blue-gray-500">
<Typography variant="small" className="font-normal">
Rates are updated every hour to provide the most accurate conversions.
</Typography>
<Typography variant="small" className="mt-1 font-normal">
<b>Last updated</b>: July 30, 2024, 3:00 PM
</Typography>
</div>
</div>
);
}