Skip to content

fixed issue for muliple tap were nedded to view sub issue.#9139

Open
notHuman9504 wants to merge 1 commit into
makeplane:previewfrom
notHuman9504:fix/multiple-taps-were-needed-to-view-sub-issues
Open

fixed issue for muliple tap were nedded to view sub issue.#9139
notHuman9504 wants to merge 1 commit into
makeplane:previewfrom
notHuman9504:fix/multiple-taps-were-needed-to-view-sub-issues

Conversation

@notHuman9504
Copy link
Copy Markdown

@notHuman9504 notHuman9504 commented May 25, 2026

Description

fixes the issue #9124
component was rendering before we were getting data from api, so we have to make it re render or make it asyncronus.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Screenshots and Media (if applicable)

Screen.Recording.2026-05-26.at.2.14.09.AM.mov

Test Scenarios

did the manual testing for behaviour of opening and closing of sub issues,

References

#9124

Summary by CodeRabbit

  • Bug Fixes

    • Improved responsiveness when expanding nested items by ensuring proper data loading before UI updates.
  • Accessibility

    • Enhanced keyboard interaction support for actions on expanded items.
    • Improved semantic markup for better screen reader compatibility.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

📝 Walkthrough

Walkthrough

The issue list block component now fetches sub-issues asynchronously before expanding, replacing the prior synchronous state updater pattern. The actions wrapper gains accessibility semantics and keyboard event handling with preventDefault and stopPropagation on key presses.

Changes

Issue List Block UI Interactions

Layer / File(s) Summary
Async expand/collapse with sub-issue fetching
apps/web/core/components/issues/issue-layouts/list/block.tsx
The handleToggleExpand handler converts to async and awaits subIssuesStore.fetchSubIssues() conditionally before calling setExpanded, replacing the prior approach of invoking fetch inside the state updater callback without awaiting.
Actions area accessibility and keyboard handling
apps/web/core/components/issues/issue-layouts/list/block.tsx
The actions wrapper element receives role="presentation" for accessibility and an onKeyDown handler that prevents default behavior and stops event propagation on keyboard input.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A toggle springs forth now with async grace,
Awaiting sub-issues before showing its face,
The actions area listens with keyboard's soft call,
Propagation halted, accessibility for all! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title mentions fixing an issue with multiple taps being needed to view sub-issues, which directly relates to the main bug fix in the PR (making the component asynchronous for sub-issue fetching).
Description check ✅ Passed The description covers most required template sections including a detailed description of the fix, the type of change (bug fix), screenshots/media, test scenarios, and references to the related issue.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
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: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/core/components/issues/issue-layouts/list/block.tsx`:
- Around line 331-334: The current onKeyDown handler in the IssueList block (the
inline onKeyDown prop defined around the ControlLink/child element) calls
e.preventDefault() and e.stopPropagation() for every key which breaks keyboard
navigation; change it so you only preventDefault()/stopPropagation() for
specific activation keys (e.g., e.key === 'Enter' or e.key === ' ' / 'Spacebar')
and return early for other keys (allowing Tab, Escape, arrow keys to behave
normally), or alternatively only call stopPropagation() without preventDefault()
when you need to stop parent handlers but preserve native focus movement.
- Around line 146-156: The handleToggleExpand handler can fire multiple
concurrent fetchSubIssues calls and flip setExpanded unpredictably; add a
loading guard (e.g., local isLoading state or reuse subIssuesStore loader)
inside handleToggleExpand to early-return while a fetch is in progress, set the
loader true before awaiting subIssuesStore.fetchSubIssues and false in a finally
block, and update the expand/collapse button to be disabled or show a loading
indicator while isLoading so rapid clicks won't trigger multiple fetchSubIssues
calls or race setExpanded; reference handleToggleExpand, fetchSubIssues,
setExpanded, nestingLevel, and subIssuesStore when making the changes.
- Around line 146-156: In handleToggleExpand, wrap the await
subIssuesStore.fetchSubIssues(...) call in a try-catch and only call setExpanded
when the fetch succeeds (or fall back to a defined error state), so an API
failure doesn't leave the chevron expanded with no data; catch the error, log it
via your logger (or console.error) with context including issue.id and
workspaceSlug, and remove the redundant .toString() on workspaceSlug when
passing it to fetchSubIssues. Ensure the catch block prevents toggling expansion
on failure and surfaces or records the error appropriately.
- Line 322: The wrapper div in IssueActions (the element with
role="presentation" that also has onClick and onKeyDown handlers) is marked
non-interactive while handling events; remove the contradictory
role="presentation" attribute so assistive tech sees its interactive behavior,
or if you intend it purely as a grouping element, replace role="presentation"
with role="group" and add an appropriate aria-label; ensure the event handlers
on that div (onClick/onKeyDown) remain or are removed consistently with your
choice so ControlLink's semantics are not broken.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f8c5f686-b4cd-41ae-a7da-2aec22c6b2b7

📥 Commits

Reviewing files that changed from the base of the PR and between 9f77ea5 and 8a709ce.

📒 Files selected for processing (1)
  • apps/web/core/components/issues/issue-layouts/list/block.tsx

Comment on lines +146 to 156
const handleToggleExpand = async (e: MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
e.preventDefault();
if (nestingLevel >= 3) {
handleIssuePeekOverview(issue);
} else {
setExpanded((prevState) => {
if (!prevState && workspaceSlug && issue && issue.project_id)
subIssuesStore.fetchSubIssues(workspaceSlug.toString(), issue.project_id, issue.id);
return !prevState;
});
if (!isExpanded && workspaceSlug && issue.project_id)
await subIssuesStore.fetchSubIssues(workspaceSlug.toString(), issue.project_id, issue.id);
setExpanded((prevState) => !prevState);
}
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard against concurrent expand/collapse operations.

The async handler has no protection against rapid successive clicks. If a user clicks the expand button multiple times while fetchSubIssues is pending, multiple API calls will be triggered and the expanded state will toggle unpredictably.

Consider adding a loading flag or disabling the button during the fetch operation.

🔒 Proposed fix with loading guard

Add a local state or use the store's loader:

+const [isTogglingExpand, setIsTogglingExpand] = useState(false);
+
 const handleToggleExpand = async (e: MouseEvent<HTMLButtonElement>) => {
   e.stopPropagation();
   e.preventDefault();
+  
+  if (isTogglingExpand) return;
+  
   if (nestingLevel >= 3) {
     handleIssuePeekOverview(issue);
   } else {
     if (!isExpanded && workspaceSlug && issue.project_id) {
+      setIsTogglingExpand(true);
       try {
         await subIssuesStore.fetchSubIssues(workspaceSlug, issue.project_id, issue.id);
         setExpanded((prevState) => !prevState);
       } catch (error) {
         // ... error handling
+      } finally {
+        setIsTogglingExpand(false);
       }
     } else {
       setExpanded((prevState) => !prevState);
     }
   }
 };

And update the button to show loading state:

 <button
   type="button"
   className="grid size-4 place-items-center rounded-xs text-placeholder hover:text-tertiary"
   onClick={handleToggleExpand}
+  disabled={isTogglingExpand}
 >
+  {isTogglingExpand ? (
+    <Spinner className="size-4" />
+  ) : (
     <ChevronRightIcon
       className={cn("size-4", {
         "rotate-90": isExpanded,
       })}
       strokeWidth={2.5}
     />
+  )}
 </button>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/core/components/issues/issue-layouts/list/block.tsx` around lines
