UI Services
Unlike classes, UI services have no common UI base class, and unlike components that are meant to be re-used, these services represent a single core UI concept that is used in a single place and must not be instanced multiple times. The API of these services is often used by other plugins, modules, and parts of the viewer to add and control different menus and UI elements.
Core Services
-
AppBar(Top menu) Manages the top navigation bar. It exposes APIs to add custom actions, submenus, and buttons. It hosts core viewer controls like View, Edit, and Plugins menus. Plugins often useAppBar.EditorAppBar.Viewto insert their controls into the main application.AppBar.Chromeis an opt-in registry that backs the "hide UI" button in the top-right. Components register aVisibilityManager(or any{ is, on, off }/{ is, set }duck) withAppBar.Chrome.register(id, vm); everything already routed throughAppBar.View.append()orAppBar.View.registerViewComponent()is auto-enrolled. The button callsAppBar.Chrome.toggle(), which snapshots each registeredvm.is()and callsvm.off()directly (bypassingVisibilityManager.set()so the user's persisted visibility choices inAppCacheare not overwritten); the next press restores only the entries that were visible before. Not related toFullscreenMenusbelow. -
MobileBottomBarA separate navigation bar service used exclusively on narrow/mobile viewports to provide touch-friendly counterparts to the AppBar items. -
FloatingManagerHandles z-index ordering and focus state for floating panels (e.g.FloatingWindowcomponents). It ensures that multiple floating UI windows properly overlap and the newly focused window always comes to the front. -
FullscreenMenusManages full-screen overlay menus (e.g., settings, data panels). Ensures that only one fullscreen menu is visible at a time and provides API to toggle or switch them.Tab body layout helpers. Plugin tab bodies look out of place when they ship their own ad-hoc DOM, so two thin van.js helpers on the service render the same DaisyUI cards core Settings uses:
const fs = USER_INTERFACE.FullscreenMenu;return fs.layout(fs.card("Export options", checkbox1, select1),fs.card("Display", checkbox2),);fs.layout(...sections)returns the outer flex shell + 2-column responsive grid;fs.layout(title, ...sections)adds a 2xl in-body header above the grid (matches the look of core Settings).fs.card(title, ...children)is a single titled card. All are optional — use them for visual parity with core, drop down to raw van.js when you need custom chrome. Passnull/""as the title to either helper to render the chromeless variant.Sidebar grouping.
FullscreenMenus.register(item, ns)places the tab under the namespacens(defaultNAMESPACE.PLUGINS). The sidebar rendersSYSTEMandPLUGINSgroups with a divider + uppercase label between them —Menu.NAMESPACE.SYSTEM(order 10) vsMenu.NAMESPACE.PLUGINS(order 20). Explicititem.namespaceoverrides thensargument.Plain chrome.
AppBar.Plugins.setMenu(...)andFullscreenMenus.setMenu(...)accept a finaloptsargument; pass{ chrome: "plain" }to skip the default rounded outer card around the plugin tab body. Use this when the tab renders its own cards viafs.card(...)and you'd otherwise see nested borders. Defaultchrome: "card"preserves the existing look for plugins that aren't migrating. -
FloatingWindowexternal mode Detached browser windows are now handled directly byFloatingWindowwithexternal: true, including inherited UI assets/theme support and Monaco-backed editor windows. -
GlobalTooltipA singleton tooltip service that allows components to display contextual help text without needing localized tooltip DOM structures everywhere. -
Tutorials (
USER_INTERFACE.Tutorials) The tutorial launcher.Tutorials.show()opens theUI.TutorialsModal(anIllustratedModal-backed two-pane modal); each card kicks off an EnjoyHint walk through the registered steps. Author new tutorials viaUSER_INTERFACE.Tutorials.add(pluginId, name, description, icon, steps, prerequisites?)and consultsrc/TUTORIALS.mdfor the selector cookbook and step grammar (next/clickactions,runIfguards, viewer-agnostic[id$="-…"]selectors).