@stom66/dcl-ui-component-kit
v0.2.5
Published
DCL UI Component Kit — reusable Decentraland SDK7 UI components, layers, zones, and themes
Downloads
1,198
Maintainers
Readme
Decentraland UI Component Kit 🦆
@stom66/dcl-ui-component-kit (aka DUCK) is a reusable UI toolkit for Decentraland SDK7.
Human? Here, take this!
If you are using AI, this is what you actually need to know.
- Layer — a collection of UI that is shown or hidden together. One layer fills one zone.
- Zones — preset slots (
ZoneType.Top,BottomRight,Default, …). Setzone: ZoneType.*on the Layer. There are noZoneTop/ZoneLefthelper components. - Components — progress bars, icons, buttons, layout helpers go in that zone (
body()).

Get started
Ask your AI. Point your agent at this repository (or @stom66/dcl-ui-component-kit on npm) and tell it to install the kit into your scene.
Install @stom66/dcl-ui-component-kit into this Decentraland SDK7 scene.
Copy stock UI assets, scaffold a custom theme, wire SetupUiComponentKit, and follow the package README.Making your own theme
You do not need a custom theme to start — defaults look like Decentraland out of the box. When you want your own art:
- Get the Affinity template (
design/ui-component-kit-assets.af) and customize buttons / progress bars / icons / etc. - Export PNGs into the theme folder the CLI scaffolds (
assets/images/themes/<name>/) — never into stockassets/images/ui-component-kit/. - Tell your agent to wire those files into the theme. Full walkthrough: docs/themes.md.
Install
WARNING — stock assets are required.
Textured UI (icons, buttons, progress bars, spinners, …) will be blank or broken untilassets/images/ui-component-kit/exists in your scene.npm installalone is not enough. Modern npm may block this package’spostinstall(allow-scriptswarning). That is expected security behaviour — runcopy-assetsyourself.
npm install @stom66/dcl-ui-component-kit
npx @stom66/dcl-ui-component-kit copy-assetsThen confirm the folder is populated (many .png files). Full detail for humans and agents: INSTALL.md.
allow-scripts / postinstall
| Approach | Command |
|---|---|
| Required (always works) | npx @stom66/dcl-ui-component-kit copy-assets |
| Optional — allow our postinstall | npm approve-scripts @stom66/dcl-ui-component-kit then npm rebuild @stom66/dcl-ui-component-kit |
| Optional — auto on every install | Consumer "postinstall": "dcl-ui-component-kit copy-assets" (project scripts are not gated) |
Opt out of automatic copy: UI_COMPONENT_KIT_SKIP_ASSETS=1 or "config": { "dcl-ui-component-kit": { "skipAssets": true } }.
npx @stom66/dcl-ui-component-kit init-theme myGameimport { SetupUiComponentKit } from '@stom66/dcl-ui-component-kit'
import { myGame } from './themes/myGame'
export function main() {
SetupUiComponentKit({
theme : myGame.theme,
layers: myGame.layers,
})
}You can also skip a custom theme and register layers directly:
import { Background, Header, Layer, Row, SetupUiComponentKit, Text, ZoneType } from '@stom66/dcl-ui-component-kit'
class ScoreboardLayer extends Layer {
constructor() {
super({ id: 'scoreboard', zone: ZoneType.Top })
}
body() {
return [
<Background key="chrome" />,
<Row key="content">
<Header value="Score" />
<Text value="12" />
</Row>,
]
}
}
export function main() {
SetupUiComponentKit({ layers: [new ScoreboardLayer()] })
}Layer notes (short):
- A Layer is a show/hide group. It fills one zone (
zone: ZoneType.*, defaultDefault). - Implement
body()only — do not remountZone/ScreenInsetArea/InteractableArea.Layer.render()already mounts<Zone type={…}>. - Override size / align with
uiTransform/uiBackground(no Layer shorthands likebackgroundColor). - Panel chrome via sibling empty
<Background />inbody()(do not nest content inside it). - Prefer
cols={12}(etc.) onColumn/Label/ButtonTextfor grid widths inside panels. For edge / corner HUDs, omitcolsso zone flex can place content-sized controls — see docs/layers-and-zones.md → Zone alignment. inseton a Layer picks canvas chrome ('none'/'device'/'interactable'). SetupscreenInsetis the default when omitted (kit default'none'). Layers with the same resolved inset share one SDK renderer — do not wrapScreenInsetArea/InteractableAreainbody().colsDesktop/colsMobileandgetLeftZoneInset()are evaluated at render. Do not snapshotisMobile()into a module-levelconst.
Building blocks
| Piece | Role |
|---|---|
| Layer | Show/hide group for a collection of UI (HUD, popup, menu). One layer = one zone. |
| Zone | Preset slot (Top, BottomRight, Default, …) via zone: ZoneType.* or <Zone type={…}>. |
| Layout | Row / RowReverse, Column / ColumnReverse, Background, BackgroundGradient, Divider, Label. |
| Components | Buttons, progress bars, text, icons, toggle, spinners / motion, toasts. |
| Theme | Colours / type / sizing. Override via SetupUiComponentKit({ theme }) — never fork the defaults in place. |
Docs
Deeper guides and per-component options tables live under docs/:
| Guide | Contents |
|---|---|
| docs/layers-and-zones.md | Layer / Zone / inset, hideable popups, toasts |
| docs/themes.md | Affinity template, init-theme, agent wiring |
| docs/custom-textures.md | Atlases, UV helpers (1-based) |
| docs/components.md | Component reference with options tables |
| docs/licensing.md | MIT package license + credits / attributions |
| docs/media | Showcase GIF / media notes |
License & credits
The package is MIT. Third-party art is credited separately:
- Font Awesome Free — this kit ships a limited subset of the Free pack as
atlasIconsFontAwesome. For the full icon set, get Font Awesome from fontawesome.com (Free license). - CraftPix.net — some showcase demo sprite sheets (not npm stock textures).
Full notes: docs/licensing.md.
0.2.0 notes
Breaking / behaviour changes vs 0.1.x (SDK 7.26 UI):
- Named zone components removed (
ZoneTop,ZoneBottomRight,ZoneDefault, …). Usezone: ZoneType.*on a Layer, or<Zone type={ZoneType.Top}>(typeis required). IS_DEVremoved (unused).LEFT_ZONE_INSET→getLeftZoneInset()— call it at layout time; a module constant frozeisMobile()/vwToPixelsat import.colsDesktop/colsMobilestill exist and are resolved at render (same live-platform rule).screenInset/ Layerinset— SetupscreenInsetis the default for layers that omitinset. Layers are grouped into at most three SDK renderers (setUiRenderer+addUiRenderer). Do not wrap layers inScreenInsetArea/InteractableArea. OnlyZoneType.Defaultgets a centering shell inside its renderer.ZoneType.InteractableAreadeprecated — useinset: 'interactable'withZoneType.FullScreen(orDefault).zIndexis applied only when the Layer sets it (not from array index). UsezIndexfor stacking across inset groups. Later siblings still paint on top when unset.- Buttons / Toggle: on mobile,
callbackfires onmouseDown; on desktop,mouseUpafter hover. UseisMobile(), not!isDesktop(). - Toast host uses
ZoneType.Nonewith no full-screen wrapper (so it does not steal clicks).
This repo as a demo scene
This GitHub repo is also a runnable Decentraland scene. Local demos live under src/exampleThemes/ (showcase kitchen-sink, skyChaser, …). Switch the active bundle in src/index.ts.
The npm package only ships src/ui-component-kit, stock assets, and the CLI — not the example themes.
npm startAgent guidance
When creating or changing UI with this kit:
