Skip to content

Latest commit

 

History

History
1334 lines (1083 loc) · 36.3 KB

File metadata and controls

1334 lines (1083 loc) · 36.3 KB

Frost-UI Documentation

A lightweight, customizable menu library for creating interactive user interfaces in userscripts.

Table of Contents

Installation

Add to your userscript header:

// @require https://raw.githubusercontent.com/FrozenProductions/Frost-UI/main/scripts/Library.js

Basic Usage

Creating a Menu

const menu = window.frostManager.addMenu(
    "uniqueId", // Unique identifier for the menu
    "Menu Title", // Display title
    { x: 100, y: 100 }, // Initial position (optional)
    "ShiftRight" // Toggle key (optional)
);

Snap-to-Grid

Menus support snap-to-grid functionality for easier alignment and positioning. When enabled, the menu will snap to grid points while dragging and optionally show a visual grid overlay.

const menu = window.frostManager.addMenu(
    "uniqueId",
    "Menu Title",
    { x: 100, y: 100 },
    "ShiftRight",
    {
        enabled: true,    // Enable snap-to-grid
        gridSize: 20,     // Grid cell size in pixels
        showGrid: true    // Show grid overlay while dragging
    }
);

Grid Configuration Options

Property Type Default Description
enabled boolean false Enable snap-to-grid functionality
gridSize number 20 Size of grid cells in pixels
showGrid boolean true Show grid overlay while dragging

Grid Methods

// Get current grid configuration
const config = menu.getGridConfig();
console.log(config); // { enabled: true, gridSize: 20, showGrid: true }

// Update grid configuration
menu.setGridConfig({ gridSize: 40 });
menu.setGridConfig({ enabled: false, showGrid: false });

// Check if grid is enabled
const isEnabled = menu.isGridEnabled();

// Enable/disable grid snapping
menu.setGridEnabled(true);
menu.setGridEnabled(false);

Components

Categories

Categories help organize menu items:

menu.addCategory("Combat") // Creates a collapsible section
    .addCategory("Movement") // Chain multiple categories
    .addCategory("Render"); // Each category can contain multiple items

Toggle-Switch

Creates a toggle with optional keybind:

menu.addToggle(
    "Combat", // Category name
    "KillAura", // Toggle name
    (enabled) => {
        console.log(`KillAura ${enabled ? "enabled" : "disabled"}`);
    },
    "KeyK" // Optional keybind
);

Slider

Creates a numeric slider:

menu.addSlider(
    "Combat", // Category name
    "Range", // Slider name
    3, // Minimum value
    6, // Maximum value
    4, // Default value
    (value) => {
        console.log(`Range set to ${value}`);
    },
    0.5 // Optional step value
);

Radio Group

Creates mutually exclusive options:

menu.addRadioGroup(
    "Combat", // Category name
    "Target Mode", // Group name
    [
        // Available options
        "Single",
        "Multiple",
        "Switch",
    ],
    "Single", // Default selected value
    (selected) => {
        console.log(`Mode changed to ${selected}`);
    }
);

Select

The Select component creates a dropdown menu with single-item selection:

// Basic usage with string array
menu.addSelect(
    "Settings", // Category name
    "Language", // Select name
    ["English", "Spanish", "French"], // Options
    "English", // Default value
    (selected) => {
        console.log(`Language changed to: ${selected}`);
    }
);

// Using key-value pairs
menu.addSelect(
    "Settings",
    "Theme",
    {
        dark: "Dark Mode",
        light: "Light Mode",
        system: "System Default",
    },
    "system",
    (selected) => {
        applyTheme(selected);
    }
);

Features

  • Smooth open/close animations
  • Keyboard navigation support
  • Search by typing
  • Custom styling per theme
  • Automatic positioning
  • Scrolling for many options

Methods

Method Description
getValue() Get the currently selected value
setValue(value: string) Programmatically set the selected value

Color Input

Creates a color input with preview and hex/rgba support:

menu.addColorInput(
    "Render", // Category name
    "ESP Color", // Input name
    "#7289DA", // Default color (hex format)
    (color) => {
        console.log(`Color changed to ${color}`);
    }
);

