Files
voidkontrol/docs/research/carbon-ui.md
T

21 KiB
Raw Blame History

IBM Carbon desktop UI strategy for VoidKontrol

Research date: 2026-09-21. Decision input for Establish a faithful IBM Carbon desktop UI strategy for Void Linux. This report recommends a direction and records evidence; it does not select the final stack, establish hardware support, or provide a prototype.

Recommendation

Evaluate official Carbon React in an unprivileged Tauri desktop application first. It combines Carbon's maintained component implementation with Void's packaged GTK3/WebKitGTK stack and leaves the device service responsible for all hardware control. Gate selection on a small native-Wayland, accessibility, and packaging proof on the actual supported Void targets. This is an architectural recommendation, not a completed compatibility test. [C1][T1][T2][V1]

Electron remains a viable Carbon rendering alternative if the project accepts owning a maintained Electron distribution/update route. Do not base that choice on the mere existence of Void's electron35 source template: the inspected template is explicitly marked broken. A QML main application can implement Carbon, but it would own a new Carbon implementation instead of consuming IBM's maintained React or Web Components libraries. Reserve that extra cost for a demonstrated requirement that the webview approach cannot satisfy. [C1][E1][E2][V2][Q1]

A Noctalia plugin and the full editor have different responsibilities. The full editor should use Carbon; the shell plugin should use Noctalia's supported API and components and expose a small entry point/status surface. They can share the device service without sharing a rendering toolkit. Exact Noctalia API choices belong to the separate desktop-integration research.

Existing behavior and boundaries

The supplied control specification requires an unprivileged UI, a single service owner for discovery/authentication/ serialization/readback, a complete backup before the first write, and comparison of readback after every update. It prohibits grabbing input devices, detaching the kernel driver, and automatic writes on startup/reconnect/resume. Protocol payloads and persistence semantics still require authenticated hardware capture.

The user has chosen verification of the observed USB presentation first and has kept firmware flashing and the factory-reset UI outside v1. A GUI library cannot close any of those protocol evidence gaps. The display should initially use the specification's Kreo Swarm 75 (signature match) identification until successful authentication; the observed VID/PID does not establish physical layout or connection-mode compatibility.

The repository contains a specification and agent documentation, with no existing UI implementation or architecture decision to extend at this research checkout. Consequently, the comparisons below do not propose replacing a working stack.

Maintained Carbon support and obligations

  1. Carbon's official developer guide lists React and Web Components as officially supported. Other web frameworks have community implementations. The maintained monorepo includes component styles, design tokens, icons, grid, spacing, motion, and typography packages. It does not list an official Qt/QML implementation. This is evidence about the supported offerings, not a claim that no third-party QML project exists. [C1][C2]
  2. @carbon/react supplies components, styles, and icons and requires a frontend build pipeline. A static bundled frontend is sufficient for this desktop editor; a web server framework is not required by Carbon. Official Web Components are a legitimate alternative if the architecture decision finds a concrete reason to avoid React; they still require a web rendering engine. [C1][C2]
  3. Carbon's themes are white, g10, g90, and g100. Use semantic theme, spacing, typography, focus, and layer tokens instead of approximate custom colors. Offer a supported light/dark choice; use Carbon's layering mechanism for nested surfaces. Shell theme synchronization can select a Carbon theme, but arbitrary wallpaper colors should not silently replace its contrast and semantic color relationships. The latter is a product recommendation. [C3]
  4. Carbon uses IBM Plex. Its current guide recommends per-family packages such as @ibm/plex-sans and @ibm/plex-mono; the legacy monolithic @ibm/plex package is no longer updated. Bundle the required fonts locally so installed operation does not depend on a font CDN. Carbon is Apache-2.0; Plex is SIL OFL-1.1 with reserved name Plex. Include the applicable notices and license texts in the distribution. [C2][C4][C5]
  5. Carbon components follow IBM's accessibility checklist, based on WCAG AA, Section 508, and European standards. Carbon explicitly says accessible components are only part of an accessible product. Test the assembled product in the selected Linux renderer, including screen-reader integration, rather than treating component adoption as application certification. [C6]

Desktop choices

Choice Carbon fidelity and ownership Linux/Void evidence Decision cost or gate
Carbon React + Tauri Reuses official components; small native IPC bridge can call the service. Tauri uses WebKitGTK on Linux; its windowing stack uses GTK3. Wry documents the GTK route for Wayland. Void packages the required GTK3/libsoup3 WebKit 4.1 variant with Wayland enabled. [T1][T2][V1] Build/runtime dependencies and WebKit behavior depend on the distribution. Test Carbon rendering, AT-SPI/screen reader operation, dialogs, scaling, and window activation on niri.
Carbon React + Electron Reuses the same official components in bundled Chromium. Upstream Linux binaries are built on Ubuntu; Electron documents native Wayland selection from version 38 when XDG_SESSION_TYPE=wayland. Void's inspected electron35 template has musl build paths but is marked broken. [E1][E3][V2] Ships Chromium/Node/Electron updates with the application. Establish a supported runtime distribution, musl route if needed, and package maintenance; the distro template is insufficient proof.
Qt Quick/QML with a custom Carbon style Uses Qt controls and explicitly recreates Carbon appearance, layout, states, and interactions. Qt provides native controls, accessibility metadata, and custom styling. Its listed styles do not include Carbon. [Q1][Q2] Own the custom Carbon component set, visual parity, accessibility behavior, token mapping, and upstream design changes. Similarity to Noctalia's toolkit does not remove this work.

