-- Roblox GUI Template (LocalScript)
-- This script creates a modular, editable GUI with helper functions to add buttons, toggles, sliders, labels and input boxes.
-- You can copy-paste the functions below into your own scripts and customize appearance or behavior.

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local player = Players.LocalPlayer
local mouse = player:GetMouse()

-- Configuration -----------------------------------------------------------
local CONFIG = {
    GuiName = "MyEditableGUI",
    TitleText = "Prison Life",
    Width = 420,
    Height = 300,
    CornerRadius = UDim.new(0, 8),
    BackgroundColor = Color3.fromRGB(30, 30, 35),
    AccentColor = Color3.fromRGB(0, 170, 255),
}

-- Utility helpers ---------------------------------------------------------
local function new(class, props)
    local obj = Instance.new(class)
    if props then
        for k, v in pairs(props) do
            if type(k) == "string" then
                pcall(function() obj[k] = v end)
            end
        end
    end
    return obj
end

local function makeCorner(parent, corner)
    local uicorner = new("UICorner", {CornerRadius = corner or CONFIG.CornerRadius})
    uicorner.Parent = parent
    return uicorner
end

-- Root GUI creation ------------------------------------------------------
local screenGui = Instance.new("ScreenGui")
screenGui.Name = CONFIG.GuiName
screenGui.ResetOnSpawn = false
screenGui.Parent = player:WaitForChild("PlayerGui")

local mainFrame = new("Frame", {
    Name = "MainFrame",
    Size = UDim2.new(0, CONFIG.Width, 0, CONFIG.Height),
    Position = UDim2.new(0.5, -CONFIG.Width/2, 0.5, -CONFIG.Height/2),
    BackgroundColor3 = CONFIG.BackgroundColor,
    BorderSizePixel = 0,
})
mainFrame.Parent = screenGui
makeCorner(mainFrame)

-- Title bar ---------------------------------------------------------------
local titleBar = new("Frame", {
    Name = "TitleBar",
    Size = UDim2.new(1, 0, 0, 36),
    BackgroundTransparency = 1,
    Parent = mainFrame,
})

local titleLabel = new("TextLabel", {
    Name = "TitleLabel",
    Size = UDim2.new(1, -10, 1, 0),
    Position = UDim2.new(0, 10, 0, 0),
    BackgroundTransparency = 1,
    Text = CONFIG.TitleText,
    TextXAlignment = Enum.TextXAlignment.Left,
    TextColor3 = Color3.fromRGB(240,240,240),
    Font = Enum.Font.GothamSemibold,
    TextSize = 18,
    Parent = titleBar,
})

local closeButton = new("TextButton", {
    Name = "Close",
    Size = UDim2.new(0, 28, 0, 28),
    Position = UDim2.new(1, -36, 0, 4),
    BackgroundTransparency = 0,
    BackgroundColor3 = Color3.fromRGB(40, 40, 44),
    Text = "X",
    TextColor3 = Color3.fromRGB(220,220,220),
    Font = Enum.Font.GothamBold,
    TextSize = 16,
    Parent = titleBar,
})
makeCorner(closeButton, UDim.new(0, 6))

-- Content area -----------------------------------------------------------
local content = new("ScrollingFrame", {
    Name = "Content",
    Size = UDim2.new(1, -20, 1, -46),
    Position = UDim2.new(0, 10, 0, 40),
    CanvasSize = UDim2.new(0, 0, 0, 0),
    ScrollBarThickness = 6,
    BackgroundTransparency = 1,
    Parent = mainFrame,
})
local uiList = new("UIListLayout", {Padding = UDim.new(0, 8)})
uiList.Parent = content
uiList.SortOrder = Enum.SortOrder.LayoutOrder

-- Make the GUI draggable -----------------------------------------------
local dragging, dragInput, dragStart, startPos

local function updateDrag(input)
    local delta = input.Position - dragStart
    mainFrame.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y)
end

titleBar.InputBegan:Connect(function(input)
    if input.UserInputType == Enum.UserInputType.MouseButton1 then
        dragging = true
        dragStart = input.Position
        startPos = mainFrame.Position
        input.Changed:Connect(function()
            if input.UserInputState == Enum.UserInputState.End then
                dragging = false
            end
        end)
    end
end)

