Skip to content

refactor: Remove the global mutation observer #2788

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from

Conversation

mrabbani
Copy link
Member

@mrabbani mrabbani commented Jul 7, 2025

All Submissions:

  • My code follow the WordPress' coding standards
  • My code satisfies feature requirements
  • My code is tested
  • My code passes the PHPCS tests
  • My code has proper inline documentation
  • I've included related pull request(s) (optional)
  • I've included developer documentation (optional)
  • I've added proper labels to this pull request

Changes proposed in this Pull Request:

Related Pull Request(s)

Closes

  • Closes #

How to test the changes in this Pull Request:

  • Steps or issue link

Changelog entry

Title

Detailed Description of the pull request. What was previous behaviour
and what will be changed in this PR.

Before Changes

Describe the issue before changes with screenshots(s).

After Changes

Describe the issue after changes with screenshot(s).

Feature Video (optional)

Link of detailed video if this PR is for a feature.

PR Self Review Checklist:

  • Code is not following code style guidelines
  • Bad naming: make sure you would understand your code if you read it a few months from now.
  • KISS: Keep it simple, Sweetie (not stupid!).
  • DRY: Don't Repeat Yourself.
  • Code that is not readable: too many nested 'if's are a bad sign.
  • Performance issues
  • Complicated constructions that need refactoring or comments: code should almost always be self-explanatory.
  • Grammar errors.

FOR PR REVIEWER ONLY:

As a reviewer, your feedback should be focused on the idea, not the person. Seek to understand, be respectful, and focus on constructive dialog.

As a contributor, your responsibility is to learn from suggestions and iterate your pull request should it be needed based on feedback. Seek to collaborate and produce the best possible contribution to the greater whole.

  • Correct — Does the change do what it’s supposed to? ie: code 100% fulfilling the requirements?
  • Secure — Would a nefarious party find some way to exploit this change? ie: everything is sanitized/escaped appropriately for any SQL or XSS injection possibilities?
  • Readable — Will your future self be able to understand this change months down the road?
  • Elegant — Does the change fit aesthetically within the overall style and architecture?

Summary by CodeRabbit

Summary by CodeRabbit

  • Refactor

    • Simplified modal components by replacing direct usage of the base modal with a custom modal, improving flexibility for header and footer rendering.
    • Removed mutation observer logic from dashboard and app components, streamlining DOM manipulation and dynamic styling.
    • Enhanced modal logic to ensure consistent application of required CSS classes for modal portals and allowed custom styling via new class name props.
    • Reorganized AI modal content structure for clearer user interaction and unified modal API usage.
    • Replaced headless UI popover components with a custom popover implementation, improving control over visibility and anchoring.
    • Updated date picker popover to use the new custom popover, enhancing toggle and visibility handling.
  • Bug Fixes

    • Added a guard to prevent unnecessary mutation observer activity when modals are closed.
  • Style

    • Updated modal width and styling for a more consistent appearance.
    • Added CSS class for improved positioning of category selector popover.

Copy link
Contributor

coderabbitai bot commented Jul 7, 2025

## Walkthrough

The updates remove custom mutation observer logic from dashboard components and centralize DOM portal management within the `DokanModal` component. Both `UpgradeModal` and `VideoPopup` are refactored to use `DokanModal`, which now ensures the portal root exists and allows explicit disabling of header and footer sections. Minor logic improvements are also included for modal rendering and mutation observer efficiency.

## Changes

