You create a GUI in Minecraft Bedrock by writing a script that opens a form, adds buttons or text fields to it, and handles what happens when a player interacts with those elements
Minecraft Bedrock's scripting system uses the GameTest framework, which includes form objects that display on screen. A GUI starts as a simple form object in your script, gets populated with UI elements like buttons or input fields, then sends back the player's choice when they submit it. The whole process happens in your behavior pack's scripts folder, and the form appears in-game when a command or event triggers it.
The three main form types are ActionFormData (buttons only), MessageFormData (yes/no dialog), and ModalFormData (text fields and dropdowns). Which one you use depends on what information you need from the player. Most custom GUIs use ActionFormData because it's the simplest and most flexible for menus.
Key Takeaways
- ActionFormData creates a form with buttons; ModalFormData adds text input fields and dropdown lists; MessageFormData shows a simple yes-or-no prompt.
- You write the form in a script file inside your behavior pack's scripts folder, then show it to a player using the showToPlayer() method.
- The form returns a response object that tells you which button the player clicked or what text they entered.
- Forms only work in multiplayer worlds or when cheats are enabled; they do not work in single-player survival without cheats turned on.
Setting up ActionFormData for a button menu
ActionFormData is the easiest form type to start with because it only displays buttons. Create a new script file in your behavior pack at the path scripts/main.js (or any name you choose). At the top, import the necessary modules from the GameTest framework.
Inside your script, create a function that builds the form. Use new ActionFormData() to start, then chain methods to add a title, body text, and buttons. Each button is added with .button("Button Label"). When you are done adding buttons, call .show(player) to display it to a specific player. The player object comes from a command or event listener in your script.
Here is the basic structure:
import { ActionFormData } from "@minecraft/server-ui"; function showMainMenu(player) { let form = new ActionFormData() .title("Main Menu") .body("Choose an option:") .button("Option 1") .button("Option 2") .button("Option 3"); form.show(player).then(response => { if (response.canceled) return; handleMenuChoice(player, response.selection); }); }
The .then() part waits for the player to submit the form. The response object contains selection, which is the index of the button they clicked (0 for the first button, 1 for the second, and so on). If the player closes the form without clicking a button, response.canceled is true.
Handling player input from forms
After a player submits a form, you need a function to decide what happens based on their choice. Create a separate function that takes the player and the button index, then runs different code for each option.
For example, if your form has three buttons for teleporting to different locations, your handler function would check which button was clicked and teleport the player accordingly. You can run commands, modify player data, trigger events, or call other functions from inside this handler.
function handleMenuChoice(player, selection) { if (selection === 0) { player.runCommand("tp @s 100 64 100"); } else if (selection === 1) { player.runCommand("tp @s 200 64 200"); } else if (selection === 2) { player.runCommand("tp @s 300 64 300"); } }
This pattern works for any form type. The response object structure changes depending on the form — ModalFormData returns an array of values instead of a single selection — but the basic idea stays the same: check the response, then act on it.
Using ModalFormData for text input and dropdowns
ModalFormData lets you collect more complex input from players. Instead of just buttons, you can add text fields where players type, dropdown lists to choose from, and toggle switches. This is useful for settings menus, naming items, or collecting configuration data.
Build a ModalFormData form the same way as ActionFormData, but use different methods to add elements. Use .textField("Label", "Placeholder") for a text input, .dropdown("Label", ["Option 1", "Option 2"]) for a dropdown, and .toggle("Label") for a switch. The order you add elements matters because the response comes back as an array in that same order.
import { ModalFormData } from "@minecraft/server-ui"; function showSettingsForm(player) { let form = new ModalFormData() .title("Settings") .textField("Player Name", "Enter name") .dropdown("Difficulty", ["Easy", "Normal", "Hard"]) .toggle("Enable PvP"); form.show(player).then(response => { if (response.canceled) return; let playerName = response.formValues[0]; let difficulty = response.formValues[1]; let pvpEnabled = response.formValues[2]; handleSettings(player, playerName, difficulty, pvpEnabled); }); }
The response.formValues array holds the player's input in the order you added the fields. Index 0 is the text field, index 1 is the dropdown selection (as a number, where 0 is the first option), and index 2 is the toggle state (true or false).
Triggering forms with commands or events
Your form functions do nothing until something calls them. The most common trigger is a command. Use the @minecraft/server module to listen for chat commands, then call your form function when a player types the command.
Import the world object and set up a command listener. When a player types a command that matches your trigger word, extract the player object and pass it to your form function.
import { world } from "@minecraft/server"; world.beforeEvents.chatSend.subscribe(event => { if (event.message === "!menu") { showMainMenu(event.sender); event.cancel = true; } });
Setting event.cancel = true prevents the command from appearing in chat. You can also trigger forms from other events, like when a player breaks a block, uses an item, or enters a certain area. The pattern is the same: listen for the event, get the player, and call your form function.
Common issues and how to fix them
Forms do not appear in single-player survival mode unless cheats are enabled. If you are testing and the form never shows up, turn on cheats in your world settings. Forms also require the behavior pack to be enabled and the scripts to be properly imported in your manifest.json file.
If your form shows but the buttons do not work, check that your response handler function is actually being called. Add a console.log() statement inside the .then() block to confirm the form is returning a response. Make sure the player object you are passing to showToPlayer() is valid and not undefined.
Text fields in ModalFormData can be left blank by the player, so always check if the returned string is empty before using it. Dropdown selections return a number, not the text of the option, so make sure you are comparing against the index, not the label. If you are chaining multiple forms together, remember that each form.show() call is asynchronous, so the next form will not appear until the first one is submitted.
Frequently Asked Questions
Can I add images or custom colors to a form?
ActionFormData and ModalFormData do not support custom colors or images in the current GameTest framework. You can only use text for titles, labels, and button names. If you need more visual control, you would need to use a different approach like resource packs with custom UI or third-party tools outside of Bedrock scripting.
How do I make a form appear when a player right-clicks a block?
Listen for the playerInteractWithBlock event from the @minecraft/server module. Check if the player is holding a specific item or if the block matches a certain type, then call your form function. You will need to set the event to canceled if you want to prevent the normal block interaction from happening.
What happens if a player closes the form without submitting it?
The response.canceled property is set to true. Your code should check for this at the start of your response handler and return early if it is true, so you do not try to use undefined values from formValues or selection.
Can I open a form for all players at once?
No, forms are shown to individual players. To show a form to multiple players, loop through all players in the world using world.getAllPlayers() and call showToPlayer() for each one separately.
Do forms work in multiplayer realms?
Yes, forms work in multiplayer worlds and Realms as long as the behavior pack with the scripts is enabled on the world. All players can see and interact with forms triggered by commands or events.