DirkScripts Logo

Login With FiveM

Login

UI

â„šī¸ Client Module - All UI functions can only be used on the client

dirk_lib ships a full suite of UI components. The active provider for each component is selected from the Bridging section of /dirk_config. Every UI provider defaults to ox_lib — install ox_lib and you get its native UIs out of the box. Switch any provider to dirk_lib to use the built-in NUI instead.

PageComponents
NotifyNotifications and compatibility wrapper
Text UIPersistent interaction text
ContextContext menus
DialogDialog trees and camera-focused conversations
ProgressProgress bars, circles, active/cancel state
InputInput dialogs
StatusStatus indicators
QuizQuiz registration and runtime
Key PromptsContextual key overlays
Utilities3D text, help notifications, clipboard, links, theme

Theming — read this before adding a UI component

Every shared UI is drawn on dirk_lib's NUI page, inside dirk_lib's provider. So without doing anything, a dialogue opened by a script with its own theme comes up in dirk_lib's colours.

Each element therefore wears the colours of the resource that opened it. Nothing is asked of the calling script: it never passes a theme, and never will — it would be boilerplate at every call site and forgotten at some of them.

How it reaches the page

  1. A resource declares a theme block in its schema.json and turns useOverride on (see Utilities).
  2. modules/scriptConfig/client.lua runs inside that resource's VM, so it is the only code that ever sees its config. On every application of that config it calls exports.dirk_lib:registerTheme(resource, theme). That covers the first hydration and every later edit through the panel — no startup special case, no polling, and nothing on the hot path.
  3. dirk_lib holds a resource -> theme map (src/ui/client/theme.lua).
  4. Each UI entry point resolves it and ships it with its payload.
  5. The React side wraps the component in <Themed>, which scopes a nested MantineProvider to that element alone.

A resource with no theme block never registers, has no entry, and falls back to dirk_lib's global appearance — which is what everything did before.

Adding a new UI component

Lua — at the entry point:

lua
lib.myThing = function(data)
  -- FIRST, before anything that can yield. `GetInvokingResource` answers only
  -- for the frame that crossed the export boundary; a Wait ends that frame and
  -- it comes back nil, so the element silently wears dirk_lib's colours.
  local theme = lib.uiTheme(GetInvokingResource() or GetCurrentResourceName())

  SendNuiMessage(json.encode({
    action = 'MY_THING',
    data = { ..., theme = theme },
  }))
end

React — report it, do not apply it:

tsx
useNuiEvent<MyThingProps>('MY_THING', (data) => {
  setUiTheme('mything', data?.theme);
  setState(data);
});

App.tsx — wrap the component, not its return:

tsx
<Themed theme={useUiTheme('mything')}><MyThing /></Themed>

Three traps, all silent

  • Wrapping the component's own return does not work. A component resolves its hooks in its BODY, which is above the JSX it returns, so anything derived from useMantineTheme() up there is still dirk_lib's. The markup looks right and the colours are wrong. Wrap from App instead.
  • GetInvokingResource() must be read before the first yield, for the reason in the snippet above. progressBar, quiz and inputDialog all wait before they send, and all read it first.
  • The scope element needs data-mantine-color-scheme. Mantine puts the raw palette in .scope { } but everything a component actually reads in .scope[data-mantine-color-scheme="dark"] { }. Without the attribute the palette scopes and the components do not. <Themed> already sets it; anything that scopes a theme by hand has to as well.

What is deliberately NOT themed

  • Notifications — server furniture. They should look the same whichever script raised them.
  • Config Studio, the admin panel — dirk_lib's own UI.
  • Gizmo, TestBed — developer tooling.

Last updated on 30 September 2026

Copyright Š 2026 DirkScripts.

Not affiliated with or endorsed by Rockstar North, Take-Two Interactive, or any other rights holders. FiveM is a copyright and registered trademark of Take-Two Interactive Software, Inc.
Our checkout system is provided by Tebex Limited, who manage payment processing, product delivery, and billing support. Prices shown in currencies other than GBP are approximate conversions updated daily. All purchases are processed in GBP, so the final amount charged may vary depending on your bank or payment provider’s exchange rate.