| File(s)                                                                 | Change Summary                                                                                                              |
|-------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|
| src/admin/dashboard/components/Dashboard.tsx,<br>src/dashboard/index.tsx | Removed custom mutation observer logic that added classes and styles to modal-related DOM nodes.                            |
| src/admin/dashboard/pages/modules/UpgradeModal.tsx,<br>src/admin/dashboard/pages/modules/VideoPopup.tsx | Refactored to use `DokanModal` instead of the package `Modal`, simplifying modal structure and centralizing behavior.      |
| src/components/modals/DokanModal.tsx                                    | Added portal root management with `useEffect`, allowed `dialogHeader`/`dialogFooter` to be `false`, improved conditional rendering, fixed import. |
| src/intelligence/components/DokanAI.tsx                                 | Added guard clause to mutation observer to skip logic when modal is closed; replaced modal usage with `DokanModal` and reorganized modal content structure. |
| src/admin/dashboard/pages/modules/CategorySelector.tsx,<br>src/components/WpDatePicker.tsx | Replaced `@headlessui/react` popover components with a custom `Popover` component using explicit state and anchor management. |
| src/components/Popover.tsx,<br>src/components/index.tsx                 | Added new `Popover` component re-exporting `@wordpress/components` Popover; exported it in component index barrel file.     |
| src/admin/dashboard/style.scss                                          | Added `.dokan-lite-module-select-category-popover` CSS class with `top-5 !important` style.                                  |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant UpgradeModal
    participant DokanModal
    participant DOM

    User->>UpgradeModal: Triggers modal open
    UpgradeModal->>DokanModal: Renders with dialogContent, dialogHeader=false, dialogFooter=false
    DokanModal->>DOM: Ensures portal root exists and has dokan-layout class
    DokanModal->>User: Displays modal content
    User->>DokanModal: Triggers close
    DokanModal->>UpgradeModal: Calls onClose callback

Possibly related PRs

Suggested labels

Needs: Dev Review

Suggested reviewers

  • mrabbani

Poem

In the warren of code where modals appear,
Mutation observers have hopped out of here.
With DokanModal now central and keen,
Headers and footers can vanish unseen.
The dashboard is neater, the portals aligned—
A rabbit’s delight, with bugs left behind!
🐇✨


<!-- walkthrough_end -->
<!-- This is an auto-generated comment: all tool run failures by coderabbit.ai -->

> [!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.
> 
> <details>
> <summary>🔧 ESLint</summary>
> 
> > 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.
> 
> npm error Exit handler never called!
> npm error This is an error with npm itself. Please report this error at:
> npm error   <https://github.com/npm/cli/issues>
> npm error A complete log of this run can be found in: /.npm/_logs/2025-07-18T06_21_39_835Z-debug-0.log
> 
> 
> 
> </details>

<!-- end of auto-generated comment: all tool run failures by coderabbit.ai -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=getdokan/dokan&utm_content=2788):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `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 explain this code block.`
  -	`@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 explain its main purpose.`
  - `@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.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

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 generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this 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](https://docs.coderabbit.ai/guides/configure-coderabbit) 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](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

@mrabbani mrabbani added the In Progress The issues is being worked on label Jul 7, 2025
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: 1

🔭 Outside diff range comments (1)
src/intelligence/components/DokanAI.tsx (1)

44-51: Handle cross-origin and missing iframe errors in getElement

Accessing iframe.contentDocument/contentWindow can throw runtime errors (e.g., cross-origin restrictions) or return null if the iframe isn’t yet loaded. Add checks and a try/catch to gracefully fall back to querying the main document.

• File: src/intelligence/components/DokanAI.tsx
Lines: 44–51

 const getElement = ( ifr: string, selector: string ) => {
-    const iframe = document.getElementById( ifr ) as HTMLIFrameElement;
-    const doc = iframe.contentDocument || iframe.contentWindow?.document;
-    return (
-        doc?.querySelector( `[data-id="${ selector }"]` ) ||
-        document.querySelector( `#${ selector }` )
-    );
+    const iframe = document.getElementById(ifr) as HTMLIFrameElement | null;
+    if (!iframe) {
+        return document.querySelector(`#${selector}`);
+    }
+
+    let doc: Document | null = null;
+    try {
+        doc = iframe.contentDocument || iframe.contentWindow?.document || null;
+    } catch (error) {
+        console.warn(`Unable to access iframe "${ifr}":`, error);
+    }
+
+    if (!doc) {
+        return document.querySelector(`#${selector}`);
+    }
+
+    return (
+        doc.querySelector(`[data-id="${selector}"]`) ||
+        document.querySelector(`#${selector}`)
+    );
 };
🧹 Nitpick comments (3)
src/intelligence/components/DokanAI.tsx (2)

287-314: Consider more targeted mutation observer scope.

While the guard clause is a good optimization, the mutation observer is still watching the entire document.body, which could be expensive for large DOM trees. Consider a more targeted approach:

-useMutationObserver(
-    document.body,
-    ( mutations ) => {
+useMutationObserver(
+    document.querySelector('#wpwrap') || document.body,
+    ( mutations ) => {

This would limit the observation scope to the WordPress admin area, reducing the performance impact.


298-299: Remove TypeScript ignore comment.

The @ts-ignore comment indicates a type issue that should be addressed rather than suppressed.

-                // @ts-ignore
-                for ( const node of mutation.addedNodes ) {
+                for ( const node of Array.from(mutation.addedNodes) ) {

This provides proper type safety by converting the NodeList to an array.

src/admin/dashboard/pages/modules/UpgradeModal.tsx (1)

4-4: Remove unused import.

The Modal import from @getdokan/dokan-ui is no longer used since the component has been refactored to use DokanModal.

Apply this diff to remove the unused import:

-import { Modal } from '@getdokan/dokan-ui';
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 017d357 and 2628ead.

📒 Files selected for processing (6)
  • src/admin/dashboard/components/Dashboard.tsx (0 hunks)
  • src/admin/dashboard/pages/modules/UpgradeModal.tsx (2 hunks)
  • src/admin/dashboard/pages/modules/VideoPopup.tsx (3 hunks)
  • src/components/modals/DokanModal.tsx (5 hunks)
  • src/dashboard/index.tsx (0 hunks)
  • src/intelligence/components/DokanAI.tsx (1 hunks)
💤 Files with no reviewable changes (2)
  • src/admin/dashboard/components/Dashboard.tsx
  • src/dashboard/index.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: api tests (1, 1)
  • GitHub Check: e2e tests (3, 3)
  • GitHub Check: e2e tests (1, 3)
  • GitHub Check: e2e tests (2, 3)
🔇 Additional comments (8)
src/intelligence/components/DokanAI.tsx (1)

290-292: Performance optimization looks good!

The guard clause prevents unnecessary DOM manipulation when the modal is closed, which is a good optimization. This aligns with the PR objective of refactoring mutation observer usage.

src/admin/dashboard/pages/modules/VideoPopup.tsx (2)

5-5: LGTM! Clean import addition.

The import of DokanModal from the components module aligns with the refactor to centralize modal management.


36-54: Excellent refactor to centralized modal component.

The migration from Modal to DokanModal is well-executed:

  • Appropriate namespace for video popups
  • Header and footer correctly disabled
  • Video content properly passed via dialogContent prop
  • Fixed width styling maintained

This change successfully centralizes modal behavior and removes the need for custom mutation observer logic.

src/admin/dashboard/pages/modules/UpgradeModal.tsx (1)

14-252: Excellent refactor to centralized modal component.

The migration to DokanModal is well-structured:

  • Clean content extraction to modalContent variable improves readability
  • Proper namespace and styling configuration
  • Header and footer correctly disabled to match the custom design
  • Modal content structure preserved intact

This change successfully centralizes modal behavior while maintaining the existing user experience.

src/components/modals/DokanModal.tsx (4)

3-3: Good change to relative import.

Moving the kebabCase import to a relative path improves code organization and reduces external dependencies.


53-64: Excellent portal management solution.

The useEffect hook properly centralizes the portal root management by:

  • Ensuring the #headlessui-portal-root element exists
  • Adding the required dokan-layout class for consistent styling
  • Creating the element if it doesn't exist
  • Running on modal open state changes

This successfully replaces the scattered mutation observer logic mentioned in the PR objectives.


66-68: Good defensive programming.

The safe handling of kebabCase prevents runtime errors if the utility function is unavailable.


172-198: Clean conditional footer rendering.

The footer conditional logic correctly implements the pattern:

  • Renders nothing when dialogFooter is false
  • Renders custom footer when provided
  • Falls back to default footer with cancel/confirm buttons

This provides the flexibility needed for different modal use cases.

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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c5f531e and f928ff7.

📒 Files selected for processing (4)
  • src/admin/dashboard/pages/modules/UpgradeModal.tsx (2 hunks)
  • src/admin/dashboard/pages/modules/VideoPopup.tsx (3 hunks)
  • src/components/modals/DokanModal.tsx (6 hunks)
  • src/intelligence/components/DokanAI.tsx (5 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/admin/dashboard/pages/modules/VideoPopup.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/admin/dashboard/pages/modules/UpgradeModal.tsx
  • src/components/modals/DokanModal.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/intelligence/components/DokanAI.tsx

[error] 502-502: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)


[error] 560-560: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: e2e tests (2, 3)
  • GitHub Check: api tests (1, 1)
  • GitHub Check: e2e tests (1, 3)
  • GitHub Check: e2e tests (3, 3)
🔇 Additional comments (3)
src/intelligence/components/DokanAI.tsx (3)

290-293: Good optimization: Early return guard for mutation observer

The early return when the modal is not open prevents unnecessary DOM processing and improves performance by avoiding mutation observer callbacks when they're not needed.


356-656: Modal API migration looks correct

The migration from the old Modal component to DokanModal with the new prop-based API (dialogHeader, dialogContent, dialogFooter) appears to be implemented correctly. The functionality is preserved while adapting to the new component structure.


658-699: Regenerate modal migration implemented correctly

The regenerate confirmation modal has been successfully migrated to use DokanModal with the new API. The header and footer are properly disabled (dialogHeader={ false } and dialogFooter={ false }) while maintaining the same functionality.

@mralaminahamed
Copy link
Member

mralaminahamed commented Jul 10, 2025

Dokan Modal usages

The usages overall from Dokan lite and Dokan pro components. here are lists of all usages.

File Navigation Url
src/admin/dashboard/pages/modules/UpgradeModal.tsx WP Admin → Dokan → Modules
src/admin/dashboard/pages/modules/VideoPopup.tsx WP Admin → Dokan → Modules
src/dashboard/withdraw/RequestList.tsx Vendor Dashboard → Withdraw
src/intelligence/components/DokanAI.tsx Vendor Dashboard → Add/Edit Product → AI Prompt modal
src/features/manual-order/components/Sections/Addresses/AddressModal.tsx Vendor Dashboard → Orders → New/Edit Order → Addresses
src/features/manual-order/components/Sections/Coupons/AddCouponModal.tsx Vendor Dashboard → Orders → New/Edit Order → Coupons
src/features/manual-order/components/Sections/OrderActions.tsx Vendor Dashboard → Orders → New/Edit Order → Order Actions
src/features/manual-order/components/Sections/OrderFeeLineItems/index.tsx Vendor Dashboard → Orders → New/Edit Order → Order Fee Line Items
src/features/manual-order/components/Sections/OrderFeeLineItems/LineItemModal.tsx Vendor Dashboard → Orders → New/Edit Order → Add/Edit Line Items
src/features/manual-order/components/Sections/OrderLineItems/index.tsx Vendor Dashboard → Orders → New/Edit Order → Order Line Items
src/features/manual-order/components/Sections/OrderLineItems/LineItemAddModal.tsx Vendor Dashboard → Orders → New/Edit Order → Add Line Items
src/features/manual-order/components/Sections/OrderLineItems/LineItemEditModal.tsx Vendor Dashboard → Orders → New/Edit Order → Edit Line Items
src/features/manual-order/components/Sections/OrderNotes.tsx Vendor Dashboard → Orders → New/Edit Order → Order Notes
src/features/manual-order/components/Sections/ShippingLineItems/index.tsx Vendor Dashboard → Orders → New/Edit Order → Shipping Line Items
src/features/manual-order/components/Sections/ShippingLineItems/LineItemModal.tsx Vendor Dashboard → Orders → New/Edit Order → Update/Edit Line Item
src/features/manual-order/components/Sections/Taxes/AddTaxModal.tsx Vendor Dashboard → Orders → New/Edit Order → Taxes
src/features/shipping/ShippingMethods.tsx Vendor Dashboard → Store → Shipping → Shipping Methods
src/frontend/coupons/components/MyCouponList.tsx Vendor Dashboard → Coupons
modules/rma/src/js/vendor-dashboard/components/Popups/CouponModal.tsx Vendor Dashboard → Return Request → View → Coupon Modal
modules/rma/src/js/vendor-dashboard/components/Popups/RefundModal.tsx Vendor Dashboard → Return Request → View → Refund Modal
modules/rma/src/js/vendor-dashboard/components/RequestsList.tsx Vendor Dashboard → Return Request → Requests List
modules/subscription/src/js/frontend/components/CurrentSubscription.tsx Vendor Dashboard → Subscription → Current Subscription
modules/subscription/src/js/frontend/components/SubscriptionOrders.tsx Vendor Dashboard → Subscription → Subscription Orders
modules/table-rate-shipping/src/js/vendor-dashboard/table-rates/index.tsx Vendor Dashboard → Store → Shipping → Table Rate Shipping
modules/vendor-staff/src/js/components/ManagePermissions.tsx Vendor Dashboard → Staff → Manage Permissions
modules/vendor-staff/src/js/components/StaffList.tsx Vendor Dashboard → Staff → Staff List
modules/vendor-subscription-product/src/components/DownloasableItem.tsx Vendor Dashboard → User Subscriptions → Downloadable Item
modules/vendor-subscription-product/src/components/NoteItem.tsx Vendor Dashboard → User Subscriptions → Note Item
src/features/announcement/AnnouncementList.tsx Vendor Dashboard → Dokan → Announcements

Pull Requests

The updated list of DokanModal usages from requested pull request components (PR getdokan/dokan-pro/pull/4440).

File Navigation Url
modules/product-qa/assets/src/js/frontend/components/LoginModal.tsx Single product page → Product tabs (Question & Answers) → Trigger login modal
modules/product-qa/assets/src/js/frontend/components/QuestionModal.tsx Single product page → Product tabs (Question & Answers) → Trigger post question modal
modules/store-support/assets/src/js/frontend/components/LoginModal.tsx Single product page, Order Details, Order recieved pages → Get Support Button → Trigger login modal
modules/store-support/assets/src/js/frontend/components/NewTicketModal.tsx Single product page, Order Details, Order recieved pages → Get Support Button → Trigger new ticket modal

@mrabbani mrabbani self-assigned this Jul 11, 2025
@mrabbani mrabbani added 👍 Dev Review Done and removed In Progress The issues is being worked on labels Jul 11, 2025
* feat: add custom Popover component using WordPress UI

* feat: integrate Popover component into WpDatePicker for enhanced date selection

* feat: enhance CategorySelector with custom Popover for category selection
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: 4

🧹 Nitpick comments (2)
src/admin/dashboard/pages/modules/CategorySelector.tsx (1)

29-30: Consider adding proper TypeScript typing for the popover anchor.

The popoverAnchor state lacks proper typing, which led to the @ts-ignore usage later.

Apply this diff to add proper typing:

-    const [ popoverAnchor, setPopoverAnchor ] = useState();
+    const [ popoverAnchor, setPopoverAnchor ] = useState<HTMLElement | null>(null);
src/components/WpDatePicker.tsx (1)

18-19: Add proper TypeScript typing for the popover anchor.

The popoverAnchor state lacks proper typing, which led to the @ts-ignore usage.

Apply this diff to add proper typing:

-    const [ popoverAnchor, setPopoverAnchor ] = useState();
+    const [ popoverAnchor, setPopoverAnchor ] = useState<HTMLElement | null>(null);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bac46eb and 15bc703.

📒 Files selected for processing (5)
  • src/admin/dashboard/pages/modules/CategorySelector.tsx (3 hunks)
  • src/admin/dashboard/style.scss (1 hunks)
  • src/components/Popover.tsx (1 hunks)
  • src/components/WpDatePicker.tsx (3 hunks)
  • src/components/index.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • src/admin/dashboard/style.scss
  • src/components/Popover.tsx
  • src/components/index.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: e2e tests (1, 3)
  • GitHub Check: e2e tests (2, 3)
  • GitHub Check: e2e tests (3, 3)
  • GitHub Check: api tests (1, 1)
🔇 Additional comments (2)
src/components/WpDatePicker.tsx (2)

9-15: Well-designed Props interface extension.

The Props interface properly extends DatePickerProps and adds the necessary optional styling props. This is a clean approach that maintains type safety while allowing customization.


57-60: Good use of twMerge for class name composition.

The usage of twMerge for combining class names is appropriate and handles Tailwind CSS class conflicts properly.

Also applies to: 63-66

Comment on lines +73 to +77
onClose={ () => {
setIsVisible( ! isVisible );
} }
onFocusOutside={ () => {
setIsVisible( ! isVisible );
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Simplify the close handler logic.

The onClose and onFocusOutside handlers use the same toggle logic, which is redundant. When closing, you should always set isVisible to false.

Apply this diff to simplify the close logic:

                     onClose={ () => {
-                        setIsVisible( ! isVisible );
+                        setIsVisible( false );
                     } }
                     onFocusOutside={ () => {
-                        setIsVisible( ! isVisible );
+                        setIsVisible( false );
                     } }
📝 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
onClose={ () => {
setIsVisible( ! isVisible );
} }
onFocusOutside={ () => {
setIsVisible( ! isVisible );
onClose={ () => {
setIsVisible(false);
} }
onFocusOutside={ () => {
setIsVisible(false);
} }
🤖 Prompt for AI Agents
In src/admin/dashboard/pages/modules/CategorySelector.tsx around lines 73 to 77,
the onClose and onFocusOutside handlers currently toggle isVisible, which is
redundant and incorrect for closing actions. Change both handlers to directly
set isVisible to false instead of toggling it, ensuring the component always
closes properly when these events occur.

Comment on lines +34 to +41
{ /* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */ }
<div
className="inline-flex items-center gap-x-1 text-sm/6 text-gray-900"
onClick={ () => {
setIsVisible( ! isVisible );
} }
// @ts-ignore
ref={ setPopoverAnchor }
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

Address accessibility violations and improve TypeScript typing.

The component has several accessibility and typing issues:

  1. Accessibility violations: The eslint-disable comments indicate missing keyboard navigation and improper interactive element usage.
  2. TypeScript suppression: The @ts-ignore comment suggests improper typing for the ref callback.

Apply this diff to fix the accessibility and typing issues:

-            { /* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */ }
-            <div
+            <button
+                type="button"
                 className="inline-flex items-center gap-x-1 text-sm/6 text-gray-900"
                 onClick={ () => {
                     setIsVisible( ! isVisible );
                 } }
-                // @ts-ignore
-                ref={ setPopoverAnchor }
+                ref={ setPopoverAnchor as React.RefCallback<HTMLButtonElement> }
             >

And update the closing tag:

-            </div>
+            </button>
📝 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
{ /* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */ }
<div
className="inline-flex items-center gap-x-1 text-sm/6 text-gray-900"
onClick={ () => {
setIsVisible( ! isVisible );
} }
// @ts-ignore
ref={ setPopoverAnchor }
<button
type="button"
className="inline-flex items-center gap-x-1 text-sm/6 text-gray-900"
onClick={() => {
setIsVisible(!isVisible);
}}
ref={setPopoverAnchor as React.RefCallback<HTMLButtonElement>}
>
{/* …existing button contents… */}
</button>
🤖 Prompt for AI Agents
In src/admin/dashboard/pages/modules/CategorySelector.tsx around lines 34 to 41,
the div used as an interactive element lacks proper keyboard event handlers and
semantic roles, causing accessibility violations, and the ref callback has
improper typing requiring a @ts-ignore. Replace the div with a button element or
add appropriate role="button" and tabIndex={0}, implement onKeyDown to handle
keyboard interactions like Enter and Space keys, and remove the eslint-disable
comments. For the ref, define the callback with correct TypeScript typing to
avoid using @ts-ignore. Also, update the closing tag accordingly to match the
new element.

Comment on lines +51 to +56
onClose={ () => {
setIsVisible( ! isVisible );
} }
onFocusOutside={ () => {
setIsVisible( ! isVisible );
} }
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Simplify the close handler logic.

The close handlers use redundant toggle logic. When closing, you should always set isVisible to false.

Apply this diff to simplify the close logic:

                     onClose={ () => {
-                        setIsVisible( ! isVisible );
+                        setIsVisible( false );
                     } }
                     onFocusOutside={ () => {
-                        setIsVisible( ! isVisible );
+                        setIsVisible( false );
                     } }
🤖 Prompt for AI Agents
In src/components/WpDatePicker.tsx around lines 51 to 56, the onClose and
onFocusOutside handlers currently toggle the isVisible state, which is redundant
and incorrect for closing actions. Change both handlers to explicitly set
isVisible to false instead of toggling it, ensuring the date picker always
closes properly when these events occur.

Comment on lines +34 to 42
{ /* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */ }
<div
className={ props?.pickerToggleClassName ?? '' }
onClick={ () => {
setIsVisible( ! isVisible );
} }
// @ts-ignore
ref={ setPopoverAnchor }
>
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

Address accessibility violations and improve TypeScript typing.

Similar to the CategorySelector component, this has accessibility and typing issues:

  1. Accessibility violations: Missing keyboard navigation and improper interactive element usage.
  2. TypeScript suppression: The @ts-ignore comment indicates improper typing for the ref callback.

Apply this diff to fix the accessibility and typing issues:

-            { /* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */ }
-            <div
+            <button
+                type="button"
                 className={ props?.pickerToggleClassName ?? '' }
                 onClick={ () => {
                     setIsVisible( ! isVisible );
                 } }
-                // @ts-ignore
-                ref={ setPopoverAnchor }
+                ref={ setPopoverAnchor as React.RefCallback<HTMLButtonElement> }
             >
                 { props.children ?? '' }
-            </div>
+            </button>
📝 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
{ /* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */ }
<div
className={ props?.pickerToggleClassName ?? '' }
onClick={ () => {
setIsVisible( ! isVisible );
} }
// @ts-ignore
ref={ setPopoverAnchor }
>
<button
type="button"
className={ props?.pickerToggleClassName ?? '' }
onClick={ () => {
setIsVisible(!isVisible);
} }
ref={ setPopoverAnchor as React.RefCallback<HTMLButtonElement> }
>
{ props.children ?? '' }
</button>
🤖 Prompt for AI Agents
In src/components/WpDatePicker.tsx around lines 34 to 42, fix accessibility by
replacing the div with a button or adding keyboard event handlers to support
keyboard navigation, ensuring it behaves as an interactive element. Remove the
@ts-ignore comment by properly typing the ref callback to match React's expected
types for refs, improving TypeScript compliance.

@mrabbani mrabbani added the Needs: Testing This requires further testing label Jul 18, 2025
@mrabbani
Copy link
Member Author

Need to also review by @mrabbani.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs: Testing This requires further testing 👍 Dev Review Done
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants