> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/ui-2d/onscreen-ui.md).

# UI no ecrã

Saiba como criar uma UI para os jogadores na sua cena. Isto é útil, por exemplo, para apresentar informações relacionadas com o jogo.

Você pode criar uma UI para sua scene, para ser exibida no espaço 2D fixo da tela, em vez do espaço 3D do mundo.

Os elementos de UI só ficam visíveis quando o jogador está dentro das parcelas LAND da scene, pois as scenes vizinhas podem ter sua própria UI para exibir. Partes da UI também podem ser acionadas para abrir quando certos eventos ocorrem no espaço do mundo, por exemplo, se o jogador clicar em um local específico.

Crie uma UI definindo uma estrutura de `UiEntity` objetos aninhados em JSX. A sintaxe usada para UIs é muito semelhante à de [React](https://reactjs.org/) (uma biblioteca muito popular baseada em JavaScript para criar UIs web).

{% hint style="warning" %}
**📔 Observação**: Você só pode definir a sintaxe da UI em arquivos que tenham uma `.tsx` extensão. `.tsx` arquivos suportam tudo o que `.ts` arquivos suportam, além da sintaxe de UI. Recomendamos criar um `ui.tsx` arquivo e definir sua UI ali. Lembre-se de chamar o seu método de renderização da UI a partir de `index.ts` com `ReactEcsRenderer.setUiRenderer(yourUiMethodName)`, veja o exemplo abaixo.
{% endhint %}

Uma UI simples com elementos estáticos pode parecer muito com HTML, mas quando você adiciona elementos dinâmicos que respondem a uma mudança de estado, você pode fazer coisas muito mais poderosas.

A UI padrão do explorer do Decentraland inclui um widget de chat, um mapa e outros elementos. Esses elementos de UI são sempre exibidos na camada superior, acima de qualquer UI específica da scene. Portanto, se sua scene tiver elementos de UI que ocupem o mesmo espaço de tela que eles, eles ficarão ocultos.

Veja [diretrizes de UX](/creator/content-creator-pt/scenes-sdk7/conceber-a-experiencia/ux-ui-guide.md) para dicas de como projetar a aparência e o comportamento da sua UI.

{% hint style="info" %}
**📱 Projetando para mobile**: Os dispositivos reservam espaço de tela para o notch, a barra de status, o indicador inicial e os cantos arredondados, e o client desenha seus próprios controles sobre parte do canvas. Você também não precisa medir nada — escolha a área em que sua UI será colocada com [`screenInset`](#screen-inset-area) abaixo. Por padrão, ela usa a área segura do dispositivo, então as margens do hardware são evitadas sem nenhum esforço da sua parte. Antes de publicar, revise a [Área segura do mobile](/creator/content-creator-pt/criar-para-mobile/desenvolver/safe-area.md) quanto a [Boas práticas de UI para mobile](/creator/content-creator-pt/criar-para-mobile/desenvolver/ui-best-practices.md).
{% endhint %}

Quando o jogador clica no *botão de fechar a UI* no canto inferior direito da tela, todos os elementos de UI ficam ocultos.

## Renderizar uma UI

Para exibir uma UI na sua scene, use a `ReactEcsRenderer.setUiRenderer()` função, passando uma estrutura válida de entities, descrita em uma `.tsx` arquivo.

Cada entity é definida como um nó semelhante a HTML, com propriedades para cada um de seus components.

***arquivo ui.tsx:***

```ts
import { UiEntity, ReactEcs } from '@dcl/sdk/react-ecs'
import { Color4 } from '@dcl/sdk/math'

export const uiMenu = () => (
  <UiEntity
    uiTransform={{
      width: 700,
      height: 400,
      margin: { top: '35px', left: '500px' },
    }}
    uiBackground={{ color: Color4.Red() }}
  />
)
```

***arquivo index.ts:***

```ts
import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
import { uiMenu } from './ui'

export function main() {
    ReactEcsRenderer.setUiRenderer(uiMenu, { virtualWidth: 1920, virtualHeight: 1080 })
}
```

Você também pode definir uma estrutura de entities e renderizá-la, tudo em um único comando em uma `.tsx` arquivo.

***arquivo ui.tsx:***

```tsx
import ReactEcs, { ReactEcsRenderer, UiEntity } from '@dcl/sdk/react-ecs'
import { Color4 } from '@dcl/sdk/math'

export function setupUI() {
  ReactEcsRenderer.setUiRenderer(() => (
    <UiEntity
      uiTransform={{
        width: 700,
        height: 400,
        margin: { top: '35px', left: '500px' },
      }}
      uiBackground={{ color: Color4.Red() }}
    />
  ), { virtualWidth: 1920, virtualHeight: 1080 })
}
```

***arquivo index.ts:***

```ts
import { setupUI } from './ui'

export function main() {
    setupUI()
}
```

{% hint style="warning" %}
**📔 Observação**: Todos os seus elementos de UI precisam estar aninhados na mesma estrutura e ter um único pai na raiz da estrutura. Você só pode chamar `ReactEcsRenderer.setUiRenderer()` uma vez na scene.
{% endhint %}

## Entities de UI

Cada elemento na UI deve ser definido como uma `UiEntity`entity separada, seja ela uma imagem, texto, fundo, uma caixa invisível de alinhamento etc. Assim como no espaço 3D da scene, cada `UiEntity` tem seus próprios components para lhe dar uma posição, cor etc.

A sintaxe parecida com React permite que você especifique cada component como uma propriedade dentro da `UiEntity`, o que torna o código mais curto e legível.

Os components usados em uma `UiEntity` são diferentes dos usados em entities regulares. Você não pode aplicar um component de UI a uma entity regular, nem um component regular a uma entity de UI.

Os seguintes components estão disponíveis para uso em uma `UiEntity`:

* `uiTransform`
* `uiBackground`
* `uiText`
* `onMouseDown`
* `onMouseUp`
* `onMouseEnter`
* `onMouseLeave`
* [`uiInputBinding`](/creator/content-creator-pt/scenes-sdk7/ui-2d/ui_input_binding.md) — mantenha ações de input enquanto o elemento estiver pressionado, para criar controles personalizados

Assim como com tags HTML, você pode definir components como auto-fechados ou aninhar um dentro de outro.

{% hint style="danger" %}
**Aviso:** Mantenha os wrappers de layout em tela cheia livres de manipuladores de pointer. Adicionar qualquer um dos `onMouse` handlers, ou `pointerFilter: 'block'`, a um `UiEntity` dimensionado `100%` de `100%` faz com que ele capture todos os cliques na tela, tornando toda a sua outra UI e o mundo 3D inteiro inacessíveis para clique. Em vez disso, coloque os handlers no painel ou botão que precisar deles. Veja [Bloqueio de pointer](/creator/content-creator-pt/scenes-sdk7/ui-2d/ui_button_events.md#pointer-blocking).
{% endhint %}

***arquivo ui.tsx:***

```tsx
import ReactEcs, { ReactEcsRenderer, UiEntity } from '@dcl/sdk/react-ecs'
import { Color4 } from '@dcl/sdk/math'

export const uiMenu = () => (
  // entity pai
  <UiEntity
    uiTransform={{
      width: 200,
      height: 200,
      margin: { top: '250px', left: '500px' },
    }}
    uiBackground={{ color: Color4.Blue() }}
  >
    {/* entity filha auto-fechada */}
    <UiEntity
      uiTransform={{
        width: 400,
        height: 400,
        margin: { top: '35px', left: '500px' },
      }}
      uiText={{ value: `Hello world!`, fontSize: 40 }}
    />
    {/* instrução de fechamento para a entity pai */}
  </UiEntity>
)
```

***arquivo index.ts:***

```ts
import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
import { uiMenu } from './ui'

export function main() {
    ReactEcsRenderer.setUiRenderer(uiMenu, { virtualWidth: 1920, virtualHeight: 1080 })
}
```

Uma definição de um módulo de UI só pode ter uma entity no nível superior. Você pode definir quantas outras entities quiser, mas todas elas devem caber dentro de uma estrutura com um único pai no topo.

## Escala Virtual da Tela

Defina uma largura e altura virtuais para a UI. Isso garante que sua UI tenha a mesma aparência em diferentes tamanhos de tela, independentemente do tamanho real da tela em pixels.

```ts
export function setupUi() {
    ReactEcsRenderer.setUiRenderer(uiComponent, { virtualWidth: 1920, virtualHeight: 1080 })
}
```

Se você definir uma largura virtual de 1920 e uma altura virtual de 1080, a UI será dimensionada para caber no tamanho da tela. Se a tela for 1920x1080, a UI será exibida no mesmo tamanho do tamanho virtual. Se a tela for maior ou menor, quaisquer valores em pixels serão dimensionados para caber no tamanho virtual. Por exemplo, se a tela for 3840x2160, um item definido com 100 pixels de largura será exibido em 200 pixels reais.

O cálculo real do fator de escala da UI que é multiplicado nos valores de pixel é [`Math.min(realWidth / virtualWidth, realHeight / virtualHeight)`](https://github.com/decentraland/js-sdk-toolchain/blob/main/packages/%40dcl/react-ecs/src/system.ts).

### Tamanho virtual padrão

O tamanho virtual é opcional, mas suas duas dimensões andam juntas: passe ambas ou nenhuma. Quando você não passar uma delas, um padrão da plataforma é aplicado:

| Plataforma    | Tamanho virtual padrão |
| ------------- | ---------------------- |
| Mobile        | `1600x720`             |
| Desktop e Web | `1920x1080`            |

Isso significa que os valores em pixels na sua UI são sempre dimensionados em relação a uma resolução de referência, mesmo quando você não passa nenhuma opção. Isso também se aplica quando a scene usa apenas `addUiRenderer()` e nunca chama `setUiRenderer()`.

Três casos especiais:

* **Optando por não usar escalonamento**: passe um tamanho inválido — qualquer valor menor que `0` ou igual a isso — para desativar totalmente a tela virtual. Os valores em pixels passam então a ser usados como pixels brutos do canvas, sem escalonamento. Essa é a forma documentada de desligar a tela virtual, então nada é registrado.

  ```ts
  ReactEcsRenderer.setUiRenderer(uiComponent, { virtualWidth: 0, virtualHeight: 0 })
  ```
* **Tamanhos incompletos**: fornecer apenas uma das duas dimensões também é inválido, então isso desativa a tela virtual assim como no caso acima — o padrão da plataforma entra **não** em ação. Diferentemente da opção de não usar acima, este caso é reportado: um tamanho parcialmente informado é um erro em vez de uma escolha deliberada, então o SDK registra `Tamanho da tela virtual incompleto (…): ambas as dimensões são necessárias, então a tela virtual é desativada e nenhuma escala de UI é aplicada.` uma vez para cada tamanho. Passe ambas as dimensões ou nenhuma.

  ```ts
  // Não faça isso — nenhuma escala é aplicada
  ReactEcsRenderer.setUiRenderer(uiComponent, { virtualWidth: 1920 })
  ```

  Vale a pena conferir isso no renderer principal, porque um tamanho incompleto ali também é um alternador para a scene inteira: uma `setUiRenderer()` chamada que menciona *qualquer uma das* dimensões tem prioridade sobre qualquer `addUiRenderer()`, então o exemplo acima desativa a tela virtual para toda a scene e descarta um tamanho válido passado a um renderer adicional.
* **Tamanhos 16:9 no mobile**: as telas de celular são muito mais largas que 16:9, então um canvas virtual 16:9 criaria barras laterais na UI. Se você passar um tamanho 16:9 (`1920x1080`, `1280x720`, …) e a scene estiver rodando no mobile, ele será substituído por `1600x720`, e uma mensagem será registrada no console uma vez. Tamanhos não 16:9 no mobile e qualquer tamanho válido em desktop ou web são respeitados como estão.

{% hint style="info" %}
**📔 Observação**: A `vw` e `vh` são independentes da tela virtual: `1vw` é 1% da largura do canvas e `1vh` é 1% da altura do canvas, exatamente como em CSS. Eles também ignoram o [`screenInset`](#screen-inset-area), então dentro do padrão `'device'` inseta um `width: '100vw'` é mais largo que um `width: '100%'` — o primeiro ocupa a tela inteira, o segundo preenche a área com inset.
{% endhint %}

{% hint style="info" %}
**📱 Observação**: A detecção da plataforma é resolvida de forma assíncrona. Durante os primeiros frames o SDK ainda não sabe que está rodando no mobile, então a tela virtual começa em `1920x1080` e muda para `1600x720` quando a detecção termina — você pode ver a UI ser reescalada brevemente ao carregar, e a mensagem de substituição de 16:9 aparece no console um momento depois do início da scene. Passe um tamanho virtual explícito não 16:9 se quiser uma resolução de referência estável desde o primeiro frame.
{% endhint %}

{% hint style="warning" %}
**📔 O que mudou para scenes escritas antes desta versão do SDK**

Três mudanças afetam scenes existentes. Nenhuma delas é opcional, então uma scene que não for tocada de forma alguma ainda parecerá diferente quando atualizar sua versão do SDK:

1. **Uma tela virtual agora é aplicada por padrão.** Uma scene que não passava opções costumava posicionar valores em pixels como pixels brutos do canvas. Agora ela é escalada em relação a `1920x1080` (`1600x720` no mobile). Para recuperar o comportamento anterior, desative explicitamente a tela virtual com `setUiRenderer(ui, { virtualWidth: 0, virtualHeight: 0 })`.
2. **`screenInset` é o padrão `'device'`.** Sua UI agora é posicionada dentro da área segura do dispositivo, então no mobile ela se move para dentro, e um `100%` na raiz já não ocupa a tela inteira — fundos em tela cheia, escurecedores e overlays deixam de alcançar o notch e o indicador inicial. Para recuperar o comportamento anterior, passe `setUiRenderer(ui, { screenInset: 'none' })`. Veja [Área de screenInset](#screen-inset-area).
3. **`devicePixelRatio` não participa do layout da UI.** A UI em tamanho de pixel agora pode ficar até 2–3 vezes maior em telas de alta densidade (retina e mobile) do que antes. **Não há opção de desativação para isso** — revise novamente quaisquer tamanhos ajustados manualmente e remova qualquer fator de escala que sua scene calculava sozinha.
   {% endhint %}

## Área de screenInset

As telas não são totalmente utilizáveis: um celular reserva espaço para o notch, a barra de status, o indicador inicial e os cantos arredondados, e cada explorer desenha sua própria HUD (minimapa, chat, …) sobre parte do canvas. O `screenInset` opcional

| Valor                 | Área em que a UI é colocada                                                                                                                                                                                                   |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `'device'` *(padrão)* | A área segura do dispositivo, excluindo o notch, a barra de status e os cantos arredondados. Lida de `UiCanvasInformation.screenInsetArea`.                                                                                   |
| `'interactable'`      | A área que o explorer relata como livre de sua própria HUD (minimapa, chat, …). Lida de `UiCanvasInformation.interactableArea`. O que ela cobre depende de cada explorer — verifique nas plataformas que você deseja atingir. |
| `'none'`              | A tela inteira, com `0,0` no canto superior esquerdo.                                                                                                                                                                         |

```ts
// A UI é mantida livre do notch, da barra de status e dos cantos arredondados — este é o padrão
ReactEcsRenderer.setUiRenderer(uiComponent, { virtualWidth: 1920, virtualHeight: 1080 })

// A UI é mantida livre da própria HUD do explorer
ReactEcsRenderer.setUiRenderer(uiComponent, { screenInset: 'interactable' })

// A UI cobre a tela inteira, você cuida das margens
ReactEcsRenderer.setUiRenderer(uiComponent, { screenInset: 'none' })
```

No desktop os insets do dispositivo são zero, então `'device'` coloca a UI sobre a tela inteira ali — o mesmo resultado que `'none'`. A área é relida a cada tick, então a UI acompanha os insets quando eles mudam, por exemplo na rotação ou quando as barras do sistema aparecem e desaparecem.

{% hint style="warning" %}
**📔 Não ancora a UI no canto superior esquerdo.** Esse canto, e toda a borda esquerda, é onde o explorer desenha seu minimapa, seu chat e, no mobile, o joystick virtual. A UI da scene colocada ali é renderizada, mas a própria UI do client é desenhada por cima dela, então fica coberta e seus botões muitas vezes não podem ser clicados. Ancora sua UI à direita ou centralize-a, ou use `screenInset: 'interactable'` para que o explorer a posicione fora da própria HUD. Veja [Nunca ancore sua UI no canto superior esquerdo](/creator/content-creator-pt/scenes-sdk7/conceber-a-experiencia/ux-ui-guide.md#never-anchor-your-ui-to-the-top-left).
{% endhint %}

{% hint style="warning" %}
**📔 `'interactable'` não é um no-op no desktop.** Diferentemente dos insets do dispositivo, a área interagível é *não* zero no client desktop: ele reserva cerca de 25% da esquerda da tela para sua própria UI, então `screenInset: 'interactable'` coloca sua UI nos 75% restantes ali. Essa é a finalidade da opção, mas isso significa que ela também muda seu layout no desktop — use branch com [`isMobile()`](/creator/content-creator-pt/criar-para-mobile/desenvolver/detect-platform.md) se você quiser isso apenas nos celulares.

**Suporte do cliente**: `'interactable'` precisa de um explorer que informe a área. É suportado no desktop e, no mobile, a partir da versão do client `1.12.1` em diante — em clients mobile mais antigos o valor é reportado como zero, e a UI volta a cobrir a tela inteira. Essa mesma `1.12.1` versão também normaliza a `'device'` área entre Android e iOS, então trate isso como o piso para qualquer layout que dependa de qualquer um dos insets. `'none'` comporta-se da mesma forma em todo lugar.
{% endhint %}

{% hint style="warning" %}
**📔 Observação**: Não envolva sua UI nos [`ScreenInsetArea` ou `InteractableArea`](/creator/content-creator-pt/criar-para-mobile/desenvolver/safe-area.md#wrap-part-of-your-ui-instead) components enquanto também deixa o `screenInset` valor correspondente no renderer — o inset seria aplicado duas vezes, empurrando a UI para dentro pelo dobro da margem. Em vez disso, baseie-se em `screenInset`, ou defina-o como `'none'` e coloque o wrapper você mesmo.
{% endhint %}

### As três áreas em um dispositivo real

As capturas abaixo são a mesma scene no mesmo celular, renderizada três vezes com apenas o `screenInset` valor alterado. O retângulo magenta é a própria UI; os contornos são as áreas que o explorer informa — ciano é todo o canvas, âmbar é `screenInsetArea`, verde é `interactableArea`.

<figure><img src="https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-78aa0fa3423a3ed51b5889f0150484a354b2dd30%2Fscreeninset-none.png?alt=media" alt="Scene UI covering the whole phone screen, including the notch strip and the areas under the client controls"><figcaption><p><code>screenInset: 'none'</code> — a UI cobre todo o canvas. Seus cantos ficam sob o notch e atrás dos controles do próprio client.</p></figcaption></figure>

<figure><img src="https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-94c4b28274282d30cda22c389b375fa30c78dc64%2Fscreeninset-device.png?alt=media" alt="Scene UI inset to the device safe area, clear of the notch"><figcaption><p><code>screenInset: 'device'</code> (o padrão) — a UI é puxada para a área segura do dispositivo, longe do notch e dos cantos arredondados. Ela ainda se sobrepõe aos controles do client, que não fazem parte dessa área.</p></figcaption></figure>

<figure><img src="https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-c0c75a80bed756d6b2b1483a7cca0cadef26c77e%2Fscreeninset-interactable.png?alt=media" alt="Scene UI inset to the area the client reports as free of its own HUD"><figcaption><p><code>screenInset: 'interactable'</code> — a UI é colocada dentro do retângulo que o client designa para a UI da scene. No client mobile <code>1.12.1</code>, capturado aqui, isso exclui a coluna da esquerda (perfil, chat, joystick); os botões de ação no canto inferior direito são desenhados sobre a área por design.</p></figcaption></figure>

{% hint style="info" %}
**💡 Dica**: `'interactable'` fornece a área que cada explorer designa para a UI da scene. Isso não é deliberadamente o mesmo que "todo controle do client fica fora dela" — como a terceira captura mostra, os botões de ação do mobile são desenhados sobre a área de propósito. Qualquer coisa que você colocar sob eles ainda estará acessível para você, mas competirá pelos mesmos toques, então tenha em mente os [cantos apertados](/creator/content-creator-pt/criar-para-mobile/desenvolver/safe-area.md#where-the-client-controls-live) e verifique as plataformas que você deseja atingir: o que a área cobre é decisão de cada explorer e pode mudar entre versões.
{% endhint %}

Cada renderer respeita seu próprio `screenInset`, então a UI principal e qualquer UI adicionada com `addUiRenderer()` podem usar áreas diferentes ao mesmo tempo. Diferentemente do tamanho virtual, esse valor nunca é compartilhado entre renderers.

## Múltiplos módulos de UI

Se sua scene contiver vários systems ou módulos que definem sua própria UI, você pode renderizar cada módulo de UI com `ReactEcsRenderer.addUiRenderer()`. Isso é especialmente útil ao trabalhar em uma scene complexa com vários componentes de UI, ou ao definir UIs para um [smart item](https://github.com/decentraland/docs/tree/main/creator/sdk7/smart-items/smart-items.md), que deve poder ser usado independentemente do que está no código do resto da scene.

O `ReactEcsRenderer.addUiRenderer()` função exige que você forneça uma entity como proprietária da UI. Isso pode ser qualquer entity, até mesmo uma entity dummy criada apenas para ser usada como proprietária da UI.

```ts
export function setupUi() {

    // Crie uma entity dummy para ser a proprietária da UI
    const dummyEntity = engine.addEntity()

    // Defina o módulo de UI como uma função que retorna um array de módulos de UI
    const uiComponent = () => [
      // Função que retorna um módulo de UI,
      // Função que retorna um módulo de UI
      // ...
    ]

    // Renderize o módulo de UI com a entity dummy como proprietária
    ReactEcsRenderer.addUiRenderer(dummyEntity, uiComponent)
}
```

Este trecho pode existir independentemente de qualquer outro código de UI na scene. O restante da scene pode incluir um `ReactEcsRenderer.setUiRenderer()`, ou nenhum, e a UI ainda assim será renderizada.

Um `addUiRenderer()` chamada também pode incluir uma largura e altura virtuais, assim como `setUiRenderer()`. No entanto, se a scene tiver uma `setUiRenderer()` chamada que também define uma largura e altura virtuais, a largura e altura virtuais da `addUiRenderer()` chamada serão ignoradas.

```tsx
ReactEcsRenderer.addUiRenderer(dummyEntity, uiComponent, { virtualWidth: 1920, virtualHeight: 1080 })
```

O tamanho virtual é um único valor em toda a scene, resolvido da seguinte forma: o tamanho em `setUiRenderer()` vence; caso contrário, a primeira `addUiRenderer()` chamada que forneceu um vence; e, se nenhum renderer forneceu um, o [padrão da plataforma](#default-virtual-size) é aplicado. Opções que contêm apenas um `screenInset` não contam como um tamanho fornecido.

O [`screenInset`](#screen-inset-area) funciona ao contrário — ele é por renderer, então cada módulo de UI pode ficar em uma área de tela diferente:

```tsx
// Este widget permanece fora da HUD do explorer, independentemente do que a UI principal use
ReactEcsRenderer.addUiRenderer(dummyEntity, uiComponent, { screenInset: 'interactable' })
```

Essa UI pode ser removida com `ReactEcsRenderer.removeUiRenderer(dummyEntity)` , também Se a entity que possui a UI for destruída, a UI também será removida. Se `ReactEcsRenderer.addUiRenderer()` for chamado novamente para a mesma entity, mas com um UiRenderer diferente, o anterior é limpo e o novo o substitui, mantendo seu lugar na ordem de empilhamento. Chamá-lo novamente também é como você altera as opções de um módulo de UI que já está renderizado, por exemplo seu `zIndex`.

### Ordem de empilhamento entre módulos de UI

Por padrão, os módulos de UI se empilham na ordem em que aparecem pela primeira vez, com os posteriores na frente. Módulos que aparecem pela primeira vez no mesmo frame — normalmente tudo registrado antes do primeiro frame da scene — são desenhados com a UI principal de `setUiRenderer()` ao fundo, seguido pelos outros módulos na ordem em que foram adicionados. Para controlar isso explicitamente, passe um `zIndex` nas opções do renderer: módulos com um `zIndex` maior renderizam na frente daqueles com um menor, independentemente da ordem em que apareceram. Módulos deixados em `0` mantêm a ordem padrão. A opção funciona da mesma forma no `setUiRenderer()`, então a UI principal também pode ser colocada na frente dos outros módulos.

```tsx
// Registrado primeiro, mas sempre na frente dos outros módulos de UI
ReactEcsRenderer.addUiRenderer(dummyEntity, uiComponent, { zIndex: 10 })

// A UI principal fica atrás de qualquer módulo que não defina um valor menor
ReactEcsRenderer.setUiRenderer(mainUi, { zIndex: -10 })
```

Essa é uma configuração diferente da `zIndex` de uma `UiEntity`, que apenas ordena [siblings dentro de um módulo de UI](/creator/content-creator-pt/scenes-sdk7/ui-2d/ui-positioning.md#z-index). A opção do renderer ordena módulos inteiros entre si, e os elementos dentro de cada módulo mantêm seu próprio `zIndex`.

### Compartilhando uma única instrução setUiRenderer

Em vez de chamar `ReactEcsRenderer.addUiRenderer()` para cada módulo de UI, você pode chamar `ReactEcsRenderer.setUiRenderer()` uma vez com um array de módulos de UI, que podem viver em arquivos diferentes.

```ts
const uiComponent = () => [
  // Função que retorna um módulo de UI,
  // Função que retorna um módulo de UI
  // ...
]

ReactEcsRenderer.setUiRenderer(uiComponent, { virtualWidth: 1920, virtualHeight: 1080 })
```

Abaixo está um exemplo mais completo:

***arquivo ui.tsx:***

```ts
export function UIModule1() {
  return (
    <UiEntity
      uiTransform={{
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'space-between',
        positionType: 'absolute',
        position: { right: '3%', bottom: '3%' },
      }}
    >
      <Label value="Hello World!" fontSize={18} textAlign="middle-center" />
    </UiEntity>
  )
}

export function UIModule2() {
  return (
    <UiEntity
      uiTransform={{
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'space-between',
        positionType: 'absolute',
        position: { right: '3%', top: '3%' },
      }}
    >
      <Label
        value="Aqui está mais alguma UI!"
        fontSize={18}
        textAlign="middle-center"
      />
    </UiEntity>
  )
}
```

***arquivo index.ts:***

```ts
import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
import { UIModule1, UIModule2 } from './ui'

export function main() {
    ReactEcsRenderer.setUiRenderer(() => [
      UIModule1(),
      UIModule2(),
      // ...
      // A linha abaixo é para usar a biblioteca DCL UI Toolkit
      // https://github.com/decentraland-scenes/dcl-ui-toolkit
      ui.render(),
    ], { virtualWidth: 1920, virtualHeight: 1080 })
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/ui-2d/onscreen-ui.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