titleBar.InputChanged:Connect(function(input)
    if input.UserInputType == Enum.UserInputType.MouseMovement then
        dragInput = input
    end
end)

game:GetService("UserInputService").InputChanged:Connect(function(input)
    if dragging and input == dragInput then
        updateDrag(input)
    end
end)

-- Close button behavior -------------------------------------------------
closeButton.MouseButton1Click:Connect(function()
    mainFrame.Visible = not mainFrame.Visible
end)

-- Helper UI builders ----------------------------------------------------
local builder = {}

-- internal helper to recalc canvas size
local function recalcCanvas()
    local contentHeight = 0
    for i, child in ipairs(content:GetChildren()) do
        if child:IsA("GuiObject") and child ~= uiList then
            contentHeight = contentHeight + child.AbsoluteSize.Y + uiList.Padding.Offset
        end
    end
    content.CanvasSize = UDim2.new(0, 0, 0, contentHeight + 8)
end

function builder:AddLabel(text)
    local lbl = new("TextLabel", {
        Name = "Label",
        Size = UDim2.new(1, -8, 0, 28),
        BackgroundTransparency = 1,
        Text = text or "Label",
        TextColor3 = Color3.fromRGB(230,230,230),
        Font = Enum.Font.Gotham,
        TextSize = 14,
        Parent = content,
    })
    recalcCanvas()
    return lbl
end

function builder:AddButton(text, onClick)
    local btn = new("TextButton", {
        Name = "Button",
        Size = UDim2.new(1, -8, 0, 34),
        BackgroundColor3 = Color3.fromRGB(50,50,60),
        Text = text or "Button",
        TextColor3 = Color3.fromRGB(240,240,240),
        Font = Enum.Font.GothamBold,
        TextSize = 15,
        Parent = content,
    })
    makeCorner(btn)
    btn.MouseButton1Click:Connect(function()
        if onClick then
            pcall(onClick, btn)
        end
    end)
    recalcCanvas()
    return btn
end

function builder:AddToggle(text, default, callback)
    local container = new("Frame", {Size = UDim2.new(1, -8, 0, 34), BackgroundTransparency = 1, Parent = content})
    local lbl = new("TextLabel", {Size = UDim2.new(1, -50, 1, 0), Position = UDim2.new(0, 0, 0, 0), BackgroundTransparency = 1, Text = text or "Toggle", TextColor3 = Color3.fromRGB(230,230,230), Font = Enum.Font.Gotham, TextSize = 14, Parent = container})
    local toggle = new("TextButton", {Size = UDim2.new(0, 36, 0, 26), Position = UDim2.new(1, -36, 0, 4), BackgroundColor3 = Color3.fromRGB(70,70,80), Text = "", Parent = container})
    makeCorner(toggle)
    local state = default and true or false
    local knob = new("Frame", {Size = UDim2.new(0, 14, 0, 14), Position = UDim2.new(state and 1 or 0, -18, 0.5, -7), AnchorPoint = Vector2.new(0,0), BackgroundColor3 = CONFIG.AccentColor, Parent = toggle})
    makeCorner(knob, UDim.new(0, 6))

    local function setState(v)
        state = not not v
        knob:TweenPosition(UDim2.new(state and 1 or 0, state and -18 or 4, 0.5, -7), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.16, true)
        if callback then pcall(callback, state) end
    end

    toggle.MouseButton1Click:Connect(function()
        setState(not state)
    end)

    recalcCanvas()
    return {Container = container, Set = setState, Get = function() return state end}
end