Features

  • Color picker with hue/saturation selection
  • Hex and RGBA input support
  • Live color preview
  • Copy/paste support
  • Theme-aware styling

Methods

Method Description
getValue() Get the current color value
setValue(color: string) Set the color programmatically

Advanced Usage

// With RGBA values
menu.addColorInput(
    "Visual",
    "Overlay Color",
    "rgba(114, 137, 218, 0.5)", // Semi-transparent color
    (color) => updateOverlay(color)
);

// Get/Set programmatically
const colorInput = menu.addColorInput("Visual", "Theme Color", "#ff0000");
const currentColor = colorInput.getValue();
colorInput.setValue("#00ff00");

Multi Select

Creates a dropdown with multiple selectable options:

menu.addMultiSelect(
    "Combat", // Category name
    "Target Types", // Select name
    [
        // Available options
        "Players",
        "Animals",
        "Monsters",
    ],
    ["Players"], // Default selected values
    (selected) => {
        console.log("Selected targets:", selected);
    }
);

Features

  • Multiple item selection
  • Search/filter functionality
  • Checkbox indicators
  • Select all/none options
  • Keyboard navigation
  • Custom styling per theme

Methods

Method Description
getValues() Get array of selected values
setValues(values: string[]) Set selected values programmatically

Advanced Usage

// With key-value pairs
menu.addMultiSelect(
    "Settings",
    "Features",
    {
        esp: "ESP Overlay",
        tracers: "Tracers",
        boxes: "Bounding Boxes",
        health: "Health Bars",
    },
    ["esp", "health"],
    (selected) => updateFeatures(selected)
);

// Programmatic control
const multiSelect = menu.addMultiSelect("Combat", "Targets", options, []);
multiSelect.setValues(["Players", "Monsters"]);
const currentSelection = multiSelect.getValues();

Page Selector

Creates a paginated interface for switching between different views:

menu.addPageSelector(
    "Settings", // Category name
    "Mode", // Selector name
    [
        // Page names
        "Normal",
        "Advanced",
        "Custom",
    ],
    0, // Default page index
    (page, index) => {
        console.log(`Switched to ${page} mode (index: ${index})`);
    }
);

Features

  • Smooth page transitions
  • Keyboard navigation support
  • Visual page indicators
  • Custom styling per theme
  • Automatic page management

Methods

Method Description
getValue() Get current page index
setValue(value: number) Switch to specific page by index

Advanced Usage

// Create page selector with custom configuration
const pageSelector = menu.addPageSelector(
    "Settings",
    "Configuration",
    ["Basic", "Advanced", "Expert", "Debug"],
    0,
    (page, index) => {
        console.log(`Switched to ${page} mode (index: ${index})`);
        updateConfigurationView(index);
    }
);

// Programmatic control
pageSelector.setValue(2); // Switch to "Expert" page
const currentPageIndex = pageSelector.getValue();

Buttons

Creates clickable buttons with different styles and variants:

menu.addButton(
    "Settings", // Category name
    "Save Config", // Button text
    () => {
        saveConfig();
    },
    "primary" // Button variant ('default', 'primary', 'destructive')
);

Features

  • Multiple button variants
  • Ripple effect on click
  • Loading state support
  • Custom styling per theme
  • Keyboard accessibility

Methods

Method Description
setEnabled(enabled: boolean) Enable or disable button
isEnabled() Check if button is enabled

Button Variants

// Default button
menu.addButton("Settings", "Reset", resetSettings);

// Primary button
menu.addButton("Settings", "Save", saveSettings, "primary");

// Destructive button
menu.addButton("Settings", "Delete", deleteConfig, "destructive");

// With loading state
const button = menu.addButton("Settings", "Export", async () => {
    button.setLoading(true);
    await exportData();
    button.setLoading(false);
});

Order List

Creates a draggable and reorderable list of items with smooth animations:

menu.addOrderList(
    "Category", // Category name
    "Priority List", // List name
    [
        // Initial items
        "Item 1",
        "Item 2",
        "Item 3",
    ],
    (items) => {
        console.log("New order:", items);
    }
);

