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 cf0fab94f7dbd3f1e7b7484ab31e819d9125c899..5daee074b68e22857aa21acf8e1a31a3cfd556c4 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 fd3fc967f39f215aa1ab4225ff61d3313ce807c4..bd02760ba88c8d78f8befbb536779a69bbaa1129 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 d53e4c832fc0192ddd97a8432c6cf3032a67ca30..7f9382680c0624ecc47cabaf64319de4724491f0 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 0000000000000000000000000000000000000000..5e468a3c3f44ebc1e86b078ee6df24385ec2edcd --- /dev/null +++ b/frontend/src/metabase/components/AccordionList/index.js @@ -0,0 +1 @@ +export { default } from "./AccordionList";