Skip to content

Latest commit

 

History

History
903 lines (827 loc) · 30.5 KB

input-number.mdx

File metadata and controls

903 lines (827 loc) · 30.5 KB
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-with-select
input-zip-code
input-phone-number
input-amount-buttons
input-control-with-icon
input-counter-plain-buttons
input-currency
input-credit-card
input-one-time-password
input-currency-conversion
input-number
icon-button
form
# Tailwind CSS Input Number - React

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>
  );
}