MUI OTP Input

repository·main·Indexed 41 days ago

https://github.com/viclafouch/mui-otp-input

A specialized one-time password (OTP) input component for React applications using the MUI (Material UI) library. Version 7.0.0 features automatic focus management, support for pasting codes, custom character validation via validateChar, and integration with React Hook Form and TypeScript.

Tokens
5.3K
Snippets
26
Records
30
Agent score
97%

What's inside MUI OTP Input

  1. Use MUI Box props on MuiOtpInput

    main

    The MuiOtpInput component inherits props from the MUI Box component. This allows you to pass styling and layout props (such as display, gap, padding, margin, etc.) directly to MuiOtpInput to control its container behavior without needing an extra wrapper component.

    <MuiOtpInput display="flex" gap={5} />
  2. Integrate MUI OTP Input with Next.js

    main

    Because mui-one-time-password-input is an ESM package, you must add it to the transpilePackages array in your next.config.mjs file to ensure it works correctly in your Next.js project.

    // next.config.mjs
    /** @type {import('next').NextConfig} */
    const nextConfig = {
      transpilePackages: ['mui-one-time-password-input'],
      // your config,
    }
    
    export default nextConfig
  3. Use MuiOtpInput with TypeScript

    main

    The mui-one-time-password-input package is written in TypeScript and provides built-in type definitions. You do not need to manually define types for the component's props or its callback functions. All component props are defined within the MuiOtpInputProps interface.

    When using TypeScript, you can type your state and event handlers using standard types like string and number as demonstrated in the example below.

    import React from 'react'
    import { MuiOtpInput } from 'mui-one-time-password-input'
    
    const MyComponent = () => {
      const [value, setValue] = React.useState<string>('')
    
      const handleChange = (newValue: string) => {
        setValue(newValue)
      }
    
      const handleComplete = (finalValue: string) => {
        fetch('...')
      }
    
      return (
        <MuiOtpInput
          value={value}
          onChange={handleChange}
          onComplete={handleComplete}
          length={8}
          autoFocus
          validateChar={(character: string, index: number) => true}
        />
      )
    }
  4. Deploy the documentation website

    main

    The documentation website can be deployed using the yarn deploy command with different configurations depending on your hosting method:

    Using SSH

    Set the USE_SSH environment variable to true:

    $ USE_SSH=true yarn deploy

    Using GitHub Pages

    If you are hosting on GitHub Pages, provide your GitHub username via the GIT_USER environment variable. This command builds the site and pushes it to the gh-pages branch:

    $ GIT_USER=<Your GitHub username> yarn deploy
    $ USE_SSH=true yarn deploy
    # OR
    $ GIT_USER=<Your GitHub username> yarn deploy
  5. Integrate MuiOtpInput with React Hook Form

    main

    To use MuiOtpInput within a React Hook Form managed form, wrap the component in a Controller. This allows you to pass the form's field state (value, onChange, etc.) directly to the component using the spread operator on the field object provided by the render prop.

    Key integration steps:

    1. Initialize your form with useForm and provide a defaultValues object containing the key for your OTP (e.g., otp: '').
    2. Use the Controller component from react-hook-form.
    3. In the render prop, spread {...field} onto the MuiOtpInput component.
    4. Use fieldState.invalid to conditionally render error messages (like MUI's FormHelperText).
    5. Ensure the length prop on MuiOtpInput matches your validation logic.
    import React from 'react'
    import Box from '@mui/material/Box'
    import Button from '@mui/material/Button'
    import FormHelperText from '@mui/material/FormHelperText'
    import { MuiOtpInput } from 'mui-one-time-password-input'
    import { Controller, useForm } from 'react-hook-form'
    
    const App = () => {
      const { control, handleSubmit } = useForm({
        defaultValues: {
          otp: ''
        }
      })
    
      const onSubmit = (data) => {
        alert(JSON.stringify(data))
      }
    
      return (
        <form onSubmit={handleSubmit(onSubmit)}>
          <Controller
            name="otp"
            control={control}
            rules={{ validate: (value) => value.length === 6 }}
            render={({ field, fieldState }) => (
              <Box>
                <MuiOtpInput sx={{ gap: 1 }} {...field} length={6} />
                {fieldState.invalid ? (
                  <FormHelperText error>OTP invalid</FormHelperText>
                ) : null}
              </Box>
            )}
          />
          <div>
            <Button type="submit" variant="contained" sx={{ mt: 2 }}>
              Submit
            </Button>
          </div>
        </form>
      )
    }
  6. Override MuiOtpInput styles with custom classes

    main

    You can apply custom CSS classes to the MuiOtpInput component using the className prop. Once applied, you can target internal elements using specific global class names provided by the component.

    <MuiOtpInput className="my-class-name" />
  7. Customize TextFieldsProps in MuiOtpInput

    main

    The TextFieldsProps prop allows you to customize the individual input fields (rendered via TextFieldBox). It can be provided in two ways:

    1. As an object: The same props will be applied to every input field.
    2. As a function: Receives the current index as an argument, allowing you to apply different props to specific fields (e.g., different styling for the last field).

    Note that MuiOtpInput internally handles onPaste, onFocus, onKeyDown, onBlur, onChange, and inputRef, so you should be careful when overriding these if you want to maintain the component's core functionality.

    // Using a function to customize fields based on index
    <MuiOtpInput
      value={otp}
      length={4}
      onChange={setOtp}
      TextFieldsProps={(index) => ({
        variant: 'outlined',
        sx: { borderRadius: index === 3 ? '50%' : '4px' }
      })}
    />