146 - 156, The handleToggleExpand handler can fire multiple concurrent
fetchSubIssues calls and flip setExpanded unpredictably; add a loading guard
(e.g., local isLoading state or reuse subIssuesStore loader) inside
handleToggleExpand to early-return while a fetch is in progress, set the loader
true before awaiting subIssuesStore.fetchSubIssues and false in a finally block,
and update the expand/collapse button to be disabled or show a loading indicator
while isLoading so rapid clicks won't trigger multiple fetchSubIssues calls or
race setExpanded; reference handleToggleExpand, fetchSubIssues, setExpanded,
nestingLevel, and subIssuesStore when making the changes.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Add error handling for the async fetch operation.

The async fetchSubIssues call has no try-catch block. If the API call fails, the error will propagate as an unhandled promise rejection, and the expansion state will still toggle, leaving the UI in an inconsistent state (expanded chevron with no sub-issues loaded).

As per coding guidelines, async operations should use try-catch with proper error types and log errors appropriately.

🛡️ Proposed fix with error handling
 const handleToggleExpand = async (e: MouseEvent<HTMLButtonElement>) => {
   e.stopPropagation();
   e.preventDefault();
   if (nestingLevel >= 3) {
     handleIssuePeekOverview(issue);
   } else {
-    if (!isExpanded && workspaceSlug && issue.project_id)
-      await subIssuesStore.fetchSubIssues(workspaceSlug.toString(), issue.project_id, issue.id);
-    setExpanded((prevState) => !prevState);
+    if (!isExpanded && workspaceSlug && issue.project_id) {
+      try {
+        await subIssuesStore.fetchSubIssues(workspaceSlug, issue.project_id, issue.id);
+        setExpanded((prevState) => !prevState);
+      } catch (error) {
+        setToast({
+          type: TOAST_TYPE.ERROR,
+          title: "Failed to load sub-issues",
+          message: error instanceof Error ? error.message : "An error occurred while fetching sub-issues",
+        });
+      }
+    } else {
+      setExpanded((prevState) => !prevState);
+    }
   }
 };