function builder:AddSlider(text, min, max, default, onChange)
    local container = new("Frame", {Size = UDim2.new(1, -8, 0, 42), BackgroundTransparency = 1, Parent = content})
    local lbl = new("TextLabel", {Size = UDim2.new(1, -8, 0, 16), Position = UDim2.new(0, 0, 0, 0), BackgroundTransparency = 1, Text = text or "Slider", TextColor3 = Color3.fromRGB(230,230,230), Font = Enum.Font.Gotham, TextSize = 13, Parent = container})
    local bar = new("Frame", {Size = UDim2.new(1, -8, 0, 10), Position = UDim2.new(0, 4, 0, 20), BackgroundColor3 = Color3.fromRGB(60,60,70), Parent = container})
    makeCorner(bar)
    local handle = new("Frame", {Size = UDim2.new(0, 12, 1, 0), Position = UDim2.new(0, 0, 0, 0), BackgroundColor3 = CONFIG.AccentColor, Parent = bar})
    makeCorner(handle)

    min = min or 0
    max = max or 100
    local value = default or min

    local dragging = false
    handle.InputBegan:Connect(function(input)
        if input.UserInputType == Enum.UserInputType.MouseButton1 then
            dragging = true
        end
    end)
    handle.InputEnded:Connect(function(input)
        if input.UserInputType == Enum.UserInputType.MouseButton1 then
            dragging = false
        end
    end)
    game:GetService("UserInputService").InputChanged:Connect(function(input)
        if dragging and input.UserInputType == Enum.UserInputType.MouseMovement then
            local rel = math.clamp((input.Position.X - bar.AbsolutePosition.X) / bar.AbsoluteSize.X, 0, 1)
            handle.Size = UDim2.new(0, math.max(8, rel * bar.AbsoluteSize.X), 1, 0)
            value = min + rel * (max - min)
            if onChange then pcall(onChange, value) end
        end
    end)

    recalcCanvas()
    return {Container = container, Get = function() return value end}
end

function builder:AddTextBox(placeholder, onEnter)
    local box = new("TextBox", {Size = UDim2.new(1, -8, 0, 32), BackgroundColor3 = Color3.fromRGB(50,50,60), Text = "", PlaceholderText = placeholder or "Enter text...", ClearTextOnFocus = false, Font = Enum.Font.Gotham, TextSize = 14, TextColor3 = Color3.fromRGB(240,240,240), Parent = content})
    makeCorner(box)
    box.FocusLost:Connect(function(enterPressed)
        if enterPressed and onEnter then pcall(onEnter, box.Text) end
    end)
    recalcCanvas()
    return box
end

-- Example: Pre-fill the GUI with some editable items --------------------
builder:AddLabel("Welcome — edit this GUI by adding/removing items in the builder table")
local btn = builder:AddButton("Example Button", function()
    print("Button clicked")
end)

local toggle = builder:AddToggle("Example Toggle", true, function(state)
    print("Toggle now", state)
end)

local slider = builder:AddSlider("Example Slider", 0, 120, 50, function(value)
    -- round to 1 decimal for printing
    print(string.format("Slider value: %.1f", value))
end)

local input = builder:AddTextBox("Type something and press Enter", function(text)
    print("User entered:", text)
end)

-- Public API: allow other scripts to require this or access builder -------
-- If you placed this in a ModuleScript you can return 'builder' here.
-- For convenience we store builder on the ScreenGui so other LocalScripts can find it:
local api = {}
api.Builder = builder
api.MainFrame = mainFrame
screenGui:SetAttribute("GuiAPI", true) -- marker attribute
screenGui:SetAttribute("GuiVersion", 1)

-- Final touches ----------------------------------------------------------
-- Make the GUI slightly fade in on spawn
mainFrame.BackgroundTransparency = 1
TweenService:Create(mainFrame, TweenInfo.new(0.3), {BackgroundTransparency = 0}):Play()

-- Expose API via an object on PlayerGui for quick access (optional)
local STORAGE_NAME = "_EditableGuiAPI"
player:WaitForChild("PlayerGui").Parent:SetAttribute(STORAGE_NAME, true) -- harmless marker
screenGui:SetAttribute("_hasEditableGui", true)

-- You can get this builder from other LocalScripts like this (example):
-- local myGui = player:WaitForChild("PlayerGui"):FindFirstChild("MyEditableGUI")
-- if myGui and myGui:GetAttribute("GuiAPI") then
--     -- interact with the GUI by requiring this LocalScript as a ModuleScript version
-- end

-- End of template

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: