// GUI WIDGET AUDIT

App-owned native / hand-rolled widgets vs the shared zgui-core components · verified 2026-07-11 by grep at origin/main · excludes shared clip-engine, embedded cores, comments

Docs Source
// Color scheme

>_Executive summary

The house rule is GUI-only zgui components: every app builds its UI from the shared zgui-core library (ZGui.*) — modals, dropdowns, pickers, tables — never a hand-rolled or native browser widget. This counts the app-owned native form-control elements a ZGui.* component already covers. Only three apps are real offenders: traderview, Audio-Haxor, and ztranslator. Everything else is clean or down to 1–3 stragglers.

963
App-owned native widgets
648
Native <select> → ZGui.dropdownMenu
6
Fully clean apps (0 native)
3
Heavy offenders

Resolved 2026-07-11 (fleet-wide): all four native widget types now auto-upgrade to their ZGui component at runtime via zgui-core's widget observer — <select>zs-select, rangezs-range, dateZGui.datePicker, colorZGui.colorPicker (ZGui.upgradeSelects / upgradeRanges / upgradeDates / upgradeColors), preserving each element's id / value / change wiring. Rolled to all 16 apps (zgui-core 569cfd8b). The source templates still emit native elements, so the per-app counts below stand as the source inventory — but they render as the ZGui component in every app that loads zgui-core. Opt out with <html data-zg-no-select-upgrade>. (Date/colour replace the element, so verify tight date forms, e.g. traderview, after rebuild.)


~Detection method & what is excluded

Counts are native widget elements in each app's own frontend, by fixed grep, mapped to the ZGui.* component that should replace them. To avoid over-counting, four sources of shared/false hits are excluded — an earlier pass that counted them inflated most apps (e.g. zcite 7→0, zstation 7→0, zgo 2→0):

Native elementGrepZGui replacement
native dropdown<selectZGui.dropdownMenu / combobox / searchSelect
native slidertype="range"ZGui.slider / dbFader / bipolarSlider
native colour pickertype="color"ZGui.colorPicker
native date/timetype="date|time|datetime-local"ZGui.datePicker / dateRangePicker

Excluded (not the app's own violation): (1) the vendored zgui-core lib, vendor/, node_modules, bundles, dist; (2) the shared zpwr-clip-engine clip UI (clip-* selects), which is embedded — sometimes inline in the host's own index.html — in traderview / zemail / ztranslator / zstation, so it is one shared-component fix, not per-app; (3) embedded zpdf-core viewer subtrees (/zpdf/); (4) comment lines and documented ZGui fallbacks. The JS alert/confirm/prompt metric is also excluded — apps route those through a ZGui.modal.prompt-delegating helper.


#Per-app widget audit

clean = 0 app-owned native · minor = 1–10 · heavy = >10. "ZGui calls" counts distinct ZGui.<component>() invocations (excluding chrome) as a rough adoption signal.

App<select>rangecolordate/timetotalZGui callsVerdict
traderview5653421979114heavy
Audio-Haxor546317013414heavy
ztranslator252002736heavy
zftp11103214minor
zemail11103196minor
zpdf10102118minor
zreq1000159minor
zstation0100166minor
ztunnel0100159minor
zcite0000068clean
zgo0000096clean
zoffice0000073clean
zthrottle00000114clean
zcontainer00000605clean
zphoto0000029clean

zterminal (native GPU terminal, no webview) and the JUCE plugins (no window.ZGui) are out of scope for a native-vs-ZGui widget audit.


*Findings & fix targets


*Beyond form controls — hand-rolled widget modules

A second pass looked past native form elements for whole modules that reimplement a ZGui.* component. Raw greps for native checkbox / number / text / textarea and modal/dialog class names are not reliable — they inflate wildly through vendored/embedded content (e.g. the ztranslator view embedded in traderview) and per-class-name variants, so they are deliberately not tabulated. Named widget modules are the trustworthy signal:

ModuleWhat it hand-rollsZGui.* refsVerdict
traderview/frontend/js/dialog.jsCustom modal dialogs (tConfirm / tPrompt, "replaces native confirm/prompt") — dialog-overlay / dialog-actions chrome0hand-rolled → ZGui.modal
traderview/frontend/js/tooltip.jsCustom tooltips — walks data-tip and builds its own popover0hand-rolled → ZGui.tooltip
zmax-gui/frontend/menu.jsMenu surface62already ZGui
zemail/frontend/menu.jsBridge to the native macOS menu bar (Tauri), not a webview widgetn/anot a violation

Net new fakes: traderview's dialog.js + tooltip.js — two hand-rolled widget modules (0 ZGui refs) reimplementing ZGui.modal / ZGui.tooltip, consistent with traderview being the heaviest offender. Both are traderview-only and a real (non-trivial) refactor: the dialog module has its own promise-based tConfirm/tPrompt API used across setup-wizard / accounts / brokers, so migrating means re-pointing those call sites at ZGui.modal. The menu.js pair are not violations — checked at the source.