UI kit
Import shared components from @timon/ui so your plugin uses the same React instance, controls and theme tokens as Timon.
| Export | Use |
|---|---|
Slot, SlotKeyed | Render extension points your component declares |
Tile | Frame for a widget using frame: 'none' |
BrandMark | Backend brand mark using a catalogue brand or model slug; unknown brands get a fallback |
Button, Input, Label, Switch, Separator | Form primitives |
DropdownMenu*, Tooltip* | Menus and tooltips |
Dialog, DialogPortal, DialogOverlay, DialogTrigger, DialogClose, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription | Dialog composition |
Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton | Select composition |
HUD_SURFACE | Theme-aware cockpit surface classes; opaque string for cn(HUD_SURFACE, className) |
cn | Merge class names |
t, getLocale | Product translations and current locale |
createTranslator | Translations shipped by your own plugin |
Plugin-owned translations avoid collisions with product keys. A missing translation key is displayed as its key rather than empty text. Ship your interface icons yourself; provider logos should use BrandMark so the app can keep them consistent.
The app's stylesheet is compiled before a third-party package is installed. Arbitrary classes such as text-[10px] or a generated conic-gradient class may not exist and silently do nothing. Use inline styles for precise values and SVG for drawings. Do not assume every standard Tailwind utility is present either; only compiled classes are available.
Theme custom properties remain usable in inline styles, for example hsl(var(--muted)) or hsl(var(--primary)). The supplied quota monitor demonstrates SVG usage rings without depending on plugin-specific stylesheet compilation.
Use the existing WidgetChromeProps type from @timon-ai/sdk for a
custom widget frame (widget: { frame: 'none' }). Forward className
to the root, render poignee in the header actions, and use editing
to show configuration controls. The SDK keeps poignee typed as unknown
to avoid a React dependency; narrow it to React.ReactNode when rendering.
DialogContent includes its portal, overlay and close button. Set
hideClose only when supplying your own accessible close control.
SelectContent includes its portal and scroll buttons. Compose it with
SelectItem children and give the trigger an accessible label.
HUD_SURFACE reuses compiled theme classes; do not depend on its literal
value or copy arbitrary Tailwind values into your plugin.
Reading usage
Both host and client contexts expose ctx.usage.list() with usage:read. Render all returned provider-defined windows rather than a fixed list of window names.
| Entry | Display |
|---|---|
available: true | Real measurements |
available: false, no error | No probe available; omit the gauge |
available: false, with error | Unavailable state; never substitute zero |
A host plugin can register a probe with usage:collect. It is removed when the plugin unloads, cannot displace a native probe and cannot duplicate another plugin's collector for the same backend.
Backend extensions
With backends:register, prefer a profile on an existing dialect when its protocol matches. Write a dialect only for a genuinely different CLI protocol. The daemon owns process launch and checks plugin-chosen binaries against the operator policy.
Resolve credentials through secret settings or the vault and pass values to the profile. Plugins cannot use envFrom or requiredEnv to read the daemon's ambient environment. Unloading unregisters the backend and updates the catalogue. See the real provider template for both registration paths.