public static Pair<JPanel, JBList<AnAction>> createActionGroupPanel(ActionGroup action,
                                                                      Runnable backAction,
                                                                      @NotNull Disposable parentDisposable) {
    JPanel actionsListPanel = new JPanel(new BorderLayout());

    actionsListPanel.setBackground(getProjectsBackground());
    java.util.List<AnAction> groups = flattenActionGroups(action);
    DefaultListModel<AnAction> model = JBList.createDefaultListModel(groups);
    JBList<AnAction> list = new JBList<>(model);
    ListListenerCollapsedActionGroupExpander.expandCollapsableGroupsOnSelection(list, model, parentDisposable);
    for (AnAction group : groups) {
      if (group instanceof Disposable) {
        Disposer.register(parentDisposable, (Disposable)group);
      }
    }
    Disposer.register(parentDisposable, new Disposable() {
      @Override
      public void dispose() {
        model.clear();
      }
    });

    list.setBackground(getProjectsBackground());
    list.setCellRenderer(new GroupedItemsListRenderer<>(new ListItemDescriptorAdapter<AnAction>() {
                           @Override
                           public @Nullable String getTextFor(AnAction value) {
                             return value.getTemplateText();
                           }

                           @Override
                           public @Nullable String getCaptionAboveOf(AnAction value) {
                             return getParentGroupName(value);
                           }

                           @Override
                           public boolean hasSeparatorAboveOf(AnAction value) {
                             int index = model.indexOf(value);
                             final String parentGroupName = getParentGroupName(value);

                             if (index < 1) return parentGroupName != null;
                             AnAction upper = model.get(index - 1);
                             if (getParentGroupName(upper) == null && parentGroupName != null) return true;

                             return !Objects.equals(getParentGroupName(upper), parentGroupName);
                           }
                         }) {
                           @Override
                           protected JComponent createItemComponent() {
                             JComponent component = super.createItemComponent();
                             myTextLabel.setBorder(JBUI.Borders.empty(5, 0));
                             return component;
                           }

                           @Override
                           protected Color getBackground() {
                             return getProjectsBackground();
                           }

                           @Override
                           public Component getListCellRendererComponent(JList<? extends AnAction> list,
                                                                         AnAction value,
                                                                         int index,
                                                                         boolean isSelected,
                                                                         boolean cellHasFocus) {
                             var component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                             // Collapsable group should be rendered as collapsable button
                             if (value instanceof CollapsedActionGroup actionGroup) {
                               return CollapsedButtonKt.createCollapsedButton(actionGroup, childAction -> {
                                 // To get an action width we set to the component, render it, and see component width
                                 // This approach obeys component spacing, font's size e.t.c
                                 setLabelByAction(childAction);
                                 return component.getPreferredSize().width;
                               });
                             }
                             return component;
                           }

                           @Override
                           protected void customizeComponent(JList<? extends AnAction> list, AnAction value, boolean isSelected) {
                             setLabelByAction(value);
                           }

                           private void setLabelByAction(@NotNull AnAction value) {
                             if (myTextLabel != null) {
                               myTextLabel.setText(value.getTemplateText());
                               myTextLabel.setIcon(value.getTemplatePresentation().getIcon());
                             }
                           }
                         }
    );

    JScrollPane pane = ScrollPaneFactory.createScrollPane(list, true);
    pane.setBackground(getProjectsBackground());
    actionsListPanel.add(pane, BorderLayout.CENTER);

    int width = (int)MathUtil.clamp(Math.round(list.getPreferredSize().getWidth()), JBUIScale.scale(100), JBUIScale.scale(200));
    pane.setPreferredSize(JBUI.size(width + 14, -1));

    boolean singleProjectGenerator = list.getModel().getSize() == 1;

    final Ref<Component> selected = Ref.create();
    final HashMap<Object, JPanel> panelsMap = new HashMap<>();
    final Set<JButton> actionButtonsCache = new HashSet<>();
    final JPanel main = new NonOpaquePanel(new BorderLayout()) {
      @Override
      public void updateUI() {
        super.updateUI();

        // Update all UI components that are detached from windows
        if (SwingUtilities.getWindowAncestor(this) == null) {
          for (Component component : getComponents()) {
            IJSwingUtilities.updateComponentTreeUI(component);
          }
        }
        for (JPanel panel : panelsMap.values()) {
          if (panel.getParent() == null) {
            IJSwingUtilities.updateComponentTreeUI(panel);
          }
        }
        for (JButton button : actionButtonsCache) {
          if (button.getParent() == null) {
            IJSwingUtilities.updateComponentTreeUI(button);
          }
        }
      }
    };
    main.add(actionsListPanel, BorderLayout.WEST);

    JPanel bottomPanel = new NonOpaquePanel(new FlowLayout(FlowLayout.RIGHT));
    bottomPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, new JBColor(Gray._217, Gray._81)));
    main.add(bottomPanel, BorderLayout.SOUTH);

    ListSelectionListener selectionListener = e -> {
      if (e.getValueIsAdjusting()) {
        // Update when a change has been finalized.
        // For instance, selecting an element with mouse fires two consecutive ListSelectionEvent events.
        return;
      }
      if (!selected.isNull()) {
        main.remove(selected.get());
      }
      Object value = list.getSelectedValue();
      if (value instanceof AbstractActionWithPanel) {
        final JPanel panel = panelsMap.computeIfAbsent(value, o -> ((AbstractActionWithPanel)value).createPanel());
        ((AbstractActionWithPanel)value).onPanelSelected();

        panel.setBorder(JBUI.Borders.empty(7, 10));
        selected.set(panel);
        main.add(selected.get());

        JButton actionButton = ((AbstractActionWithPanel)value).getActionButton();
        actionButtonsCache.add(actionButton);
        updateBottomPanel(panel, actionButton, bottomPanel, backAction);

        main.revalidate();
        main.repaint();
      }
    };
    list.addListSelectionListener(selectionListener);
    if (backAction != null) {
      new DumbAwareAction() {
        @Override
        public void update(@NotNull AnActionEvent e) {
          e.getPresentation().setEnabled(!StackingPopupDispatcher.getInstance().isPopupFocused());
        }

        @Override
        public @NotNull ActionUpdateThread getActionUpdateThread() {
          return ActionUpdateThread.EDT;
        }

        @Override
        public void actionPerformed(@NotNull AnActionEvent e) {
          backAction.run();
        }
      }.registerCustomShortcutSet(CommonShortcuts.ESCAPE, main, parentDisposable);
    }
    installQuickSearch(list);

    if (singleProjectGenerator) {
      actionsListPanel.setPreferredSize(new Dimension(0, 0));
    }

    return Pair.create(main, list);
  }
public static Pair<JPanel, JBList<AnAction>> createActionGroupPanel(ActionGroup action,
                                                                      Runnable backAction,
                                                                      @NotNull Disposable parentDisposable)