Note: Also removed redundant .toString() on workspaceSlug (already converted to string on line 82).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/core/components/issues/issue-layouts/list/block.tsx` around lines
146 - 156, In handleToggleExpand, wrap the await
subIssuesStore.fetchSubIssues(...) call in a try-catch and only call setExpanded
when the fetch succeeds (or fall back to a defined error state), so an API
failure doesn't leave the chevron expanded with no data; catch the error, log it
via your logger (or console.error) with context including issue.id and
workspaceSlug, and remove the redundant .toString() on workspaceSlug when
passing it to fetchSubIssues. Ensure the catch block prevents toggling expansion
on failure and surfaces or records the error appropriately.

isEpic={isEpic}
/>
<div
role="presentation"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove role="presentation" from interactive wrapper.

The role="presentation" attribute tells assistive technologies to ignore this element's semantic role, treating it as purely decorative. However, this element has onClick and onKeyDown handlers, making it functionally interactive (even if only to stop event propagation).

This creates a contradiction: the element is marked as non-interactive but has interactive behavior. Either:

  1. Remove role="presentation" if the div needs event handlers, or
  2. Remove the event handlers and role if the child buttons already handle all interaction

Since the div appears to be a click/keyboard event trap to prevent bubbling to the parent ControlLink, consider using a more appropriate ARIA role or no role at all.

♻️ Suggested alternatives

Option 1: Remove the role attribute (simplest):

 <div
-  role="presentation"
   className={cn("hidden", {

Option 2: If the div groups related actions, use role="group" with an accessible label:

 <div
-  role="presentation"
+  role="group"
+  aria-label="Quick actions"
   className={cn("hidden", {
📝 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
role="presentation"
<div
className={cn("hidden", {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/core/components/issues/issue-layouts/list/block.tsx` at line 322,
The wrapper div in IssueActions (the element with role="presentation" that also
has onClick and onKeyDown handlers) is marked non-interactive while handling
events; remove the contradictory role="presentation" attribute so assistive tech
sees its interactive behavior, or if you intend it purely as a grouping element,
replace role="presentation" with role="group" and add an appropriate aria-label;
ensure the event handlers on that div (onClick/onKeyDown) remain or are removed
consistently with your choice so ControlLink's semantics are not broken.

Comment on lines +331 to +334
onKeyDown={(e) => {
e.preventDefault();
e.stopPropagation();
}}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Prevent default on all keyboard events breaks accessibility.

The onKeyDown handler calls e.preventDefault() and e.stopPropagation() for every keyboard event. This will block essential keyboard navigation including Tab (focus movement), Enter/Space (activation), Escape (closing dialogs), and arrow keys.

If the intent is to prevent specific keys from bubbling (e.g., only Enter or Space to avoid double-triggering the parent link), you should check e.key and only prevent default for those specific keys.

♿ Proposed fix for selective event handling

Only prevent activation keys that might trigger the parent ControlLink:

 onKeyDown={(e) => {
-  e.preventDefault();
-  e.stopPropagation();
+  // Only prevent Enter/Space to avoid triggering parent link
+  if (e.key === 'Enter' || e.key === ' ') {
+    e.preventDefault();
+    e.stopPropagation();
+  }
 }}

Alternatively, if you want to stop all propagation but still allow default browser behavior (like Tab navigation):

 onKeyDown={(e) => {
-  e.preventDefault();
   e.stopPropagation();
 }}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/core/components/issues/issue-layouts/list/block.tsx` around lines
331 - 334, The current onKeyDown handler in the IssueList block (the inline
onKeyDown prop defined around the ControlLink/child element) calls
e.preventDefault() and e.stopPropagation() for every key which breaks keyboard
navigation; change it so you only preventDefault()/stopPropagation() for
specific activation keys (e.g., e.key === 'Enter' or e.key === ' ' / 'Spacebar')
and return early for other keys (allowing Tab, Escape, arrow keys to behave
normally), or alternatively only call stopPropagation() without preventDefault()
when you need to stop parent handlers but preserve native focus movement.

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.

1 participant