Skip to main content
The Button class represents a clickable item in a menu. Foundation provides several ways to create buttons, from simple static buttons to complex interactive prompts.

Creating buttons

Basic button

Extend the Button class and implement the required methods:
Button myButton = new Button() {
    @Override
    public void onClickedInMenu(Player player, Menu menu, ClickType click) {
        player.sendMessage("Button clicked!");
    }
    
    @Override
    public ItemStack getItem() {
        return ItemCreator.of(CompMaterial.DIAMOND)
            .name("&bClick Me")
            .make();
    }
};

Button with slot

Button slottedButton = new Button(13) {
    @Override
    public void onClickedInMenu(Player player, Menu menu, ClickType click) {
        player.sendMessage("Center button clicked!");
    }
    
    @Override
    public ItemStack getItem() {
        return ItemCreator.of(CompMaterial.NETHER_STAR).make();
    }
};

Core methods

onClickedInMenu(Player player, Menu menu, ClickType click)
void
required
Called automatically when the button is clicked.
@Override
public void onClickedInMenu(Player player, Menu menu, ClickType click) {
    if (click == ClickType.RIGHT) {
        player.sendMessage("Right clicked!");
    } else if (click == ClickType.SHIFT_LEFT) {
        player.sendMessage("Shift left clicked!");
    }
}
getItem()
ItemStack
required
Returns the ItemStack representing this button.
@Override
public ItemStack getItem() {
    return ItemCreator.of(CompMaterial.EMERALD)
        .name("&aAccept")
        .lore("&7Click to confirm")
        .glow(true)
        .make();
}
getSlot()
int
Returns the slot position of this button, or -1 if not set.

Static factory methods

Dummy buttons

makeEmpty()
DummyButton
Creates an empty (air) button that does nothing when clicked.
Button emptyButton = Button.makeEmpty();
makeInfo(String... description)
DummyButton
Creates an info button (Nether Star) with descriptive text.
Button info = Button.makeInfo(
    "&7This menu allows you to",
    "&7manage your settings.",
    "&7Click items to configure."
);
makeDummy(CompMaterial material, String title, String... lore)
DummyButton
Creates a dummy button with the specified material, title, and lore.
Button dummy = Button.makeDummy(
    CompMaterial.STONE,
    "&7Decorative Item",
    "This does nothing"
);
makeDummy(ItemCreator creator)
DummyButton
Creates a dummy button from an ItemCreator.
Button dummy = Button.makeDummy(
    ItemCreator.of(CompMaterial.GOLD_BLOCK)
        .name("&6Decoration")
        .glow(true)
);

Interactive buttons

makeSimple(CompMaterial icon, String title, String label, Consumer<Player> onClickFunction)
Button
Creates a simple button with an icon, title, label, and click handler.
The icon won’t update when calling Menu.restartMenu(). For dynamic icons, create an anonymous Button class.
Button simple = Button.makeSimple(
    CompMaterial.DIAMOND_SWORD,
    "&6Weapon Shop",
    "&7Click to browse weapons",
    player -> {
        new WeaponShop().displayTo(player);
    }
);
makeSimple(ItemCreator builder, Consumer<Player> onClickFunction)
Button
Creates a simple button from an ItemCreator with a click handler.
Button simple = Button.makeSimple(
    ItemCreator.of(CompMaterial.EMERALD)
        .name("&aAccept")
        .lore("&7Click to confirm"),
    player -> {
        player.sendMessage("Accepted!");
    }
);
makeSimple(CompMaterial icon, String title, String label, BiConsumer<Player, ClickType> onClickFunction)
Button
Creates a simple button that passes both player and click type to the handler.
Button simple = Button.makeSimple(
    CompMaterial.CHEST,
    "&6Storage",
    "&7Left: Open | Right: Info",
    (player, click) -> {
        if (click.isLeftClick()) {
            openStorage(player);
        } else if (click.isRightClick()) {
            showStorageInfo(player);
        }
    }
);

Boolean toggle buttons

makeBoolean(ItemCreator creator, Supplier<Boolean> getter, Consumer<Boolean> setter)
Button
Creates a toggle button for boolean settings. The item will glow when enabled.
Button toggle = Button.makeBoolean(
    ItemCreator.of(CompMaterial.REDSTONE_TORCH)
        .name("&6PvP Enabled")
        .lore("&7Status: {status}")
        .lore("&7Click to toggle"),
    () -> arena.isPvpEnabled(),
    enabled -> arena.setPvpEnabled(enabled)
);
Use {status} in lore - it will be replaced with “&aEnabled” or “&cDisabled”.

Prompt buttons