A smaller Tauri application bundle would not prove a smaller total installed system or better memory/startup performance: GTK and WebKit dependencies still exist. No benchmark was run. Conversely, Electron's bundled renderer can reduce renderer-version variability but creates direct runtime update responsibility; Electron supports the latest three stable major releases. [T1][E2]

glibc and musl

  • Upstream Tauri now includes Alpine/musl prerequisites, warning that some static dependencies may need source builds. Therefore, a blanket claim that Tauri cannot run on musl would be incorrect. Those Alpine instructions are not a Void compatibility result. [T3]
  • Void's libwebkit2gtk41 template at 954278b83979958bcfdff05f22cf699c9dc20346 is version 2.50.4_1, enables Wayland, defaults to a bubblewrap sandbox, and depends on xdg-dbus-proxy when that option is enabled. It includes musl-compatible build paths rather than a blanket musl prohibition. libwebkitgtk60 is the GTK4 subpackage; it is not a drop-in substitute for Tauri's GTK3 WebKit 4.1 requirement. Package source availability alone does not prove a successful application build. [V1][T2]
  • Void's electron35 template at the same revision is 35.7.2_1, has x86_64* aarch64* architecture patterns and musl-legacy-compat paths, but is marked broken because its configure tooling uses FancyURLopener removed in Python 3.14. This disproves neither all Electron-on-musl possibilities nor the possible existence of an older binary package; it does mean that this template cannot establish a reproducible, maintained current runtime. [V2]
  • Treat glibc and musl as separate build and runtime targets. A glibc binary or AppImage must not be presented as proof of native musl support. Tauri's own Linux distribution guidance warns that the build system's libc baseline affects compatibility. Which libc and architectures v1 promises remains an architecture decision informed by the Void research. [T4]

Security and process boundary

Both wrappers can preserve the service boundary in the supplied specification. Keep packaged UI assets local, render imported names as text, and expose only typed domain operations through the desktop bridge. Neither JavaScript nor a QML plugin should accept arbitrary HID frames, open /dev/hidraw*, run arbitrary shell commands, or gain service credentials. The service must independently authorize and validate requests; hiding a control is not authorization.

For Tauri, capability/permission configuration constrains webview-to-core calls, while core/plugin code itself has the application's OS privileges. Command implementations remain responsible for enforcing scopes. This is a separate boundary from the service's own peer authentication and device policy. [T5]

For Electron, retain renderer sandboxing and context isolation, disable Node integration in the renderer, validate IPC sender and arguments, constrain navigation, and use a restrictive content-security policy. Its security guidance also explicitly assigns responsibility for updating Electron, Chromium, Node, and dependencies to the application maintainer. [E4]

Proposed interaction requirements

These are design recommendations derived from the supplied protocol invariants, not additional asserted keyboard capabilities. The service remains authoritative for advertised features, verified ranges, physical key identifiers, raw-value translation, and transaction state.

Main organization and keyboard accessibility

Use a compact Carbon application shell with Device, Lighting, Key mapping, Macros, Typing and power, and Backups as ordinary navigation destinations. Use standard forms for editors and a restrained amount of custom rendering for the physical keyboard preview. This is information architecture for later review, not a locked wireframe.

The layout preview should use the authenticated physical layout map and identify each key by its position, legend, selected layer, and current assignment. A keyboard-accessible list/form view must offer the same selection and editing operations. The preview cannot be the only means of choosing a key, and color cannot be the only indication of selection, assignment, or errors. A labelled hex/RGB input or equivalent text entry should accompany any color picker.

For layers, Carbon Tabs can expose Base, Fn, Fn1, and Fn2. Carbon supplies arrow-key navigation and distinguishes automatic versus manual activation. Choose manual activation if changing tabs causes a perceptible read delay; switching the editor layer must not itself write settings or claim to change the keyboard's active hardware layer. [C7]

All functionality must be reachable without dragging or mouse-only gestures: visible focus, logical tab order, standard activation keys, Escape for transient surfaces, and focus restoration after dialogs. Preserve a path out of every custom control. Provide move-up/down controls if macro actions are reorderable. Avoid stealing ordinary typing or compositor shortcuts just to select physical keys. Carbon's accessibility guidance explicitly requires full keyboard access and testing beyond automated checks. [C6][C8]

