Research IBM Carbon desktop strategy for VoidKontrol
This commit is contained in:
@@ -0,0 +1,278 @@
|
|||||||
|
# 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](https://git.bongbetic.com/xavierk/voidkontrol/issues/4).
|
||||||
|
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](../../KREO-SWARM75-LINUX-CONTROL-SPEC.md)
|
||||||
|
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.
|
||||||
|
|
||||||
|
- [C1] [Carbon developer introduction](https://carbondesignsystem.com/developing/get-started/) and [React guide](https://carbondesignsystem.com/developing/frameworks/react/).
|
||||||
|
- [C2] [Carbon official repository, packages and license](https://github.com/carbon-design-system/carbon/blob/main/README.md).
|
||||||
|
- [C3] [Carbon themes](https://github.com/carbon-design-system/carbon/blob/main/packages/themes/README.md), [Theme component](https://github.com/carbon-design-system/carbon/blob/main/packages/react/src/components/Theme/Theme.mdx), and [Layer component](https://github.com/carbon-design-system/carbon/blob/main/packages/react/src/components/Layer/Layer.mdx).
|
||||||
|
- [C4] [Carbon IBM Plex guide](https://github.com/carbon-design-system/carbon/blob/main/docs/guides/ibm-plex.md).
|
||||||
|
- [C5] [IBM Plex license](https://github.com/IBM/plex/blob/master/LICENSE.txt).
|
||||||
|
- [C6] [Carbon accessibility overview](https://carbondesignsystem.com/guidelines/accessibility/overview/).
|
||||||
|
- [C7] [Carbon Tabs accessibility](https://carbondesignsystem.com/components/tabs/accessibility/).
|
||||||
|
- [C8] [Carbon accessibility verification guide](https://github.com/carbon-design-system/carbon/blob/main/docs/guides/accessibility.md). Its old IBM-internal DAP setup instructions are not adopted as a project tool requirement.
|
||||||
|
- [C9] [Carbon InlineLoading usage](https://carbondesignsystem.com/components/inline-loading/usage/).
|
||||||
|
- [C10] [Carbon notification usage](https://carbondesignsystem.com/components/notification/usage/) and [Form usage](https://carbondesignsystem.com/components/form/usage/).
|
||||||
|
- [T1] [Tauri webview versions](https://v2.tauri.app/reference/webview-versions/).
|
||||||
|
- [T2] [Wry Wayland/GTK integration](https://github.com/tauri-apps/wry/blob/dev/README.md) and [Tao Linux GTK3 dependency](https://github.com/tauri-apps/tao/blob/dev/README.md).
|
||||||
|
- [T3] [Tauri prerequisites, including Alpine](https://github.com/tauri-apps/tauri-docs/blob/v2/src/content/docs/start/prerequisites.mdx).
|
||||||
|
- [T4] [Tauri Linux distribution/libc baseline guidance](https://github.com/tauri-apps/tauri-docs/blob/v2/src/content/docs/distribute/debian.mdx).
|
||||||
|
- [T5] [Tauri security boundaries](https://github.com/tauri-apps/tauri-docs/blob/v2/src/content/docs/security/index.mdx) and [capabilities](https://github.com/tauri-apps/tauri-docs/blob/v2/src/content/docs/security/capabilities.mdx).
|
||||||
|
- [E1] [Electron platform support](https://github.com/electron/electron/blob/main/README.md).
|
||||||
|
- [E2] [Electron version support policy and cadence](https://github.com/electron/electron/blob/main/docs/tutorial/electron-timelines.md).
|
||||||
|
- [E3] [Electron breaking changes, v38 Wayland default](https://github.com/electron/electron/blob/main/docs/breaking-changes.md).
|
||||||
|
- [E4] [Electron security guidance](https://github.com/electron/electron/blob/main/docs/tutorial/security.md).
|
||||||
|
- [V1] [Void WebKitGTK package source at inspected revision](https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/libwebkit2gtk41/template).
|
||||||
|
- [V2] [Void Electron package source at inspected revision](https://github.com/void-linux/void-packages/blob/954278b83979958bcfdff05f22cf699c9dc20346/srcpkgs/electron35/template).
|
||||||
|
- [Q1] [Qt Quick Controls available styles](https://doc.qt.io/qt-6/qtquickcontrols-styles.html).
|
||||||
|
- [Q2] [Qt Quick accessibility](https://doc.qt.io/qt-6/accessible-qtquick.html).
|
||||||
Reference in New Issue
Block a user