JComponent () { JPanel pane = new JPanel(new MigLayout("fillx, debug, novisualpadding, ins 0, gap 5")); pane.add(new JLabel("Shows a combobox with custom JBPopup and multiple layers of items"), "baseline, wrap"); final class Item { final Icon myIcon; final String myText; final List<Item> myChildren; Item(@NotNull Icon icon, @NotNull @NlsContexts.ListItem String text) { this(icon, text, ImmutableList.of()); } Item(@NotNull Icon icon, @NotNull @NlsContexts.ListItem String text, @NotNull List<? extends Item> myChildren) { this.myIcon = icon; this.myText = text; this.myChildren = List.copyOf(myChildren); } } final class Model extends DefaultComboBoxModel<Item> implements ComboBoxPopupState<Item> { Model(List<Item> items) { super(items.toArray(new Item[0])); } @Override public @Nullable ListModel<Item> onChosen(Item selectedValue) { if (selectedValue.myChildren.isEmpty()) return null; return new Model(selectedValue.myChildren); } @Override public boolean hasSubstep(Item selectedValue) { return !selectedValue.myChildren.isEmpty(); } } ImmutableList.Builder<Item> builder2 = ImmutableList.builder(); builder2.add(new Item(AllIcons.General.Add, "Add")); builder2.add(new Item(AllIcons.General.ArrowDown, "ArrowDown")); builder2.add(new Item(AllIcons.General.Balloon, "Balloon")); builder2.add(new Item(AllIcons.General.Filter, "Filter")); builder2.add(new Item(AllIcons.General.Remove, "Remove")); ImmutableList<Item> level2 = builder2.build(); ImmutableList.Builder<Item> builder1 = ImmutableList.builder(); builder1.add(new Item(AllIcons.Icons.Ide.NextStep, "Next")); builder1.add(new Item(AllIcons.Vcs.Patch_applied, "Patch")); builder1.add(new Item(AllIcons.General.Settings, "SubList", level2)); builder1.add(new Item(AllIcons.General.Remove, "Remove")); ComboBox<Item> comboBox = new ComboBox<>(new Model(builder1.build())); comboBox.setSwingPopup(false); ColoredListCellRenderer<Item> renderer = new ColoredListCellRenderer<>() { @Override protected void customizeCellRenderer(@NotNull JList<? extends Item> list, Item value, int index, boolean selected, boolean hasFocus) { setIcon(value.myIcon); append(value.myText); append(" "); append("this text is gray", SimpleTextAttributes.GRAY_ATTRIBUTES); append(" "); append("error", SimpleTextAttributes.ERROR_ATTRIBUTES); if (!value.myChildren.isEmpty()) { append(" ->"); } } }; comboBox.setRenderer(renderer); pane.add(new JLabel("The ComboBox:"), "baseline"); pane.add(comboBox, "baseline"); return pane; }