Readback, changes, and failures

Keep three concepts separate: the last configuration read from the device, the user's unapplied edits, and the service's current transaction status. Recommended visible states are:

Condition UI behavior
No device, unsupported signature, unavailable service, or permission failure Show a persistent, specific status with the relevant recovery action. Do not present cached state as live device state.
Authenticating or reading Identify the operation and withhold hardware writes until the service declares them safe.
Edits pending Clearly show unapplied changes and an explicit Apply action. Updating a form or selecting an effect changes local intent only.
Backing up, writing, or verifying Show those actual stages. Prevent duplicate submission; do not call a sent command “Saved.”
Readback matches Show “Applied and verified.” Claim persistence across power cycles only if the protocol/hardware evidence establishes it.
Timeout, disconnect, malformed reply, or mismatch Preserve useful edit context, mark device state uncertain, and show a persistent error. Reconnection/readback precedes an explicit retry; no blind automatic replay.

Carbon InlineLoading supplies active/finished/error states and recommends disabling associated actions during submission. Inline notifications persist, and error messages should state the user action that resolves the problem. Use these patterns for operation status; a fleeting toast is insufficient for a failed hardware update. [C9][C10]

Feature editors

Area v1 editor implications from the supplied specification
Lighting Only capability-backed effects; five brightness/speed levels; monochrome/colourful; LED enable; one custom per-key frame. Use protocol-owned mappings for self-defined mode and colour-mode raw IDs. Do not invent direction controls or multiple onboard lighting profiles.
Key mapping Four layers; physical keys only; keyboard/modifier/combination/media/mouse/disabled/macro choices where verified. Show current and proposed assignments; flag unknown readback without silently replacing it.
Macros List the 32 slots; edit ordered press/release/delay actions with visible bounds and slot usage. Limit to 112 actions, 0–65,535 ms delays, and 127 encoded name bytes. Confirm the name encoding before implementing byte counting; “127 characters” is not equivalent. Offer only verified execution modes and validated parameter ranges.
Typing Debounce choices 0/10/20/30/40 ms. Tap-delay UI must await its verified range/units. Do not expose unsupported NKRO, report-rate, OS-mode, Win-lock, or Hall-effect controls.
Power Display battery/charging only when valid data is available; unknown is not zero. Sleep uses the stated discrete choices, not a free-form unbounded duration.
Backups and restore Export a versioned, protocol-independent document; show source identity, timestamp, compatibility checks, and a change preview before explicit restore. Validation and a fresh pre-write backup belong to the service. Do not promise atomic restore unless evidence establishes it; identify partial/interrupted outcomes.

A macro action form is sufficient for complete authoring. If a later decision adds recording, it must remain an explicit focused interaction with an obvious stop path and must obey the specification's ban on input-device grabs. Global keyboard recording is not required by the supplied capabilities and should not be added as an implicit interpretation of “complete control.” Never execute a macro merely because a user previews its steps. Layer reset, if included, needs separate verified protocol behavior and explicit user intent; factory reset and firmware flashing remain excluded.

Smallest sufficient proof before choosing the stack

The later architecture/prototype decision should evaluate one packaged Carbon form, layer tabs, a modal, a representative long macro list, the labelled keyboard selector, and simulated service states. It does not need hardware writes.

  1. Build/install/uninstall on the intended Void libc/architecture targets with declared runtime dependencies. Confirm local fonts/assets work without network access and record exact dependency versions.
  2. Launch as a native Wayland window on niri; verify app identity, keyboard focus, normal resizing, fractional scaling, dialogs/file selection, and behavior when launched from the shell integration. A successful XWayland fallback does not satisfy a native-Wayland claim.
  3. Operate every representative control by keyboard; test meaningful reading and actions with the target Linux accessibility stack, including modal focus and operation-status announcements. Carbon's upstream tabs screen-reader evidence names JAWS, VoiceOver, and NVDA, so it is not a substitute for a Linux/Orca test. [C7]
  4. Exercise disconnected, unauthenticated, pending, verifying, and failed states against a fake service; prove no simulated write occurs on launch, navigation, refresh, or reconnect. Confirm duplicate Apply is blocked and stale drafts cannot overwrite a newly read configuration without review.

Unresolved product decisions are the supported libc/architecture matrix, wrapper selection, theme synchronization policy, and the preferred editor interaction. Unresolved hardware facts include the layout, name encoding, tap-delay parameters, transaction persistence, and individual capability read/write validation. These are explicit decision/proof obligations, not missing Carbon documentation.

Sources and retrieval

Context7 was used first for Carbon, Tauri, Electron, and Qt (library then docs, no more than three commands for each question). Findings were checked against the following primary documentation/source. No application was built, no packages were installed, no host configuration was changed, and no device I/O was performed for this report.