makeStringPrompt(ItemCreator creator, String question, Consumer<String> onPromptFinish)
Button
Creates a button that prompts the player for text input.
Button stringPrompt = Button.makeStringPrompt(
    ItemCreator.of(CompMaterial.NAME_TAG)
        .name("&6Set Name")
        .lore("&7Click to rename"),
    "&6Enter a new name:",
    input -> {
        item.setName(input);
        player.sendMessage("Name set to: " + input);
    }
);
makeStringPrompt(ItemCreator creator, String question, String menuTitle, Consumer<String> onPromptFinish)
Button
Creates a string prompt with a custom animated menu title on completion.
Button stringPrompt = Button.makeStringPrompt(
    ItemCreator.of(CompMaterial.NAME_TAG)
        .name("&6Set Arena Name"),
    "&6Enter arena name:",
    "&aName Updated",
    input -> arena.setName(input)
);
makeIntegerPrompt(ItemCreator item, String question, RangedValue minMaxRange, Supplier<Object> getter, Consumer<Integer> setter)
Button
Creates a button that prompts for an integer within a range.
Button intPrompt = Button.makeIntegerPrompt(
    ItemCreator.of(CompMaterial.CLOCK)
        .name("&6Set Duration")
        .lore("&7Current: {current} seconds"),
    "&6Enter duration in seconds (current: {current}):",
    new RangedValue(10, 300),
    () -> arena.getDuration(),
    duration -> arena.setDuration(duration)
);
makeDecimalPrompt(ItemCreator item, String question, RangedValue minMaxRange, Supplier<Object> getter, Consumer<Double> setter)
Button
Creates a button that prompts for a decimal number within a range.
Button decimalPrompt = Button.makeDecimalPrompt(
    ItemCreator.of(CompMaterial.GOLD_NUGGET)
        .name("&6Set Multiplier")
        .lore("&7Current: {current}x"),
    "&6Enter multiplier (current: {current}):",
    new RangedValue(0.1, 10.0),
    () -> arena.getMultiplier(),
    multiplier -> arena.setMultiplier(multiplier)
);

Button positioning

Use the @Position annotation to automatically place buttons:
public class MyMenu extends Menu {
    
    @Position(4)
    private final Button centerButton = new Button() {
        @Override
        public void onClickedInMenu(Player player, Menu menu, ClickType click) {
            player.sendMessage("Center!");
        }
        
        @Override
        public ItemStack getItem() {
            return ItemCreator.of(CompMaterial.NETHER_STAR).make();
        }
    };
}
You can also use StartPosition for relative positioning:
@Position(value = 0, start = StartPosition.CENTER)
private final Button centerButton = ...;

@Position(value = 0, start = StartPosition.BOTTOM_LEFT)
private final Button bottomLeftButton = ...;

DummyButton

The DummyButton class is a special button type that does nothing when clicked. It’s useful for decorative items or spacers.
DummyButton spacer = Button.makeDummy(
    ItemCreator.of(CompMaterial.GRAY_STAINED_GLASS_PANE)
        .name(" ")
);

Complete example

public class SettingsMenu extends Menu {
    
    @Position(10)
    private final Button pvpToggle;
    
    @Position(12)
    private final Button maxPlayersButton;
    
    @Position(14)
    private final Button nameButton;
    
    private final Arena arena;
    
    public SettingsMenu(Arena arena) {
        this.arena = arena;
        
        setTitle("&6Arena Settings");
        setSize(9 * 3);
        
        // Toggle button for PvP
        pvpToggle = Button.makeBoolean(
            ItemCreator.of(CompMaterial.DIAMOND_SWORD)
                .name("&6PvP Enabled")
                .lore("&7Status: {status}")
                .lore("", "&7Click to toggle"),
            () -> arena.isPvpEnabled(),
            enabled -> {
                arena.setPvpEnabled(enabled);
                arena.save();
            }
        );
        
        // Integer prompt for max players
        maxPlayersButton = Button.makeIntegerPrompt(
            ItemCreator.of(CompMaterial.PLAYER_HEAD)
                .name("&6Max Players")
                .lore("&7Current: {current}")
                .lore("", "&7Click to change"),
            "&6Enter max players (current: {current}):",
            "Max players",
            new RangedValue(2, 100),
            () -> arena.getMaxPlayers(),
            max -> {
                arena.setMaxPlayers(max);
                arena.save();
            }
        );
        
        // String prompt for arena name
        nameButton = Button.makeStringPrompt(
            ItemCreator.of(CompMaterial.NAME_TAG)
                .name("&6Arena Name")
                .lore("&7Current: " + arena.getName())
                .lore("", "&7Click to rename"),
            "&6Enter new arena name:",
            "&aArena renamed",
            name -> {
                arena.setName(name);
                arena.save();
            }
        );
    }
}

Build docs developers (and LLMs) love