Skip to main content

Popup

Features​

  • Sizing based on content
  • Resizable and movable (by dragging header)
  • Connected to, and positioned by a trigger, or positioned in center otherwise.
  • Layout with Header, Content and Hint

Live example​

Result
Loading...
Live Editor
// import { PopupTrigger, Popup, Button } from "@intellij-platform/core";

<PopupTrigger
  interactions="move" // Other values: "all", "none"
  placement="bottom" // Other values: "top"
  nonDismissable={false} // Other values: true
  allowScroll="auto" // Other values: false, true
  popup={
    <Popup>
      <Popup.Layout
        header={<Popup.Header>Header</Popup.Header>}
        content={
          <div style={{ padding: "0.5rem" }}>
            Popup Content. Popup Content. Popup Content. <br />
            Popup Content. Popup Content. Popup Content. <br />
            Popup Content. Popup Content. Popup Content. <br />
          </div>
        }
        footer={<Popup.Hint>Hint text</Popup.Hint>}
      />
    </Popup>
  }
>
  <Button>Open popup</Button>
</PopupTrigger>

Popup component, rendered as a draggable overlay which is positioned either in the center of the viewport or relative to a trigger element. If there is a trigger element, use PopupTrigger instead.

PopupTrigger​

Popup opened by a trigger. trigger can be an element of any pressable component (such as Button or IconButton), and is rendered in place. Similar to component, children defines the content of Popup.

Popup.Layout​

Popup content layout, supporting fixed header and footer sections, and a scrollable content area.
<Popup>
<Popup.Layout
header={<Popup.Header>Header</Popup.Header>}
content={<>...</>}
footer={<Popup.Hint>Hint text</Popup.Hint>}
/>
</Popup>

Popup.Header​

Implements appearance of Popup Header, and also acts as a handle for moving the panel. Expected to be used with Popup#Layout:

<Popup>
<Popup.Layout header={<Popup.Header>Header</Popup.Header>} />
</Popup>

Custom header​

By default, Popup header is a simple centered title. But more complex cases can be handled by just rendering a custom UI inside the header, without any specific support for those variations, from Popup.Header:

Open in storybook

Note how anywhere on the header, except for the action button, can still be used to move the Popup.

Hint​

Use Popup.Hint to render a hint (aka Advertiser) in Popup's footer.

<Popup>
<Popup.Layout footer={<Popup.Hint>Hint text</Popup.Hint>} />
</Popup>

Sizing and positioning​

TODO

Imperative API​

PopupManager​

PopupManager allows for imperatively showing popups, via usePopupManager. It holds the state of the stack of opened popups, and renders those popups. Although it's technically not required, only a single PopupManager is usually rendered as a wrapper, in an application.

usePopupManager​

Returns PopupManagerAPI, which has a show method to imperatively open a popup. Requires PopupManager to be rendered above in the component hierarchy.

// import { Popup, usePopupManager } from "@intellij-platform/core";
const { show } = usePopupManager();

show(
<Popup>
<Popup.Layout>...</Popup.Layout>
</Popup>, // The content of the popup. Typically a PopupLayout element,
{ interactions: "all" } // Other popup props
);

// More flexible interface which gets access to a `close` function to be called when needed.
show(({ close }) => <Popup.Layout>...</Popup.Layout>, { interactions: "all" });
Result
Loading...
Live Editor
const App = () => (
  <PopupManager>
    <SomeComponent />
  </PopupManager>
);
const SomeComponent = () => {
  const { show } = usePopupManager();
  const showPopup = () => {
    show(
      ({ close }) => (
        <Popup>
          <Popup.Layout
            header={<Popup.Header>Title</Popup.Header>}
            content={
              <SpeedSearchMenu
                onClose={close}
                autoFocus="first"
                fillAvailableSpace
              >
                <Item textValue="File">
                  <MenuItemLayout
                    icon={<PlatformIcon icon={"fileTypes/text"} />}
                    content="File"
                  />
                </Item>
                <Item textValue="Directory">
                  <MenuItemLayout
                    icon={<PlatformIcon icon={"nodes/folder"} />}
                    content="Directory"
                  />
                </Item>
                <Divider />
                <Item textValue="HTML File">
                  <MenuItemLayout
                    icon={<PlatformIcon icon={"fileTypes/html"} />}
                    content="HTML File"
                  />
                </Item>
                <Item textValue="Stylesheet">
                  <MenuItemLayout
                    icon={<PlatformIcon icon={"fileTypes/css"} />}
                    content="Stylesheet"
                  />
                </Item>
                <Item textValue="Javascript">
                  <MenuItemLayout
                    icon={<PlatformIcon icon={"fileTypes/javaScript"} />}
                    content="Javascript"
                  />
                </Item>
                <Item
                  title={
                    <MenuItemLayout
                      content=".ignore File"
                      icon={<PlatformIcon icon={"fileTypes/text"} />}
                    />
                  }
                >
                  <Item>.gitignore File (Git)</Item>
                  <Item>.bzrignore File (Bazaar)</Item>
                  <Item>.npmignore File (Npm)</Item>
                </Item>
              </SpeedSearchMenu>
            }
          />
        </Popup>
      ),
      { interactions: "all", allowScroll: false }
    );
  };
  return <Button onPress={showPopup}>Show popup</Button>;
};

render(<App />);