Skip to content

fix: autofocus and keyboard navigation issues#3328

Merged
gupta-piyush19 merged 3 commits intomainfrom
auto-focus-fix
Oct 10, 2024
Merged

fix: autofocus and keyboard navigation issues#3328
gupta-piyush19 merged 3 commits intomainfrom
auto-focus-fix

Conversation

@Dhruwang
Copy link
Member

@Dhruwang Dhruwang commented Oct 8, 2024

What does this PR do?

Fixes #3089

Fixes autofocus and keyboard navigation across all questions

How should this be tested?

Check keyboard navigation for questions

Checklist

Required

  • Filled out the "How to test" section in this PR
  • Read How we Code at Formbricks
  • Self-reviewed my own code
  • Commented on my code in hard-to-understand bits
  • Ran pnpm build
  • Checked for warnings, there are none
  • Removed all console.logs
  • Merged the latest changes from main onto my branch with git pull origin main
  • My changes don't cause any responsiveness issues
  • First PR at Formbricks? Please sign the CLA! Without it we wont be able to merge it 🙏

Appreciated

  • If a UI change was made: Added a screen recording or screenshots to this PR
  • Updated the Formbricks Docs if changes were necessary

Summary by CodeRabbit

  • New Features

    • Enhanced accessibility with conditional focus management for various question components.
    • Improved tab navigation by introducing tabIndex properties based on the current question state.
  • Bug Fixes

    • Adjusted button focus behavior to ensure only the current question's buttons are focusable, improving keyboard navigation.
  • Style

    • Updated button layouts to use a row-reverse flexbox arrangement for better visual structure.

@vercel
Copy link

vercel bot commented Oct 8, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
formbricks-cloud ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 10, 2024 11:53am
1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
formbricks-docs ⬜️ Ignored (Inspect) Visit Preview Oct 10, 2024 11:53am

@github-actions github-actions bot added the bug Something isn't working label Oct 8, 2024
@github-actions
Copy link
Contributor

github-actions bot commented Oct 8, 2024

Thank you for following the naming conventions for pull request titles! 🙏

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 8, 2024

Walkthrough

The pull request introduces several modifications across various components in the survey application, primarily focused on improving the management of input field focus based on the current question state. Key changes include the introduction of a new isCurrent variable to conditionally manage the tabIndex and focus properties of buttons and input fields, ensuring only relevant fields are auto-focused and accessible. Additionally, the layout of buttons has been adjusted in some components to enhance user experience during form navigation.

Changes

File Path Change Summary
packages/surveys/src/components/general/WelcomeCard.tsx Modified focus prop of SubmitButton to be conditional on isCurrent. Introduced tabIndex prop for better keyboard navigation.
packages/surveys/src/components/questions/CTAQuestion.tsx Introduced isCurrent constant for determining current question state, modified tabIndex and focus properties of buttons.
packages/surveys/src/components/questions/OpenTextQuestion.tsx Added isCurrent for focus management, modified button layout and rendering logic.
apps/web/app/s/[surveyId]/components/LegalFooter.tsx Added tabIndex={-1} to three <Link> elements to prevent them from being focusable via keyboard navigation.

Assessment against linked issues

