Skip to content

Commit 15615f8

Browse files
committed
Merge branch 'mobile-supervisor-sheet-flat' into develop
2 parents 2f5902b + b4b6fe6 commit 15615f8

6 files changed

Lines changed: 554 additions & 89 deletions

File tree

Lines changed: 334 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,334 @@
1+
# Mobile Supervisor Sheet Flat Redesign Implementation Plan
2+
3+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4+
5+
**Goal:** Redesign the mobile Supervisor fullscreen sheet into a flatter, denser settings-panel surface without changing Supervisor behavior.
6+
7+
**Architecture:** Keep the existing `Sheet` flow and shared `ObjectiveDialogContent` logic intact, then tighten the mobile experience in three layers: remove redundant detail chrome in the React structure, flatten the mobile-only container styling, and lock the result with mobile regression and style-contract tests.
8+
9+
**Tech Stack:** React, TypeScript, shared `Sheet` and form primitives, Vitest, Testing Library, CSS design tokens
10+
11+
---
12+
13+
## File Structure
14+
15+
- Modify: `packages/web/src/features/supervisor/views/mobile/mobile-supervisor-sheet.tsx`
16+
- Keep the current root/detail workflow.
17+
- Remove the redundant detail header card from the mobile body.
18+
- Continue wiring the same draft state and submit callbacks.
19+
20+
- Modify: `packages/web/src/features/supervisor/views/mobile/mobile-supervisor-sheet.test.tsx`
21+
- Add assertions that the mobile detail view no longer renders duplicate body chrome.
22+
- Keep existing enable/edit/disable behavior coverage intact.
23+
24+
- Modify: `packages/web/src/styles/components.css`
25+
- Flatten `.mobile-supervisor-sheet__root`, `.mobile-supervisor-sheet__detail`, and `.mobile-supervisor-sheet__footer`.
26+
- Remove the dedicated `.mobile-supervisor-sheet__detail-header` treatment.
27+
28+
- Modify: `packages/web/src/styles/components.theme.test.ts`
29+
- Update the mobile Supervisor style contract from thick inner-card chrome to flat fullscreen settings chrome.
30+
31+
## Task 1: Remove duplicate mobile detail header chrome
32+
33+
**Files:**
34+
- Modify: `packages/web/src/features/supervisor/views/mobile/mobile-supervisor-sheet.tsx`
35+
- Test: `packages/web/src/features/supervisor/views/mobile/mobile-supervisor-sheet.test.tsx`
36+
37+
- [ ] **Step 1: Write the failing mobile structure tests**
38+
39+
Add coverage that the fullscreen mobile detail flow relies on the shared `Sheet` header only.
40+
41+
```tsx
42+
it("does not render a duplicate detail header card inside the mobile enable form", () => {
43+
const store = createStore();
44+
window.localStorage.setItem("ui.locale", JSON.stringify("en"));
45+
store.set(localeAtom, "en");
46+
store.set(wsClientAtom, { sendCommand: vi.fn() } as never);
47+
store.set(supervisorsAtom, new Map());
48+
49+
render(
50+
<Provider store={store}>
51+
<MobileSupervisorSheet sessionId="sess-1" workspaceId="ws-1" onClose={vi.fn()} />
52+
</Provider>
53+
);
54+
55+
expect(document.querySelector(".mobile-supervisor-sheet__detail-header")).toBeNull();
56+
expect(screen.getByRole("heading", { name: "Enable Supervisor", level: 2 })).toBeInTheDocument();
57+
});
58+
59+
it("does not render a duplicate detail header card after opening edit mode", () => {
60+
const store = createStore();
61+
window.localStorage.setItem("ui.locale", JSON.stringify("en"));
62+
store.set(localeAtom, "en");
63+
store.set(wsClientAtom, { sendCommand: vi.fn() } as never);
64+
store.set(supervisorsAtom, new Map([["sess-1", createSupervisor()]]));
65+
66+
render(
67+
<Provider store={store}>
68+
<MobileSupervisorSheet sessionId="sess-1" workspaceId="ws-1" onClose={vi.fn()} />
69+
</Provider>
70+
);
71+
72+
fireEvent.click(screen.getByRole("button", { name: "Edit Supervisor" }));
73+
74+
expect(document.querySelector(".mobile-supervisor-sheet__detail-header")).toBeNull();
75+
expect(screen.getByRole("heading", { name: "Edit Supervisor", level: 2 })).toBeInTheDocument();
76+
});
77+
```
78+
79+
- [ ] **Step 2: Run the mobile sheet test to verify it fails**
80+
81+
Run:
82+
83+
```bash
84+
pnpm --filter @coder-studio/web exec vitest run src/features/supervisor/views/mobile/mobile-supervisor-sheet.test.tsx
85+
```
86+
87+
Expected:
88+
89+
- FAIL because `.mobile-supervisor-sheet__detail-header` still exists in mobile detail views
90+
91+
- [ ] **Step 3: Remove the duplicate body header from the mobile detail structure**
92+
93+
In `mobile-supervisor-sheet.tsx`, delete the dedicated detail header block and let the `Sheet` header carry the title.
94+
95+
```tsx
96+
const detailBody = (
97+
<div className="mobile-supervisor-sheet__detail">
98+
<ObjectiveDialogContent
99+
mode={mode}
100+
draftObjective={dialog.draftObjective}
101+
draftEvaluatorProviderId={dialog.draftEvaluatorProviderId}
102+
draftEvaluatorModel={dialog.draftEvaluatorModel}
103+
draftMaxSupervisionCount={dialog.draftMaxSupervisionCount}
104+
draftScheduledAt={dialog.draftScheduledAt}
105+
isMaxSupervisionCountValid={isMaxSupervisionCountValid}
106+
disableObjective={disableObjective}
107+
onDraftObjectiveChange={(draftObjective) => updateDraft({ draftObjective })}
108+
onDraftEvaluatorProviderChange={(draftEvaluatorProviderId) =>
109+
updateDraft({ draftEvaluatorProviderId })
110+
}
111+
onDraftEvaluatorModelChange={(draftEvaluatorModel) => updateDraft({ draftEvaluatorModel })}
112+
onDraftMaxSupervisionCountChange={(draftMaxSupervisionCount) =>
113+
updateDraft({ draftMaxSupervisionCount })
114+
}
115+
onDraftScheduledAtChange={(draftScheduledAt) => updateDraft({ draftScheduledAt })}
116+
/>
117+
</div>
118+
);
119+
```
120+
121+
Remove now-unused imports related to the deleted header chrome.
122+
123+
- [ ] **Step 4: Run the mobile sheet test to verify it passes**
124+
125+
Run:
126+
127+
```bash
128+
pnpm --filter @coder-studio/web exec vitest run src/features/supervisor/views/mobile/mobile-supervisor-sheet.test.tsx
129+
```
130+
131+
Expected:
132+
133+
- PASS for the duplicate-header assertions
134+
- PASS for unchanged enable/edit/picker behavior
135+
136+
- [ ] **Step 5: Commit**
137+
138+
```bash
139+
git add \
140+
packages/web/src/features/supervisor/views/mobile/mobile-supervisor-sheet.tsx \
141+
packages/web/src/features/supervisor/views/mobile/mobile-supervisor-sheet.test.tsx
142+
git commit -m "Flatten mobile supervisor detail structure"
143+
```
144+
145+
## Task 2: Flatten the mobile Supervisor sheet surface and footer chrome
146+
147+
**Files:**
148+
- Modify: `packages/web/src/styles/components.css`
149+
- Test: `packages/web/src/styles/components.theme.test.ts`
150+
151+
- [ ] **Step 1: Write the failing mobile style contract assertions**
152+
153+
Replace the current “inner card” assumptions with flat mobile sheet expectations.
154+
155+
```ts
156+
it("keeps mobile supervisor sheets on a flat fullscreen settings-panel contract", () => {
157+
const supervisorRoot = getLastRuleBlock(".mobile-supervisor-sheet__root").replace(/\s+/g, " ");
158+
const supervisorDetail = getLastRuleBlock(".mobile-supervisor-sheet__detail").replace(/\s+/g, " ");
159+
const supervisorFooter = getLastRuleBlock(".mobile-supervisor-sheet__footer").replace(/\s+/g, " ");
160+
const fullscreenFooter = getLastRuleBlock(
161+
".mobile-supervisor-sheet.mobile-sheet--fullscreen .mobile-sheet__footer"
162+
).replace(/\s+/g, " ");
163+
164+
expect(hasRuleBlock(".mobile-supervisor-sheet__detail-header")).toBe(false);
165+
expect(supervisorRoot).toContain("padding: var(--sp-3)");
166+
expect(supervisorRoot).not.toContain("border: 1px solid");
167+
expect(supervisorRoot).not.toContain("box-shadow:");
168+
expect(supervisorDetail).toContain("padding: var(--sp-3)");
169+
expect(supervisorDetail).not.toContain("border: 1px solid");
170+
expect(supervisorDetail).not.toContain("box-shadow:");
171+
expect(supervisorFooter).toContain("padding: var(--sp-1) var(--sp-2)");
172+
expect(supervisorFooter).not.toContain("border-radius: var(--radius-xl)");
173+
expect(fullscreenFooter).toContain(
174+
"padding: var(--sp-1) var(--sp-3) calc(var(--mobile-safe-bottom) + var(--sp-3))"
175+
);
176+
});
177+
```
178+
179+
- [ ] **Step 2: Run the style contract test to verify it fails**
180+
181+
Run:
182+
183+
```bash
184+
pnpm --filter @coder-studio/web exec vitest run src/styles/components.theme.test.ts
185+
```
186+
187+
Expected:
188+
189+
- FAIL because the mobile Supervisor stylesheet still defines `__detail-header`
190+
- FAIL because root/detail still have border, radius, and shadow-heavy inner-card styling
191+
192+
- [ ] **Step 3: Implement the flat mobile sheet styling**
193+
194+
In `components.css`, replace the current mobile Supervisor card-shell treatment with flatter mobile fullscreen spacing.
195+
196+
```css
197+
.mobile-sheet__body--supervisor-detail {
198+
display: flex;
199+
flex-direction: column;
200+
gap: var(--sp-3);
201+
}
202+
203+
.mobile-supervisor-sheet {
204+
gap: 0;
205+
padding: 0;
206+
background: color-mix(in srgb, var(--bg-page) 98%, var(--bg-surface) 2%);
207+
}
208+
209+
.mobile-supervisor-sheet__root,
210+
.mobile-supervisor-sheet__detail {
211+
display: flex;
212+
flex: 1;
213+
min-height: 0;
214+
flex-direction: column;
215+
gap: var(--sp-3);
216+
padding: var(--sp-3);
217+
padding-bottom: var(--sp-4);
218+
background: transparent;
219+
overflow: auto;
220+
}
221+
222+
.mobile-supervisor-sheet__footer {
223+
width: 100%;
224+
padding: var(--sp-1) var(--sp-2);
225+
border: none;
226+
border-radius: 0;
227+
background: transparent;
228+
box-shadow: none;
229+
}
230+
231+
.mobile-supervisor-sheet.mobile-sheet--fullscreen .mobile-sheet__footer {
232+
padding: var(--sp-1) var(--sp-3) calc(var(--mobile-safe-bottom) + var(--sp-3));
233+
background: color-mix(in srgb, var(--bg-page) 94%, var(--bg-surface) 6%);
234+
}
235+
```
236+
237+
Delete the obsolete `.mobile-supervisor-sheet__detail-header*` rules.
238+
239+
- [ ] **Step 4: Run the style contract test to verify it passes**
240+
241+
Run:
242+
243+
```bash
244+
pnpm --filter @coder-studio/web exec vitest run src/styles/components.theme.test.ts
245+
```
246+
247+
Expected:
248+
249+
- PASS for the new flat mobile Supervisor contract
250+
- PASS for unchanged mobile fullscreen header/footer token expectations elsewhere
251+
252+
- [ ] **Step 5: Commit**
253+
254+
```bash
255+
git add \
256+
packages/web/src/styles/components.css \
257+
packages/web/src/styles/components.theme.test.ts
258+
git commit -m "Restyle mobile supervisor sheet as flat settings panel"
259+
```
260+
261+
## Task 3: Verify the mobile redesign slice end-to-end
262+
263+
**Files:**
264+
- No code changes expected
265+
- Verify: `packages/web/src/features/supervisor/views/mobile/mobile-supervisor-sheet.test.tsx`
266+
- Verify: `packages/web/src/features/supervisor/views/shared/objective-dialog-content.test.tsx`
267+
- Verify: `packages/web/src/styles/components.theme.test.ts`
268+
269+
- [ ] **Step 1: Run the focused mobile Supervisor regression suite**
270+
271+
Run:
272+
273+
```bash
274+
pnpm --filter @coder-studio/web exec vitest run \
275+
src/features/supervisor/views/mobile/mobile-supervisor-sheet.test.tsx \
276+
src/features/supervisor/views/shared/objective-dialog-content.test.tsx \
277+
src/styles/components.theme.test.ts
278+
```
279+
280+
Expected:
281+
282+
- PASS for mobile flow behavior, shared compact control behavior, and updated style contracts
283+
284+
- [ ] **Step 2: Run the targeted UI preview metadata tests**
285+
286+
Run:
287+
288+
```bash
289+
pnpm --filter @coder-studio/web exec vitest run \
290+
src/ui-preview/catalog.test.tsx \
291+
src/ui-preview/scene-metadata.test.ts
292+
```
293+
294+
Expected:
295+
296+
- PASS if no shared preview inventory assumptions were broken by the Supervisor sheet changes
297+
298+
- [ ] **Step 3: Inspect the git diff for scope control**
299+
300+
Run:
301+
302+
```bash
303+
git diff -- \
304+
docs/superpowers/specs/2026-05-19-mobile-supervisor-sheet-flat-redesign-design.md \
305+
docs/superpowers/plans/2026-05-19-mobile-supervisor-sheet-flat-redesign.md \
306+
packages/web/src/features/supervisor/views/mobile/mobile-supervisor-sheet.tsx \
307+
packages/web/src/features/supervisor/views/mobile/mobile-supervisor-sheet.test.tsx \
308+
packages/web/src/styles/components.css \
309+
packages/web/src/styles/components.theme.test.ts
310+
```
311+
312+
Expected:
313+
314+
- Only the intended mobile Supervisor files, plan/spec docs, and related tests are changed
315+
- No unrelated workspace edits are reverted
316+
317+
## Self-Review
318+
319+
Spec coverage check:
320+
321+
- Mobile-only scope correction: covered by Task 1 and Task 2 file scope.
322+
- Remove duplicate mobile detail header: covered in Task 1.
323+
- Flatten root/detail container chrome and footer: covered in Task 2.
324+
- Preserve shared compact form behavior: verified in Task 3 with shared form tests.
325+
326+
Placeholder scan:
327+
328+
- No `TODO`, `TBD`, or deferred implementation notes remain.
329+
- Every code-changing task includes exact files, commands, and representative code.
330+
331+
Type consistency:
332+
333+
- `MobileSupervisorSheet`, `ObjectiveDialogContent`, `Sheet`, and the existing draft callbacks keep their current names.
334+
- No new public component APIs are introduced.

0 commit comments

Comments
 (0)