Skip to content

Limitations

  • Read this article: Supported Web Features

  • WebKit version is 615.1.18.100.1.

  • Supports ES2022 and below JavaScript features.

  • Video is not supported. Use GIF images instead.

  • Audio is not supported. Play sounds from SKSE.

  • WebGL is not supported.

  • UI refresh rate has 60 FPS cap for now.

  • CPU rendering is only available for now.

  • If you use TailwindCSS in your UI then use v3.

  • Avoid using heavy CSS operations like shadows/filters/gradients/blur in large amount for now. CPU rendering struggles with these, leading to potential FPS drops. We plan to add GPU rendering in the future.

  • JS event contextmenu doesn’t work. Use this implementation instead:

    window.addEventListener('mousedown', function (event) {
    if (event.button === 2) {
    // right-click
    const contextMenuEvent = new MouseEvent('contextmenu', {
    ...event,
    view: window,
    bubbles: true,
    cancelable: true,
    screenX: event.pageX,
    screenY: event.pageY,
    clientX: event.pageX,
    clientY: event.pageY,
    });
    event.target?.dispatchEvent(contextMenuEvent);
    }
    });
  • Blocking specific keys from input: To prevent certain keys (e.g., numpad keys) from adding content to focused inputs, you need to use a combination of keydown and beforeinput event listeners:

    React Example:

    import { useEffect } from 'react';
    // Define keys you want to block (e.g., numpad keys)
    const blockedKeys = [
    { keyCode: 96 }, // Numpad 0
    { keyCode: 97 }, // Numpad 1
    { keyCode: 98 }, // Numpad 2
    { keyCode: 99 }, // Numpad 3
    { keyCode: 100 }, // Numpad 4
    { keyCode: 101 }, // Numpad 5
    { keyCode: 102 }, // Numpad 6
    { keyCode: 103 }, // Numpad 7
    { keyCode: 104 }, // Numpad 8
    { keyCode: 105 }, // Numpad 9
    ];
    function MyComponent() {
    useEffect(() => {
    let lastKey: null | number = null;
    const handleKeyDown = (event: KeyboardEvent) => {
    lastKey = event.keyCode;
    };
    const handleBeforeInput = (event: InputEvent) => {
    if (lastKey !== null && blockedKeys.some(k => k.keyCode === lastKey)) {
    console.log("Blocked input:", { data: event.data, lastKey });
    event.preventDefault();
    }
    };
    window.addEventListener("keydown", handleKeyDown, { capture: true });
    window.addEventListener("beforeinput", handleBeforeInput, { capture: true });
    return () => {
    window.removeEventListener("keydown", handleKeyDown, { capture: true });
    window.removeEventListener("beforeinput", handleBeforeInput, { capture: true });
    };
    }, []);
    return <input type="text" placeholder="Type here..." />;
    }

    Vanilla JavaScript Example:

    // Define keys you want to block (e.g., numpad keys)
    const blockedKeys = [
    { keyCode: 96 }, // Numpad 0
    { keyCode: 97 }, // Numpad 1
    { keyCode: 98 }, // Numpad 2
    { keyCode: 99 }, // Numpad 3
    { keyCode: 100 }, // Numpad 4
    { keyCode: 101 }, // Numpad 5
    { keyCode: 102 }, // Numpad 6
    { keyCode: 103 }, // Numpad 7
    { keyCode: 104 }, // Numpad 8
    { keyCode: 105 }, // Numpad 9
    ];
    let lastKey = null;
    function handleKeyDown(event) {
    lastKey = event.keyCode;
    }
    function handleBeforeInput(event) {
    if (lastKey !== null && blockedKeys.some(k => k.keyCode === lastKey)) {
    console.log("Blocked input:", { data: event.data, lastKey });
    event.preventDefault();
    }
    }
    // Add event listeners
    window.addEventListener("keydown", handleKeyDown, { capture: true });
    window.addEventListener("beforeinput", handleBeforeInput, { capture: true });
    // Don't forget to cleanup when needed
    // window.removeEventListener("keydown", handleKeyDown, { capture: true });
    // window.removeEventListener("beforeinput", handleBeforeInput, { capture: true });