---
name: mobile-screen-view-mode-toggle
description: Add a persisted segmented-pill view-mode toggle (e.g. MASTER/FLEET, Board/List) to an existing InfiniBot mobile screen without disturbing its current layout
---
# Mobile Screen View-Mode Toggle

## When to use
- User asks to add a view mode, subview, or toggle (e.g. "Master/Fleet", "Board/List", "Mine/Team") to an existing screen in `mobile/src/screens/*.js`.
- The new mode should reuse data already loaded by the screen's existing hooks rather than fetch from a new endpoint.
- The existing mode must remain visually and behaviorally unchanged — the toggle is additive.

## How to apply
1. **Find the styling reference.** Read `mobile/src/screens/DisciplineScreen.js` for its subview pill toggle. Mirror the same structure: a row of pressables using `COLORS.primary + '18'` for the active background and `COLORS.primary + '60'` for the active border. Reuse the same typography and padding so the new toggle looks native to the app.
2. **Place the toggle just below the screen title**, above all existing content. Render a count pip on a chip when the count is meaningful (e.g. fleet size).
3. **Persist the selected mode** to `AsyncStorage` under a namespaced key matching existing conventions: `@moltbot/<screen>_view_mode`. Restore on mount inside a `useEffect` before first render of mode-dependent content; default to the legacy mode so first-run users see the unchanged screen.
4. **Wrap each mode's render block in a conditional** (`mode === 'master' ? <…/> : <…/>`). Do NOT restructure the legacy block — keep its JSX and styles byte-identical so a section-by-section diff confirms zero regression.
5. **For aggregate/fleet views**, factor the aggregation into a pure top-level function (e.g. `computeFleetSummary(nodes)`) and wrap the call in `useMemo` keyed on the source array. Use only fields already present on the hook's row type; do not introduce new hooks or API calls.
6. **For expandable cards in the new mode**, hold the expanded id in local `useState` and render the detail block inline beneath the card when its id matches. Don't open a modal — match the existing screen's interaction style.
7. **Verify without a bundler**: parse the file with `@babel/core` + `babel-preset-expo` via a one-off node script and confirm zero bracket/brace/paren delta against the original. State explicitly that UI was not run if no Expo/Metro server is available — never claim visual success without it.

## Rules
- Never restructure or restyle the existing mode's JSX while adding the toggle — additive changes only, so a reviewer can scan for net-new blocks.
- Never introduce a new API call or hook when the existing hook already returns the rows you need to aggregate; compute in-memory with `useMemo`.
- Never hardcode toggle colors; always use the `COLORS.primary + '18'`/`'60'` token pattern from `DisciplineScreen` so the look stays consistent across screens.
- Always persist the mode to `AsyncStorage` under `@moltbot/<screen>_view_mode` and restore on mount, defaulting to the legacy mode.
- Always parse-check the file via babel after editing a large mobile screen, and report that UI was not run when no bundler is available — do not claim a screen "works" from a parse pass alone.