LearnNewsExamplesServices
Frontmatter
id15202
titleUse component class APIs across application state transitions
stateOpen
labels
enhancementjavascriptairefactoring
assignees[]
createdAtJul 15, 2026, 9:14 PM
updatedAt6:01 AM
githubUrlhttps://github.com/neomjs/neo/issues/15202
authorneo-gpt-emmy
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]

Use component class APIs across application state transitions

Open Backlog/active-chunk-6 enhancementjavascriptairefactoring
neo-gpt-emmy
neo-gpt-emmy commented on Jul 15, 2026, 9:14 PM

Context

A repository-wide audit after the closed class-ownership refactor found six non-AgentOS application files that manually read an aggregate component cls array, mutate it, and assign the whole value back. These sites do not need a new class architecture: each already knows the exact old/new or Boolean class intent and can use Neo.component.Base's existing public mutation methods.

The canonical methods are addCls(), removeCls(), and toggleCls(). Moving application consumers onto that boundary removes their dependency on today's array representation without deciding the planned future object representation.

Live latest-open sweep: checked the latest 20 open issues and the latest 30 A2A messages at 2026-07-15T19:13:56Z; no equivalent ticket or in-flight claim surfaced. Targeted issue, Discussion, Knowledge Base, Memory Core, and local-content sweeps also found no owner for this cleanup.

The Problem

The following six files manually duplicate component class mutation:

  • apps/covid/view/MainContainerController.mjs:403-412 clones the main view's classes, scans out a theme class, adds the next theme, and reassigns the aggregate.
  • apps/sharedcovid/view/MainContainerController.mjs:597-609 repeats the same pattern across connected main views.
  • apps/devindex/view/Viewport.mjs:92-102 removes the previous size class, adds the next, and reassigns me.cls.
  • apps/portal/view/Viewport.mjs:95-103 performs the equivalent Portal size transition.
  • apps/portal/view/ViewportController.mjs:391-407 toggles two header state classes through a local aggregate and reassigns it.
  • apps/shareddialog/view/MainContainerController.mjs:616-621 replaces the previous theme class with the current theme through a local aggregate and reassigns it.

The semantic owner is known at every site. Reading the complete aggregate couples these applications to framework-owned, layout-owned, and other caller-authored classes that are unrelated to the transition being expressed.

The Architectural Reality

cls is a reactive component config; Neo.component.Base owns its update path. The getter returns a copied array, and the public class methods deliberately perform add/remove/toggle operations before re-entering the config setter.

This ticket is limited to component instances. StylingAndTheming.md explicitly preserves direct class-array writes for descendant raw-VDOM nodes. RealWorld descendant-node updates and Dock Demo progress pips are therefore legitimate and excluded.

Workstation is also excluded. Its two writes use setSilent() during dock projection staging and have a batching contract that today's public class methods do not express. That seam is an explicit consumer requirement in D#15200, not a mechanical cleanup.

The Fix

Use the current public component class methods only in the six listed files:

  • theme transitions remove only the known prior/theme vocabulary and add the selected theme without cloning the aggregate;
  • DevIndex and Portal viewport transitions remove the previous size class and add the next;
  • Portal header state uses enforced toggleCls() calls for hide-sidebar and separate-bar;
  • SharedDialog removes previousTheme and adds currentTheme through the component API;
  • remove NeoArray imports that become unused.

Preserve all existing text, icon, map-style, visibility, connected-window, and state-provider behavior. Do not broaden the patch to other cls assignments that replace a complete authored input without reading the current aggregate.

Because remove-then-add can enter the reactive setter more than once, focused evidence must prove that no observable intermediate class state, extra motion, or render regression is introduced. If the existing API cannot satisfy that, stop and route the missing atomic/batched primitive back to D#15200.

Decision Record impact

None. This is an application-only consumer cleanup using an existing public API. It does not define or amend the class-config architecture.

Acceptance Criteria

  • The six listed files no longer read a component's aggregate cls value for mutation and no longer assign the transformed aggregate back.
  • Each transition uses only existing addCls(), removeCls(), and/or enforced toggleCls() behavior; no core API or config-shape changes.
  • COVID and SharedCovid theme transitions leave exactly the selected application theme class while preserving unrelated component classes.
  • DevIndex and Portal viewport size transitions remove only the prior size class, add the next size class, and preserve unrelated classes.
  • Portal header transitions independently enforce hide-sidebar and separate-bar for all current activeIndex/size branches.
  • SharedDialog removes only previousTheme, adds currentTheme, and preserves every unrelated dialog class.
  • Repeated transitions remain duplicate-free and idempotent.
  • Focused evidence proves no observable intermediate class state, extra motion, or update regression compared with the current single aggregate assignment.
  • A scoped source check finds no component aggregate read-transform-reassign pattern in the six target files.
  • Workstation and descendant raw-VDOM class writes remain unchanged.

Out of Scope

  • AgentOS Fleet primitives.
  • apps/workstation/view/Workspace.mjs silent projection staging.
  • The future object-shaped cls / wrapperCls contract.
  • Neo.component.Base, VDOM, serialization, Neural Link, layout, plugin, or drag changes.
  • Static class configs, full authored class replacements, and descendant VDOM class arrays.
  • Theme, layout, or visual redesign.

Avoided Traps

  • No owner/contribution architecture hidden in an application cleanup.
  • No aggregate spread/filter/reassign replacement under a different helper name.
  • No wildcard removal of unrelated classes; mutate only the known transition vocabulary.
  • No direct component-root vdom.cls writes.
  • No migration of raw descendant VDOM classes, which are already the documented idiom.
  • No bundling of Workstation's unresolved silent-batching seam into mechanical work.

Related

Origin Session ID: e0413ff9-4738-42b2-9f76-c50690e9edea

Retrieval Hint: "application component cls aggregate rewrite covid sharedcovid devindex portal shareddialog addCls removeCls toggleCls"