Not a member of GistPad yet?
Sign Up,
it unlocks many cool features!
- --[[
- ECHELON UI LIBRARY v1.0
- Premium Dark / Cyber Glass UI Library for Roblox
- Usage: local EchelonUI = loadstring(game:HttpGet("URL"))()
- ]]
- local EchelonUI = {}
- EchelonUI.__index = EchelonUI
- EchelonUI.Version = "1.0"
- EchelonUI.Name = "EchelonUI"
- -- Services
- local Players = game:GetService("Players")
- local TweenService = game:GetService("TweenService")
- local UserInputService = game:GetService("UserInputService")
- local RunService = game:GetService("RunService")
- local HttpService = game:GetService("HttpService")
- local CoreGui = game:GetService("CoreGui")
- local GuiService = game:GetService("GuiService")
- local LocalPlayer = Players.LocalPlayer
- local Mouse = LocalPlayer:GetMouse()
- -- Utilities
- local function isMobile()
- return UserInputService.TouchEnabled and not UserInputService.KeyboardEnabled
- end
- local function deepCopy(t)
- if type(t) ~= "table" then return t end
- local n = {}
- for k, v in pairs(t) do
- n[k] = deepCopy(v)
- end
- return n
- end
- local function clamp(v, min, max)
- return math.max(min, math.min(max, v))
- end
- local function round(n, step)
- if not step or step == 0 then return n end
- return math.floor(n / step + 0.5) * step
- end
- local function create(class, props)
- local inst = Instance.new(class)
- for k, v in pairs(props or {}) do
- if k ~= "Parent" then
- inst[k] = v
- end
- end
- if props and props.Parent then
- inst.Parent = props.Parent
- end
- return inst
- end
- local function tween(obj, props, duration, style, dir)
- local t = TweenService:Create(
- obj,
- TweenInfo.new(duration or 0.25, style or Enum.EasingStyle.Quint, dir or Enum.EasingDirection.Out),
- props
- )
- t:Play()
- return t
- end
- local function makeCorner(parent, radius)
- return create("UICorner", { CornerRadius = UDim.new(0, radius or 8), Parent = parent })
- end
- local function makeStroke(parent, color, thickness, transparency)
- return create("UIStroke", {
- Color = color or Color3.fromRGB(60, 60, 80),
- Thickness = thickness or 1,
- Transparency = transparency or 0.4,
- ApplyStrokeMode = Enum.ApplyStrokeMode.Border,
- Parent = parent
- })
- end
- local function makePadding(parent, t, b, l, r)
- return create("UIPadding", {
- PaddingTop = UDim.new(0, t or 0),
- PaddingBottom = UDim.new(0, b or 0),
- PaddingLeft = UDim.new(0, l or 0),
- PaddingRight = UDim.new(0, r or 0),
- Parent = parent
- })
- end
- local function makeList(parent, pad, dir, hAlign, vAlign)
- return create("UIListLayout", {
- Padding = UDim.new(0, pad or 6),
- FillDirection = dir or Enum.FillDirection.Vertical,
- HorizontalAlignment = hAlign or Enum.HorizontalAlignment.Left,
- VerticalAlignment = vAlign or Enum.VerticalAlignment.Top,
- SortOrder = Enum.SortOrder.LayoutOrder,
- Parent = parent
- })
- end
- -- ============================================================
- -- THEME SYSTEM
- -- ============================================================
- local ThemeRegistry = {} -- elements that react to theme changes
- local DefaultThemes = {
- Aqua = {
- bg = Color3.fromRGB(12, 14, 22),
- bg2 = Color3.fromRGB(18, 22, 34),
- bg3 = Color3.fromRGB(24, 30, 46),
- bg4 = Color3.fromRGB(32, 40, 58),
- accent = Color3.fromRGB(0, 210, 200),
- accent2 = Color3.fromRGB(0, 160, 180),
- accent3 = Color3.fromRGB(40, 240, 220),
- accentGlow = Color3.fromRGB(0, 255, 240),
- text = Color3.fromRGB(235, 240, 250),
- text2 = Color3.fromRGB(160, 175, 200),
- text3 = Color3.fromRGB(100, 115, 140),
- border = Color3.fromRGB(45, 55, 80),
- borderSoft = Color3.fromRGB(30, 38, 55),
- red = Color3.fromRGB(255, 70, 90),
- green = Color3.fromRGB(60, 220, 140),
- gold = Color3.fromRGB(255, 200, 60),
- },
- Purple = {
- bg = Color3.fromRGB(14, 12, 22),
- bg2 = Color3.fromRGB(22, 18, 34),
- bg3 = Color3.fromRGB(30, 24, 46),
- bg4 = Color3.fromRGB(40, 32, 58),
- accent = Color3.fromRGB(170, 90, 255),
- accent2 = Color3.fromRGB(130, 60, 220),
- accent3 = Color3.fromRGB(200, 130, 255),
- accentGlow = Color3.fromRGB(190, 110, 255),
- text = Color3.fromRGB(235, 235, 250),
- text2 = Color3.fromRGB(170, 160, 200),
- text3 = Color3.fromRGB(110, 100, 140),
- border = Color3.fromRGB(55, 45, 80),
- borderSoft = Color3.fromRGB(38, 30, 55),
- red = Color3.fromRGB(255, 70, 90),
- green = Color3.fromRGB(60, 220, 140),
- gold = Color3.fromRGB(255, 200, 60),
- },
- Red = {
- bg = Color3.fromRGB(16, 12, 14),
- bg2 = Color3.fromRGB(26, 16, 20),
- bg3 = Color3.fromRGB(36, 22, 26),
- bg4 = Color3.fromRGB(48, 28, 34),
- accent = Color3.fromRGB(255, 70, 90),
- accent2 = Color3.fromRGB(200, 40, 60),
- accent3 = Color3.fromRGB(255, 120, 130),
- accentGlow = Color3.fromRGB(255, 90, 110),
- text = Color3.fromRGB(245, 235, 235),
- text2 = Color3.fromRGB(190, 160, 165),
- text3 = Color3.fromRGB(130, 100, 105),
- border = Color3.fromRGB(70, 40, 48),
- borderSoft = Color3.fromRGB(48, 28, 34),
- red = Color3.fromRGB(255, 70, 90),
- green = Color3.fromRGB(60, 220, 140),
- gold = Color3.fromRGB(255, 200, 60),
- },
- Blue = {
- bg = Color3.fromRGB(10, 14, 24),
- bg2 = Color3.fromRGB(14, 20, 36),
- bg3 = Color3.fromRGB(20, 28, 48),
- bg4 = Color3.fromRGB(28, 38, 62),
- accent = Color3.fromRGB(60, 140, 255),
- accent2 = Color3.fromRGB(40, 100, 220),
- accent3 = Color3.fromRGB(100, 180, 255),
- accentGlow = Color3.fromRGB(80, 160, 255),
- text = Color3.fromRGB(230, 240, 255),
- text2 = Color3.fromRGB(150, 175, 210),
- text3 = Color3.fromRGB(90, 115, 150),
- border = Color3.fromRGB(40, 55, 90),
- borderSoft = Color3.fromRGB(28, 38, 60),
- red = Color3.fromRGB(255, 70, 90),
- green = Color3.fromRGB(60, 220, 140),
- gold = Color3.fromRGB(255, 200, 60),
- },
- }
- local CurrentTheme = deepCopy(DefaultThemes.Aqua)
- local CustomThemes = {}
- function EchelonUI:AddTheme(name, data)
- CustomThemes[name] = data
- end
- function EchelonUI:GetTheme(name)
- return CustomThemes[name] or DefaultThemes[name] or CurrentTheme
- end
- local function applyThemeToRegistry()
- for _, entry in ipairs(ThemeRegistry) do
- if entry and entry.Update then
- pcall(entry.Update, CurrentTheme)
- end
- end
- end
- local function registerTheme(updateFn)
- local entry = { Update = updateFn }
- table.insert(ThemeRegistry, entry)
- return entry
- end
- -- ============================================================
- -- ICON SYSTEM
- -- ============================================================
- local IconPack = "lucide"
- local IconCache = {}
- local IconsModule = nil
- local function loadIcons()
- if IconsModule then return IconsModule end
- local sources = {
- }
- for _, url in ipairs(sources) do
- local ok, result = pcall(function()
- return loadstring(game:HttpGet(url))()
- end)
- if ok and result then
- IconsModule = result
- return IconsModule
- end
- end
- return nil
- end
- function EchelonUI:SetIconPack(pack)
- IconPack = pack or "lucide"
- IconCache = {}
- end
- function EchelonUI:GetIcon(name)
- if not name or name == "" then return nil end
- if typeof(name) == "string" and name:find("rbxassetid://") then
- return { Image = name, ImageRectSize = Vector2.new(0, 0), ImageRectOffset = Vector2.new(0, 0) }
- end
- if IconCache[name] then return IconCache[name] end
- local mod = loadIcons()
- if mod and mod.GetIcon then
- local ok, data = pcall(mod.GetIcon, name, IconPack)
- if ok and data then
- IconCache[name] = data
- return data
- end
- end
- -- fallback empty
- return { Image = "rbxassetid://0", ImageRectSize = Vector2.new(0, 0), ImageRectOffset = Vector2.new(0, 0) }
- end
- local function applyIcon(imageLabel, iconName, color)
- local data = EchelonUI:GetIcon(iconName)
- if not data then return end
- imageLabel.Image = data.Image or data
- if data.ImageRectSize and data.ImageRectSize.X > 0 then
- imageLabel.ImageRectSize = data.ImageRectSize
- imageLabel.ImageRectOffset = data.ImageRectOffset or Vector2.new(0, 0)
- end
- if color then
- imageLabel.ImageColor3 = color
- end
- end
- -- ============================================================
- -- CONFIG SYSTEM
- -- ============================================================
- local ConfigFolder = "EchelonUI_Configs"
- local ConfigData = {} -- in-memory + file if possible
- local FlagMap = {} -- Flag -> {Set, Get}
- local function ensureFolder()
- if not isfolder then return false end
- if not isfolder(ConfigFolder) then
- pcall(makefolder, ConfigFolder)
- end
- return true
- end
- function EchelonUI:SaveConfig(name)
- name = name or "default"
- local data = {}
- for flag, handlers in pairs(FlagMap) do
- if handlers.Get then
- data[flag] = handlers.Get()
- end
- end
- ConfigData[name] = data
- if ensureFolder() and writefile then
- pcall(writefile, ConfigFolder .. "/" .. name .. ".json", HttpService:JSONEncode(data))
- end
- return true
- end
- function EchelonUI:LoadConfig(name)
- name = name or "default"
- local data = ConfigData[name]
- if not data and ensureFolder() and readfile and isfile then
- local path = ConfigFolder .. "/" .. name .. ".json"
- if isfile(path) then
- local ok, decoded = pcall(function()
- return HttpService:JSONDecode(readfile(path))
- end)
- if ok and decoded then
- data = decoded
- ConfigData[name] = data
- end
- end
- end
- if not data then return false end
- for flag, value in pairs(data) do
- local handlers = FlagMap[flag]
- if handlers and handlers.Set then
- pcall(handlers.Set, value)
- end
- end
- return true
- end
- function EchelonUI:DeleteConfig(name)
- name = name or "default"
- ConfigData[name] = nil
- if ensureFolder() and isfile and delfile then
- local path = ConfigFolder .. "/" .. name .. ".json"
- if isfile(path) then pcall(delfile, path) end
- end
- end
- function EchelonUI:GetConfigs()
- local list = {}
- for k in pairs(ConfigData) do
- table.insert(list, k)
- end
- if ensureFolder() and listfiles then
- local ok, files = pcall(listfiles, ConfigFolder)
- if ok and files then
- for _, f in ipairs(files) do
- local n = f:match("([^/\\]+)%.json$")
- if n and not table.find(list, n) then
- table.insert(list, n)
- end
- end
- end
- end
- return list
- end
- local function registerFlag(flag, getFn, setFn)
- if not flag or flag == "" then return end
- FlagMap[flag] = { Get = getFn, Set = setFn }
- end
- -- ============================================================
- -- PLATFORM HELPERS
- -- ============================================================
- function EchelonUI:GetPlatform()
- if isMobile() then return "Mobile" end
- return "PC"
- end
- function EchelonUI:GetExecutor()
- local names = { "Synapse", "Script-Ware", "Krnl", "Fluxus", "Oxygen", "Electron", "Delta", "Codex", "Solara", "Wave" }
- for _, n in ipairs(names) do
- if identifyexecutor and identifyexecutor():lower():find(n:lower()) then
- return n
- end
- end
- if identifyexecutor then return identifyexecutor() end
- return "Unknown"
- end
- -- ============================================================
- -- NOTIFICATION SYSTEM
- -- ============================================================
- local NotifyContainer = nil
- local ActiveNotifies = {}
- local function ensureNotifyContainer()
- if NotifyContainer and NotifyContainer.Parent then return NotifyContainer end
- local gui = create("ScreenGui", {
- Name = "EchelonUI_Notifications",
- ResetOnSpawn = false,
- ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
- DisplayOrder = 9999,
- Parent = (gethui and gethui()) or CoreGui
- })
- NotifyContainer = create("Frame", {
- Name = "Container",
- BackgroundTransparency = 1,
- Size = UDim2.new(0, 320, 1, -40),
- Position = UDim2.new(1, -340, 0, 20),
- Parent = gui
- })
- makeList(NotifyContainer, 8, Enum.FillDirection.Vertical, Enum.HorizontalAlignment.Right, Enum.VerticalAlignment.Top)
- return NotifyContainer
- end
- local TypeColors = {
- Success = function(t) return t.green end,
- Error = function(t) return t.red end,
- Warning = function(t) return t.gold end,
- Info = function(t) return t.accent end,
- }
- function EchelonUI:Notify(opts)
- opts = opts or {}
- local title = opts.Title or "Notification"
- local content = opts.Content or ""
- local nType = opts.Type or "Info"
- local duration = opts.Duration or 4
- local theme = CurrentTheme
- local container = ensureNotifyContainer()
- local accent = (TypeColors[nType] or TypeColors.Info)(theme)
- local card = create("Frame", {
- Name = "Notify",
- BackgroundColor3 = theme.bg2,
- BackgroundTransparency = 0.1,
- Size = UDim2.new(1, 0, 0, 0),
- ClipsDescendants = true,
- Parent = container
- })
- makeCorner(card, 10)
- local stroke = makeStroke(card, accent, 1.2, 0.3)
- local accentBar = create("Frame", {
- BackgroundColor3 = accent,
- BorderSizePixel = 0,
- Size = UDim2.new(0, 3, 1, 0),
- Parent = card
- })
- makeCorner(accentBar, 2)
- local titleL = create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 14, 0, 8),
- Size = UDim2.new(1, -40, 0, 18),
- Font = Enum.Font.GothamBold,
- Text = title,
- TextColor3 = theme.text,
- TextSize = 14,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = card
- })
- local contentL = create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 14, 0, 28),
- Size = UDim2.new(1, -24, 0, 0),
- Font = Enum.Font.Gotham,
- Text = content,
- TextColor3 = theme.text2,
- TextSize = 12,
- TextXAlignment = Enum.TextXAlignment.Left,
- TextWrapped = true,
- Parent = card
- })
- contentL.Size = UDim2.new(1, -24, 0, contentL.TextBounds.Y + 4)
- card.Size = UDim2.new(1, 0, 0, 40 + contentL.TextBounds.Y)
- local closeBtn = create("TextButton", {
- BackgroundTransparency = 1,
- Position = UDim2.new(1, -28, 0, 6),
- Size = UDim2.new(0, 22, 0, 22),
- Text = "×",
- Font = Enum.Font.GothamBold,
- TextSize = 16,
- TextColor3 = theme.text3,
- Parent = card
- })
- local progress = create("Frame", {
- BackgroundColor3 = accent,
- BorderSizePixel = 0,
- Position = UDim2.new(0, 0, 1, -2),
- Size = UDim2.new(1, 0, 0, 2),
- Parent = card
- })
- card.Position = UDim2.new(1, 40, 0, 0)
- tween(card, { Position = UDim2.new(0, 0, 0, 0) }, 0.35)
- local closed = false
- local function close()
- if closed then return end
- closed = true
- tween(card, { Position = UDim2.new(1, 40, 0, 0), BackgroundTransparency = 1 }, 0.3)
- task.delay(0.35, function()
- if card then card:Destroy() end
- end)
- end
- closeBtn.MouseButton1Click:Connect(close)
- tween(progress, { Size = UDim2.new(0, 0, 0, 2) }, duration, Enum.EasingStyle.Linear)
- task.delay(duration, close)
- registerTheme(function(t)
- if not card or not card.Parent then return end
- card.BackgroundColor3 = t.bg2
- titleL.TextColor3 = t.text
- contentL.TextColor3 = t.text2
- local a = (TypeColors[nType] or TypeColors.Info)(t)
- accentBar.BackgroundColor3 = a
- progress.BackgroundColor3 = a
- stroke.Color = a
- end)
- end
- -- ============================================================
- -- WINDOW
- -- ============================================================
- local Windows = {}
- function EchelonUI:CreateWindow(opts)
- opts = opts or {}
- local title = opts.Title or "ECHELON UI"
- local subTitle = opts.SubTitle or opts.Version or "1.0"
- local logoId = opts.Logo
- local size = opts.Size or UDim2.fromOffset(500, 580)
- local mobileSize = opts.MobileSize or UDim2.fromOffset(340, 420)
- local themeName = opts.Theme or "Aqua"
- local bgTrans = opts.BackgroundTransparency or 0.05
- local titleAnim = opts.TitleAnimation ~= false
- local draggable = opts.Draggable ~= false
- local minimizable = opts.Minimizable ~= false
- local closable = opts.Closable ~= false
- local keybind = opts.Keybind or Enum.KeyCode.RightShift
- local cornerR = opts.CornerRadius or 12
- local strokeT = opts.StrokeThickness or 1.2
- local showStatus = opts.ShowStatusBar ~= false
- local loadingScreen = opts.LoadingScreen ~= false
- local accentOverride = opts.AccentColor
- local fontTitle = opts.FontTitle or Enum.Font.GothamBold
- local fontBody = opts.FontBody or Enum.Font.Gotham
- -- Apply theme
- local themeData = EchelonUI:GetTheme(themeName)
- CurrentTheme = deepCopy(themeData)
- if accentOverride then
- CurrentTheme.accent = accentOverride
- CurrentTheme.accent2 = accentOverride
- CurrentTheme.accent3 = accentOverride
- CurrentTheme.accentGlow = accentOverride
- end
- local finalSize = isMobile() and mobileSize or size
- local guiParent = (gethui and gethui()) or CoreGui
- local screenGui = create("ScreenGui", {
- Name = "EchelonUI_" .. HttpService:GenerateGUID(false):sub(1, 8),
- ResetOnSpawn = false,
- ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
- DisplayOrder = 100,
- Parent = guiParent
- })
- -- Loading Screen
- local loadingFrame = nil
- if loadingScreen then
- loadingFrame = create("Frame", {
- Name = "Loading",
- BackgroundColor3 = CurrentTheme.bg,
- Size = UDim2.fromScale(1, 1),
- ZIndex = 50,
- Parent = screenGui
- })
- local loadLogo = create("ImageLabel", {
- BackgroundTransparency = 1,
- AnchorPoint = Vector2.new(0.5, 0.5),
- Position = UDim2.fromScale(0.5, 0.38),
- Size = UDim2.fromOffset(64, 64),
- Image = logoId or "rbxassetid://0",
- ImageColor3 = CurrentTheme.accent,
- Parent = loadingFrame
- })
- makeCorner(loadLogo, 12)
- local loadTitle = create("TextLabel", {
- BackgroundTransparency = 1,
- AnchorPoint = Vector2.new(0.5, 0),
- Position = UDim2.new(0.5, 0, 0.38, 80),
- Size = UDim2.new(0, 300, 0, 28),
- Font = fontTitle,
- Text = title,
- TextColor3 = CurrentTheme.text,
- TextSize = 22,
- Parent = loadingFrame
- })
- local loadVer = create("TextLabel", {
- BackgroundTransparency = 1,
- AnchorPoint = Vector2.new(0.5, 0),
- Position = UDim2.new(0.5, 0, 0.38, 110),
- Size = UDim2.new(0, 200, 0, 18),
- Font = fontBody,
- Text = "v" .. subTitle,
- TextColor3 = CurrentTheme.text2,
- TextSize = 13,
- Parent = loadingFrame
- })
- local progressBg = create("Frame", {
- BackgroundColor3 = CurrentTheme.bg3,
- AnchorPoint = Vector2.new(0.5, 0),
- Position = UDim2.new(0.5, 0, 0.38, 150),
- Size = UDim2.new(0, 200, 0, 4),
- Parent = loadingFrame
- })
- makeCorner(progressBg, 2)
- local progressFill = create("Frame", {
- BackgroundColor3 = CurrentTheme.accent,
- Size = UDim2.new(0, 0, 1, 0),
- Parent = progressBg
- })
- makeCorner(progressFill, 2)
- local statusText = create("TextLabel", {
- BackgroundTransparency = 1,
- AnchorPoint = Vector2.new(0.5, 0),
- Position = UDim2.new(0.5, 0, 0.38, 165),
- Size = UDim2.new(0, 250, 0, 16),
- Font = fontBody,
- Text = "Initializing...",
- TextColor3 = CurrentTheme.text3,
- TextSize = 11,
- Parent = loadingFrame
- })
- task.spawn(function()
- local steps = { "Loading assets", "Building interface", "Applying theme", "Ready" }
- for i, s in ipairs(steps) do
- statusText.Text = s
- tween(progressFill, { Size = UDim2.new(i / #steps, 0, 1, 0) }, 0.25)
- task.wait(0.22)
- end
- tween(loadingFrame, { BackgroundTransparency = 1 }, 0.4)
- for _, c in ipairs(loadingFrame:GetDescendants()) do
- if c:IsA("TextLabel") or c:IsA("ImageLabel") then
- tween(c, { TextTransparency = 1, ImageTransparency = 1 }, 0.35)
- elseif c:IsA("Frame") then
- tween(c, { BackgroundTransparency = 1 }, 0.35)
- end
- end
- task.wait(0.45)
- if loadingFrame then loadingFrame:Destroy() end
- end)
- end
- -- Main Window
- local main = create("Frame", {
- Name = "Main",
- BackgroundColor3 = CurrentTheme.bg,
- BackgroundTransparency = bgTrans,
- Size = finalSize,
- Position = UDim2.fromScale(0.5, 0.5),
- AnchorPoint = Vector2.new(0.5, 0.5),
- ClipsDescendants = true,
- Visible = not loadingScreen,
- Parent = screenGui
- })
- makeCorner(main, cornerR)
- local mainStroke = makeStroke(main, CurrentTheme.border, strokeT, 0.35)
- -- Top gradient line
- local topLine = create("Frame", {
- Name = "TopLine",
- BackgroundColor3 = CurrentTheme.accent,
- BorderSizePixel = 0,
- Size = UDim2.new(1, 0, 0, 2),
- Position = UDim2.new(0, 0, 0, 0),
- ZIndex = 5,
- Parent = main
- })
- local topGrad = create("UIGradient", {
- Color = ColorSequence.new({
- ColorSequenceKeypoint.new(0, CurrentTheme.accent),
- ColorSequenceKeypoint.new(0.5, CurrentTheme.accent3),
- ColorSequenceKeypoint.new(1, CurrentTheme.accent2),
- }),
- Parent = topLine
- })
- if titleAnim then
- task.spawn(function()
- while topLine and topLine.Parent do
- tween(topGrad, { Offset = Vector2.new(1, 0) }, 2.5, Enum.EasingStyle.Linear)
- task.wait(2.5)
- topGrad.Offset = Vector2.new(-1, 0)
- end
- end)
- end
- -- Title Bar
- local titleBar = create("Frame", {
- Name = "TitleBar",
- BackgroundColor3 = CurrentTheme.bg2,
- BackgroundTransparency = 0.3,
- Size = UDim2.new(1, 0, 0, 48),
- Parent = main
- })
- -- only bottom corners avoided by clipping
- local logoImg = nil
- if logoId then
- logoImg = create("ImageLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 12, 0.5, 0),
- AnchorPoint = Vector2.new(0, 0.5),
- Size = UDim2.fromOffset(28, 28),
- Image = logoId,
- Parent = titleBar
- })
- makeCorner(logoImg, 6)
- end
- local titleLabel = create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, logoId and 48 or 14, 0, 6),
- Size = UDim2.new(1, -140, 0, 20),
- Font = fontTitle,
- Text = title,
- TextColor3 = CurrentTheme.text,
- TextSize = 15,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = titleBar
- })
- local subLabel = create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, logoId and 48 or 14, 0, 26),
- Size = UDim2.new(1, -140, 0, 14),
- Font = fontBody,
- Text = subTitle,
- TextColor3 = CurrentTheme.text3,
- TextSize = 11,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = titleBar
- })
- -- Window controls
- local controls = create("Frame", {
- BackgroundTransparency = 1,
- Position = UDim2.new(1, -90, 0.5, 0),
- AnchorPoint = Vector2.new(0, 0.5),
- Size = UDim2.fromOffset(80, 28),
- Parent = titleBar
- })
- makeList(controls, 4, Enum.FillDirection.Horizontal, Enum.HorizontalAlignment.Right)
- local function makeControlBtn(txt, color)
- local b = create("TextButton", {
- BackgroundColor3 = CurrentTheme.bg3,
- Size = UDim2.fromOffset(24, 24),
- Text = txt,
- Font = Enum.Font.GothamBold,
- TextSize = 12,
- TextColor3 = color or CurrentTheme.text2,
- AutoButtonColor = false,
- Parent = controls
- })
- makeCorner(b, 6)
- b.MouseEnter:Connect(function()
- tween(b, { BackgroundColor3 = CurrentTheme.bg4 }, 0.15)
- end)
- b.MouseLeave:Connect(function()
- tween(b, { BackgroundColor3 = CurrentTheme.bg3 }, 0.15)
- end)
- return b
- end
- local minimized = false
- local minBtn, closeBtn
- if minimizable then
- minBtn = makeControlBtn("–")
- end
- if closable then
- closeBtn = makeControlBtn("×", CurrentTheme.red)
- end
- -- Tab bar (left)
- local tabBarWidth = 58
- local tabBar = create("Frame", {
- Name = "TabBar",
- BackgroundColor3 = CurrentTheme.bg2,
- BackgroundTransparency = 0.25,
- Position = UDim2.new(0, 0, 0, 48),
- Size = UDim2.new(0, tabBarWidth, 1, showStatus and -70 or -48),
- Parent = main
- })
- local tabList = create("ScrollingFrame", {
- BackgroundTransparency = 1,
- Size = UDim2.fromScale(1, 1),
- CanvasSize = UDim2.new(0, 0, 0, 0),
- ScrollBarThickness = 0,
- BorderSizePixel = 0,
- Parent = tabBar
- })
- makeList(tabList, 4, Enum.FillDirection.Vertical, Enum.HorizontalAlignment.Center)
- makePadding(tabList, 8, 8, 6, 6)
- -- Content area
- local contentArea = create("Frame", {
- Name = "Content",
- BackgroundTransparency = 1,
- Position = UDim2.new(0, tabBarWidth, 0, 48),
- Size = UDim2.new(1, -tabBarWidth, 1, showStatus and -70 or -48),
- ClipsDescendants = true,
- Parent = main
- })
- -- Status bar
- local statusBar = nil
- if showStatus then
- statusBar = create("Frame", {
- Name = "StatusBar",
- BackgroundColor3 = CurrentTheme.bg2,
- BackgroundTransparency = 0.3,
- Position = UDim2.new(0, 0, 1, -22),
- Size = UDim2.new(1, 0, 0, 22),
- Parent = main
- })
- local statusL = create("TextLabel", {
- BackgroundTransparency = 1,
- Size = UDim2.fromScale(1, 1),
- Font = fontBody,
- Text = " " .. EchelonUI:GetPlatform() .. " | " .. EchelonUI:GetExecutor() .. " | EchelonUI " .. EchelonUI.Version,
- TextColor3 = CurrentTheme.text3,
- TextSize = 10,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = statusBar
- })
- end
- -- Dragging
- if draggable then
- local dragging, dragStart, startPos
- titleBar.InputBegan:Connect(function(input)
- if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
- dragging = true
- dragStart = input.Position
- startPos = main.Position
- end
- end)
- titleBar.InputEnded:Connect(function(input)
- if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
- dragging = false
- end
- end)
- UserInputService.InputChanged:Connect(function(input)
- if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
- local delta = input.Position - dragStart
- main.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y)
- end
- end)
- end
- -- Minimize
- local originalSize = finalSize
- if minBtn then
- minBtn.MouseButton1Click:Connect(function()
- minimized = not minimized
- if minimized then
- tween(main, { Size = UDim2.fromOffset(finalSize.X.Offset, 48) }, 0.3)
- contentArea.Visible = false
- tabBar.Visible = false
- if statusBar then statusBar.Visible = false end
- else
- tween(main, { Size = originalSize }, 0.3)
- contentArea.Visible = true
- tabBar.Visible = true
- if statusBar then statusBar.Visible = true end
- end
- end)
- end
- -- Close
- if closeBtn then
- closeBtn.MouseButton1Click:Connect(function()
- tween(main, { Size = UDim2.fromOffset(0, 0), BackgroundTransparency = 1 }, 0.25)
- task.delay(0.3, function()
- screenGui:Destroy()
- end)
- end)
- end
- -- Keybind toggle
- local visible = true
- UserInputService.InputBegan:Connect(function(input, gpe)
- if gpe then return end
- if input.KeyCode == keybind then
- visible = not visible
- main.Visible = visible
- end
- end)
- -- Theme live update registration
- registerTheme(function(t)
- main.BackgroundColor3 = t.bg
- mainStroke.Color = t.border
- titleBar.BackgroundColor3 = t.bg2
- titleLabel.TextColor3 = t.text
- subLabel.TextColor3 = t.text3
- tabBar.BackgroundColor3 = t.bg2
- topLine.BackgroundColor3 = t.accent
- topGrad.Color = ColorSequence.new({
- ColorSequenceKeypoint.new(0, t.accent),
- ColorSequenceKeypoint.new(0.5, t.accent3),
- ColorSequenceKeypoint.new(1, t.accent2),
- })
- if statusBar then
- statusBar.BackgroundColor3 = t.bg2
- end
- end)
- -- Window object
- local Window = {}
- Window._gui = screenGui
- Window._main = main
- Window._tabs = {}
- Window._currentTab = nil
- Window._theme = CurrentTheme
- function Window:SetTheme(name)
- local t = EchelonUI:GetTheme(name)
- if not t then return end
- CurrentTheme = deepCopy(t)
- applyThemeToRegistry()
- end
- function Window:SetBackgroundTransparency(v)
- bgTrans = clamp(v, 0, 0.6)
- main.BackgroundTransparency = bgTrans
- end
- function Window:SetTitleAnimation(enabled)
- titleAnim = enabled
- end
- function Window:Notify(opts)
- EchelonUI:Notify(opts)
- end
- function Window:Destroy()
- screenGui:Destroy()
- end
- -- ========================================================
- -- TAB
- -- ========================================================
- function Window:CreateTab(tabOpts)
- tabOpts = tabOpts or {}
- local tabName = tabOpts.Name or "Tab"
- local tabIcon = tabOpts.Icon or "circle"
- local order = tabOpts.Order or (#Window._tabs + 1)
- local tabBtn = create("TextButton", {
- BackgroundColor3 = CurrentTheme.bg3,
- BackgroundTransparency = 0.4,
- Size = UDim2.fromOffset(44, 44),
- Text = "",
- AutoButtonColor = false,
- LayoutOrder = order,
- Parent = tabList
- })
- makeCorner(tabBtn, 10)
- local iconImg = create("ImageLabel", {
- BackgroundTransparency = 1,
- AnchorPoint = Vector2.new(0.5, 0.5),
- Position = UDim2.fromScale(0.5, 0.5),
- Size = UDim2.fromOffset(20, 20),
- Parent = tabBtn
- })
- applyIcon(iconImg, tabIcon, CurrentTheme.text2)
- local indicator = create("Frame", {
- BackgroundColor3 = CurrentTheme.accent,
- Size = UDim2.new(0, 3, 0, 0),
- Position = UDim2.new(0, 0, 0.5, 0),
- AnchorPoint = Vector2.new(0, 0.5),
- Visible = false,
- Parent = tabBtn
- })
- makeCorner(indicator, 2)
- local page = create("ScrollingFrame", {
- Name = tabName,
- BackgroundTransparency = 1,
- Size = UDim2.fromScale(1, 1),
- CanvasSize = UDim2.new(0, 0, 0, 0),
- ScrollBarThickness = 3,
- ScrollBarImageColor3 = CurrentTheme.accent,
- BorderSizePixel = 0,
- Visible = false,
- Parent = contentArea
- })
- makePadding(page, 10, 10, 12, 12)
- local pageLayout = makeList(page, 8)
- pageLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function()
- page.CanvasSize = UDim2.new(0, 0, 0, pageLayout.AbsoluteContentSize.Y + 20)
- end)
- local Tab = {
- _btn = tabBtn,
- _page = page,
- _name = tabName,
- }
- local function selectTab()
- for _, t in ipairs(Window._tabs) do
- t._page.Visible = false
- t._btn.BackgroundTransparency = 0.4
- t._btn.BackgroundColor3 = CurrentTheme.bg3
- local ind = t._btn:FindFirstChild("Frame")
- if ind then ind.Visible = false; ind.Size = UDim2.new(0, 3, 0, 0) end
- local ic = t._btn:FindFirstChildOfClass("ImageLabel")
- if ic then ic.ImageColor3 = CurrentTheme.text2 end
- end
- page.Visible = true
- tabBtn.BackgroundTransparency = 0.1
- tabBtn.BackgroundColor3 = CurrentTheme.bg4
- indicator.Visible = true
- tween(indicator, { Size = UDim2.new(0, 3, 0.6, 0) }, 0.2)
- iconImg.ImageColor3 = CurrentTheme.accent
- Window._currentTab = Tab
- end
- tabBtn.MouseButton1Click:Connect(selectTab)
- tabBtn.MouseEnter:Connect(function()
- if Window._currentTab ~= Tab then
- tween(tabBtn, { BackgroundTransparency = 0.2 }, 0.15)
- end
- end)
- tabBtn.MouseLeave:Connect(function()
- if Window._currentTab ~= Tab then
- tween(tabBtn, { BackgroundTransparency = 0.4 }, 0.15)
- end
- end)
- registerTheme(function(t)
- tabBtn.BackgroundColor3 = (Window._currentTab == Tab) and t.bg4 or t.bg3
- iconImg.ImageColor3 = (Window._currentTab == Tab) and t.accent or t.text2
- indicator.BackgroundColor3 = t.accent
- page.ScrollBarImageColor3 = t.accent
- end)
- table.insert(Window._tabs, Tab)
- if #Window._tabs == 1 then
- selectTab()
- end
- -- Auto canvas
- tabList.CanvasSize = UDim2.new(0, 0, 0, (#Window._tabs) * 48 + 16)
- -- ====================================================
- -- SECTION
- -- ====================================================
- function Tab:CreateSection(secOpts)
- secOpts = secOpts or {}
- local secTitle = secOpts.Title or "Section"
- local secIcon = secOpts.Icon
- local sec = create("Frame", {
- BackgroundTransparency = 1,
- Size = UDim2.new(1, 0, 0, 28),
- Parent = page
- })
- local bar = create("Frame", {
- BackgroundColor3 = CurrentTheme.accent,
- Size = UDim2.new(0, 3, 0, 14),
- Position = UDim2.new(0, 0, 0.5, 0),
- AnchorPoint = Vector2.new(0, 0.5),
- Parent = sec
- })
- makeCorner(bar, 2)
- local iconS = nil
- if secIcon then
- iconS = create("ImageLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0.5, 0),
- AnchorPoint = Vector2.new(0, 0.5),
- Size = UDim2.fromOffset(14, 14),
- Parent = sec
- })
- applyIcon(iconS, secIcon, CurrentTheme.accent)
- end
- local titleS = create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, secIcon and 28 or 10, 0, 0),
- Size = UDim2.new(1, -30, 1, 0),
- Font = Enum.Font.GothamBold,
- Text = secTitle:upper(),
- TextColor3 = CurrentTheme.accent,
- TextSize = 12,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = sec
- })
- registerTheme(function(t)
- bar.BackgroundColor3 = t.accent
- titleS.TextColor3 = t.accent
- if iconS then iconS.ImageColor3 = t.accent end
- end)
- return sec
- end
- -- ====================================================
- -- ELEMENT CONTAINER HELPER
- -- ====================================================
- local function makeElementContainer(height)
- local frame = create("Frame", {
- BackgroundColor3 = CurrentTheme.bg3,
- BackgroundTransparency = 0.35,
- Size = UDim2.new(1, 0, 0, height or 42),
- Parent = page
- })
- makeCorner(frame, 8)
- makeStroke(frame, CurrentTheme.borderSoft, 1, 0.5)
- return frame
- end
- -- ====================================================
- -- TOGGLE
- -- ====================================================
- function Tab:CreateToggle(tOpts)
- tOpts = tOpts or {}
- local name = tOpts.Name or "Toggle"
- local desc = tOpts.Description
- local default = tOpts.Default or false
- local flag = tOpts.Flag
- local callback = tOpts.Callback or function() end
- local h = desc and 52 or 40
- local frame = makeElementContainer(h)
- local value = default
- local nameL = create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 12, 0, desc and 6 or 0),
- Size = UDim2.new(1, -70, 0, 18),
- Font = Enum.Font.GothamMedium,
- Text = name,
- TextColor3 = CurrentTheme.text,
- TextSize = 13,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame
- })
- if desc then
- create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 12, 0, 26),
- Size = UDim2.new(1, -70, 0, 16),
- Font = fontBody,
- Text = desc,
- TextColor3 = CurrentTheme.text3,
- TextSize = 11,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame
- })
- end
- local track = create("Frame", {
- BackgroundColor3 = value and CurrentTheme.accent or CurrentTheme.bg4,
- Position = UDim2.new(1, -48, 0.5, 0),
- AnchorPoint = Vector2.new(0, 0.5),
- Size = UDim2.fromOffset(36, 20),
- Parent = frame
- })
- makeCorner(track, 10)
- local thumb = create("Frame", {
- BackgroundColor3 = Color3.fromRGB(255, 255, 255),
- Position = value and UDim2.new(1, -18, 0.5, 0) or UDim2.new(0, 2, 0.5, 0),
- AnchorPoint = Vector2.new(0, 0.5),
- Size = UDim2.fromOffset(16, 16),
- Parent = track
- })
- makeCorner(thumb, 8)
- local function set(v, silent)
- value = v
- tween(track, { BackgroundColor3 = value and CurrentTheme.accent or CurrentTheme.bg4 }, 0.2)
- tween(thumb, { Position = value and UDim2.new(1, -18, 0.5, 0) or UDim2.new(0, 2, 0.5, 0) }, 0.2)
- if not silent then
- pcall(callback, value)
- end
- end
- local btn = create("TextButton", {
- BackgroundTransparency = 1,
- Size = UDim2.fromScale(1, 1),
- Text = "",
- Parent = frame
- })
- btn.MouseButton1Click:Connect(function() set(not value) end)
- registerFlag(flag, function() return value end, function(v) set(v, true) end)
- registerTheme(function(t)
- nameL.TextColor3 = t.text
- track.BackgroundColor3 = value and t.accent or t.bg4
- frame.BackgroundColor3 = t.bg3
- end)
- local obj = {
- SetValue = function(_, v) set(v) end,
- GetValue = function() return value end,
- SetVisible = function(_, v) frame.Visible = v end,
- Destroy = function() frame:Destroy() end,
- }
- return obj
- end
- -- ====================================================
- -- BUTTON
- -- ====================================================
- function Tab:CreateButton(bOpts)
- bOpts = bOpts or {}
- local name = bOpts.Name or "Button"
- local desc = bOpts.Description
- local icon = bOpts.Icon
- local image = bOpts.Image
- local color = bOpts.Color
- local callback = bOpts.Callback or function() end
- local h = desc and 52 or 40
- local frame = makeElementContainer(h)
- if color then frame.BackgroundColor3 = color end
- if image then
- create("ImageLabel", {
- BackgroundTransparency = 1,
- Size = UDim2.fromScale(1, 1),
- Image = image,
- ImageTransparency = 0.7,
- ScaleType = Enum.ScaleType.Crop,
- Parent = frame
- })
- end
- local iconImgB = nil
- if icon then
- iconImgB = create("ImageLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 12, 0.5, 0),
- AnchorPoint = Vector2.new(0, 0.5),
- Size = UDim2.fromOffset(16, 16),
- Parent = frame
- })
- applyIcon(iconImgB, icon, color and Color3.new(1,1,1) or CurrentTheme.accent)
- end
- local nameL = create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, icon and 34 or 12, 0, desc and 6 or 0),
- Size = UDim2.new(1, -20, 0, 18),
- Font = Enum.Font.GothamMedium,
- Text = name,
- TextColor3 = CurrentTheme.text,
- TextSize = 13,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame
- })
- if desc then
- create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, icon and 34 or 12, 0, 26),
- Size = UDim2.new(1, -20, 0, 16),
- Font = fontBody,
- Text = desc,
- TextColor3 = CurrentTheme.text3,
- TextSize = 11,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame
- })
- end
- local btn = create("TextButton", {
- BackgroundTransparency = 1,
- Size = UDim2.fromScale(1, 1),
- Text = "",
- Parent = frame
- })
- btn.MouseEnter:Connect(function()
- tween(frame, { BackgroundTransparency = 0.15 }, 0.15)
- end)
- btn.MouseLeave:Connect(function()
- tween(frame, { BackgroundTransparency = 0.35 }, 0.15)
- end)
- btn.MouseButton1Down:Connect(function()
- tween(frame, { Size = UDim2.new(1, -4, 0, h - 2) }, 0.08)
- end)
- btn.MouseButton1Up:Connect(function()
- tween(frame, { Size = UDim2.new(1, 0, 0, h) }, 0.1)
- end)
- btn.MouseButton1Click:Connect(function()
- pcall(callback)
- end)
- registerTheme(function(t)
- if not color then frame.BackgroundColor3 = t.bg3 end
- nameL.TextColor3 = t.text
- if iconImgB then iconImgB.ImageColor3 = t.accent end
- end)
- return {
- SetVisible = function(_, v) frame.Visible = v end,
- Destroy = function() frame:Destroy() end,
- }
- end
- -- ====================================================
- -- SLIDER
- -- ====================================================
- function Tab:CreateSlider(sOpts)
- sOpts = sOpts or {}
- local name = sOpts.Name or "Slider"
- local min = sOpts.Min or 0
- local max = sOpts.Max or 100
- local default = sOpts.Default or min
- local increment = sOpts.Increment or 1
- local suffix = sOpts.Suffix or ""
- local flag = sOpts.Flag
- local callback = sOpts.Callback or function() end
- local frame = makeElementContainer(56)
- local value = clamp(default, min, max)
- local nameL = create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 12, 0, 6),
- Size = UDim2.new(0.6, 0, 0, 16),
- Font = Enum.Font.GothamMedium,
- Text = name,
- TextColor3 = CurrentTheme.text,
- TextSize = 13,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame
- })
- local valueL = create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0.6, 0, 0, 6),
- Size = UDim2.new(0.4, -12, 0, 16),
- Font = Enum.Font.Gotham,
- Text = tostring(value) .. suffix,
- TextColor3 = CurrentTheme.accent,
- TextSize = 12,
- TextXAlignment = Enum.TextXAlignment.Right,
- Parent = frame
- })
- local track = create("Frame", {
- BackgroundColor3 = CurrentTheme.bg4,
- Position = UDim2.new(0, 12, 0, 32),
- Size = UDim2.new(1, -24, 0, 6),
- Parent = frame
- })
- makeCorner(track, 3)
- local fill = create("Frame", {
- BackgroundColor3 = CurrentTheme.accent,
- Size = UDim2.new((value - min) / (max - min), 0, 1, 0),
- Parent = track
- })
- makeCorner(fill, 3)
- local knob = create("Frame", {
- BackgroundColor3 = Color3.fromRGB(255, 255, 255),
- Size = UDim2.fromOffset(14, 14),
- Position = UDim2.new((value - min) / (max - min), 0, 0.5, 0),
- AnchorPoint = Vector2.new(0.5, 0.5),
- Parent = track
- })
- makeCorner(knob, 7)
- local function set(v, silent)
- value = clamp(round(v, increment), min, max)
- local pct = (value - min) / math.max(max - min, 0.001)
- fill.Size = UDim2.new(pct, 0, 1, 0)
- knob.Position = UDim2.new(pct, 0, 0.5, 0)
- valueL.Text = tostring(value) .. suffix
- if not silent then pcall(callback, value) end
- end
- local sliding = false
- local function updateFromInput(input)
- local rel = (input.Position.X - track.AbsolutePosition.X) / track.AbsoluteSize.X
- set(min + rel * (max - min))
- end
- track.InputBegan:Connect(function(input)
- if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
- sliding = true
- updateFromInput(input)
- end
- end)
- UserInputService.InputEnded:Connect(function(input)
- if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
- sliding = false
- end
- end)
- UserInputService.InputChanged:Connect(function(input)
- if sliding and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
- updateFromInput(input)
- end
- end)
- registerFlag(flag, function() return value end, function(v) set(v, true) end)
- registerTheme(function(t)
- nameL.TextColor3 = t.text
- valueL.TextColor3 = t.accent
- fill.BackgroundColor3 = t.accent
- frame.BackgroundColor3 = t.bg3
- track.BackgroundColor3 = t.bg4
- end)
- return {
- SetValue = function(_, v) set(v) end,
- GetValue = function() return value end,
- SetVisible = function(_, v) frame.Visible = v end,
- Destroy = function() frame:Destroy() end,
- }
- end
- -- ====================================================
- -- DROPDOWN
- -- ====================================================
- function Tab:CreateDropdown(dOpts)
- dOpts = dOpts or {}
- local name = dOpts.Name or "Dropdown"
- local options = dOpts.Options or {}
- local default = dOpts.Default or 1
- local multi = dOpts.Multi or false
- local flag = dOpts.Flag
- local callback = dOpts.Callback or function() end
- local search = dOpts.Search
- local frame = makeElementContainer(40)
- local selected = multi and {} or (options[default] or options[1])
- if multi and type(default) == "table" then selected = default end
- local nameL = create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 12, 0, 0),
- Size = UDim2.new(0.45, 0, 1, 0),
- Font = Enum.Font.GothamMedium,
- Text = name,
- TextColor3 = CurrentTheme.text,
- TextSize = 13,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame
- })
- local display = create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0.45, 0, 0, 0),
- Size = UDim2.new(0.45, 0, 1, 0),
- Font = fontBody,
- Text = multi and (table.concat(selected, ", ") or "None") or tostring(selected),
- TextColor3 = CurrentTheme.text2,
- TextSize = 12,
- TextXAlignment = Enum.TextXAlignment.Right,
- TextTruncate = Enum.TextTruncate.AtEnd,
- Parent = frame
- })
- local arrow = create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(1, -24, 0, 0),
- Size = UDim2.fromOffset(20, 40),
- Font = Enum.Font.GothamBold,
- Text = "▾",
- TextColor3 = CurrentTheme.text3,
- TextSize = 12,
- Parent = frame
- })
- local dropFrame = create("Frame", {
- BackgroundColor3 = CurrentTheme.bg2,
- Size = UDim2.new(1, 0, 0, 0),
- Position = UDim2.new(0, 0, 1, 4),
- Visible = false,
- ClipsDescendants = true,
- ZIndex = 20,
- Parent = frame
- })
- makeCorner(dropFrame, 8)
- makeStroke(dropFrame, CurrentTheme.border, 1, 0.4)
- local dropList = create("ScrollingFrame", {
- BackgroundTransparency = 1,
- Size = UDim2.fromScale(1, 1),
- CanvasSize = UDim2.new(0, 0, 0, 0),
- ScrollBarThickness = 3,
- BorderSizePixel = 0,
- ZIndex = 21,
- Parent = dropFrame
- })
- makeList(dropList, 2)
- makePadding(dropList, 4, 4, 4, 4)
- local open = false
- local function refreshDisplay()
- if multi then
- display.Text = #selected > 0 and table.concat(selected, ", ") or "None"
- else
- display.Text = tostring(selected)
- end
- end
- local function toggleDrop()
- open = not open
- dropFrame.Visible = open
- if open then
- local h = math.min(#options * 28 + 8, 160)
- tween(dropFrame, { Size = UDim2.new(1, 0, 0, h) }, 0.2)
- frame.ZIndex = 10
- else
- tween(dropFrame, { Size = UDim2.new(1, 0, 0, 0) }, 0.15)
- task.delay(0.15, function()
- if not open then dropFrame.Visible = false; frame.ZIndex = 1 end
- end)
- end
- end
- local function buildOptions()
- for _, c in ipairs(dropList:GetChildren()) do
- if c:IsA("TextButton") then c:Destroy() end
- end
- for i, opt in ipairs(options) do
- local optBtn = create("TextButton", {
- BackgroundColor3 = CurrentTheme.bg3,
- BackgroundTransparency = 0.5,
- Size = UDim2.new(1, -8, 0, 26),
- Text = " " .. tostring(opt),
- Font = fontBody,
- TextSize = 12,
- TextColor3 = CurrentTheme.text,
- TextXAlignment = Enum.TextXAlignment.Left,
- AutoButtonColor = false,
- ZIndex = 22,
- Parent = dropList
- })
- makeCorner(optBtn, 5)
- optBtn.MouseEnter:Connect(function()
- tween(optBtn, { BackgroundTransparency = 0.2 }, 0.1)
- end)
- optBtn.MouseLeave:Connect(function()
- tween(optBtn, { BackgroundTransparency = 0.5 }, 0.1)
- end)
- optBtn.MouseButton1Click:Connect(function()
- if multi then
- local idx = table.find(selected, opt)
- if idx then table.remove(selected, idx) else table.insert(selected, opt) end
- refreshDisplay()
- pcall(callback, selected)
- else
- selected = opt
- refreshDisplay()
- toggleDrop()
- pcall(callback, selected)
- end
- end)
- end
- dropList.CanvasSize = UDim2.new(0, 0, 0, #options * 28 + 8)
- end
- buildOptions()
- local clickBtn = create("TextButton", {
- BackgroundTransparency = 1,
- Size = UDim2.fromScale(1, 1),
- Text = "",
- ZIndex = 5,
- Parent = frame
- })
- clickBtn.MouseButton1Click:Connect(toggleDrop)
- registerFlag(flag, function() return selected end, function(v)
- selected = v
- refreshDisplay()
- end)
- registerTheme(function(t)
- nameL.TextColor3 = t.text
- display.TextColor3 = t.text2
- frame.BackgroundColor3 = t.bg3
- dropFrame.BackgroundColor3 = t.bg2
- end)
- return {
- SetValue = function(_, v) selected = v; refreshDisplay() end,
- GetValue = function() return selected end,
- SetOptions = function(_, opts) options = opts; buildOptions() end,
- SetVisible = function(_, v) frame.Visible = v end,
- Destroy = function() frame:Destroy() end,
- }
- end
- -- ====================================================
- -- INPUT
- -- ====================================================
- function Tab:CreateInput(iOpts)
- iOpts = iOpts or {}
- local name = iOpts.Name or "Input"
- local placeholder = iOpts.Placeholder or ""
- local default = iOpts.Default or ""
- local numeric = iOpts.Numeric
- local flag = iOpts.Flag
- local callback = iOpts.Callback or function() end
- local frame = makeElementContainer(40)
- create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 12, 0, 0),
- Size = UDim2.new(0.35, 0, 1, 0),
- Font = Enum.Font.GothamMedium,
- Text = name,
- TextColor3 = CurrentTheme.text,
- TextSize = 13,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame
- })
- local box = create("TextBox", {
- BackgroundColor3 = CurrentTheme.bg4,
- Position = UDim2.new(0.38, 0, 0.5, 0),
- AnchorPoint = Vector2.new(0, 0.5),
- Size = UDim2.new(0.58, 0, 0, 26),
- Font = fontBody,
- Text = default,
- PlaceholderText = placeholder,
- PlaceholderColor3 = CurrentTheme.text3,
- TextColor3 = CurrentTheme.text,
- TextSize = 12,
- ClearTextOnFocus = false,
- Parent = frame
- })
- makeCorner(box, 6)
- makePadding(box, 0, 0, 8, 8)
- box.FocusLost:Connect(function(enter)
- local txt = box.Text
- if numeric then
- txt = tonumber(txt) or 0
- box.Text = tostring(txt)
- end
- pcall(callback, txt)
- end)
- registerFlag(flag, function() return box.Text end, function(v) box.Text = tostring(v) end)
- registerTheme(function(t)
- box.BackgroundColor3 = t.bg4
- box.TextColor3 = t.text
- box.PlaceholderColor3 = t.text3
- frame.BackgroundColor3 = t.bg3
- end)
- return {
- SetValue = function(_, v) box.Text = tostring(v) end,
- GetValue = function() return box.Text end,
- SetVisible = function(_, v) frame.Visible = v end,
- Destroy = function() frame:Destroy() end,
- }
- end
- -- ====================================================
- -- KEYBIND
- -- ====================================================
- function Tab:CreateKeybind(kOpts)
- kOpts = kOpts or {}
- local name = kOpts.Name or "Keybind"
- local default = kOpts.Default or Enum.KeyCode.E
- local flag = kOpts.Flag
- local callback = kOpts.Callback or function() end
- local frame = makeElementContainer(40)
- local current = default
- local listening = false
- create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 12, 0, 0),
- Size = UDim2.new(0.5, 0, 1, 0),
- Font = Enum.Font.GothamMedium,
- Text = name,
- TextColor3 = CurrentTheme.text,
- TextSize = 13,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame
- })
- local keyBtn = create("TextButton", {
- BackgroundColor3 = CurrentTheme.bg4,
- Position = UDim2.new(1, -100, 0.5, 0),
- AnchorPoint = Vector2.new(0, 0.5),
- Size = UDim2.fromOffset(88, 26),
- Font = fontBody,
- Text = current.Name,
- TextColor3 = CurrentTheme.accent,
- TextSize = 12,
- AutoButtonColor = false,
- Parent = frame
- })
- makeCorner(keyBtn, 6)
- keyBtn.MouseButton1Click:Connect(function()
- listening = true
- keyBtn.Text = "..."
- end)
- UserInputService.InputBegan:Connect(function(input, gpe)
- if not listening then return end
- if input.UserInputType == Enum.UserInputType.Keyboard then
- current = input.KeyCode
- keyBtn.Text = current.Name
- listening = false
- pcall(callback, current)
- end
- end)
- registerFlag(flag, function() return current end, function(v)
- current = v
- keyBtn.Text = current.Name
- end)
- registerTheme(function(t)
- keyBtn.BackgroundColor3 = t.bg4
- keyBtn.TextColor3 = t.accent
- frame.BackgroundColor3 = t.bg3
- end)
- return {
- SetValue = function(_, v) current = v; keyBtn.Text = v.Name end,
- GetValue = function() return current end,
- SetVisible = function(_, v) frame.Visible = v end,
- Destroy = function() frame:Destroy() end,
- }
- end
- -- ====================================================
- -- PARAGRAPH / LABEL
- -- ====================================================
- function Tab:CreateParagraph(pOpts)
- pOpts = pOpts or {}
- local title = pOpts.Title or ""
- local content = pOpts.Content or ""
- local frame = create("Frame", {
- BackgroundColor3 = CurrentTheme.bg3,
- BackgroundTransparency = 0.4,
- Size = UDim2.new(1, 0, 0, 0),
- Parent = page
- })
- makeCorner(frame, 8)
- makePadding(frame, 10, 10, 12, 12)
- local tL = create("TextLabel", {
- BackgroundTransparency = 1,
- Size = UDim2.new(1, 0, 0, 16),
- Font = Enum.Font.GothamBold,
- Text = title,
- TextColor3 = CurrentTheme.accent,
- TextSize = 12,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame
- })
- local cL = create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 0, 0, 20),
- Size = UDim2.new(1, 0, 0, 0),
- Font = fontBody,
- Text = content,
- TextColor3 = CurrentTheme.text2,
- TextSize = 12,
- TextXAlignment = Enum.TextXAlignment.Left,
- TextWrapped = true,
- Parent = frame
- })
- cL.Size = UDim2.new(1, 0, 0, cL.TextBounds.Y + 4)
- frame.Size = UDim2.new(1, 0, 0, 36 + cL.TextBounds.Y)
- registerTheme(function(t)
- tL.TextColor3 = t.accent
- cL.TextColor3 = t.text2
- frame.BackgroundColor3 = t.bg3
- end)
- return {
- SetVisible = function(_, v) frame.Visible = v end,
- Destroy = function() frame:Destroy() end,
- }
- end
- function Tab:CreateLabel(lOpts)
- lOpts = lOpts or {}
- local text = lOpts.Text or "Label"
- local gradient = lOpts.Gradient
- local frame = create("Frame", {
- BackgroundTransparency = 1,
- Size = UDim2.new(1, 0, 0, 22),
- Parent = page
- })
- local lbl = create("TextLabel", {
- BackgroundTransparency = 1,
- Size = UDim2.fromScale(1, 1),
- Font = Enum.Font.GothamMedium,
- Text = text,
- TextColor3 = CurrentTheme.text,
- TextSize = 13,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame
- })
- if gradient then
- local g = create("UIGradient", {
- Color = ColorSequence.new({
- ColorSequenceKeypoint.new(0, CurrentTheme.accent),
- ColorSequenceKeypoint.new(1, CurrentTheme.accent3),
- }),
- Parent = lbl
- })
- registerTheme(function(t)
- g.Color = ColorSequence.new({
- ColorSequenceKeypoint.new(0, t.accent),
- ColorSequenceKeypoint.new(1, t.accent3),
- })
- end)
- else
- registerTheme(function(t) lbl.TextColor3 = t.text end)
- end
- return {
- SetText = function(_, t) lbl.Text = t end,
- SetVisible = function(_, v) frame.Visible = v end,
- Destroy = function() frame:Destroy() end,
- }
- end
- -- ====================================================
- -- DIVIDER
- -- ====================================================
- function Tab:CreateDivider()
- local frame = create("Frame", {
- BackgroundTransparency = 1,
- Size = UDim2.new(1, 0, 0, 12),
- Parent = page
- })
- local line = create("Frame", {
- BackgroundColor3 = CurrentTheme.borderSoft,
- AnchorPoint = Vector2.new(0.5, 0.5),
- Position = UDim2.fromScale(0.5, 0.5),
- Size = UDim2.new(1, 0, 0, 1),
- Parent = frame
- })
- registerTheme(function(t) line.BackgroundColor3 = t.borderSoft end)
- return frame
- end
- -- ====================================================
- -- COLOR PICKER (simple)
- -- ====================================================
- function Tab:CreateColorPicker(cOpts)
- cOpts = cOpts or {}
- local name = cOpts.Name or "Color"
- local default = cOpts.Default or Color3.fromRGB(255, 255, 255)
- local flag = cOpts.Flag
- local callback = cOpts.Callback or function() end
- local frame = makeElementContainer(40)
- local value = default
- create("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 12, 0, 0),
- Size = UDim2.new(0.6, 0, 1, 0),
- Font = Enum.Font.GothamMedium,
- Text = name,
- TextColor3 = CurrentTheme.text,
- TextSize = 13,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame
- })
- local preview = create("Frame", {
- BackgroundColor3 = value,
- Position = UDim2.new(1, -40, 0.5, 0),
- AnchorPoint = Vector2.new(0, 0.5),
- Size = UDim2.fromOffset(28, 28),
- Parent = frame
- })
- makeCorner(preview, 6)
- makeStroke(preview, CurrentTheme.border, 1, 0.3)
- -- Simple cycle / click to open is complex; provide SetValue primarily
- -- For full picker would need HSV wheel — keep lightweight
- local btn = create("TextButton", {
- BackgroundTransparency = 1,
- Size = UDim2.fromScale(1, 1),
- Text = "",
- Parent = frame
- })
- -- Basic: user can SetValue externally; click does nothing heavy
- registerFlag(flag, function() return value end, function(v)
- value = v
- preview.BackgroundColor3 = v
- end)
- registerTheme(function(t) frame.BackgroundColor3 = t.bg3 end)
- return {
- SetValue = function(_, v) value = v; preview.BackgroundColor3 = v; pcall(callback, v) end,
- GetValue = function() return value end,
- SetVisible = function(_, v) frame.Visible = v end,
- Destroy = function() frame:Destroy() end,
- }
- end
- -- ====================================================
- -- PLAYER SELECTOR
- -- ====================================================
- function Tab:CreatePlayerSelector(pOpts)
- pOpts = pOpts or {}
- local name = pOpts.Name or "Player"
- local multi = pOpts.Multi or false
- local flag = pOpts.Flag
- local callback = pOpts.Callback or function() end
- local options = {}
- for _, p in ipairs(Players:GetPlayers()) do
- if p ~= LocalPlayer then
- table.insert(options, p.Name)
- end
- end
- local dd = Tab:CreateDropdown({
- Name = name,
- Options = options,
- Multi = multi,
- Flag = flag,
- Callback = callback,
- })
- -- Refresh button via small extra
- return dd
- end
- return Tab
- end
- table.insert(Windows, Window)
- -- Reveal after loading
- if loadingScreen then
- task.delay(1.2, function()
- main.Visible = true
- main.Size = UDim2.fromOffset(0, 0)
- tween(main, { Size = finalSize }, 0.4, Enum.EasingStyle.Back)
- end)
- end
- return Window
- end
- -- Global notify alias
- EchelonUI.Notify = function(_, opts)
- EchelonUI:Notify(opts)
- end
- --[[
- ============================================================
- EXAMPLE USAGE (remove or comment in production)
- ============================================================
- local Lib = EchelonUI
- local Win = Lib:CreateWindow({
- Title = "ECHELON HUB",
- SubTitle = "1.0",
- Theme = "Aqua",
- Logo = nil,
- })
- local T = Win:CreateTab({ Name = "Main", Icon = "house" })
- T:CreateSection({ Title = "General", Icon = "settings" })
- T:CreateToggle({
- Name = "Enabled",
- Description = "Turn on feature",
- Default = false,
- Flag = "Enabled",
- Callback = function(v) print("Toggle:", v) end,
- })
- T:CreateButton({
- Name = "Click Me",
- Icon = "mouse-pointer-click",
- Callback = function()
- Win:Notify({ Title = "OK", Content = "Clicked successfully", Type = "Success" })
- end,
- })
- T:CreateSlider({
- Name = "WalkSpeed",
- Min = 16, Max = 100, Default = 16,
- Flag = "WS",
- Callback = function(v) print(v) end,
- })
- T:CreateDropdown({
- Name = "Mode",
- Options = {"Safe", "Normal", "Rage"},
- Default = 2,
- Flag = "Mode",
- Callback = print,
- })
- T:CreateInput({ Name = "Config", Placeholder = "name", Flag = "Cfg" })
- T:CreateKeybind({ Name = "Key", Default = Enum.KeyCode.Q, Flag = "Key" })
- T:CreateLabel({ Text = "Status: Ready", Gradient = true })
- T:CreateParagraph({ Title = "Info", Content = "EchelonUI v1.0 — Premium dark cyber library." })
- T:CreateDivider()
- ]]
- return EchelonUI
RAW Paste Data
Copied
