From 20b514c00007ee58533205cb2ded2bd81491dbaf Mon Sep 17 00:00:00 2001
From: Dalton <daltojohnso@users.noreply.github.com>
Date: Mon, 13 Dec 2021 10:11:40 -0800
Subject: [PATCH] add renderItemWrapper fn to AccordionList (#19279)

---
 .../{ => AccordionList}/AccordionList.info.js | 22 +++++++++++++++++
 .../{ => AccordionList}/AccordionList.jsx     |  6 +++++
 .../AccordionList}/AccordionList.unit.spec.js | 24 +++++++++++++++++++
 .../components/AccordionList/index.js         |  1 +
 4 files changed, 53 insertions(+)
 rename frontend/src/metabase/components/{ => AccordionList}/AccordionList.info.js (67%)
 rename frontend/src/metabase/components/{ => AccordionList}/AccordionList.jsx (99%)
 rename frontend/{test/metabase/components => src/metabase/components/AccordionList}/AccordionList.unit.spec.js (78%)
 create mode 100644 frontend/src/metabase/components/AccordionList/index.js

diff --git a/frontend/src/metabase/components/AccordionList.info.js b/frontend/src/metabase/components/AccordionList/AccordionList.info.js
similarity index 67%
rename from frontend/src/metabase/components/AccordionList.info.js
rename to frontend/src/metabase/components/AccordionList/AccordionList.info.js
index cf0fab94f7d..5daee074b68 100644
--- a/frontend/src/metabase/components/AccordionList.info.js
+++ b/frontend/src/metabase/components/AccordionList/AccordionList.info.js
@@ -1,5 +1,8 @@
 import React from "react";
+import styled from "styled-components";
+
 import AccordionList from "metabase/components/AccordionList";
+import TippyPopover from "metabase/components/Popover/TippyPopover";
 
 export const component = AccordionList;
 export const category = "pickers";
@@ -8,6 +11,9 @@ export const description = `
 An expandable and searchable list of sections and items.
 `;
 
+const PopoverContent = styled.div`
+  padding: 1em;
+`;
 const sections = [
   {
     name: "Widgets",
@@ -51,4 +57,20 @@ export const examples = {
       hideSingleSectionTitle
     />
   ),
+  "List Item Popover": (
+    <AccordionList
+      className="text-brand full"
+      sections={sections}
+      itemIsSelected={item => item.name === "Foo"}
+      renderItemWrapper={(itemContent, item) => (
+        <TippyPopover
+          placement="left-start"
+          interactive
+          content={<PopoverContent>{item.name}</PopoverContent>}
+        >
+          {itemContent}
+        </TippyPopover>
+      )}
+    />
+  ),
 };
diff --git a/frontend/src/metabase/components/AccordionList.jsx b/frontend/src/metabase/components/AccordionList/AccordionList.jsx
similarity index 99%
rename from frontend/src/metabase/components/AccordionList.jsx
rename to frontend/src/metabase/components/AccordionList/AccordionList.jsx
index fd3fc967f39..bd02760ba88 100644
--- a/frontend/src/metabase/components/AccordionList.jsx
+++ b/frontend/src/metabase/components/AccordionList/AccordionList.jsx
@@ -73,6 +73,7 @@ export default class AccordionList extends Component {
     renderItemDescription: PropTypes.func,
     renderItemIcon: PropTypes.func,
     renderItemExtra: PropTypes.func,
+    renderItemWrapper: PropTypes.func,
     getItemClassName: PropTypes.func,
 
     alwaysTogglable: PropTypes.bool,
@@ -474,6 +475,7 @@ const AccordionListCell = ({
   renderItemDescription,
   renderItemIcon,
   renderItemExtra,
+  renderItemWrapper,
   searchText,
   onChangeSearchText,
   searchPlaceholder,
@@ -601,6 +603,10 @@ const AccordionListCell = ({
         )}
       </div>
     );
+
+    if (renderItemWrapper) {
+      content = renderItemWrapper(content, item);
+    }
   }
 
   return (
diff --git a/frontend/test/metabase/components/AccordionList.unit.spec.js b/frontend/src/metabase/components/AccordionList/AccordionList.unit.spec.js
similarity index 78%
rename from frontend/test/metabase/components/AccordionList.unit.spec.js
rename to frontend/src/metabase/components/AccordionList/AccordionList.unit.spec.js
index d53e4c832fc..7f9382680c0 100644
--- a/frontend/test/metabase/components/AccordionList.unit.spec.js
+++ b/frontend/src/metabase/components/AccordionList/AccordionList.unit.spec.js
@@ -1,7 +1,9 @@
 import React from "react";
 import { render, screen, fireEvent } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
 
 import AccordionList from "metabase/components/AccordionList";
+import TippyPopover from "metabase/components/Popover/TippyPopover";
 
 const SECTIONS = [
   {
@@ -80,6 +82,28 @@ describe("AccordionList", () => {
     fireEvent.change(SEARCH_FIELD, { target: { value: "Something Else" } });
     assertAbsence(["Foo", "Bar", "Baz"]);
   });
+
+  describe("with the `renderItemWrapper` prop", () => {
+    it("should be able to wrap the list items in components like popovers", async () => {
+      const renderItemWrapper = (itemContent, item) => {
+        return (
+          <TippyPopover content={<div>popover</div>}>
+            {itemContent}
+          </TippyPopover>
+        );
+      };
+
+      render(
+        <AccordionList
+          sections={SECTIONS}
+          renderItemWrapper={renderItemWrapper}
+        />,
+      );
+
+      userEvent.hover(screen.getByText("Foo"));
+      expect(await screen.findByText("popover")).toBeVisible();
+    });
+  });
 });
 
 function assertAbsence(array) {
diff --git a/frontend/src/metabase/components/AccordionList/index.js b/frontend/src/metabase/components/AccordionList/index.js
new file mode 100644
index 00000000000..5e468a3c3f4
--- /dev/null
+++ b/frontend/src/metabase/components/AccordionList/index.js
@@ -0,0 +1 @@
+export { default } from "./AccordionList";
-- 
GitLab