Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[base-ui][Input] Add OTP input demo #40539

Merged
merged 32 commits into from
Jan 29, 2024
Merged

[base-ui][Input] Add OTP input demo #40539

merged 32 commits into from
Jan 29, 2024

Conversation

sai6855
Copy link
Contributor

@sai6855 sai6855 commented Jan 11, 2024

Demo: https://deploy-preview-40539--material-ui.netlify.app/base-ui/react-input/#otp-input

looking at downloads of https://www.npmjs.com/package/react-otp-input and considering its applicability in various everyday scenarios, I believe this component warrants inclusion as the demo.

few Inspiration/ benchmarks:

@sai6855 sai6855 marked this pull request as draft January 11, 2024 12:50
@sai6855 sai6855 added docs Improvements or additions to the documentation package: base-ui Specific to @mui/base component: input This is the name of the generic UI component, not the React module! labels Jan 11, 2024
@mui-bot
Copy link

mui-bot commented Jan 11, 2024

Netlify deploy preview

Bundle size report

No bundle size changes (Toolpad)
No bundle size changes

Generated by 🚫 dangerJS against 0da0fb5

@sai6855 sai6855 marked this pull request as ready for review January 12, 2024 11:26
Copy link
Contributor

@zanivan zanivan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great! Design-wise looks good :)

@marcpachecog
Copy link

@sai6855 @michaldudak @zanivan, I believe it would be fantastic to introduce an additional base-ui hook specifically designed for handling OTP inputs. Chakra already offers a PinInput component along with a headless UI hook in their zag library (https://zagjs.com/components/react/pin-input).

@DiegoAndai
Copy link
Member

@marcpachecog that sounds like a good idea. Could you please open a feature request issue for it? 😊

@DiegoAndai DiegoAndai requested review from michaldudak and removed request for DiegoAndai January 16, 2024 12:32
@marcpachecog
Copy link

@DiegoAndai Done! mui/base-ui#75

@michaldudak
Copy link
Member

Great idea! I have a couple of remarks regarding functionality:

  • pressing Left Arrow when the cursor is in the filled first input should not deselect its content (unless entering another digit will replace the old value)
  • how do you get the value from the component?
  • each input could have a label saying which digit/character it corresponds to, so it's announced by screen readers
  • nice to have: if we paste a whole value, all the inputs should be updated

@sai6855
Copy link
Contributor Author

sai6855 commented Jan 16, 2024

  • pressing Left Arrow when the cursor is in the filled first input should not deselect its content (unless entering another digit will replace the old value)

fixed in 23ee497

  • how do you get the value from the component?

fixed in 51965ca

  • each input could have a label saying which digit/character it corresponds to, so it's announced by screen readers

fixed in d67da7c

  • nice to have: if we paste a whole value, all the inputs should be updated

fixed in b8b382f


const handleKeyDown = (event, currentIndex) => {
switch (event.key) {
case 'ArrowLeft':
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please handle ArrowUp the same way as ArrowLeft and ArrowDown the same way as ArrowRight

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both ArrowUp and ArrowLeft does nothing (not even deselection of input) in mentioned benchmarks . so i reflected same behaviour in bb2f3a8

import { Input as BaseInput } from '@mui/base/Input';
import { Box, styled } from '@mui/system';

function OTP({ seperator, inputCount, otp, setOtp }) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

otp and setOpt are not really a standard way of providing a value. Could you change it to value and onChange?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed here 7c6a232

selectInput(currentIndex);
};

const handlePaste = (event, currentIndex) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works great! I'm wondering if pasting in any of the digits shouldn't replace the whole value, though (so if your value is [9][9][9][9][9], have a cursor in the third input and have 12345 in the clipboard, the component should display [1][2][3][4][5] instead of [9][9][1][2][3]), but I'm not 100% sure about that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both mentioned benchmarks displays [9][9][1][2][3] on pasting. so i reflected same behaviour.

setOtp={setOtp}
inputCount={inputCount}
/>
</Box>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we display the entered code as plain text below the OTP component?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed here 50c9913


export default function OTPInput() {
const inputCount = 5;
const [otp, setOtp] = React.useState<string[]>(new Array(inputCount).fill(''));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having just a string here instead of an array would be more convenient. The value would usually be sent to server as a single string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}}
>
<OTP
seperator={<span>-</span>}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo:

Suggested change
seperator={<span>-</span>}
separator={<span>-</span>}

seperator={<span>-</span>}
value={otp}
onChange={setOtp}
inputCount={inputCount}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

length could be more intiutive (+ shorter)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since otp is string now, couldn't use otp.length

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant the prop name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opps sorry.. fixed in this commit 7dee93b

@sai6855
Copy link
Contributor Author

sai6855 commented Jan 22, 2024

ping @michaldudak

Copy link
Member

@michaldudak michaldudak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks OK to me!

@DiegoAndai DiegoAndai merged commit 2d0d52c into mui:master Jan 29, 2024
19 checks passed
@sai6855 sai6855 deleted the otp-input branch January 29, 2024 13:21
mostafa-rio pushed a commit to mostafa-rio/material-ui that referenced this pull request Feb 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: input This is the name of the generic UI component, not the React module! docs Improvements or additions to the documentation package: base-ui Specific to @mui/base
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants