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

feat(input-otp): Adding Input OTP component #3748

Open
wants to merge 14 commits into
base: canary
Choose a base branch
from

Conversation

macci001
Copy link
Contributor

@macci001 macci001 commented Sep 13, 2024

Closes #2678

📝 Description

PR adds the input-otp componenet

⛳️ Current behavior (updates)

Currently NextUI do not have input-otp component.

🚀 New behavior

  • Default Color
Screenshot 2024-09-16 at 11 58 32 PM
  • Primary Variant (other variant such as Secondary, Success, Warning and Danger follow similar styles)
Screenshot 2024-09-16 at 11 58 41 PM
  • Video represention
Screen.Recording.2024-09-15.at.11.24.23.PM.mov

Copy link

changeset-bot bot commented Sep 13, 2024

🦋 Changeset detected

Latest commit: 397b9fa

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@nextui-org/input-otp Patch
@nextui-org/theme Patch
@nextui-org/react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

vercel bot commented Sep 13, 2024

Someone is attempting to deploy a commit to the NextUI Inc Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

coderabbitai bot commented Sep 13, 2024

Walkthrough

This update introduces a new input-otp component to the project, designed for user-friendly entry of one-time passwords (OTPs). It features automatic focus management, input validation, and visual feedback, ensuring a consistent design with existing themes. A suite of unit tests is included to validate the component's functionality and integration with React Hook Form. Additionally, documentation and package configuration are provided for the new component.

Changes

File(s) Change Summary
.changeset/spotty-flies-jump.md Added AI-generated summary of changes.
packages/components/input-otp/src/input-otp.tsx Added InputOtp component with focus management and input handling.
packages/components/input-otp/src/use-input-otp.ts Added useInputOtp hook for managing OTP input logic.
packages/components/input-otp/stories/input-otp.stories.tsx Added storybook configuration for InputOtp component.
packages/components/input-otp/package.json Added package configuration for @nextui-org/input-otp.
packages/components/input-otp/README.md Added documentation for input-otp component.
packages/core/theme/src/components/input-otp.ts Added theming support for input-otp.
index.ts Updated exports for InputOtp and related types.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant InputOtp
    participant Form

    User->>InputOtp: Enter OTP digit
    InputOtp->>InputOtp: Validate input
    InputOtp->>InputOtp: Focus next input field
    InputOtp->>Form: Submit OTP
    Form->>Form: Process OTP
Loading

Assessment against linked issues

Objective Addressed Explanation
Introduce input-otp component (#[2678])
Facilitate OTP input for user-friendly access (#[2678])

Possibly related PRs


Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 19d9bf5 and 397b9fa.

Files selected for processing (2)
  • packages/components/input-otp/stories/input-otp.stories.tsx (1 hunks)
  • packages/core/theme/src/components/input-otp.ts (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • packages/core/theme/src/components/input-otp.ts
Additional comments not posted (5)
packages/components/input-otp/stories/input-otp.stories.tsx (5)

1-7: LGTM!

The imports are correctly specified and include the necessary dependencies for the Storybook configuration and the InputOtp component.


8-34: LGTM!

The default export correctly sets up the Storybook configuration for the InputOtp component, including a comprehensive set of customizable properties with appropriate control types and options.


36-40: LGTM!

The defaultProps object correctly spreads the default variants for the InputOtp component, and the Template function provides a reusable way to render the component with custom arguments and a fixed otplength of 4.


42-68: LGTM!

The WithReactHookFormTemplate function effectively demonstrates the integration of the InputOtp component within a form context using React Hook Form. The template properly manages form state, validation, and submission, providing a clear example of how to use the component in a real-world scenario.


70-82: LGTM!

The named exports, Default and InputOtpInForm, provide different configurations of the InputOtp component for Storybook. The Default export showcases the component with its default properties, while the InputOtpInForm export demonstrates the component's integration within a form context. Both exports utilize the previously defined templates and spread the defaultProps for a consistent base configuration.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    -- I pushed a fix in commit <commit_id>, please review it.
    -- Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    -- @coderabbitai generate unit testing code for this file.
    -- @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    -- @coderabbitai generate interesting stats about this repository and render them as a table.
    -- @coderabbitai read src/utils.ts and generate unit testing code.
    -- @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    -- @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@wingkwong wingkwong added this to the v2.5.0 milestone Sep 13, 2024
@macci001 macci001 marked this pull request as ready for review September 15, 2024 17:51
@macci001
Copy link
Contributor Author

@coderabbitai full review

Copy link
Contributor

coderabbitai bot commented Sep 15, 2024

Actions performed

Full review triggered.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Outside diff range and nitpick comments (5)
.changeset/spotty-flies-jump.md (2)

2-3: Consider using a minor version bump for the new component.

Since you're adding a new input-otp component, it would be more appropriate to use a minor version bump (minor) instead of a patch (patch) for the @nextui-org/input-otp package. Patch versions are typically used for bug fixes, while minor versions are used for new features that are non-breaking.

-"@nextui-org/input-otp": patch
+"@nextui-org/input-otp": minor
 "@nextui-org/theme": patch

6-6: Provide more context in the changeset message.

The current changeset message briefly mentions the addition of the new input-otp component. To provide more clarity and context for the change, consider expanding the message to include details such as:

  • The motivation behind adding this component (e.g., to facilitate the input of one-time passwords)
  • How the component fits into the overall NextUI library
  • Any notable features or benefits of using this component
packages/components/input-otp/README.md (2)

1-5: LGTM! Consider using the synonym "brief" to strengthen the wording.

The component description is concise and clearly states the purpose of the component. It also sets the context for the intended audience by mentioning that it is an internal utility.

Based on the static analysis hint, consider using the synonym "brief" instead of "quick" to strengthen the wording:

-A Quick description of the component
+A brief description of the component
Tools
LanguageTool

[style] ~3-~3: Consider using the synonym “brief” (= concise, using a few words, not lasting long) to strengthen your wording.
Context: # @nextui-org/input-otp A Quick description of the component > This is...

(QUICK_BRIEF)


15-19: LGTM! Add a comma before "please" for grammatical correctness.

The contribution section encourages community involvement by referring to the contribution guidelines.

Based on the static analysis hint, add a comma before "please" at the end of the sentence for grammatical correctness:

-Yes please! See the
+Yes, please! See the
Tools
LanguageTool

[typographical] ~17-~17: Usually, a comma is necessary before ‘Yes’ at the end of a sentence. Did you mean “, please”?
Context: ...-org/input-otp ``` ## Contribution Yes please! See the [contributing guidelines](http...

(COMMA_BEFORE_PLEASE)

packages/components/input-otp/stories/input-otp.stories.tsx (1)

39-39: Consider making the otplength prop configurable.

The Template function currently hardcodes the otplength prop to 4. To enhance the flexibility of the InputOtp component in the Storybook, consider making the otplength prop configurable through the Storybook controls.

You can add the otplength prop to the argTypes object and provide a control type and options for selection. For example:

argTypes: {
  // ...existing argTypes
  otplength: {
    control: { type: "number", min: 1, max: 10 },
    defaultValue: 4,
  },
},

Then, update the Template function to use the otplength prop from the args:

const Template = (args: InputOtpProps) => <InputOtp {...args} />;

This way, users can easily configure the otplength prop directly in the Storybook, providing more flexibility and customization options.

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 5b5a974 and 84ac1d0.

Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
Files selected for processing (13)
  • .changeset/spotty-flies-jump.md (1 hunks)
  • packages/components/input-otp/README.md (1 hunks)
  • packages/components/input-otp/tests/input-otp.test.tsx (1 hunks)
  • packages/components/input-otp/package.json (1 hunks)
  • packages/components/input-otp/src/index.ts (1 hunks)
  • packages/components/input-otp/src/input-otp-segment.tsx (1 hunks)
  • packages/components/input-otp/src/input-otp.tsx (1 hunks)
  • packages/components/input-otp/src/use-input-otp.ts (1 hunks)
  • packages/components/input-otp/stories/input-otp.stories.tsx (1 hunks)
  • packages/components/input-otp/tsconfig.json (1 hunks)
  • packages/components/input-otp/tsup.config.ts (1 hunks)
  • packages/core/theme/src/components/index.ts (1 hunks)
  • packages/core/theme/src/components/input-otp.ts (1 hunks)
Files skipped from review due to trivial changes (1)
  • packages/components/input-otp/src/index.ts
Additional context used
LanguageTool
packages/components/input-otp/README.md

[style] ~3-~3: Consider using the synonym “brief” (= concise, using a few words, not lasting long) to strengthen your wording.
Context: # @nextui-org/input-otp A Quick description of the component > This is...

(QUICK_BRIEF)


[typographical] ~17-~17: Usually, a comma is necessary before ‘Yes’ at the end of a sentence. Did you mean “, please”?
Context: ...-org/input-otp ``` ## Contribution Yes please! See the [contributing guidelines](http...

(COMMA_BEFORE_PLEASE)

Additional comments not posted (34)
packages/components/input-otp/tsup.config.ts (1)

1-8: LGTM!

The tsup configuration for the OTP input component is well-defined and follows best practices:

  • Cleaning the output before each build ensures a clean slate and prevents interference from old files.
  • Targeting ECMAScript 2019 allows the use of modern JavaScript features while maintaining compatibility with older environments.
  • Providing both CommonJS and ECMAScript Modules as output formats enhances flexibility and caters to different module systems.
  • Including a banner to indicate client-side execution helps clarify the intended execution environment for the generated code.

Overall, this configuration streamlines the build process and ensures compatibility with various JavaScript environments.

packages/components/input-otp/tsconfig.json (1)

1-10: LGTM!

The TypeScript configuration for the OTP input component is well-structured and follows best practices:

  • Extending the base configuration ensures consistency with the project's TypeScript settings.
  • The baseUrl and path mapping settings facilitate cleaner imports and usage of the tailwind-variants package.
  • The include array comprehensively covers the relevant source files for compilation.

No issues or inconsistencies are identified. The configuration is appropriate for the component.

packages/components/input-otp/README.md (2)

7-13: LGTM!

The installation instructions are clear and provide the necessary commands for both Yarn and npm.


21-24: LGTM!

The license section clearly states the project's licensing under the MIT license.

packages/core/theme/src/components/index.ts (1)

20-20: LGTM!

The export statement for the new input-otp component follows the existing pattern in the file and aligns with the PR objectives. The change does not introduce any breaking changes.

packages/components/input-otp/stories/input-otp.stories.tsx (3)

1-33: LGTM!

The import statements and default export configuration for the Storybook setup are correctly structured. The argTypes object properly defines the customizable properties for the InputOtp component, enhancing its usability and flexibility within Storybook.


35-37: LGTM!

The defaultProps object is correctly defined using the spread operator to include the inputOtp.defaultVariants from the NextUI theme. This ensures consistency with the theme's default variants for the InputOtp component.


41-46: LGTM!

The Default export is correctly structured and specifies the render function and args for the Storybook story. It properly uses the Template function as the render function and sets the args using the spread operator to include the defaultProps.

packages/components/input-otp/src/input-otp-segment.tsx (4)

1-6: LGTM!

The import statements are correctly used to bring in the required dependencies for the component. The imported dependencies are used in the component implementation, and there are no apparent issues with the import statements.


7-59: LGTM!

The InputOtpSegment component implementation is well-structured and follows best practices. The use of useMemo hook is appropriate to optimize performance by memoizing values that depend on props. The component correctly calculates whether it is active based on the current value length and the focused state. The component applies conditional class names for styling using the clsx utility, which is a good practice. The component renders a div that reflects the active state and whether it contains a value, enhancing the user experience for OTP input fields. There are no apparent issues with the component implementation.


26-32: LGTM!

The use of useMemo hook is appropriate to memoize the isActive value, as it depends on the value and isInputFocused props. The calculation of the isActive value is correct and handles the edge case when the current value length is equal to the otplength and the accessorIndex is equal to otplength - 1. The dependencies array of the useMemo hook is correctly specified with [value, isInputFocused].


38-47: LGTM!

The use of useMemo hook is appropriate to memoize the displayValue, as it depends on the hasValue, value, and isActive values. The calculation of the displayValue is correct and handles the different cases based on the hasValue and isActive values. The displayValue is set to the character at the accessorIndex of the value string when hasValue is true, which is the expected behavior. The displayValue is set to a div element with the slots.caret class name when isActive is true and hasValue is false, indicating the active state of the input segment. The displayValue is set to null when both hasValue and isActive are false, which is the expected behavior.

packages/components/input-otp/package.json (3)

1-26: LGTM!

The package metadata looks good:

  • The package name follows the NextUI naming convention.
  • The version aligns with the NextUI ecosystem.
  • The main entry point correctly points to the TypeScript source file.
  • The author and repository details are consistent with other NextUI packages.

27-35: LGTM!

The package scripts are well-defined:

  • The build scripts use tsup for fast and efficient bundling.
  • The dev script enables quick development with watch mode.
  • The clean script ensures a clean build environment.
  • The typecheck script helps catch type errors early.
  • The prepack and postpack scripts maintain a clean package distribution.

36-58: LGTM!

The package dependencies are properly defined:

  • The peer dependencies ensure compatibility with React and other NextUI packages.
  • The dependencies on NextUI utility packages and React Aria libraries provide necessary functionality and accessibility features.
  • The dev dependencies include essential tools for development and testing.
  • The clean-package configuration file helps maintain a clean package structure.
packages/components/input-otp/src/input-otp.tsx (1)

1-95: LGTM! The InputOtp component is a great addition to the NextUI library.

The component is well-structured, follows best practices, and enhances the library's functionality without introducing any breaking changes. Here are a few observations and suggestions:

  1. The use of useMemo for the three sections (Segments, Input, and Helper) is a good performance optimization.
  2. The component is properly typed using TypeScript, which enhances type safety and maintainability.
  3. The component is accessible and customizable through the use of props and the useInputOtp hook.
  4. The component follows best practices such as using forwardRef for ref forwarding and displayName for better debugging.

Suggestions for improvement:

  1. Consider adding more documentation and examples to showcase the usage and customization options of the component.
  2. Consider adding unit tests to ensure the component's behavior and edge cases are properly covered.
  3. Consider adding accessibility attributes (e.g., aria-label, aria-describedby) to improve the component's accessibility.

Overall, great work on this new component! It will be a valuable addition to the NextUI library.

packages/components/input-otp/src/use-input-otp.ts (1)

83-259: Excellent work on the useInputOtp hook implementation!

The hook encapsulates the logic for managing the state and behavior of an OTP input component in a reusable and maintainable way. It uses the inputOtp function from the theme to generate the styles and slots objects, ensuring consistency with the theme. The use of the useFocusRing and useHover hooks from react-aria enhances the accessibility of the component. The validation of user input against the allowed keys regex ensures that only valid characters are entered. The getter functions provided by the hook promote a clean and readable component implementation.

Overall, the implementation is well-structured, follows best practices, and promotes reusability and maintainability.

packages/components/input-otp/__tests__/input-otp.test.tsx (12)

15-19: LGTM!

The test case correctly verifies that the component renders without errors.


21-26: LGTM!

The test case correctly verifies that the component forwards refs as expected.


28-48: LGTM!

The test case correctly verifies that clicking on the input selects the first segment and sets the appropriate attributes on the base, input, and segment elements.


50-59: LGTM!

The test case correctly verifies that the input is not focused when the component is disabled.


61-86: LGTM!

The test case correctly verifies that typing a valid digit shifts the focus to the next segment and updates the appropriate attributes on the input and segment elements.


88-115: LGTM!

The test case correctly verifies that the input can be erased using the backspace key and updates the appropriate attributes on the input and segment elements.


117-133: LGTM!

The test case correctly verifies that a value can be pasted into the input and updates the value attribute on the input element.


135-152: LGTM!

The test case correctly verifies that non-allowed inputs are not accepted by the component and do not update the value attribute on the input element or the data-active attribute on the segment elements.


154-173: LGTM!

The test case correctly verifies that inputs matching a custom regex are allowed by the component and update the value attribute on the input element and the data-active attribute on the segment elements.


175-195: LGTM!

The test case correctly verifies that the onFill callback is called when the input is completely filled by checking the value of a test variable that is updated in the callback.


240-244: LGTM!

The test case correctly verifies that the component works with default values provided by React Hook Form by checking the value attribute of the InputOtp elements.


246-262: LGTM!

The test cases correctly verify the form submission behavior when a required InputOtp field is empty or filled by checking the number of times the onSubmit callback has been called.

packages/core/theme/src/components/input-otp.ts (5)

1-4: LGTM!

The imports are correctly used for defining the component's variants and using the tv utility.


5-45: Great work on defining the component slots!

The slots are correctly defined with appropriate styling classes. The use of data attributes for conditional styling is a good practice. The slot names are descriptive and follow a consistent naming convention.


46-110: The component variants are well-defined!

The variants are correctly defined with appropriate styling classes. The variant names are descriptive and follow a consistent naming convention. The defaultVariants are also correctly defined.


111-340: Excellent use of compound variants!

The compound variants are correctly defined with appropriate styling classes. The use of compound variants provides a comprehensive styling solution for various use cases. The compound variants cover all possible combinations of variant and color.


342-346: Great job on exporting the necessary types and the component!

The exported types facilitate type safety and enhance the developer experience when using this component in TypeScript. The component is correctly exported.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Outside diff range and nitpick comments (3)
packages/components/input-otp/README.md (2)

3-3: Consider using "brief" instead of "quick".

To strengthen the wording and better convey the intent of a concise description, consider using the synonym "brief" instead of "quick".

-A Quick description of the component
+A brief description of the component
Tools
LanguageTool

[style] ~3-~3: Consider using the synonym “brief” (= concise, using a few words, not lasting long) to strengthen your wording.
Context: # @nextui-org/input-otp A Quick description of the component > This is...

(QUICK_BRIEF)


17-17: Add a comma before "please".

To improve readability and align with grammatical conventions, add a comma before "please" at the end of the sentence.

-Yes please! See the
+Yes, please! See the
Tools
LanguageTool

[typographical] ~17-~17: Usually, a comma is necessary before ‘Yes’ at the end of a sentence. Did you mean “, please”?
Context: ...-org/input-otp ``` ## Contribution Yes please! See the [contributing guidelines](http...

(COMMA_BEFORE_PLEASE)

packages/components/input-otp/stories/input-otp.stories.tsx (1)

39-39: Consider making the otplength prop configurable.

The Template function currently hardcodes the otplength prop to 4. To make it more flexible for different use cases, consider adding otplength to the args object or providing a default value that can be overridden.

You can modify the Template function like this:

-const Template = (args: InputOtpProps) => <InputOtp {...args} otplength={4} />;
+const Template = (args: InputOtpProps) => <InputOtp {...args} otplength={args.otplength || 4} />;

This way, the otplength can be configured through the args object, and if not provided, it will default to 4.

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 5b5a974 and 84ac1d0.

Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
Files selected for processing (13)
  • .changeset/spotty-flies-jump.md (1 hunks)
  • packages/components/input-otp/README.md (1 hunks)
  • packages/components/input-otp/tests/input-otp.test.tsx (1 hunks)
  • packages/components/input-otp/package.json (1 hunks)
  • packages/components/input-otp/src/index.ts (1 hunks)
  • packages/components/input-otp/src/input-otp-segment.tsx (1 hunks)
  • packages/components/input-otp/src/input-otp.tsx (1 hunks)
  • packages/components/input-otp/src/use-input-otp.ts (1 hunks)
  • packages/components/input-otp/stories/input-otp.stories.tsx (1 hunks)
  • packages/components/input-otp/tsconfig.json (1 hunks)
  • packages/components/input-otp/tsup.config.ts (1 hunks)
  • packages/core/theme/src/components/index.ts (1 hunks)
  • packages/core/theme/src/components/input-otp.ts (1 hunks)
Additional context used
LanguageTool
packages/components/input-otp/README.md

[style] ~3-~3: Consider using the synonym “brief” (= concise, using a few words, not lasting long) to strengthen your wording.
Context: # @nextui-org/input-otp A Quick description of the component > This is...

(QUICK_BRIEF)


[typographical] ~17-~17: Usually, a comma is necessary before ‘Yes’ at the end of a sentence. Did you mean “, please”?
Context: ...-org/input-otp ``` ## Contribution Yes please! See the [contributing guidelines](http...

(COMMA_BEFORE_PLEASE)

Additional comments not posted (43)
.changeset/spotty-flies-jump.md (1)

1-6: LGTM!

The changeset file follows the correct format and accurately describes the changes made in this patch release. The addition of the input-otp component is a valuable feature that improves user experience and security. The patch to the @nextui-org/theme package ensures a consistent design language for the new component.

The changes described in this file should not introduce any breaking changes or negative impacts to the codebase.

packages/components/input-otp/tsup.config.ts (5)

4-4: LGTM!

Setting clean to true is a good practice to ensure a clean build output directory.


5-5: LGTM!

Targeting "es2019" is a good balance between using modern JavaScript features and maintaining compatibility with older environments.


6-6: LGTM!

Generating both CommonJS (cjs) and ECMAScript Modules (esm) output enhances versatility for different module systems.


7-7: LGTM!

Including the "use client"; banner in the generated JavaScript files is a good practice for Next.js applications to differentiate between server-side and client-side code.


3-8: LGTM!

The tsup configuration for the OTP input component is well-defined and follows best practices. It enhances the build process by streamlining output management and ensuring compatibility across various JavaScript environments.

packages/components/input-otp/src/index.ts (1)

1-10: LGTM!

The index.ts file is well-structured and follows best practices for exporting components, types, and hooks. It serves as a centralized export hub for the InputOtp component and its related entities, which promotes better organization and ease of use.

The file has the following positive aspects:

  • Clear separation of imports, type exports, hook exports, and component exports.
  • Consistent naming convention for the component, type, and hook.
  • Named exports for clarity and avoiding naming conflicts.
  • Enhances type safety and clarity in TypeScript usage by exporting the InputOtpProps type.

Great job on creating this export file!

packages/components/input-otp/tsconfig.json (1)

1-10: LGTM!

The TypeScript configuration for the OTP input component is well-structured and follows best practices:

  • Extending the base configuration ensures consistency with the overall project settings.
  • The baseUrl and path mapping simplify import statements and module resolution within the component.
  • Including both the src directory and index.ts file ensures all necessary source files are compiled.

This setup enhances the development experience by streamlining module resolution and maintaining adherence to project-wide TypeScript configurations.

packages/components/input-otp/README.md (1)

1-24: README looks good with minor nitpicks!

The README.md file provides a clear and informative overview of the @nextui-org/input-otp component. It covers the essential aspects, including the component's purpose, installation instructions, contribution guidelines, and licensing details.

The suggested nitpicks regarding the wording and grammar are minor improvements that enhance the quality of the documentation.

Overall, the file is well-structured and serves its purpose effectively.

Tools
LanguageTool

[style] ~3-~3: Consider using the synonym “brief” (= concise, using a few words, not lasting long) to strengthen your wording.
Context: # @nextui-org/input-otp A Quick description of the component > This is...

(QUICK_BRIEF)


[typographical] ~17-~17: Usually, a comma is necessary before ‘Yes’ at the end of a sentence. Did you mean “, please”?
Context: ...-org/input-otp ``` ## Contribution Yes please! See the [contributing guidelines](http...

(COMMA_BEFORE_PLEASE)

packages/core/theme/src/components/index.ts (1)

20-20: LGTM! Verify the implementation of the input-otp module.

The export statement is syntactically correct and aligns with the PR objective of adding an "Input OTP" component. However, please ensure that the implementation of the input-otp module integrates correctly with the existing codebase and follows the project's coding standards and best practices.

packages/components/input-otp/stories/input-otp.stories.tsx (3)

1-33: LGTM!

The import statements and the default export for the Storybook configuration are correctly set up. The argTypes are properly defined for the component's props, specifying their control types and options.


35-37: LGTM!

The defaultProps object is correctly defined using the spread operator to include the inputOtp.defaultVariants from the theme. This ensures consistency with the default styling of the component.


41-46: LGTM!

The Default export is correctly set up with the render property pointing to the Template function. The args property spreads the defaultProps object, ensuring that the default props are applied to the component in the Storybook.

packages/components/input-otp/src/input-otp-segment.tsx (5)

1-15: LGTM!

The imports and interface definition are correct and appropriate for the component.


17-33: LGTM!

The component definition and memoized values are implemented correctly. The use of useMemo is a good optimization technique to avoid unnecessary re-calculations.


35-47: LGTM!

The usage of clsx for combining class names and memoizing displayValue is implemented correctly. The logic for determining the displayValue based on hasValue and isActive states is accurate and enhances the user experience.


49-58: LGTM!

The component's return statement is implemented correctly. It applies the segment styles, sets the appropriate data attributes, and renders the displayValue within the div. This allows for dynamic styling and behavior based on the component's state.


1-59: Great work on the InputOtpSegment component!

The component is well-structured, modular, and reusable. It effectively manages individual segments of an OTP input field by accepting relevant props and utilizing React hooks for performance optimization. The logic and rendering are implemented correctly, providing a clean and efficient solution.

Some key highlights:

  • Proper use of memoization to optimize performance.
  • Conditional rendering based on the component's state.
  • Utilization of utility functions for combining class names.
  • Well-defined prop types using an interface.

Overall, this component is a valuable addition to the NextUI library and enhances the functionality of OTP input handling.

packages/components/input-otp/package.json (3)

1-26: Metadata and configuration look good!

The package metadata and configuration follow the NextUI conventions and best practices. The package name, main entry point, public access, and repository details are all properly specified.

Please ensure that the version 2.0.0 aligns with the NextUI release cycle and follows semantic versioning.


27-35: Package scripts are well-defined!

The package scripts cover essential tasks such as building, cleaning, type-checking, and managing package cleanliness. The use of tsup for builds, rimraf for cleaning, and clean-package for package management aligns with best practices. The dev script enhances the development experience with fast builds and watch mode.


36-58: Dependencies are properly specified!

The package dependencies are well-structured and include the necessary peer dependencies, dependencies, and dev dependencies.

  • The peer dependencies ensure compatibility with React, React DOM, and NextUI packages, which is essential for seamless integration.
  • The dependencies on NextUI utilities and React Aria libraries provide crucial functionality and accessibility features.
  • The dev dependencies include relevant packages for development and testing, such as React, React DOM, and react-hook-form for form handling.

The use of clean-package as a dev dependency aligns with the package cleanliness management setup in the scripts.

packages/components/input-otp/src/input-otp.tsx (3)

1-7: LGTM!

The imports and interfaces are properly organized and follow the necessary conventions. The InputOtpProps interface extending UseInputOtpProps allows for proper prop type checking and validation.


9-91: LGTM!

The main InputOtp component is well-structured and follows best practices:

  • The use of forwardRef allows for ref forwarding to the underlying DOM element.
  • Memoizing the sections improves performance by avoiding unnecessary re-renders.
  • The dynamic creation of InputOtpSegment components based on otplength provides flexibility.
  • The standard HTML input element serves as a fallback for OTP entry.
  • The conditional rendering in the helperSection enhances the user experience by providing relevant feedback.

The component is modular, reusable, and maintains a clean separation of concerns.


93-95: LGTM!

The component export and display name are properly set:

  • Exporting the component as the default export makes it easily accessible for use in other parts of the application.
  • Setting the display name to "NextUI.InputOtp" follows the naming convention for NextUI components.
packages/components/input-otp/src/use-input-otp.ts (1)

83-259: LGTM! The useInputOtp hook is well-implemented and provides a robust solution for managing OTP input.

The hook encapsulates the complex logic of handling OTP input, including state management, accessibility features, and input validation. It offers a flexible API through various props and callbacks, allowing customization and integration with other components.

Some key highlights:

  • Effective use of useFocusRing and useHover for enhanced accessibility and user experience.
  • Proper validation of user input against the allowed keys regex.
  • Triggering the onFill callback when the input is complete.
  • Support for dynamic class names through the classNames prop for customizable styling.

The use of TypeScript ensures type safety and helps catch potential errors during development.

Overall, this hook promotes reusability, maintainability, and provides a consistent user experience for OTP input scenarios.

packages/components/input-otp/__tests__/input-otp.test.tsx (13)

15-19: LGTM!

The test case correctly verifies that the component renders without errors.


21-26: LGTM!

The test case correctly verifies that the component forwards the ref.


28-48: LGTM!

The test case correctly verifies that clicking on the input selects the first segment.


50-59: LGTM!

The test case correctly verifies that the component does not gain focus when disabled.


61-86: LGTM!

The test case correctly verifies that typing a valid digit shifts the focus to the next segment.


88-115: LGTM!

The test case correctly verifies that the input can be erased using backspace and the active segment is updated accordingly.


117-133: LGTM!

The test case correctly verifies that a value can be pasted into the input.


135-152: LGTM!

The test case correctly verifies that non-allowed inputs are not accepted.


154-173: LGTM!

The test case correctly verifies that inputs based on a custom regex are allowed.


175-195: LGTM!

The test case correctly verifies that the onFill callback is called when the input is completely filled.


240-244: LGTM!

The test case correctly verifies that the InputOtp components work with default values.


246-252: LGTM!

The test case correctly verifies that the form is not submitted when the required field is empty.


254-262: LGTM!

The test case correctly verifies that the form is submitted when the required field is not empty.

packages/core/theme/src/components/input-otp.ts (5)

1-4: LGTM!

The import statements and the inputOtp component definition using the tv utility look good.

Also applies to: 5-5


6-45: LGTM!

The slots definition provides a clear and modular structure for the component. The use of Tailwind CSS classes allows for easy customization and consistent styling.


46-105: LGTM!

The variants definition provides flexibility in customizing the component's appearance. The use of Tailwind CSS classes ensures consistent styling across different variants.


106-110: LGTM!

The defaultVariants ensure a consistent default appearance for the component. The compoundVariants provide fine-grained control over the styling based on specific variant and color combinations. The use of Tailwind CSS classes in the compound variants maintains consistency with the overall styling approach.

Also applies to: 111-340


342-346: LGTM!

Exporting the types improves the developer experience by providing type information for the component's props, slots, and return type. Exporting the inputOtp component allows it to be imported and used in other parts of the codebase.

@macci001 macci001 force-pushed the macci001/add-input-otp-component branch from 84ac1d0 to 520b54d Compare September 16, 2024 17:41
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Outside diff range and nitpick comments (1)
packages/components/input-otp/README.md (1)

1-24: LGTM! The README.md file provides clear and concise information about the component.

The file structure and content are well-organized, making it easy for developers to understand the purpose, installation, contribution, and licensing details of the @nextui-org/input-otp component. The clear statement that this is an internal utility not intended for public usage sets the right context for its intended audience.

Minor suggestions based on static analysis hints:

  • Consider using the synonym "brief" instead of "quick" to strengthen the wording in line 3.
  • Consider adding a comma before "please" in line 17 to improve readability.

Overall, the changes in this file are approved.

Tools
LanguageTool

[style] ~3-~3: Consider using the synonym “brief” (= concise, using a few words, not lasting long) to strengthen your wording.
Context: # @nextui-org/input-otp A Quick description of the component > This is...

(QUICK_BRIEF)


[typographical] ~17-~17: Usually, a comma is necessary before ‘Yes’ at the end of a sentence. Did you mean “, please”?
Context: ...-org/input-otp ``` ## Contribution Yes please! See the [contributing guidelines](http...

(COMMA_BEFORE_PLEASE)

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 84ac1d0 and 520b54d.

Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
Files selected for processing (13)
  • .changeset/spotty-flies-jump.md (1 hunks)
  • packages/components/input-otp/README.md (1 hunks)
  • packages/components/input-otp/tests/input-otp.test.tsx (1 hunks)
  • packages/components/input-otp/package.json (1 hunks)
  • packages/components/input-otp/src/index.ts (1 hunks)
  • packages/components/input-otp/src/input-otp-segment.tsx (1 hunks)
  • packages/components/input-otp/src/input-otp.tsx (1 hunks)
  • packages/components/input-otp/src/use-input-otp.ts (1 hunks)
  • packages/components/input-otp/stories/input-otp.stories.tsx (1 hunks)
  • packages/components/input-otp/tsconfig.json (1 hunks)
  • packages/components/input-otp/tsup.config.ts (1 hunks)
  • packages/core/theme/src/components/index.ts (1 hunks)
  • packages/core/theme/src/components/input-otp.ts (1 hunks)
Files skipped from review due to trivial changes (2)
  • .changeset/spotty-flies-jump.md
  • packages/components/input-otp/tsconfig.json
Files skipped from review as they are similar to previous changes (9)
  • packages/components/input-otp/tests/input-otp.test.tsx
  • packages/components/input-otp/package.json
  • packages/components/input-otp/src/index.ts
  • packages/components/input-otp/src/input-otp-segment.tsx
  • packages/components/input-otp/src/use-input-otp.ts
  • packages/components/input-otp/stories/input-otp.stories.tsx
  • packages/components/input-otp/tsup.config.ts
  • packages/core/theme/src/components/index.ts
  • packages/core/theme/src/components/input-otp.ts
Additional context used
LanguageTool
packages/components/input-otp/README.md

[style] ~3-~3: Consider using the synonym “brief” (= concise, using a few words, not lasting long) to strengthen your wording.
Context: # @nextui-org/input-otp A Quick description of the component > This is...

(QUICK_BRIEF)


[typographical] ~17-~17: Usually, a comma is necessary before ‘Yes’ at the end of a sentence. Did you mean “, please”?
Context: ...-org/input-otp ``` ## Contribution Yes please! See the [contributing guidelines](http...

(COMMA_BEFORE_PLEASE)

Additional comments not posted (3)
packages/components/input-otp/src/input-otp.tsx (3)

35-51: LGTM!

The Segments Section is implemented correctly:

  • The use of useMemo is appropriate to memoize the segment components and avoid unnecessary re-renders.
  • The Array.from(Array(otplength)) pattern is used effectively to create an array of the specified length for mapping over.
  • The InputOtpSegment component is rendered with the required props, and the key prop is correctly set using the index to ensure unique keys for each segment.

53-59: LGTM!

The Input Section is implemented correctly:

  • The use of useMemo is appropriate to memoize the input element and avoid unnecessary re-renders.
  • The input element is correctly rendered with the props returned by the getInputProps function from the useInputOtp hook.
  • The input element is wrapped in a div element with props returned by the getInputWrapperProps function from the useInputOtp hook.

61-82: LGTM!

The Helper Section is implemented correctly:

  • The use of useMemo is appropriate to memoize the helper section and avoid unnecessary re-renders.
  • The helper section is conditionally rendered based on the hasHelper prop.
  • The error message is conditionally rendered based on the isInvalid and errorMessage props.
  • The description is rendered if there is no error message.
  • The helper section is wrapped in a div element with props returned by the getHelperWrapperProps function from the useInputOtp hook.
  • The error message and description are wrapped in div elements with props returned by the getErrorMessageProps and getDescriptionProps functions from the useInputOtp hook, respectively.

@macci001 macci001 force-pushed the macci001/add-input-otp-component branch from 19d9bf5 to 9c8ed60 Compare September 16, 2024 18:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature Request] Input OTP
2 participants