JSPM

@rbxts/tutorial-ui-highlight

0.1.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 7
  • Score
    100M100P100Q35747F
  • License MIT

A React-based tutorial UI highlighting system for Roblox TypeScript projects. Create interactive tutorials with customizable overlay highlighting and step-by-step guidance.

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@rbxts/tutorial-ui-highlight) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    @rbxts/tutorial-ui-highlight

    A React-based tutorial UI highlighting system for Roblox TypeScript projects. Create interactive tutorials with customizable overlay highlighting and step-by-step guidance.

    Features

    • 🎯 Precise UI Element Highlighting - Automatically highlights specific UI elements with dark overlay around them
    • ⚛️ React Integration - Built specifically for React-based Roblox TypeScript projects
    • 🎨 Customizable Styling - Configure background colors, transparency, and interaction behavior
    • 📱 Responsive - Automatically adapts to different screen sizes and camera changes
    • 🔄 Step Management - Easy step-by-step tutorial progression with automatic cleanup
    • 🎮 Interactive Controls - Optional click-through prevention for guided experiences

    Installation

    npm install @rbxts/tutorial-ui-highlight

    Peer Dependencies

    Make sure you have the required peer dependencies installed:

    npm install @rbxts/charm @rbxts/react-charm @rbxts/react @rbxts/react-roblox

    Quick Start

    1. Set up the Highlight Component

    Add the HighlightGui component to your main UI:

    import React from "@rbxts/react";
    import { HighlightGui } from "@rbxts/tutorial-ui-highlight";
    
    export function App() {
        return (
            <>
                {/* Your existing UI */}
                <YourMainUI />
    
                {/* Add the highlight overlay */}
                <HighlightGui />
            </>
        );
    }

    2. Register UI Elements

    Use the useReportUiRectRef hook to register elements you want to highlight:

    import { TutorialUiHightlight } from "@rbxts/tutorial-ui-highlight";
    
    function MyButton() {
        const buttonRef = TutorialUiHightlight.useReportUiRectRef("my-button");
    
        return (
            <textbutton
                ref={buttonRef}
                Text="Click me!"
                Size={UDim2.fromOffset(200, 50)}
                // ... other props
            />
        );
    }

    3. Start a Tutorial

    import { TutorialUiHightlight } from "@rbxts/tutorial-ui-highlight";
    
    // Start a tutorial sequence
    TutorialUiHightlight.SetTutorial(["my-button", "next-step", "final-step"]);
    
    // Resolve steps as the user progresses
    TutorialUiHightlight.Resolve("my-button");

    API Reference

    Core Functions

    SetTutorial(steps: string[])

    Starts a new tutorial with the specified steps.

    TutorialUiHightlight.SetTutorial(["step1", "step2", "step3"]);

    Resolve(id: string)

    Completes a tutorial step and moves to the next one.

    TutorialUiHightlight.Resolve("step1");

    StopTutorial()

    Immediately stops the current tutorial and clears all remaining steps.

    // Stop tutorial (e.g., if user clicks "Skip Tutorial")
    TutorialUiHightlight.StopTutorial();

    ReportGuiInstance(instance: GuiBase2d, id: string)

    Manually register a GUI instance for highlighting.

    RemoveGuiInstance(id: string)

    Unregister a GUI instance.

    Configuration

    SetGlobalConfig(config: IStepData)

    Set default configuration for all tutorial steps.

    TutorialUiHightlight.SetGlobalConfig({
        BgColor3: Color3.fromRGB(0, 0, 0),
        BgTransparency: 0.5,
        CanClickCenter: false,
    });

    SetStepConfig(step: string, config: IStepData)

    Set configuration for a specific step.

    TutorialUiHightlight.SetStepConfig("important-step", {
        BgColor3: Color3.fromRGB(255, 0, 0),
        BgTransparency: 0.2,
        CanClickCenter: true,
    });

    React Hooks

    useReportUiRectRef<T>(id: string, ref?: React.MutableRefObject<T>)

    Returns a ref callback that automatically registers/unregisters the element. The optional ref parameter allows you to still maintain your own reference to the element if needed.

    // Basic usage - just for tutorial highlighting
    const myRef = TutorialUiHightlight.useReportUiRectRef("my-element");
    
    // Advanced usage - when you need both tutorial highlighting AND your own ref
    const myElementRef = useRef<TextButton>();
    const tutorialRef = TutorialUiHightlight.useReportUiRectRef("my-element", myElementRef);
    
    return (
        <textbutton
            ref={tutorialRef}
            // Now you can also access the element via myElementRef.current
        />
    );

    useIsTutorialActive(): boolean

    Returns whether any tutorial is currently active. Use this to disable other UI elements during tutorials.

    function MyButton() {
        const isTutorialActive = TutorialUiHightlight.useIsTutorialActive();
    
        return (
            <textbutton
                Text="My Button"
                // Disable button during tutorial unless it's part of the tutorial
                Event={{
                    MouseButton1Click: isTutorialActive ? undefined : handleClick,
                }}
                BackgroundTransparency={isTutorialActive ? 0.5 : 0}
            />
        );
    }

    useCurrentTutorialStep(): string | undefined

    Returns the current tutorial step ID. Use this to show contextual UI overlays or "Next" buttons for steps that don't require clicking.

    function TutorialOverlay() {
        const currentStep = TutorialUiHightlight.useCurrentTutorialStep();
        const isTutorialActive = TutorialUiHightlight.useIsTutorialActive();
    
        if (!isTutorialActive || !currentStep) return null;
    
        // Show "Next" button for read-only steps
        const isReadOnlyStep = currentStep === "read-instructions";
    
        return (
            <frame>
                {isReadOnlyStep && (
                    <textbutton
                        Text="Next"
                        Position={UDim2.fromScale(0.9, 0.9)}
                        Event={{
                            MouseButton1Click: () => TutorialUiHightlight.Resolve(currentStep),
                        }}
                    />
                )}
    
                {/* Step-specific instructions */}
                {currentStep === "click-settings" && (
                    <textlabel Text="Click the Settings button to continue" />
                )}
            </frame>
        );
    }

    Interfaces

    interface IStepData {
        BgColor3: Color3; // Background overlay color
        BgTransparency: number; // Background transparency (0-1)
        CanClickCenter: boolean; // Whether the highlighted area is clickable
    }
    
    interface IPartData {
        Position: UDim2;
        Size: UDim2;
        AnchorPoint: Vector2;
    }

    Complete Example

    // TutorialExample.tsx
    import React, { useState } from "@rbxts/react";
    import { TutorialUiHightlight, HighlightGui } from "@rbxts/tutorial-ui-highlight";
    
    enum TutorialSteps {
        OpenMenu = "open-menu",
        ClickSettings = "click-settings",
        CloseMenu = "close-menu",
    }
    
    function TutorialExample() {
        const [menuOpen, setMenuOpen] = useState(false);
    
        // Register refs
        const menuButtonRef = TutorialUiHightlight.useReportUiRectRef(TutorialSteps.OpenMenu);
        const settingsButtonRef = TutorialUiHightlight.useReportUiRectRef(TutorialSteps.ClickSettings);
        const closeButtonRef = TutorialUiHightlight.useReportUiRectRef(TutorialSteps.CloseMenu);
    
        // Start tutorial
        const startTutorial = () => {
            TutorialUiHightlight.SetTutorial([
                TutorialSteps.OpenMenu,
                TutorialSteps.ClickSettings,
                TutorialSteps.CloseMenu,
            ]);
        };
    
        return (
            <screengui>
                {/* Tutorial overlay */}
                <HighlightGui />
    
                {/* Main UI */}
                <textbutton
                    ref={menuButtonRef}
                    Text="Open Menu"
                    Position={UDim2.fromScale(0.1, 0.1)}
                    Size={UDim2.fromOffset(100, 50)}
                    Event={{
                        MouseButton1Click: () => {
                            setMenuOpen(true);
                            TutorialUiHightlight.Resolve(TutorialSteps.OpenMenu);
                        },
                    }}
                />
    
                {menuOpen && (
                    <frame Position={UDim2.fromScale(0.3, 0.3)} Size={UDim2.fromOffset(200, 300)}>
                        <textbutton
                            ref={settingsButtonRef}
                            Text="Settings"
                            Size={UDim2.fromOffset(150, 40)}
                            Event={{
                                MouseButton1Click: () => {
                                    TutorialUiHightlight.Resolve(TutorialSteps.ClickSettings);
                                },
                            }}
                        />
    
                        <textbutton
                            ref={closeButtonRef}
                            Text="Close"
                            Position={UDim2.fromScale(0, 0.8)}
                            Size={UDim2.fromOffset(150, 40)}
                            Event={{
                                MouseButton1Click: () => {
                                    setMenuOpen(false);
                                    TutorialUiHightlight.Resolve(TutorialSteps.CloseMenu);
                                },
                            }}
                        />
                    </frame>
                )}
    
                <textbutton
                    Text="Start Tutorial"
                    Position={UDim2.fromScale(0.8, 0.1)}
                    Size={UDim2.fromOffset(120, 50)}
                    Event={{ MouseButton1Click: startTutorial }}
                />
            </screengui>
        );
    }

    Configuration Examples

    Custom Step Styling

    // Make a step have a red overlay with low transparency
    TutorialUiHightlight.SetStepConfig("critical-step", {
        BgColor3: Color3.fromRGB(139, 0, 0),
        BgTransparency: 0.1,
        CanClickCenter: false,
    });
    
    // Make another step completely non-interactive
    TutorialUiHightlight.SetStepConfig("read-only-step", {
        BgColor3: Color3.fromRGB(0, 0, 0),
        BgTransparency: 0.7,
        CanClickCenter: false,
    });

    Global Configuration

    // Set up global defaults
    TutorialUiHightlight.SetGlobalConfig({
        BgColor3: Color3.fromRGB(25, 25, 25),
        BgTransparency: 0.4,
        CanClickCenter: true,
    });

    Advanced Usage Patterns

    Disabling UI During Tutorials

    Disable other UI elements while a tutorial is active to guide user focus:

    function GameUI() {
        const isTutorialActive = TutorialUiHightlight.useIsTutorialActive();
    
        return (
            <screengui>
                <textbutton
                    Text="Play"
                    Event={{
                        MouseButton1Click: isTutorialActive ? undefined : startGame,
                    }}
                    BackgroundTransparency={isTutorialActive ? 0.7 : 0}
                />
    
                <textbutton
                    Text="Settings"
                    Event={{
                        MouseButton1Click: isTutorialActive ? undefined : openSettings,
                    }}
                    BackgroundTransparency={isTutorialActive ? 0.7 : 0}
                />
            </screengui>
        );
    }

    Tutorial with Overlay Instructions

    Create tutorials with contextual instructions and "Next" buttons for read-only steps:

    function TutorialWithInstructions() {
        const currentStep = TutorialUiHightlight.useCurrentTutorialStep();
        const isTutorialActive = TutorialUiHightlight.useIsTutorialActive();
    
        // Configure read-only steps
        useEffect(() => {
            TutorialUiHightlight.SetStepConfig("read-instructions", {
                BgColor3: Color3.fromRGB(0, 0, 0),
                BgTransparency: 0.5,
                CanClickCenter: false, // Prevent clicking the highlighted area
            });
        }, []);
    
        const stepInstructions = {
            "read-instructions": "Welcome! This is your dashboard.",
            "click-play": "Click the Play button to start a game.",
            "click-settings": "Now try opening the Settings menu.",
        };
    
        return (
            <>
                {/* Your main UI */}
                <MainGameUI />
    
                {/* Tutorial overlay */}
                {isTutorialActive && currentStep && (
                    <screengui ZIndexBehavior={Enum.ZIndexBehavior.Sibling}>
                        {/* Instruction text */}
                        <frame
                            Position={UDim2.fromScale(0.5, 0.1)}
                            Size={UDim2.fromOffset(400, 100)}
                            AnchorPoint={new Vector2(0.5, 0)}
                        >
                            <textlabel
                                Text={stepInstructions[currentStep] || ""}
                                Size={UDim2.fromScale(1, 1)}
                                TextScaled={true}
                            />
                        </frame>
    
                        {/* Next button for read-only steps */}
                        {currentStep === "read-instructions" && (
                            <textbutton
                                Text="Next"
                                Position={UDim2.fromScale(0.85, 0.85)}
                                Size={UDim2.fromOffset(100, 40)}
                                Event={{
                                    MouseButton1Click: () => TutorialUiHightlight.Resolve(currentStep),
                                }}
                            />
                        )}
    
                        {/* Skip tutorial button */}
                        <textbutton
                            Text="Skip Tutorial"
                            Position={UDim2.fromScale(0.02, 0.02)}
                            Size={UDim2.fromOffset(120, 30)}
                            Event={{
                                MouseButton1Click: () => TutorialUiHightlight.StopTutorial(),
                            }}
                        />
                    </screengui>
                )}
            </>
        );
    }

    License

    MIT

    Contributing

    Contributions are welcome! Please feel free to submit a Pull Request.