Objective Addressed Explanation
Input should be auto-focussed similar to Typeform (#3089)

Possibly related PRs

  • fix: Added DialogTitle and DialogDescrtiption components to the dialog. #3146: The changes in the ShareEmbedSurvey.tsx and ShareSurveyResults.tsx files involve the addition of DialogTitle and DialogDescription components, which enhance accessibility and semantic structure, similar to the focus and tab management improvements made in the WelcomeCard and CTAQuestion components.
  • feat: Data table for persons #3154: The PersonTable.tsx and ResponseTable.tsx modifications include enhancements to focus management and accessibility, which relate to the focus and tab navigation improvements in the WelcomeCard component.
  • fix: keyboard opening unexpectedly #3278: The fix for the unexpected keyboard opening in the OpenTextQuestion component relates to the focus management changes in the WelcomeCard and CTAQuestion components, as both address user interaction and focus behavior in survey questions.

Suggested labels

🙋🏻‍♂️help wanted, 🕹️ oss.gg, 🕹️ 50 points

🐰 In the fields where questions bloom,
A focus change dispels the gloom.
With every click, a field's embrace,
Auto-focussed, we find our place.
So hop along, let typing start,
With every question, we play our part! 🐇✨


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 gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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.

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: 3

🧹 Outside diff range and nitpick comments (21)
packages/surveys/src/components/questions/CalQuestion.tsx (3)

92-96: Good improvement for keyboard navigation

The addition of the tabIndex prop to the SubmitButton, conditionally set based on isCurrent, is an excellent improvement for keyboard navigation. This ensures that only the active question's submit button is focusable, which aligns perfectly with the PR's objective.

Consider extracting the tabIndex logic into a variable for better readability:

const buttonTabIndex = isCurrent ? 0 : -1;

Then use it in both SubmitButton and BackButton components.


105-105: Consistent improvement for BackButton

The addition of the tabIndex prop to the BackButton, consistent with the SubmitButton changes, is a good improvement for keyboard navigation. This ensures that the back button is only focusable when the question is current.

For consistency, consider applying the same extraction of tabIndex logic as suggested for the SubmitButton:

const buttonTabIndex = isCurrent ? 0 : -1;

Use this variable for both SubmitButton and BackButton to maintain consistency and improve code readability.


Line range hint 1-110: Summary: Excellent improvements for autofocus and keyboard navigation

Overall, the changes in this file significantly improve the autofocus and keyboard navigation issues, directly addressing the objectives outlined in PR #3328 and the linked issue #3089. The introduction of the isCurrent variable and its use in managing tabIndex for both SubmitButton and BackButton components ensures that only the active question's buttons are focusable, enhancing the user experience.

Key improvements:

  1. Conditional rendering of the SubmitButton based on question requirements.
  2. Proper focus management for both SubmitButton and BackButton using tabIndex.
  3. Layout adjustments to improve the overall structure of the form.

These changes collectively contribute to a more streamlined and accessible form navigation, similar to the Typeform functionality mentioned in the PR objectives.

To further enhance the implementation:

  1. Consider extracting the tabIndex logic into a shared variable for both buttons.
  2. Evaluate the necessity of the empty <div> and remove if not required for layout purposes.
  3. If not already done, ensure these focus management improvements are consistently applied across all question types in the survey.
packages/surveys/src/components/questions/CTAQuestion.tsx (1)

76-76: Excellent improvements to button focus and tabIndex

These changes directly address the PR's objective of improving keyboard navigation and autofocus:

  1. The conditional tabIndex ensures only the current question's button is focusable, enhancing keyboard navigation.
  2. The conditional focus prop applies autofocus only to the current question when enabled, addressing the issue in the linked bug report.

These modifications align well with the expected behavior described in the PR objectives, similar to Typeform functionality.

For consistency, consider applying the same tabIndex condition to the SubmitButton as well:

<SubmitButton
  buttonLabel={getLocalizedValue(question.buttonLabel, languageCode)}
  isLastQuestion={isLastQuestion}
+ tabIndex={isCurrent ? 0 : -1}
  focus={isCurrent ? autoFocusEnabled : false}
  onClick={() => {
    // ... (existing code)
  }}
  type="button"
/>

This change would ensure consistent keyboard navigation behavior across all buttons in the question.

Also applies to: 91-91

packages/surveys/src/components/questions/FileUploadQuestion.tsx (1)

115-115: LGTM: Improved keyboard navigation for BackButton

The addition of the tabIndex prop to the BackButton, conditional on isCurrent, is a good improvement for keyboard navigation. This change is consistent with the modifications made to the SubmitButton and aligns well with the PR's objectives.

For consistency, consider extracting the tabIndex logic into a variable:

const buttonTabIndex = isCurrent ? 0 : -1;

Then use this variable for both SubmitButton and BackButton:

<SubmitButton tabIndex={buttonTabIndex} ... />
...
<BackButton tabIndex={buttonTabIndex} ... />

This would make the code more DRY and easier to maintain.

packages/surveys/src/components/questions/OpenTextQuestion.tsx (3)

99-99: LGTM: Enhanced keyboard navigation

The addition of the dynamic tabIndex attribute improves keyboard navigation by making only the current question focusable. This change aligns well with the PR objectives and accessibility best practices.

Consider adding an aria-label attribute to the input for better screen reader support. For example:

 <input
   ref={openTextRef}
   tabIndex={isCurrent ? 1 : -1}
+  aria-label={getLocalizedValue(question.headline, languageCode)}
   name={question.id}
   id={question.id}
   // ... other attributes
 />

118-118: LGTM: Consistent keyboard navigation for long-answer questions

The addition of the dynamic tabIndex attribute to the textarea element is consistent with the input element modification and improves keyboard navigation for long-answer questions.

For consistency with the input element, consider adding an aria-label attribute to the textarea as well:

 <textarea
   ref={openTextRef}
   rows={3}
   name={question.id}
   tabIndex={isCurrent ? 1 : -1}
-  aria-label="textarea"
+  aria-label={getLocalizedValue(question.headline, languageCode)}
   id={question.id}
   // ... other attributes
 />

139-143: LGTM: Consistent button placement

The relocation of the SubmitButton component to the beginning of the button container is consistent with the layout changes and doesn't introduce any functional issues.

The empty onClick handler on the SubmitButton component seems unnecessary. Consider removing it if it's not needed:

 <SubmitButton
   buttonLabel={getLocalizedValue(question.buttonLabel, languageCode)}
   isLastQuestion={isLastQuestion}
-  onClick={() => {}}
 />

If there's a specific reason for including an empty onClick handler, please add a comment explaining why it's necessary.

packages/surveys/src/components/questions/ContactInfoQuestion.tsx (1)

104-112: LGTM: Implementation of contactInfoRef for autofocus

The contactInfoRef callback effectively implements the autofocus functionality, addressing a key objective of the PR. The use of useCallback for memoization is a good performance consideration.

Consider adding a small delay before focusing to ensure smooth transitions, especially in cases of animations:

if (question.id && currentElement && autoFocusEnabled && question.id === currentQuestionId) {
  setTimeout(() => currentElement.focus(), 100);
}

This can help prevent potential issues with focus being applied before animations or renders complete.

packages/surveys/src/components/questions/NPSQuestion.tsx (2)

95-95: LGTM: Enhanced keyboard navigation

The conditional tabIndex improves keyboard navigation by making labels focusable only for the current question. This is an excellent accessibility improvement.

Consider extracting the tabIndex logic into a separate variable for better readability:

const labelTabIndex = isCurrent ? 0 : -1;

Then use it in the JSX:

tabIndex={labelTabIndex}

This would make the code more maintainable and easier to understand at a glance.


145-152: LGTM: Improved button rendering and focus management

The conditional rendering of the SubmitButton for non-required questions and the addition of the tabIndex prop are good improvements. They enhance the form's usability and keyboard navigation.

For consistency with the label implementation, consider extracting the tabIndex logic:

const buttonTabIndex = isCurrent ? 0 : -1;

Then use it in both SubmitButton and BackButton:

<SubmitButton
  tabIndex={buttonTabIndex}
  // ... other props
/>

<BackButton
  tabIndex={buttonTabIndex}
  // ... other props
/>

This would make the code more consistent and easier to maintain.

packages/surveys/src/components/questions/MatrixQuestion.tsx (2)

152-152: Great implementation of focus management!

The use of isCurrent to control the tabIndex is an excellent way to implement the desired keyboard navigation behavior. This ensures that only the cells of the current question are focusable, which aligns perfectly with the PR objectives.

For slightly improved readability, consider using a constant for the non-focusable tabIndex value:

const NON_FOCUSABLE_TAB_INDEX = -1;
// ...
tabIndex={isCurrent ? 0 : NON_FOCUSABLE_TAB_INDEX}

This makes the intent clearer and allows for easier updates if the non-focusable value needs to change in the future.


199-204: Excellent focus management for navigation buttons!

The addition of the tabIndex prop to both the SubmitButton and BackButton components, using the isCurrent constant, is a great implementation of focus management for the navigation buttons. This ensures that these buttons are only focusable when the current question is active, which aligns perfectly with the PR objectives of improving keyboard navigation.

For consistency with the earlier suggestion, consider using the same constant for the non-focusable tabIndex value:

const NON_FOCUSABLE_TAB_INDEX = -1;
// ...
<SubmitButton
  // ...
  tabIndex={isCurrent ? 0 : NON_FOCUSABLE_TAB_INDEX}
/>
// ...
<BackButton
  // ...
  tabIndex={isCurrent ? 0 : NON_FOCUSABLE_TAB_INDEX}
/>

This would maintain consistency throughout the component and make future updates easier.

Also applies to: 206-211

packages/surveys/src/components/questions/PictureSelectionQuestion.tsx (2)

117-117: LGTM: Improved keyboard navigation with dynamic tabIndex

The update to the tabIndex attribute enhances keyboard navigation by making labels focusable only when the question is current. This change aligns well with the PR objective of improving keyboard navigation.

Consider adding an aria-label to provide more context for screen readers, especially when the label is not focusable:

 <label
   key={choice.id}
   tabIndex={isCurrent ? 0 : -1}
+  aria-label={isCurrent ? `Select ${choice.imageUrl.split("/").pop()}` : `${choice.imageUrl.split("/").pop()} (not selectable)`}
   htmlFor={choice.id}
   // ... rest of the label properties
 >

Line range hint 1-224: Overall LGTM: Effective improvements to keyboard navigation and focus management

The changes in this file successfully address the PR objectives related to autofocus and keyboard navigation issues. The introduction of the isCurrent variable and its consistent use throughout the component improves code readability and maintainability. The updates to tabIndex attributes for labels, SubmitButton, and BackButton enhance keyboard navigation significantly.

To further improve accessibility, consider adding appropriate aria-label or aria-describedby attributes to the main form elements. This would provide more context for screen readers, especially when elements are not focusable. For example:

<form
  key={question.id}
  onSubmit={...}
  className="fb-w-full"
  aria-labelledby={`question-${question.id}-headline`}
>
  {/* ... */}
  <Headline
    headline={getLocalizedValue(question.headline, languageCode)}
    questionId={question.id}
    required={question.required}
    id={`question-${question.id}-headline`}
  />
  {/* ... */}
</form>

This change would tie the form more closely to its headline for screen readers, improving the overall accessibility of the component.

packages/surveys/src/components/general/QuestionConditional.tsx (1)

Line range hint 1-318: Summary: Autofocus functionality successfully implemented across question types.

The changes made to the QuestionConditional component effectively implement the autofocus functionality as per the PR objectives. The autoFocusEnabled prop has been added to the component's props interface and correctly passed down to the AddressQuestion and ContactInfoQuestion components. These changes should improve the user experience by allowing for more granular control over autofocus behavior in different question types.

To ensure full coverage of the autofocus functionality:

  1. Verify that all other question type components (e.g., OpenTextQuestion, MultipleChoiceSingleQuestion, etc.) also implement the autoFocusEnabled prop correctly.
  2. Consider adding unit tests to verify the behavior of the autoFocusEnabled prop across different question types.
  3. Update the component documentation to reflect the new autoFocusEnabled prop and its usage.

Would you like assistance in generating a script to verify the implementation of autoFocusEnabled across all question type components?

packages/surveys/src/components/questions/RankingQuestion.tsx (2)

151-156: Excellent improvement to keyboard accessibility

The addition of conditional tabIndex and keyboard event handling significantly enhances the accessibility and usability of the ranking items. This change directly addresses the PR's objectives for improving keyboard navigation.

A minor suggestion for improvement:

Consider adding keyboard navigation for the "up" and "down" actions as well. For example:

onKeyDown={(e) => {
  if (e.key === " ") {
    handleItemClick(item);
  } else if (e.key === "ArrowUp") {
    handleMove(item.id, "up");
  } else if (e.key === "ArrowDown") {
    handleMove(item.id, "down");
  }
}}

This would provide a more complete keyboard navigation experience for users.


242-247: Improved button layout and focus management

The changes to the button layout and SubmitButton properties enhance both the visual arrangement and keyboard navigation. The conditional tabIndex on the SubmitButton is consistent with the overall focus management strategy.

A minor suggestion for improvement:

Consider adding an aria-label to the SubmitButton to improve accessibility, especially if the button text might not be descriptive enough on its own. For example:

<SubmitButton
  tabIndex={isCurrent ? 0 : -1}
  buttonLabel={getLocalizedValue(question.buttonLabel, languageCode)}
  isLastQuestion={isLastQuestion}
  aria-label={`Submit answer for ${getLocalizedValue(question.headline, languageCode)}`}
/>

This would provide more context to screen reader users about the purpose of the button.

packages/surveys/src/components/questions/MultipleChoiceSingleQuestion.tsx (1)

136-136: LGTM: Enhanced keyboard navigation

The update to the label's tabIndex improves keyboard navigation by making the label focusable only when the question is current. This aligns well with the PR objective of enhancing keyboard navigation and accessibility.

For consistency, consider using a constant or a utility function for the tabIndex values, e.g.:

const getTabIndex = (isCurrent: boolean) => isCurrent ? 0 : -1;

Then use it like this:

tabIndex={getTabIndex(isCurrent)}

This would make it easier to maintain and update the tabIndex logic across the component if needed in the future.

packages/surveys/src/components/questions/RatingQuestion.tsx (2)

Line range hint 141-158: Great accessibility improvements

The changes to the number rating label significantly improve keyboard navigation and accessibility:

  1. The conditional tabIndex ensures only the current question is focusable.
  2. The onKeyDown handler allows selection using the space bar, enhancing keyboard accessibility.

These improvements align well with the PR objectives.

Consider adding an aria-label to the label element to provide more context for screen readers. For example:

aria-label={`Rating ${number} out of ${question.range}`}

Line range hint 170-187: Consistent accessibility improvements for star rating

The changes to the star rating label mirror the improvements made to the number rating label:

  1. Conditional tabIndex for focused navigation.
  2. onKeyDown handler for keyboard selection.

This consistency is excellent for maintaining a uniform user experience across different rating types.

Similar to the number rating, consider adding an aria-label here as well:

aria-label={`${number} star${number !== 1 ? 's' : ''} out of ${question.range}`}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ed7662b and 6970df0.

📒 Files selected for processing (19)
  • packages/surveys/src/components/general/EndingCard.tsx (1 hunks)
  • packages/surveys/src/components/general/Input.tsx (1 hunks)
  • packages/surveys/src/components/general/QuestionConditional.tsx (2 hunks)
  • packages/surveys/src/components/general/WelcomeCard.tsx (1 hunks)
  • packages/surveys/src/components/questions/AddressQuestion.tsx (5 hunks)
  • packages/surveys/src/components/questions/CTAQuestion.tsx (3 hunks)
  • packages/surveys/src/components/questions/CalQuestion.tsx (2 hunks)
  • packages/surveys/src/components/questions/ConsentQuestion.tsx (5 hunks)
  • packages/surveys/src/components/questions/ContactInfoQuestion.tsx (6 hunks)
  • packages/surveys/src/components/questions/DateQuestion.tsx (3 hunks)
  • packages/surveys/src/components/questions/FileUploadQuestion.tsx (2 hunks)
  • packages/surveys/src/components/questions/MatrixQuestion.tsx (3 hunks)
  • packages/surveys/src/components/questions/MultipleChoiceMultiQuestion.tsx (5 hunks)
  • packages/surveys/src/components/questions/MultipleChoiceSingleQuestion.tsx (5 hunks)
  • packages/surveys/src/components/questions/NPSQuestion.tsx (4 hunks)
  • packages/surveys/src/components/questions/OpenTextQuestion.tsx (4 hunks)
  • packages/surveys/src/components/questions/PictureSelectionQuestion.tsx (3 hunks)
  • packages/surveys/src/components/questions/RankingQuestion.tsx (5 hunks)
  • packages/surveys/src/components/questions/RatingQuestion.tsx (5 hunks)
🧰 Additional context used
🔇 Additional comments (72)
packages/surveys/src/components/general/Input.tsx (4)

3-3: LGTM: Correct import for forwardRef

The import statement for forwardRef from "preact/compat" is correctly added. This is necessary for implementing ref forwarding in Preact components.


9-9: Excellent use of forwardRef for enhanced component flexibility

The Input component has been correctly updated to use forwardRef. This change allows the component to accept and forward a ref to the underlying input element. The type annotations are accurate, using HTMLInputElement for the ref type and InputProps for the props type.

This modification enhances the component's reusability and allows parent components to directly interact with the input element, which is particularly useful for focus management and other DOM manipulations. This aligns well with the PR's objective of improving autofocus and keyboard navigation.


13-13: Correct implementation of ref forwarding

The ref is properly forwarded to the input element. This implementation allows parent components to access the underlying input element directly, which is crucial for the autofocus and keyboard navigation improvements targeted by this PR.

The explanatory comment is helpful for code maintainability and clarity.


1-21: Summary: Excellent modifications to support autofocus and keyboard navigation

The changes made to the Input component in this file are well-implemented and directly support the PR's objective of improving autofocus and keyboard navigation. By using forwardRef and properly forwarding the ref to the input element, this component now allows for more precise control over focus management.

These modifications lay a solid foundation for addressing the autofocus issues mentioned in the linked bug report (#3089). The ability to directly access the input element from parent components will be crucial in implementing the desired auto-focus behavior across form fields.

Great job on these changes! They are concise, well-documented, and align perfectly with the PR's goals.

packages/surveys/src/components/questions/CalQuestion.tsx (1)

47-47: LGTM: Good addition for managing question state

The introduction of the isCurrent variable is a good practice. It clearly indicates whether the current question is active, which will be useful for managing focus and interaction states throughout the component.

packages/surveys/src/components/questions/CTAQuestion.tsx (3)

44-44: Excellent addition of the isCurrent constant

This change enhances code readability and maintainability by extracting the comparison logic into a well-named constant. It aligns well with the PR's objective of improving autofocus and keyboard navigation across questions.


45-45: Good use of the isCurrent constant in useTtc hook

This change consistently applies the newly introduced isCurrent constant, maintaining the same logic while improving code readability. It's a good follow-up to the previous change and contributes to better question state management.


Line range hint 1-106: Summary: Effective implementation addressing autofocus and keyboard navigation

The changes in this file successfully address the PR objectives related to autofocus and keyboard navigation issues. The implementation:

  1. Introduces a clear isCurrent flag for better state management.
  2. Improves keyboard navigation by conditionally setting tabIndex.
  3. Enhances autofocus behavior by conditionally setting the focus prop.

These modifications align well with the expected behavior described in the PR objectives and the linked issue #3089. The code is clean, readable, and consistent.

To ensure these changes have been applied consistently across all question types, please run the following script:

This script will help verify that the improvements have been consistently applied across all question types in the survey component.

packages/surveys/src/components/questions/FileUploadQuestion.tsx (4)

51-51: LGTM: Improved focus management

The introduction of the isCurrent variable is a good practice for managing focus and improving accessibility. It clearly determines whether the current question is active, which will be useful for conditional rendering and focus management later in the component.


107-107: Please clarify the reason for changing the button layout

The flex direction of the button container has been changed to row-reverse. While this might be intentional for improving keyboard navigation or visual layout, it's not immediately clear why this change was made. Could you please provide more context on the reasoning behind this layout modification? It's important to ensure that this change aligns with the PR's objective of improving keyboard navigation and doesn't negatively impact the user experience.


108-112: LGTM: Improved keyboard navigation for SubmitButton

The changes to the SubmitButton component are well-implemented:

  1. The button is now rendered unconditionally, ensuring it's always present.
  2. The addition of the tabIndex prop, conditional on isCurrent, improves keyboard navigation by only allowing focus when the question is active.

These modifications align well with the PR's objective of enhancing keyboard navigation and autofocus functionality.


Line range hint 1-124: Summary: Good progress on keyboard navigation, minor clarifications needed

Overall, the changes in this file significantly improve keyboard navigation and focus management for the FileUploadQuestion component, aligning well with the PR objectives. The introduction of the isCurrent variable and its use in managing tabIndex for buttons is a good practice.

Next steps:

  1. Clarify the reasoning behind the button container layout change (flex-row-reverse).
  2. Consider implementing the suggested improvement for consistency in tabIndex management.
  3. Ensure these changes are tested thoroughly, especially for keyboard navigation scenarios.

Great work on improving the accessibility of the form!

To verify the improvements in keyboard navigation, please run the following commands:

These tests will help ensure that the keyboard navigation improvements are consistently applied across all question components and that there are no potential accessibility issues introduced by the changes.

✅ Verification successful

Verification of Keyboard Navigation Enhancements

All question components consistently implement tabIndex based on currentQuestionId. No potential accessibility issues were detected.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent use of tabIndex and keyboard navigation improvements across all question components

# Test 1: Check for consistent use of tabIndex in question components
echo "Checking for consistent use of tabIndex in question components:"
rg --type typescript 'tabIndex=\{.*\}' packages/surveys/src/components/questions/

# Test 2: Verify the use of currentQuestionId for focus management
echo "Verifying use of currentQuestionId for focus management:"
rg --type typescript 'currentQuestionId' packages/surveys/src/components/questions/

# Test 3: Check for potential accessibility issues
echo "Checking for potential accessibility issues:"
npx eslint packages/surveys/src/components/questions/*.tsx --rule 'jsx-a11y/no-noninteractive-tabindex: error'

Length of output: 1688


Script:

#!/bin/bash
# Description: Check for consistent use of tabIndex and keyboard navigation improvements across all question components

# Test 1: Check for consistent use of tabIndex in question components
echo "Checking for consistent use of tabIndex in question components:"
rg --type tsx 'tabIndex=\{.*\}' packages/surveys/src/components/questions/

# Test 2: Verify the use of currentQuestionId for focus management
echo "Verifying use of currentQuestionId for focus management:"
rg --type tsx 'currentQuestionId' packages/surveys/src/components/questions/

# Test 3: Check for potential accessibility issues by searching for non-interactive elements with tabIndex
echo "Checking for potential accessibility issues (elements with tabIndex):"
rg --type tsx '<[^>]+tabIndex=' packages/surveys/src/components/questions/

Length of output: 723


Script:

#!/bin/bash
# Description: Check for consistent use of tabIndex and keyboard navigation improvements across all question components

# Test 1: Check for consistent use of tabIndex in question components
echo "Checking for consistent use of tabIndex in question components:"
rg --type typescriptreact 'tabIndex=\{.*\}' packages/surveys/src/components/questions/

# Test 2: Verify the use of currentQuestionId for focus management
echo "Verifying use of currentQuestionId for focus management:"
rg --type typescriptreact 'currentQuestionId' packages/surveys/src/components/questions/

# Test 3: Check for potential accessibility issues by searching for non-interactive elements with tabIndex
echo "Checking for potential accessibility issues (elements with tabIndex):"
rg --type typescriptreact '<[^>]+tabIndex=' packages/surveys/src/components/questions/

Length of output: 795


Script:

#!/bin/bash
# Description: Check for consistent use of tabIndex and keyboard navigation improvements across all question components

# Test 1: Check for consistent use of tabIndex in question components
echo "Checking for consistent use of tabIndex in question components:"
rg --glob '*.tsx' 'tabIndex=\{.*\}' packages/surveys/src/components/questions/

# Test 2: Verify the use of currentQuestionId for focus management
echo "Verifying use of currentQuestionId for focus management:"
rg --glob '*.tsx' 'currentQuestionId' packages/surveys/src/components/questions/

# Test 3: Check for potential accessibility issues by searching for non-interactive elements with tabIndex
echo "Checking for potential accessibility issues (elements with tabIndex):"
rg --glob '*.tsx' '<[^>]+tabIndex=' packages/surveys/src/components/questions/

Length of output: 14505

packages/surveys/src/components/general/EndingCard.tsx (1)

131-131: Improved focus management for SubmitButton

This change enhances the focus behavior of the SubmitButton component, aligning well with the PR objectives to improve autofocus and keyboard navigation. By conditionally setting the focus prop based on both isCurrent and autoFocusEnabled, it ensures that:

  1. The submit button is only focused when the card is current and autofocus is enabled.
  2. Unnecessary focus on submit buttons of non-current cards is prevented, improving overall keyboard navigation.

This implementation effectively addresses the issue described in #3089, where input fields were not automatically gaining focus after submission.

packages/surveys/src/components/questions/OpenTextQuestion.tsx (2)

47-47: LGTM: Improved focus management

The addition of the isCurrent variable is a good approach to determine the active question. This change aligns well with the PR objective of improving focus management and keyboard navigation.


138-138: Improved button layout, but consider tab order

The change to fb-flex fb-flex-row-reverse improves the visual layout by placing the submit button on the right, which aligns with common UX patterns. However, this modification might affect the tab order, potentially causing accessibility issues.

To ensure this change doesn't negatively impact accessibility, please verify the tab order remains logical. Consider using the order CSS property instead of flex-row-reverse to maintain the visual order while preserving the logical tab order:

- <div className="fb-flex fb-flex-row-reverse fb-w-full fb-justify-between fb-px-6 fb-py-4">
+ <div className="fb-flex fb-w-full fb-justify-between fb-px-6 fb-py-4">
+   <div className="fb-order-2">
      <SubmitButton ... />
+   </div>
+   <div className="fb-order-1">
      {!isFirstQuestion && (
        <BackButton ... />
      )}
+   </div>
  </div>

This approach would maintain the desired visual layout while ensuring a logical tab order for keyboard navigation.

packages/surveys/src/components/general/WelcomeCard.tsx (1)

164-164: Improved focus management for better user experience

This change enhances the focus behavior of the submit button by considering both the isCurrent state and autoFocusEnabled prop. It ensures that the button only receives focus when the card is current and autofocus is enabled, which aligns with the PR objective of improving autofocus and keyboard navigation.

This modification prevents unintended focus on non-current cards, leading to a more intuitive user experience similar to Typeform, as mentioned in the PR objectives.

packages/surveys/src/components/questions/AddressQuestion.tsx (5)

10-10: LGTM: Import of useCallback is appropriate.

The addition of useCallback from 'react' is consistent with its usage in the component for optimizing the addressRef function.


27-27: LGTM: autoFocusEnabled prop added correctly.

The autoFocusEnabled boolean prop has been appropriately added to both the AddressQuestionProps interface and the component's props. This addition aligns with the PR objective to improve autofocus functionality.

Also applies to: 42-42


51-51: LGTM: isCurrent variable improves code readability.

The addition of the isCurrent variable enhances code readability and is used consistently for managing focus and tab indices. This aligns well with the PR objectives for improving keyboard navigation.


109-117: LGTM: addressRef callback implements autofocus correctly.

The addressRef callback is well-implemented using useCallback for performance optimization. It correctly handles the autofocus functionality based on the current question and the autoFocusEnabled prop. The dependency array is properly set, ensuring the callback updates when necessary.


162-163: LGTM: JSX changes improve keyboard navigation, but verify button order.

The changes to the Input, SubmitButton, and BackButton components correctly implement the improved focus management and keyboard navigation. The use of addressRef and dynamic tabIndex values based on isCurrent aligns well with the PR objectives.

However, please note the change in the button container's flex direction to row-reverse. While this doesn't affect functionality, it may change the visual order of the buttons.

Could you please verify that the new button order matches the intended design? You can run the following command to check for any related design specifications:

Also applies to: 171-177, 181-181

packages/surveys/src/components/questions/ContactInfoQuestion.tsx (6)

9-9: LGTM: Import and prop additions for autofocus functionality

The new imports (useCallback, useRef) and the autoFocusEnabled prop are appropriate additions for implementing the autofocus functionality. These changes align well with the PR's objective of addressing autofocus issues.

Also applies to: 27-27, 42-42


48-48: LGTM: Addition of isCurrent for improved navigation

The isCurrent constant is a good addition for managing the current question state. It's effectively used to control tabIndex values, which improves keyboard navigation as per the PR objectives.


157-157: LGTM: Input component enhancements for focus and navigation

The additions to the Input component effectively implement the autofocus and keyboard navigation improvements:

  1. The ref prop on the first input ensures proper initial focus.
  2. The conditional tabIndex ensures that only inputs in the current question are keyboard accessible.

These changes align perfectly with the PR objectives.

Also applies to: 165-165


174-174: Please clarify the reason for changing the flex direction

The change from flex-row to flex-row-reverse for the button container will alter the visual layout of the buttons. While this doesn't directly relate to the autofocus or keyboard navigation objectives of the PR, it may impact the user experience.

Could you please explain the reasoning behind this change? Is it intentional, and if so, what improvement does it bring to the form's usability or design?


175-180: LGTM: Button enhancements for keyboard navigation

The addition of the conditional tabIndex prop to both the SubmitButton and BackButton components is an excellent improvement for keyboard navigation. This ensures that only the buttons in the current question are keyboard accessible, which aligns perfectly with the PR objectives of enhancing keyboard navigation.

Also applies to: 183-183


Line range hint 1-195: Overall assessment: Improvements align well with PR objectives

The changes in this file effectively address the autofocus and keyboard navigation issues as per the PR objectives. Key improvements include:

  1. Implementation of autoFocusEnabled prop and contactInfoRef for managing focus.
  2. Addition of isCurrent check and conditional tabIndex values for better keyboard navigation.
  3. Enhancements to Input and Button components to support these features.

These changes should significantly improve the user experience when navigating through the form questions.

There's one point that needs clarification:

  • The change in flex direction for the button container (line 174).

Once this is addressed, the implementation looks solid and ready for integration.

packages/surveys/src/components/questions/NPSQuestion.tsx (4)

45-45: LGTM: Improved focus management

The addition of the isCurrent variable is a good approach for determining the active question. This aligns well with the PR objectives of improving autofocus and keyboard navigation.


155-155: LGTM: Consistent focus management for BackButton

The addition of the tabIndex prop to the BackButton is consistent with the SubmitButton implementation and improves keyboard navigation. This change aligns well with the PR objectives.

As mentioned in the previous comment, consider using the extracted buttonTabIndex variable here for consistency and maintainability.


Line range hint 1-168: Summary: Good improvements to accessibility and focus management

Overall, the changes in this file significantly improve the accessibility and keyboard navigation of the NPS question component, aligning well with the PR objectives. Here's a summary of the key points:

  1. The introduction of the isCurrent variable effectively manages focus for the active question.
  2. The conditional tabIndex attributes on labels and buttons enhance keyboard navigation.
  3. The conditional rendering of the SubmitButton for non-required questions is a logical improvement.

To further enhance the code:

  1. Consider extracting the tabIndex logic into variables for better readability and consistency.
  2. Clarify the accessibility approach for setting tabIndex={-1} on input elements, ensuring it doesn't negatively impact screen reader or keyboard-only users.

These changes represent a significant step towards improving the user experience, especially for users relying on keyboard navigation or assistive technologies.


130-130: Please clarify the accessibility approach for input elements

Setting tabIndex={-1} on the input element prevents it from receiving focus via keyboard navigation. While making the label focusable instead can be a valid accessibility pattern, it's important to ensure that this approach doesn't negatively impact screen reader users or keyboard-only users.

Could you please provide more context on this decision? Have you tested this with various assistive technologies to ensure it provides a good user experience for all users?

To help verify the accessibility of this approach, you could run the following automated checks:

packages/surveys/src/components/questions/MatrixQuestion.tsx (3)

45-45: Excellent addition for focus management!

The isCurrent constant is a key improvement that aligns with the PR objective of enhancing keyboard navigation. It will be used to dynamically control the tabIndex of various elements, ensuring that only the current question is focusable. This change is crucial for creating a more accessible and user-friendly form navigation experience.


198-198: Please clarify the reason for changing the flex direction.

The flex direction of the button container has been changed to flex-row-reverse. While this doesn't directly relate to the focus management or keyboard navigation objectives of the PR, it does affect the visual layout of the buttons.

Could you please explain the reasoning behind this change? Is it to match a specific design requirement or to improve the user experience in some way?


Line range hint 1-215: Overall excellent implementation of focus management and keyboard navigation!

The changes made to the MatrixQuestion component effectively address the PR objectives of improving autofocus and keyboard navigation. The introduction of the isCurrent constant and its consistent use throughout the component ensures that only the active question and its elements are focusable. This significantly enhances the user experience, especially for keyboard users.

A few minor suggestions have been made for improved clarity and consistency, but these are not critical. The overall implementation is solid and achieves the desired functionality.

To fully validate the changes:

  1. Ensure that the focus behavior works as expected across different question types in the survey.
  2. Test the keyboard navigation flow to confirm it matches the intended user experience.
  3. Verify that these changes resolve the specific issues mentioned in the linked bug report (#3089).

Great work on improving the accessibility and usability of the survey component!

packages/surveys/src/components/questions/PictureSelectionQuestion.tsx (3)

44-45: LGTM: Improved code readability with isCurrent variable

The introduction of the isCurrent variable is a good refactoring. It simplifies condition checking and improves code readability. This change also reduces the potential for errors when checking if the current question is active.


199-204: LGTM: Improved SubmitButton placement and accessibility

The relocation of the SubmitButton within the flex container improves the logical flow of the form. The addition of the tabIndex prop, controlled by the isCurrent variable, enhances keyboard navigation by making the button focusable only when the question is current. These changes align well with the PR objectives of improving keyboard navigation and addressing autofocus issues.


207-207: LGTM: Enhanced BackButton accessibility

The addition of the tabIndex prop to the BackButton, controlled by the isCurrent variable, improves keyboard navigation. This change makes the BackButton focusable only when the question is current, which is consistent with the behavior of the SubmitButton. This enhancement aligns well with the PR objective of improving keyboard navigation.

packages/surveys/src/components/questions/DateQuestion.tsx (6)

95-95: LGTM: Introduction of isCurrent variable

The addition of the isCurrent variable is a good approach to determine if the current question is active. This will help in managing focus and keyboard navigation, addressing the issues mentioned in the PR objectives.


Line range hint 165-170: Improved keyboard accessibility for date picker button

Great job on enhancing the keyboard accessibility of the date picker button:

  1. The tabIndex is now conditionally set based on whether the question is current, which aligns with the PR objectives.
  2. The addition of the onKeyDown event handler allows users to open the date picker using the space key, further improving keyboard navigation.

These changes effectively address the keyboard navigation issues mentioned in the PR objectives.


258-258: Enhanced focus management for SubmitButton

The addition of the tabIndex prop to the SubmitButton, conditionally set based on isCurrent, is a good improvement. This ensures that the submit button is only focusable when the current question is active, contributing to better keyboard navigation as outlined in the PR objectives.


262-272: Improved BackButton rendering and accessibility

Excellent improvements to the BackButton component:

  1. Conditional rendering ensures the back button is only shown when it's not the first question.
  2. The addition of the tabIndex prop, conditionally set based on isCurrent, enhances keyboard navigation.
  3. The updated onClick handler now includes TTC (Time to Completion) tracking, which will be useful for measuring user interaction time.

These changes contribute to better navigation and user experience, aligning well with the PR objectives.


Line range hint 1-277: Overall assessment: Effective improvements to autofocus and keyboard navigation

The changes made to the DateQuestion component successfully address the autofocus and keyboard navigation issues mentioned in the PR objectives. Key improvements include:

  1. Introduction of the isCurrent variable to manage focus states.
  2. Enhanced keyboard accessibility for the date picker button.
  3. Improved focus management for SubmitButton and BackButton components.
  4. Better conditional rendering of the BackButton.
  5. Addition of TTC (Time to Completion) tracking for user interactions.

These modifications collectively contribute to a more accessible and user-friendly form navigation experience, aligning well with the intended goals of the PR.


256-256: Verify tab order with new flex layout

The change to use flex-row-reverse for the button container is noted. While this achieves the desired visual arrangement, it's important to ensure that it doesn't negatively impact the natural tab order of the buttons.

Please verify that the tab order of the buttons (from left to right: Submit, then Back) matches the visual order and user expectations. You can use the following script to check the tab order:

packages/surveys/src/components/general/QuestionConditional.tsx (3)

Line range hint 30-30: LGTM: Addition of autoFocusEnabled prop enhances component flexibility.

The addition of the autoFocusEnabled prop to the QuestionConditionalProps interface is a well-implemented change that directly addresses the PR's objective of improving autofocus functionality. This boolean prop will allow for fine-grained control over the autofocus behavior across different question types, enhancing the overall user experience.


315-315: LGTM: autoFocusEnabled prop correctly passed to ContactInfoQuestion.

The autoFocusEnabled prop is correctly passed to the ContactInfoQuestion component, which is in line with the PR objectives and the interface modification. This change enables control over the autofocus behavior specifically for contact information questions, potentially enhancing the user experience when inputting contact details.

To ensure this change is implemented correctly in the ContactInfoQuestion component, please run the following verification script:

#!/bin/bash
# Description: Verify the implementation of autoFocusEnabled in ContactInfoQuestion component

# Test: Check if ContactInfoQuestion component uses the autoFocusEnabled prop
rg --type typescript 'const ContactInfoQuestion.*autoFocusEnabled.*:.*boolean' packages/surveys/src/components/questions/ContactInfoQuestion.tsx

# Test: Verify the usage of autoFocusEnabled within the component
rg --type typescript 'autoFocusEnabled.*&&' packages/surveys/src/components/questions/ContactInfoQuestion.tsx

This script will help confirm that the ContactInfoQuestion component properly implements the autoFocusEnabled prop.


285-285: LGTM: autoFocusEnabled prop correctly passed to AddressQuestion.

The autoFocusEnabled prop is correctly passed to the AddressQuestion component, which is consistent with the PR objectives and the interface modification. This change allows for controlling the autofocus behavior specifically for address questions, potentially improving the user experience when filling out address information.

To ensure this change is implemented correctly in the AddressQuestion component, please run the following verification script:

This script will help confirm that the AddressQuestion component properly implements the autoFocusEnabled prop.

✅ Verification successful

Action Required: Update Verification Scripts for Accurate Results

The initial verification script targeted the wrong file and used an unrecognized file type. Please update the shell scripts to:

  • Search within AddressQuestion.tsx.
  • Use the correct file type identifier for TypeScript, such as ts.

Here's the updated script to run:

Please execute this script to ensure the autoFocusEnabled prop is correctly implemented in the AddressQuestion component.


Action Required: Verify autoFocusEnabled Prop Typing in AddressQuestion Component

The autoFocusEnabled prop is used within the AddressQuestion component, but its type declaration as boolean was not found. Please verify that autoFocusEnabled is explicitly typed as boolean in the component's props.

To assist with this verification, please run the following shell scripts:

This will confirm whether the autoFocusEnabled prop is correctly typed as boolean in the AddressQuestion component's props definition.


Verification Successful: autoFocusEnabled Prop is Correctly Typed

The autoFocusEnabled prop is explicitly defined as a boolean in the AddressQuestion component's props. Additionally, its usage within the component confirms that it is correctly implemented to control autofocus behavior.

  • Location Verified:
    • packages/surveys/src/components/questions/AddressQuestion.tsx
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of autoFocusEnabled in AddressQuestion component

# Test: Check if AddressQuestion component uses the autoFocusEnabled prop
rg --type typescript 'const AddressQuestion.*autoFocusEnabled.*:.*boolean' packages/surveys/src/components/questions/AddressQuestion.tsx

# Test: Verify the usage of autoFocusEnabled within the component
rg --type typescript 'autoFocusEnabled.*&&' packages/surveys/src/components/questions/AddressQuestion.tsx

Length of output: 328


Script:

#!/bin/bash
# Description: Verify the implementation of autoFocusEnabled in AddressQuestion component

# Test: Check if AddressQuestion component uses the autoFocusEnabled prop
rg --type ts 'const AddressQuestion.*autoFocusEnabled.*:.*boolean' packages/surveys/src/components/questions/AddressQuestion.tsx

# Test: Verify the usage of autoFocusEnabled within the component
rg --type ts 'autoFocusEnabled.*&&' packages/surveys/src/components/questions/AddressQuestion.tsx

Length of output: 330


Script:

#!/bin/bash
# Description: Verify the type declaration of autoFocusEnabled prop in AddressQuestion component

# Test: Find the props interface or type definition in AddressQuestion.tsx
rg --type ts '(interface|type)\s+\w+\s*{\s*[^}]*autoFocusEnabled\s*:\s*boolean\s*;?' packages/surveys/src/components/questions/AddressQuestion.tsx

# Test: Ensure autoFocusEnabled is defined as boolean in the props
rg --type ts 'autoFocusEnabled\s*:\s*boolean' packages/surveys/src/components/questions/AddressQuestion.tsx

Length of output: 465

packages/surveys/src/components/questions/RankingQuestion.tsx (5)

45-45: LGTM: Improved focus management with isCurrent variable

The introduction of the isCurrent variable is a good addition. It allows for better control over focus management and keyboard navigation, which directly addresses the PR's objectives.


181-181: LGTM: Consistent focus management for "up" button

Setting the tabIndex to -1 for the "up" button is consistent with the overall focus management strategy. This ensures that users can't tab to these buttons when they're not part of the current question, improving the navigation experience.


206-206: LGTM: Consistent focus management for "down" button

The tabIndex change for the "down" button mirrors the change made to the "up" button, maintaining a consistent focus management approach throughout the component.


251-251: LGTM: Consistent focus management for BackButton

The addition of a conditional tabIndex to the BackButton is consistent with the overall focus management strategy implemented in this component. This ensures that the BackButton is only focusable when the current question is active, improving the keyboard navigation experience.


Line range hint 1-260: Overall excellent improvements to accessibility and user experience

The changes made to the RankingQuestion component significantly enhance its accessibility and usability, particularly in terms of keyboard navigation and focus management. These improvements directly address the PR objectives of resolving autofocus and keyboard navigation issues.

Key improvements include:

  1. Introduction of the isCurrent variable for better focus control.
  2. Enhanced keyboard interaction for ranking items.
  3. Consistent focus management across all interactive elements (ranking items, up/down buttons, submit button, and back button).
  4. Improved button layout for better visual hierarchy.

These changes collectively create a more seamless and accessible experience for users navigating the survey using a keyboard, which is a substantial improvement over the previous implementation.

While there are a few minor suggestions for further enhancements (such as adding arrow key navigation for ranking items and improving aria labels), the overall implementation is solid and achieves the intended goals of the PR.

packages/surveys/src/components/questions/MultipleChoiceSingleQuestion.tsx (5)

48-48: LGTM: Improved focus management

The introduction of the isCurrent constant is a good practice for managing focus and improving accessibility. It allows for conditional rendering and behavior based on whether the current question is active.


179-179: LGTM: Consistent keyboard navigation for "other" option

The update to the "other" option label's tabIndex is consistent with the previous label updates, maintaining improved keyboard navigation throughout the component. This change aligns well with accessibility best practices.

As suggested in the previous comment, consider using a constant or utility function for the tabIndex values to improve consistency and maintainability across the component.


242-251: LGTM: Improved button accessibility and layout

The changes to the SubmitButton and BackButton components enhance keyboard navigation by making their tabIndex conditional on the current question state. This aligns well with the PR objective of improving accessibility.

The layout changes (moving the SubmitButton and using fb-flex-row-reverse) may affect the visual design. Please ensure that:

  1. The new layout meets the design requirements.
  2. The order of the buttons (Submit on the right, Back on the left) is intentional and consistent with other parts of the application.

To verify the visual layout changes, please provide screenshots of the form in various states (e.g., first question, middle question, last question) to ensure the button positioning is correct and consistent.


Line range hint 1-262: Summary: Successful implementation of accessibility improvements

This PR successfully addresses the main objectives of improving autofocus functionality and keyboard navigation across all questions in the form. The changes implemented in the MultipleChoiceSingleQuestion component significantly enhance accessibility by:

  1. Introducing conditional focus management based on the current question state.
  2. Improving keyboard navigation for labels, radio buttons, and form controls.
  3. Ensuring that only relevant fields are focusable, streamlining the user experience.

These improvements align well with the goal of creating a more seamless form interaction, similar to Typeform's functionality. The changes should resolve the issues mentioned in #3089, where input fields were not automatically gaining focus after submission.

To fully validate the implementation:

  1. Conduct thorough testing of the keyboard navigation flow, ensuring that users can smoothly progress through the form using only the keyboard.
  2. Verify that the visual layout changes meet the design requirements and maintain consistency across the application.
  3. Test the autofocus behavior to confirm that the appropriate field gains focus automatically after each submission.

Great job on improving the accessibility and user experience of the survey form!


196-196: LGTM: Improved focus management for radio buttons

Setting the tabIndex to -1 for radio inputs is a good practice within a radio group. This allows the group itself to be navigable while preventing individual radio buttons from receiving focus during tab navigation.

To ensure full accessibility:

  1. Verify that users can navigate between radio buttons using arrow keys when the radio group is focused.
  2. Ensure that the radio group itself is properly focusable and has the correct ARIA attributes.

To verify arrow key navigation within the radio group, you can use the following script:

This script will help identify if there are proper keydown event listeners in place to handle arrow key navigation within the radio group.

packages/surveys/src/components/questions/MultipleChoiceMultiQuestion.tsx (7)

46-46: LGTM: Improved focus management

The addition of the isCurrent variable is a good practice for managing focus and accessibility in multi-step forms. It allows for conditional rendering and focus control based on the current active question.


168-168: Excellent: Enhanced keyboard navigation

The update to the tabIndex attribute using the isCurrent variable is a significant improvement. This change ensures that only the choices of the current question are focusable, enhancing keyboard navigation and preventing focus on inactive questions. This implementation aligns well with accessibility best practices.


219-219: LGTM: Consistent focus management

The update to the tabIndex attribute for the "other" option is consistent with the previous changes to choice labels. This ensures that the "other" option is only focusable when the question is current, maintaining a coherent focus management strategy throughout the component.


263-263: LGTM: Consistent focus management for input fields

The update to the tabIndex attribute for the "other" option's input field is consistent with previous changes. This ensures that the input field is only focusable when the question is current, maintaining a coherent focus management strategy throughout the component, including form inputs.


293-293: LGTM: Consistent focus management for navigation

The update to the tabIndex attribute for the BackButton is consistent with previous changes. This ensures that the BackButton is only focusable when the question is current, maintaining a coherent focus management strategy throughout the component, including navigation elements.


Line range hint 46-293: Summary: Excellent improvements to autofocus and keyboard navigation

The changes made to the MultipleChoiceMultiQuestion component significantly enhance the autofocus functionality and keyboard navigation across all questions in the form. These improvements directly address the issues mentioned in the linked bug report (#3089) and align well with the PR objectives.

Key improvements include:

  1. Introduction of the isCurrent variable to manage focus states.
  2. Consistent application of conditional tabIndex attributes to all interactive elements.
  3. Restructuring of the button container for better layout and accessibility.

These changes collectively create a more streamlined and accessible user experience, similar to the functionality seen in Typeform as mentioned in the PR description. The implementation ensures that only the current question's elements are focusable, addressing the core issue of automatic focus progression after submitting an input field.

To further validate these improvements:

  1. Please conduct thorough testing to ensure the focus behavior works as expected across different question types and scenarios.
  2. Consider adding end-to-end tests that simulate user interactions to verify the autofocus and keyboard navigation functionality.

Great job on addressing this important usability issue!


285-290: LGTM: Improved button layout and accessibility

The changes to the button container and SubmitButton improve the overall structure and accessibility of the form:

  1. The flex direction change (fb-flex-row-reverse) alters the visual order of buttons.
  2. Moving the SubmitButton inside the container simplifies the component structure.
  3. Adding the tabIndex to the SubmitButton is consistent with other focus management improvements.

These changes enhance the component's organization and accessibility. However, it's important to verify that the new button order aligns with the intended user experience.

Please run the following script to check the visual layout of the buttons:

✅ Verification successful

Comment on lines +90 to +98
<div className="fb-flex fb-flex-row-reverse fb-w-full fb-justify-between fb-px-6 fb-py-4">
{!question.required && (
<SubmitButton
buttonLabel={getLocalizedValue(question.buttonLabel, languageCode)}
isLastQuestion={isLastQuestion}
tabIndex={isCurrent ? 0 : -1}
/>
)}
<div></div>
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Empty <div> Confirmed—Please Verify Its Necessity

The empty <div> on line 98 is present within the flex container. Please verify whether it serves a specific purpose for layout or spacing:

  • If it's necessary for alignment or spacing, consider adding a comment to clarify its intent.
  • If it's not required, removing it can help keep the codebase clean and maintainable.
🔗 Analysis chain

Layout changes improve navigation, but clarification needed

The changes to the button container's class and structure align well with the PR's objective of improving navigation:

  1. Changing to fb-flex-row-reverse reverses the order of flex items, which can improve the layout for certain designs.
  2. Conditional rendering of the SubmitButton based on whether the question is required is a good practice.

However, I have a question:

What's the purpose of the empty <div> on line 98? Is it necessary for layout or spacing? If it's not needed, consider removing it to keep the code clean.

To verify the impact of these changes, let's check for any related styles or layout components:


The initial shell scripts encountered issues with unrecognized file types. Here's an updated set of scripts to continue the verification:


To address the issues with the previous shell scripts, here are updated scripts that use fd to locate the necessary files and then search for the specified patterns:


To further investigate the issue, let's verify the existence of the packages/ directory and list its .tsx and .css files:


To accurately verify the review comment, let's extract and examine lines 90-98 from CalQuestion.tsx:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for related flex classes and empty divs in layout components
rg --type tsx --type css 'fb-flex-row-reverse|fb-justify-between' packages/
rg --type tsx '<div></div>' packages/

Length of output: 173


Script:

#!/bin/bash
# Search for related flex classes in .tsx and .css files
rg 'fb-flex-row-reverse|fb-justify-between' 'packages/**/*.{tsx,css}'

# Search for empty <div> elements in .tsx files
rg '<div>\s*</div>' 'packages/**/*.tsx'

Length of output: 235


Script:

#!/bin/bash
# Find all .tsx and .css files in the packages directory and search for related flex classes
fd --extension tsx --extension css --base-directory packages -0 | xargs -0 rg 'fb-flex-row-reverse|fb-justify-between'

# Find all .tsx files in the packages directory and search for empty <div> elements
fd --extension tsx --base-directory packages -0 | xargs -0 rg '<div>\s*</div>'

Length of output: 57870


Script:

#!/bin/bash
# Check if the 'packages' directory exists
if [ -d "packages" ]; then
  echo "packages/ directory exists."
  echo "Listing all .tsx and .css files within 'packages/':"
  find packages -type f \( -name "*.tsx" -o -name "*.css" \)
else
  echo "packages/ directory does not exist."
fi

Length of output: 18310


Script:

#!/bin/bash
# Extract lines 90-98 from CalQuestion.tsx
sed -n '90,98p' packages/surveys/src/components/questions/CalQuestion.tsx

Length of output: 437

Comment on lines +243 to +254
<div className="fb-flex fb-flex-row-reverse fb-w-full fb-justify-between fb-px-6 fb-py-4">
{!question.required && (
<SubmitButton
tabIndex={isCurrent ? 0 : -1}
buttonLabel={getLocalizedValue(question.buttonLabel, languageCode)}
isLastQuestion={isLastQuestion}
/>
)}
<div></div>
{!isFirstQuestion && (
<BackButton
tabIndex={!question.required || value ? question.range + 2 : question.range + 1}
tabIndex={isCurrent ? 0 : -1}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improved button accessibility, but potential UX concern

The changes to the submit and back buttons improve accessibility:

  1. Setting tabIndex based on isCurrent ensures proper focus management.
  2. This aligns well with the PR objectives for improving keyboard navigation.

However, there's a potential user experience issue:

The submit button is only rendered when the question is not required. This might prevent users from submitting the form if they choose not to answer an optional question. Consider always rendering the submit button, but disabling it for required questions that haven't been answered yet.

Suggested implementation:

<SubmitButton
  tabIndex={isCurrent ? 0 : -1}
  buttonLabel={getLocalizedValue(question.buttonLabel, languageCode)}
  isLastQuestion={isLastQuestion}
  disabled={question.required && !value}
/>

This approach maintains accessibility while ensuring users can always submit the form when appropriate.

}}
className="fb-border-border fb-bg-input-bg fb-text-heading hover:fb-bg-input-bg-selected focus:fb-bg-input-bg-selected focus:fb-ring-brand fb-rounded-custom fb-relative fb-z-10 fb-my-2 fb-flex fb-w-full fb-cursor-pointer fb-items-center fb-border fb-p-4 fb-text-sm focus:fb-outline-none focus:fb-ring-2 focus:fb-ring-offset-2">
<input
tabIndex={-1}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Consider the accessibility implications of tabIndex={-1} on the checkbox input.

Setting tabIndex={-1} on the checkbox input may prevent keyboard users from directly accessing the checkbox. Ensure that this does not hinder accessibility and that users can still interact with the checkbox via the label as intended.

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: 3

🧹 Outside diff range and nitpick comments (1)
apps/web/app/s/[surveyId]/components/LegalFooter.tsx (1)

Line range hint 22-38: Summary: Accessibility improvements needed for footer links

The changes made to the LegalFooter component, while consistent, introduce significant accessibility concerns by removing keyboard focus from all footer links. This approach, although aligned with the PR's goal of improving form navigation, inadvertently creates barriers for users relying on keyboard navigation.

Recommended next steps:

  1. Revert the tabIndex={-1} additions to maintain basic keyboard accessibility.
  2. Implement a more sophisticated focus management system that prioritizes form fields without completely blocking access to footer links.
  3. Consider refactoring the LegalFooter component to encapsulate accessibility logic, possibly using custom hooks or higher-order components.
  4. Ensure compliance with WCAG 2.1 guidelines, particularly success criterion 2.1.1 (Keyboard).
  5. Add comprehensive unit and integration tests to verify both the desired form navigation behavior and maintained accessibility of footer links.

These changes will require careful balance between improving form usability and maintaining essential accessibility features.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 6970df0 and 92f6ccc.

📒 Files selected for processing (4)
  • apps/web/app/s/[surveyId]/components/LegalFooter.tsx (2 hunks)
  • packages/surveys/src/components/general/WelcomeCard.tsx (1 hunks)
  • packages/surveys/src/components/questions/CTAQuestion.tsx (3 hunks)
  • packages/surveys/src/components/questions/OpenTextQuestion.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/surveys/src/components/general/WelcomeCard.tsx
  • packages/surveys/src/components/questions/CTAQuestion.tsx
  • packages/surveys/src/components/questions/OpenTextQuestion.tsx
🧰 Additional context used

Comment on lines +28 to 30
<Link href={PRIVACY_URL} target="_blank" className="hover:underline" tabIndex={-1}>
Privacy Policy
</Link>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Consistent but problematic treatment of Privacy Policy link

The addition of tabIndex={-1} to the Privacy Policy link is consistent with the change made to the Imprint link. However, this change perpetuates the same accessibility issue by preventing keyboard navigation to important legal information.

Apply the same solution as suggested for the Imprint link to maintain consistency and accessibility:

- <Link href={PRIVACY_URL} target="_blank" className="hover:underline" tabIndex={-1}>
+ <Link href={PRIVACY_URL} target="_blank" className="hover:underline">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Link href={PRIVACY_URL} target="_blank" className="hover:underline" tabIndex={-1}>
Privacy Policy
</Link>
<Link href={PRIVACY_URL} target="_blank" className="hover:underline">
Privacy Policy
</Link>

Comment on lines +22 to 24
<Link href={IMPRINT_URL} target="_blank" className="hover:underline" tabIndex={-1}>
Imprint
</Link>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Accessibility concern: Removing keyboard focus from legal links

Adding tabIndex={-1} to the Imprint link prevents it from being focusable via keyboard navigation. While this aligns with the PR objective to improve form field navigation, it introduces an accessibility issue by making important legal information inaccessible to keyboard users.

Consider the following alternatives:

  1. Remove tabIndex={-1} to maintain keyboard accessibility for all users.
  2. If the intent is to prevent tab focus during form filling, implement a more sophisticated focus management system that allows access to these links when appropriate (e.g., after form completion).

Example of maintaining accessibility:

- <Link href={IMPRINT_URL} target="_blank" className="hover:underline" tabIndex={-1}>
+ <Link href={IMPRINT_URL} target="_blank" className="hover:underline">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Link href={IMPRINT_URL} target="_blank" className="hover:underline" tabIndex={-1}>
Imprint
</Link>
<Link href={IMPRINT_URL} target="_blank" className="hover:underline">
Imprint
</Link>

Comment on lines +37 to +38
className="hover:underline"
tabIndex={-1}>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Consistent treatment of Report Survey link raises broader accessibility concerns

The addition of tabIndex={-1} to the Report Survey link maintains consistency with the other footer links but extends the accessibility issue to all interactive elements in the footer.

To address this systematically:

  1. Remove tabIndex={-1} from all links in the footer:
- className="hover:underline"
- tabIndex={-1}>
+ className="hover:underline">
  1. Consider implementing a more sophisticated focus management system that doesn't compromise accessibility. This could involve:
    • Using aria-hidden="true" on the footer during form filling and removing it after completion.
    • Implementing a skip link at the start of the form to bypass the main content and reach the footer.
    • Using JavaScript to manage focus order, ensuring form fields are prioritized without making footer links completely inaccessible.

Given the complexity introduced by these changes, it may be beneficial to refactor the LegalFooter component to encapsulate the accessibility logic. This could involve creating a custom hook for managing focus states or implementing a higher-order component that handles focus management for the entire survey form.

Committable suggestion was skipped due to low confidence.

Copy link
Contributor

@gupta-piyush19 gupta-piyush19 left a comment

Choose a reason for hiding this comment

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

Thanks, @Dhruwang, for the fix 🚀
Keyboard navigation works much better now 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Input Fields in a Form should be auto-focussed

2 participants