@luna/ui
@luna/ui is the standard UI toolkit for TidaLuna plugins. Most settings pages in real plugin repos use these components.
What it does
- Gives you ready to use settings components (
LunaSwitchSetting,LunaNumberSetting, ...) - Provides consistent Luna styling (
LunaSettings,LunaStack,lunaMuiTheme) - Lets plugins register custom pages via
Page.register(...) - Provides a global confirm helper for modal-like confirmation flows
Function/component reference
Page API (classes/Page)
Page.register(name, unloads, component?)- Registers/reuses a page by name and ties lifecycle to unloads.
page.open()- Navigates to and opens that page in Luna flow.
page.render()- Renders component if it has not rendered yet.
Settings wrappers (components/settings/*)
LunaSettings(props)- Main settings container.
LunaSwitchSetting(props)- Boolean setting control.
LunaTextSetting(props)- Text input setting.
LunaNumberSetting(props)- Numeric setting with min/max and
onNumber.
- Numeric setting with min/max and
LunaSelectSetting<T>(props)andLunaSelectItem- Dropdown/multi-select setting.
LunaButtonSetting(props)- Action button row.
Common controls
LunaButton(props)LunaSwitch(props)LunaNumber(props)LunaStack(props)LunaTitle(props)LunaTrashButton(props)SpinningButton(props)
Helper
confirm(options)from@luna/ui/helpers/confirm- Global async confirm prompt.
Practical settings pattern (from real plugins)
This is the common pattern used in plugins like SpinnyCover, Syncify, AudioVisualiser, and CustomFonts:
tsx
import React from "react";
import { ReactiveStore } from "@luna/core";
import { LunaSettings, LunaSwitchSetting, LunaNumberSetting, LunaButtonSetting } from "@luna/ui";
export const settings = await ReactiveStore.getPluginStorage("MyPlugin", {
enabled: true,
speed: 25,
});
export const Settings = () => {
const [enabled, setEnabled] = React.useState(settings.enabled);
const [speed, setSpeed] = React.useState(settings.speed);
return (
<LunaSettings>
<LunaSwitchSetting
title="Enabled"
checked={enabled}
onChange={(_, checked) => setEnabled((settings.enabled = checked))}
/>
<LunaNumberSetting
title="Speed"
value={speed}
min={1}
max={100}
onNumber={(value) => setSpeed((settings.speed = value))}
/>
<LunaButtonSetting title="Reset" onClick={() => setSpeed((settings.speed = 25))} />
</LunaSettings>
);
};Notes
Prefer
Luna*Settingcomponents so your plugin looks like the rest of Luna.Update both local React state and persistent plugin storage in the same handler.
Keep complex async actions behind
LunaButtonSettingso users explicitly trigger them.For advanced UX flows, combine settings components with
confirm(...).See Plugin Settings guide for full patterns.