Features

  • Drag and drop reordering
  • Smooth animations
  • Up/down arrow buttons
  • Visual feedback during drag
  • Touch-friendly interface
  • Keyboard accessibility

Methods

Method Description
getValue() Get current items array
setValue(items: string[]) Update list items

Advanced Usage

// With configuration object
const config = {
    priority: ["High", "Medium", "Low"],
};

const orderList = menu.addOrderList("Priority", "Task Priority", config.priority, (items) => {
    config.priority = items;
    saveConfig();
});

// Programmatic control
const currentOrder = orderList.getValue();
orderList.setValue(["Critical", "High", "Medium", "Low"]);

Dual Slider

Creates a dual-handle slider for selecting a range of values:

menu.addDualSlider(
    "Combat", // Category name
    "Distance Range", // Slider name
    3, // Minimum value
    10, // Maximum value
    4, // Default start value
    7, // Default end value
    (values) => {
        console.log(`Range set to ${values.start} - ${values.end}`);
    },
    0.5 // Optional step value
);

Features

  • Two draggable handles
  • Range selection
  • Smooth animations
  • Step value support
  • Visual range indicator
  • Touch-friendly interface

Methods

Method Description
getValue() Get current range values
setValue({ start, end }) Set range values

Advanced Usage

// Create dual slider with configuration
const dualSlider = menu.addDualSlider(
    "Settings",
    "Price Range",
    0,
    1000,
    200,
    800,
    (values) => {
        updatePriceFilter(values.start, values.end);
    },
    50
);

// Programmatic control
dualSlider.setValue({ start: 300, end: 700 });
const currentRange = dualSlider.getValue();

Grid Selector

Creates a grid of selectable items with optional icons and labels:

menu.addGridSelector(
    "Combat", // Category name
    "Targets", // Selector name
    [
        // Grid items
        { id: "player", icon: "👤", label: "Players" },
        { id: "monster", icon: "👾", label: "Monsters" },
        { id: "animal", icon: "🦊", label: "Animals" },
        { id: "vehicle", icon: "🚗", label: "Vehicles" },
        { id: "item", icon: "📦", label: "Items" },
        { id: "block", icon: "⬛", label: "Blocks" },
    ],
    ["player", "monster"], // Default selected items
    (selected) => {
        console.log("Selected targets:", selected);
    },
    3 // Number of columns (optional)
);

Features

  • Grid layout with customizable columns
  • Icon and label support
  • Multiple item selection
  • Smooth hover animations
  • Keyboard navigation
  • Touch-friendly interface

Methods

Method Description
getValue() Get selected item IDs
setValue(ids: string[]) Set selected items

Advanced Usage

// Create grid selector with custom configuration
const gridSelector = menu.addGridSelector(
    "Settings",
    "Quick Actions",
    [
        { id: "save", icon: "💾", label: "Save" },
        { id: "load", icon: "📂", label: "Load" },
        { id: "reset", icon: "🔄", label: "Reset" },
        { id: "export", icon: "📤", label: "Export" },
    ],
    ["save"],
    (selected) => updateQuickActions(selected),
    2
);

// Programmatic control
gridSelector.setValue(["save", "load"]);
const currentSelection = gridSelector.getValue();

Charts

Creates real-time data visualization with smooth animations and multiple series support:

menu.addChart(
    "Performance", // Category name
    "FPS Monitor", // Chart name
    {
        width: 260, // Optional, default: 260
        height: 150, // Optional, default: 150
        maxDataPoints: 100, // Optional, default: 100
        series: [
            {
                label: "FPS",
                color: "#2ecc71",
                data: [], // Initial data points
            },
            {
                label: "Frame Time",
                color: "#e74c3c",
                data: [], // Initial data points
            },
        ],
        minY: 0, // Optional, minimum Y-axis value
        maxY: 144, // Optional, maximum Y-axis value
    }
);

Features

  • Real-time data visualization
  • Multiple data series support
  • Interactive tooltips
  • Smooth animations
  • Auto-scaling Y-axis
  • Grid lines
  • Hover indicators

Methods

Method Description
addDataPoint(seriesIndex: number, value: number) Add new data point
clearData() Clear all data
getValue() Get current data

Example with Real-time Updates

// Create performance monitor
const chart = menu.addChart("Metrics", "System Performance", {
    series: [
        {
            label: "CPU Usage",
            color: "#3498db",
        },
        {
            label: "Memory Usage",
            color: "#e67e22",
        },
    ],
    minY: 0,
    maxY: 100,
});

// Update chart every second
setInterval(() => {
    chart.addDataPoint(0, Math.random() * 100); // CPU usage
    chart.addDataPoint(1, Math.random() * 100); // Memory usage
}, 1000);

Search Menu

The Search component provides a macOS Spotlight-like search interface for finding items across one or multiple menus:

// Basic usage with single menu
const menu = new FrostUI("myMenu", "My Menu");
const search = new window.frostSearch(menu);

// With multiple menus
const search = new window.frostSearch(
    {
        "Main Menu": mainMenu,
        Settings: settingsMenu,
    },
    "k"
); // Use Cmd/Ctrl+K to open search

Features

  • Real-time search through categories and items
  • Shows parent category name for each item
  • Displays component type badge (Toggle, Slider, Grid Selector, etc.)
  • Keyboard navigation (up/down/enter)
  • Visual highlighting of matches
  • Smooth scrolling to selected items
  • Theme synchronization with menus
  • Multiple menu support
  • Customizable keyboard shortcut

Search Result Display

Search results show enhanced information:

  • Categories: Category Name - Menu Name
  • Items: Item Name (Parent Category) [Component Type]

For example:

  • Movement Abilities (Movement) [Grid Selector]
  • Enabled (AutoClicker) [Toggle]
  • Reach (Combat) [Slider]

Methods

Method Description
setKeybind(key: string) Change keyboard shortcut key
getKeybind() Get current shortcut key
setTheme(theme: string) Set search menu theme
getTheme() Get current theme
show() Show search menu
hide() Hide search menu
toggle() Toggle visibility

Keyboard Controls

Shortcut Action
Cmd/Ctrl + K Open search (default)
Escape Close search
Arrow Up Previous result
Arrow Down Next result
Enter Select result

Example with Theme Sync

const mainMenu = new FrostUI("main", "Main Menu");
const settingsMenu = new FrostUI("settings", "Settings");

// Add items to menus
mainMenu.addCategory("General").addToggle("General", "Dark Mode").addSlider("General", "Volume", 0, 100, 50);

settingsMenu.addCategory("Preferences").addColorInput("Preferences", "Theme Color", "#ffffff");

// Create search with custom keybind
const search = new window.frostSearch(
    {
        "Main Menu": mainMenu,
        Settings: settingsMenu,
    },
    "p"
); // Use Cmd/Ctrl+P to open

// Match search theme with menu theme
search.setTheme(mainMenu.getTheme());

Modal

The Modal component provides centered dialog overlays for user confirmations, alerts, and custom interactions:

const manager = window.frostManager;

// Basic modal with buttons
const result = await manager.showModal({
    title: 'Confirm Action',
    message: 'Are you sure you want to proceed?',
    buttons: [
        { text: 'Cancel', variant: manager.buttonVariant.DEFAULT, result: 'cancel' },
        { text: 'Confirm', variant: manager.buttonVariant.PRIMARY, result: 'confirm' }
    ]
});
console.log(result); // 'cancel', 'confirm', or null (if dismissed)

// Info-only modal (no buttons)
await manager.showModal({
    title: 'Notice',
    message: 'Click outside to close',
    closeOn: [manager.modal.closeOn.BACKDROP]
});

Type Constants

Frost-UI provides type constants for better autocomplete and type safety:

// Theme constants
manager.themes.DARK                    // 'dark'
manager.themes.MIDNIGHT                // 'midnight'
manager.themes.NORD                    // 'nord'
manager.themes.DEEP                    // 'deep'
manager.themes.OBSIDIAN                // 'obsidian'
manager.themes.DUSK                    // 'dusk'
manager.themes.CATPPUCCIN_MACCHIATO    // 'catppuccin-macchiato'
manager.themes.CATPPUCCIN_LATTE        // 'catppuccin-latte'
manager.themes.DRACULA                 // 'dracula'
manager.themes.GRUVBOX                 // 'gruvbox'
manager.themes.TOKYO_NIGHT             // 'tokyo-night'

// Close method constants
manager.modal.closeOn.BUTTON   // 'button'
manager.modal.closeOn.ESCAPE   // 'escape'
manager.modal.closeOn.BACKDROP // 'backdrop'
manager.modal.closeOn.ANY      // 'any'

// Button variant constants
manager.buttonVariant.DEFAULT     // 'default'
manager.buttonVariant.PRIMARY     // 'primary'
manager.buttonVariant.DESTRUCTIVE // 'destructive'

// Toast type constants
manager.toastType.SUCCESS // 'success'
manager.toastType.ERROR   // 'error'
manager.toastType.INFO    // 'info'
manager.toastType.WARNING // 'warning'

Modal Options

Property Type Default Description
title string required Modal title text
message string required Modal content message
buttons ModalButton[] [] Array of button objects (0-2 buttons)
closeOn ModalCloseMethod[] [manager.modal.closeOn.ANY] How modal can be closed
dim boolean true Enable backdrop darkening
blur boolean true Enable backdrop blur effect
theme string auto-detect Theme to apply (use manager.themes.*)

Modal Button

Property Type Default Description
text string required Button label
variant 'default' | 'primary' | 'destructive' manager.buttonVariant.DEFAULT Button style variant
result string button text Value returned when this button is clicked

Close Methods

Method Description
'button' Only close via button click
'escape' Close on Escape key press
'backdrop' Close on backdrop click
'any' All of the above methods

Return Value

The showModal() method returns a Promise<string | null>:

  • Returns the result value of the clicked button
  • Returns null if closed via Escape or backdrop click (when allowed)

Features

  • Promise-based API for async/await usage
  • 0-2 button support with customizable variants
  • Flexible close behavior (button, escape, backdrop, or any combination)
  • Optional backdrop dimming and blur effects
  • Automatic theme detection or explicit theme setting
  • Keyboard accessibility (Escape key)
  • Smooth fade/slide animations

Examples

// Confirmation dialog
const result = await manager.showModal({
    title: 'Delete Item',
    message: 'This action cannot be undone.',
    buttons: [
        { text: 'Cancel', variant: manager.buttonVariant.DEFAULT, result: 'cancel' },
        { text: 'Delete', variant: manager.buttonVariant.DESTRUCTIVE, result: 'delete' }
    ]
});
if (result === 'delete') {
    deleteItem();
}

// Force button choice (no escape/backdrop)
const choice = await manager.showModal({
    title: 'Required Choice',
    message: 'You must select an option:',
    buttons: [
        { text: 'Option A', result: 'a' },
        { text: 'Option B', result: 'b' }
    ],
    closeOn: [manager.modal.closeOn.BUTTON]
});
// choice is guaranteed to be 'a' or 'b', never null

// No visual effects
await manager.showModal({
    title: 'Subtle Notice',
    message: 'No backdrop effects applied',
    dim: false,
    blur: false
});

// Explicit theme
await manager.showModal({
    title: 'Themed Modal',
    message: 'Using midnight theme',
    buttons: [{ text: 'Close', result: 'close' }],
    theme: manager.themes.MIDNIGHT
});

// Close on specific methods only
await manager.showModal({
    title: 'Escape or Backdrop',
    message: 'Close via Escape key or backdrop click',
    closeOn: [manager.modal.closeOn.ESCAPE, manager.modal.closeOn.BACKDROP]
});

// Single button
const confirmed = await manager.showModal({
    title: 'Welcome',
    message: 'Press Continue to proceed',
    buttons: [
        { text: 'Continue', variant: manager.buttonVariant.PRIMARY, result: 'continue' }
    ]
});

Advanced Usage

// Async confirmation with error handling
try {
    const result = await manager.showModal({
        title: 'Save Changes',
        message: 'Do you want to save your changes before exiting?',
        buttons: [
            { text: "Don't Save", variant: manager.buttonVariant.DEFAULT, result: 'discard' },
            { text: 'Save', variant: manager.buttonVariant.PRIMARY, result: 'save' }
        ],
        closeOn: [manager.modal.closeOn.BUTTON, manager.modal.closeOn.ESCAPE]
    });

    if (result === 'save') {
        await saveChanges();
    } else if (result === 'discard') {
        // User chose to discard
    } else {
        // User pressed Escape - don't exit
        return;
    }

    exitApplication();

} catch (error) {
    console.error('Modal error:', error);
}

// With custom theme per modal
const themes = [manager.themes.DARK, manager.themes.MIDNIGHT, manager.themes.NORD];
for (const theme of themes) {
    await manager.showModal({
        title: `${theme.charAt(0).toUpperCase() + theme.slice(1)} Theme`,
        message: `This modal uses the ${theme} theme`,
        buttons: [{ text: 'Next', result: 'next' }],
        theme: theme
    });
}

Themes

Frost-UI comes with a built-in theme system and several preset themes:

Dark Themes:

  • Dark (default)
  • Midnight
  • Nord
  • Deep
  • Obsidian
  • Dusk
  • Catppuccin Macchiato
  • Dracula
  • Gruvbox
  • Tokyo Night

Light Themes:

  • Catppuccin Latte
const menuElement = document.querySelector(".frost-menu");
menuElement.setTheme("Dark");
menuElement.setTheme("Midnight");
menuElement.setTheme("Nord");
menuElement.setTheme("Deep");
menuElement.setTheme("Obsidian");
menuElement.setTheme("Dusk");
menuElement.setTheme("Catppuccin-Macchiato");
menuElement.setTheme("Catppuccin-Latte");
menuElement.setTheme("Dracula");
menuElement.setTheme("Gruvbox");
menuElement.setTheme("Tokyo-Night");

Theme Constants

For type-safe theme references, use the FrostThemes constant:

import { FrostThemes } from 'frost-ui';

menuElement.setTheme(FrostThemes.DARK);
menuElement.setTheme(FrostThemes.MIDNIGHT);
menuElement.setTheme(FrostThemes.NORD);
menuElement.setTheme(FrostThemes.DEEP);
menuElement.setTheme(FrostThemes.OBSIDIAN);
menuElement.setTheme(FrostThemes.DUSK);
menuElement.setTheme(FrostThemes.CATPPUCCIN_MACCHIATO);
menuElement.setTheme(FrostThemes.CATPPUCCIN_LATTE);
menuElement.setTheme(FrostThemes.DRACULA);
menuElement.setTheme(FrostThemes.GRUVBOX);
menuElement.setTheme(FrostThemes.TOKYO_NIGHT);

Available constants:

Dark Themes:

  • FrostThemes.DARK - Default blue-accented dark theme
  • FrostThemes.MIDNIGHT - Purple-accented darker theme
  • FrostThemes.NORD - Nord-inspired arctic theme
  • FrostThemes.DEEP - Deep ocean blue/teal theme
  • FrostThemes.OBSIDIAN - Dark stone theme with green accents
  • FrostThemes.DUSK - Warm sunset orange/purple theme
  • FrostThemes.CATPPUCCIN_MACCHIATO - Soothing pastel dark theme with mauve accents (Catppuccin Macchiato)
  • FrostThemes.DRACULA - Popular dark theme with purple accents
  • FrostThemes.GRUVBOX - Warm retro dark theme with orange accents
  • FrostThemes.TOKYO_NIGHT - Clean dark theme with blue accents

Light Themes:

  • FrostThemes.CATPPUCCIN_LATTE - Soothing pastel light theme with purple accents (Catppuccin Latte)

Custom Themes

Create custom themes by defining CSS variables:

.frost-theme-custom {
    --frost-bg-primary: rgba(20, 25, 35, 0.95); /* Main background */
    --frost-bg-secondary: rgba(25, 30, 40, 0.6); /* Secondary elements */
    --frost-bg-tertiary: rgba(30, 35, 45, 0.4); /* Interactive elements */
    --frost-text-primary: rgba(255, 255, 255, 0.9); /* Main text */
    --frost-text-secondary: rgba(255, 255, 255, 0.7); /* Secondary text */
    --frost-accent-color: #ff7675; /* Primary accent color */
    --frost-accent-hover: #e66767; /* Accent hover color */
    --frost-border-color: rgba(255, 255, 255, 0.1); /* Borders */
    --frost-shadow-color: rgba(0, 0, 0, 0.2); /* Shadows */
    --frost-ripple-color: rgba(255, 255, 255, 0.7); /* Click effects */
}

Theme Variables

Variable Description
--frost-bg-primary Main background color
--frost-bg-secondary Secondary background
--frost-bg-tertiary Interactive elements
--frost-text-primary Main text color
--frost-text-secondary Secondary text
--frost-accent-color Primary accent
--frost-accent-hover Hover state color
--frost-border-color Border color
--frost-shadow-color Shadow color
--frost-ripple-color Click effect color

Example Themes

/* Emerald theme */
.frost-theme-emerald {
    --frost-bg-primary: rgba(20, 30, 25, 0.95);
    --frost-bg-secondary: rgba(25, 35, 30, 0.6);
    --frost-bg-tertiary: rgba(30, 40, 35, 0.4);
    --frost-text-primary: rgba(255, 255, 255, 0.9);
    --frost-text-secondary: rgba(255, 255, 255, 0.7);
    --frost-accent-color: #2ecc71;
    --frost-accent-hover: #27ae60;
    --frost-border-color: rgba(255, 255, 255, 0.1);
    --frost-shadow-color: rgba(0, 0, 0, 0.2);
    --frost-ripple-color: rgba(255, 255, 255, 0.7);
}

/* Ocean theme */
.frost-theme-ocean {
    --frost-bg-primary: rgba(20, 25, 35, 0.95);
    --frost-bg-secondary: rgba(25, 30, 45, 0.6);
    --frost-bg-tertiary: rgba(30, 35, 55, 0.4);
    --frost-text-primary: rgba(255, 255, 255, 0.9);
    --frost-text-secondary: rgba(255, 255, 255, 0.7);
    --frost-accent-color: #3498db;
    --frost-accent-hover: #2980b9;
    --frost-border-color: rgba(255, 255, 255, 0.1);
    --frost-shadow-color: rgba(0, 0, 0, 0.2);
    --frost-ripple-color: rgba(255, 255, 255, 0.7);
}

Menu Manager

The Menu Manager provides basic control over Frost-UI menus in your application:

const manager = window.frostManager;

// Create a new menu
const menu = manager.addMenu(
    "uniqueId", // Unique identifier for the menu
    "Menu Title", // Display title
    { x: 100, y: 100 }, // Initial position (optional)
    "ShiftRight" // Toggle key (optional, defaults to 'ShiftRight')
);

// Update menu toggle key
manager.updateMenuToggleKey("uniqueId", "ShiftLeft");

// Update keybind for a specific toggle
manager.updateKeybind(
    "uniqueId", // Menu ID
    "Combat", // Category name
    "KillAura", // Toggle name
    "KeyK" // New keybind
);

// Show toast notification
manager.showToast("Operation completed");
// or with options (using constants for type safety)
manager.showToast({
    message: "Settings saved",
    type: manager.toastType.SUCCESS,
    duration: 3000,
});

// Show modal dialog (using constants)
const result = await manager.showModal({
    title: "Confirm Action",
    message: "Are you sure you want to proceed?",
    buttons: [
        { text: "Cancel", variant: manager.buttonVariant.DEFAULT, result: "cancel" },
        { text: "Confirm", variant: manager.buttonVariant.PRIMARY, result: "confirm" }
    ]
});
console.log(result); // 'cancel', 'confirm', or null

Menu Instance Methods

Once you have a menu instance, you can use these methods:

// Toggle menu visibility
menu.toggle();

// Check if menu is open
const isOpen = menu.isMenuOpen();

// Change toggle key
menu.setToggleKey("ShiftLeft");

// Change theme
menu.setTheme("dark"); // or "midnight", "nord", etc.

// Get menu container element
const container = menu.getContainer();

// Get all categories
const categories = menu.getCategories();

