User Interfaces

User Interfaces

This docs page is under construction. Expect more information coming to this page soon!
If you have questions, please ask them in our Discord server and we'll answer them promptly! 😊

Dreamlab allows you to create a UI layer on top of the game window using web technologies. You can use familiar DOM manipulation to create and update your UI.

Creating a UI Layer

⚠️

UI layers are not interactable by default. This allows the underlying game canvas to respond to click events correctly.
Set pointer-events to all for any elements you wish to be interactable.

TypeScript
import type { InitClient } from '@dreamlab.gg/core/sdk'
 
export const init: InitClient = async game => {
  // ... initialize client
 
  // Create a Shadow DOM root
  const root = game.client.ui.create()
 
  // Create a div and append it to the Shadow DOM
  const container = document.createElement('div')
  container.style.width = '100%'
  container.style.height = '100%'
  root.append(container)
 
  // ... setup your UI and event listeners
}

Dreamlab UI

Dreamlab UI is a separate package dedicated to making common UI patterns easier. Currently only React is supported. The package is published on npm as @dreamlab.gg/ui and is available by default in the Dreamlab scripting runtime.

💡

While Dreamlab UI is a quick way to get started using UI frameworks, you can roll your own manually should you wish.

Dreamlab UI React exposes many hooks that allow you to get references to game state in a react-safe way, such that they trigger re-renders when their state changes. This requires some setup internally, so it also provides a renderUI function that takes care of all the UI setup and state tracking for you.

💡
See the React example below.

React Hooks

For a full list of hooks, consult the source.

Hook SignatureDescription
useGame(): GameReturns a reference to the current Game
usePlayer(): PlayerReturns a reference to the player
useCamera(): CameraReturns a reference to the camera
useSpawnableEntities(): readonly SpawnableEntity[]Returns a list of only spawnable entities

Styling

CSS Files

You can use CSS files included in your world scripts in order to style your UI. Dreamlab UI provides a simple css utility to add a CSS file to the shadow DOM.

💡

See the Scripting page for more information on using static assets with world:// URLs.

public/styles.css
h1 {
  font-family: 'Comic Sans MS';
}
src/client.ts
import type { InitClient } from '@dreamlab.gg/core/sdk'
import { css } from '@dreamlab.gg/ui'
 
export const init: InitClient = async game => {
  // ... initialize client
 
  const root = game.client.ui.create()
  // Add your CSS file to the shadow DOM
  css(root, 'world://public/styles.css')
 
  const header = document.createElement('h1')
  header.textContent = 'Hello World!'
  root.append(header)
 
  // ...
}

CSS-in-JS

You can also use CSS-in-JS libraries to make styling easier when using UI libraries such as React.

Examples

Vanilla JS

ui.html
<div id="title">Counter</div>
<button id="button" type="button">Click Me</button>
<div>You have clicked <span id="counter">0</span> times.</div>
ui.css
/* Make the title text slightly larger and bolder */
#title {
  font-size: 1.5rem;
  font-weight: 500;
}
 
/* Make the button interactable */
#button {
  pointer-events: all;
}
client.ts
import type { InitClient } from '@dreamlab.gg/core/sdk'
 
// Import the HTML and CSS files as raw strings
import html from './ui.html'
import css from './ui.css'
 
export const init: InitClient = async game => {
  // Create UI layer
  const ui = game.client.ui.create()
 
  // Assign HTML to UI root
  ui.innerHTML = html
 
  // Create style tag from CSS and append to UI
  const styles = document.createElement('style')
  styles.appendChild(document.createTextNode(css))
  ui.appendChild(styles)
 
  // Get references to elements by ID
  const button = ui.querySelector<HTMLButtonElement>('#button')
  const counter = ui.querySelector<HTMLSpanElement>('#counter')
 
  // Guard against elements being `null`
  if (!button) throw new Error('cannot find element with id: button')
  if (!counter) throw new Error('cannot find element with id: counter')
 
  // Increment count on click
  let count = 0
  button.onclick = () => {
    count += 1
    counter.innerText = count.toString()
  }
}

React

TSX
import type { InitClient } from '@dreamlab.gg/core/sdk'
import { renderUI } from '@dreamlab.gg/ui/react'
 
const Root = () => {
  return <div>Hello React!</div>
}
 
export const init: InitClient = async game => {
  // ... initialize client
 
  // Render React using Dreamlab UI
  renderUI(game, <Root />)
}

React with Styled Components

Using CSS-in-JS libraries can drastically reduce complexity introduced by styling your UI.

Native UI

It is also possible to create UI using Pixi.js natively, although this is not recommended due to the complexity with drawing using Pixi.js and managing inputs.

💡

See the dedicated page on Graphics for more info.