All Docs
FeaturesSaaS FactoryUpdated February 21, 2026

Beast Mode Agent Cards: Fixing a Hidden Accessibility Anti-Pattern

Beast Mode Agent Cards: Fixing a Hidden Accessibility Anti-Pattern

Version: 1.0.97 Area: Beast Mode — Agent Selection UI


Background

Beast Mode lets you orchestrate multiple AI agents in parallel supercycles to accelerate feature delivery. In the idle view — where you choose which agents to activate — each agent is presented as a selectable card. Clicking a card toggles the agent in or out of the active set.

The Problem

Prior to v1.0.97, each agent card was implemented as a <button> element. That is a reasonable starting point for keyboard navigation and click handling. However, inside each <button> was a <Switch> component — itself an interactive control — used to visually indicate whether the agent was selected.

This created three compounding problems:

1. ARIA Specification Violation

The ARIA specification explicitly prohibits interactive elements from being descendants of other interactive elements. A <Switch> inside a <button> is a direct violation. The practical consequence is that assistive technologies — screen readers in particular — cannot reliably determine the role, state, or purpose of the control. Different AT implementations handle this inconsistently; some ignore the inner element, some announce both, some expose incorrect state.

2. Conflicting Event Handlers

Because both the outer <button> and the inner <Switch> responded to click events, the <Switch> had to call e.stopPropagation() to prevent a single user interaction from toggling the agent twice. This is a common patch for a structural problem — it works in the happy path but is fragile and obscures the intent of the component.

3. Mobile Interaction Ambiguity

On touch devices, the hit targets of the card and the toggle overlapped. Depending on exactly where a user tapped, behavior could be inconsistent — particularly on smaller screens where the toggle occupied a meaningful fraction of the card area.

The Fix

The structural fix is straightforward:

  • Replace the outer <button> with a <div> that carries the onClick handler. A <div> is not a native interactive element, so it does not create the nesting conflict.
  • Remove the functional <Switch> from inside the card entirely.
  • Render a decorative toggle indicator — a non-interactive element styled with CSS — in place of the <Switch>. It looks identical to the previous toggle but carries no interactivity of its own.
  • Rely on the existing selection styles (border-primary/30 bg-primary/5) as the primary selection affordance. These classes were already applied correctly; they are now the single source of truth for communicating selected state.

Before (problematic pattern)

// ❌ Interactive element nested inside another interactive element
<button onClick={() => toggleAgent(agent.id)}>
  <AgentCardContent agent={agent} />
  <Switch
    checked={isSelected}
    onClick={(e) => {
      e.stopPropagation(); // patching a structural problem
      toggleAgent(agent.id);
    }}
  />
</button>

After (correct pattern)

// ✅ Single interaction target; decorative indicator only
<div
  role="checkbox"
  aria-checked={isSelected}
  onClick={() => toggleAgent(agent.id)}
  className={isSelected ? 'border-primary/30 bg-primary/5' : ''}
>
  <AgentCardContent agent={agent} />
  <ToggleIndicator active={isSelected} aria-hidden="true" />
</div>

What Stays the Same

  • Visual design: The cards look identical. Selected agents are still highlighted with the same border and background treatment.
  • Keyboard behavior: Cards remain navigable and activatable via keyboard.
  • Agent selection logic: The underlying toggle logic is unchanged — clicking a card still adds or removes the agent from the active Beast Mode set.

Summary

This fix resolves a genuine ARIA spec violation in the Beast Mode agent selection UI, removes a fragile stopPropagation workaround, and eliminates mobile tap ambiguity — all without any visible change to the user experience.