// Grid configuration methods
const gridConfig = menu.getGridConfig();     // Get grid config
menu.setGridConfig({ gridSize: 40 });        // Update grid config
menu.setGridEnabled(true);                   // Enable/disable grid
const isGridEnabled = menu.isGridEnabled();  // Check if grid is enabled

Multiple Menus Example

// Create multiple menus
const mainMenu = manager.addMenu("main", "Main Menu", { x: 100, y: 100 });
const settingsMenu = manager.addMenu("settings", "Settings", { x: 400, y: 100 });

// Create search that works with both menus
const search = new window.frostSearch(
    {
        "Main Menu": mainMenu,
        Settings: settingsMenu,
    },
    "k"
); // Use Cmd/Ctrl+K to open search

Configuration

Frost-UI supports global configuration options that control behavior across all menus:

const manager = window.frostManager;

// Get current configuration
const config = manager.getConfig();
console.log(config);
// {
//     dimOnMenuOpen: false,
//     blurOnMenuOpen: false,
//     rememberPositions: false,
//     theme: undefined
// }

// Update configuration (partial updates supported)
manager.setConfig({
    dimOnMenuOpen: true,
    blurOnMenuOpen: true,
    rememberPositions: true,
    theme: 'nord'
});

Configuration Options

Option Type Default Description
dimOnMenuOpen boolean false Dim the background when any menu is open
blurOnMenuOpen boolean false Blur the background when any menu is open
rememberPositions boolean false Save menu positions to localStorage
theme string undefined Global theme override (see Global Theme)

Dim/Blur Backdrop

When dimOnMenuOpen or blurOnMenuOpen is enabled, a backdrop effect appears whenever any menu is open:

// Enable both dim and blur effects
window.frostManager.setConfig({
    dimOnMenuOpen: true,
    blurOnMenuOpen: true
});

// Now opening any menu will show the backdrop effect
menu.toggle();

The backdrop automatically shows when at least one menu is open and hides when all menus are closed.

Position Persistence

When rememberPositions is enabled, menu positions are automatically saved to localStorage and restored on page load:

// Enable position persistence
window.frostManager.setConfig({
    rememberPositions: true
});

// Move a menu by dragging it...
// Position is automatically saved when drag ends

// On page reload, the menu will appear at its last position

Note: Position persistence uses the frost-menu-positions key in localStorage. Each menu's position is stored by its unique ID.

Global Theme

The theme configuration option allows you to set a global theme that overrides all individual component themes:

// Set a global theme - applies to all menus, modals, search, and toasts
window.frostManager.setConfig({
    theme: 'nord'
});

When a global theme is set:

  • All existing menus immediately update to the new theme
  • All new modals use the global theme
  • The search menu uses the global theme
  • All toast notifications use the global theme
  • Individual setTheme() calls on components are ignored
  • The setting persists across page reloads
// Create menus with individual themes
const menu1 = window.frostManager.addMenu("menu1", "Menu 1");
const menu2 = window.frostManager.addMenu("menu2", "Menu 2");

menu1.setTheme('tokyo-night');
menu2.setTheme('midnight');

// Set global theme - overrides both menus
window.frostManager.setConfig({ theme: 'nord' });
// Both menu1 and menu2 now use 'nord' theme

// Individual theme changes are ignored when global theme is active
menu1.setTheme('dracula'); // No effect - global theme takes precedence

// Clear global theme to restore individual themes
window.frostManager.setConfig({ theme: undefined });
// Menus revert to their individual themes (tokyo-night and midnight)

Note: Global theme uses the frost-config key in localStorage and is automatically restored on page load.

Complete Example

// Setup Frost-UI with custom configuration
const manager = window.frostManager;

// Configure global settings
manager.setConfig({
    dimOnMenuOpen: true,
    blurOnMenuOpen: true,
    rememberPositions: true
});

// Create menus - positions will be remembered
const mainMenu = manager.addMenu("main", "Main Menu", { x: 100, y: 100 });
const settingsMenu = manager.addMenu("settings", "Settings", { x: 400, y: 100 });

// When user drags menus to new positions, they're saved automatically
// On next page load, menus appear at their saved positions