Skip to content

Commit a0e75ec

Browse files
committed
Refine supervisor dialog structure and compact controls
1 parent 5f371de commit a0e75ec

3 files changed

Lines changed: 114 additions & 7 deletions

File tree

packages/web/src/features/supervisor/components/objective-dialog.test.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,28 @@ describe("ObjectiveDialog", () => {
179179
expect(screen.getByRole("textbox", { name: "Objective" })).toHaveClass("input", "textarea");
180180
});
181181

182+
it("renders the intro strip in the desktop wrapper for enable mode", () => {
183+
const store = createStore();
184+
window.localStorage.setItem("ui.locale", JSON.stringify("en"));
185+
store.set(localeAtom, "en");
186+
store.set(wsClientAtom, { sendCommand: vi.fn() } as never);
187+
store.set(
188+
supervisorDialogAtom,
189+
createDialogState({
190+
draftObjective: "Ship phase 4B1",
191+
})
192+
);
193+
store.set(supervisorsAtom, new Map());
194+
195+
render(
196+
<Provider store={store}>
197+
<ObjectiveDialog workspaceId="ws-1" />
198+
</Provider>
199+
);
200+
201+
expect(document.querySelector(".supervisor-dialog-intro")).toBeTruthy();
202+
});
203+
182204
it("renders disable confirmation mode", () => {
183205
const store = createStore();
184206
window.localStorage.setItem("ui.locale", JSON.stringify("en"));
@@ -201,6 +223,7 @@ describe("ObjectiveDialog", () => {
201223
expect(screen.getByText("Disabling stops evaluation cycles")).toBeInTheDocument();
202224
expect(screen.getByText("Finish the server refactor")).toBeInTheDocument();
203225
expect(screen.getByRole("dialog")).toHaveClass("supervisor-dialog--disable");
226+
expect(document.querySelector(".supervisor-dialog-intro")).toBeNull();
204227
});
205228

206229
it("renders the dialog header through the canonical dialog header anatomy", () => {

packages/web/src/features/supervisor/views/shared/objective-dialog-content.test.tsx

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,35 @@ afterEach(() => {
2727
});
2828

2929
describe("ObjectiveDialogContent", () => {
30-
it("renders shared textarea and desktop select trigger primitives with helper text wiring", () => {
31-
render(
30+
it("renders a flat supervisor intro strip for enable and edit modes", () => {
31+
const { rerender } = render(
32+
<ObjectiveDialogContent
33+
mode="enable"
34+
draftObjective="Investigate regressions"
35+
draftEvaluatorProviderId="claude"
36+
draftEvaluatorModel=""
37+
draftMaxSupervisionCount="0"
38+
draftScheduledAt=""
39+
disableObjective=""
40+
onDraftObjectiveChange={vi.fn()}
41+
onDraftEvaluatorProviderChange={vi.fn()}
42+
onDraftEvaluatorModelChange={vi.fn()}
43+
onDraftMaxSupervisionCountChange={vi.fn()}
44+
onDraftScheduledAtChange={vi.fn()}
45+
/>
46+
);
47+
48+
let intro = document.querySelector(".supervisor-dialog-intro");
49+
expect(intro).toBeTruthy();
50+
expect(intro?.querySelector('[data-icon-semantic="supervisor.mode.enable"]')).toBeTruthy();
51+
expect(intro?.querySelector(".supervisor-dialog-intro__title")).toHaveTextContent(
52+
"supervisor.dialog.enable.title"
53+
);
54+
expect(intro?.querySelector(".supervisor-dialog-intro__description")).toHaveTextContent(
55+
"supervisor.dialog.enable.subtitle"
56+
);
57+
58+
rerender(
3259
<ObjectiveDialogContent
3360
mode="edit"
3461
draftObjective="Investigate regressions"
@@ -45,8 +72,38 @@ describe("ObjectiveDialogContent", () => {
4572
/>
4673
);
4774

75+
intro = document.querySelector(".supervisor-dialog-intro");
76+
expect(intro).toBeTruthy();
77+
expect(intro?.querySelector('[data-icon-semantic="supervisor.mode.edit"]')).toBeTruthy();
78+
expect(intro?.querySelector(".supervisor-dialog-intro__title")).toHaveTextContent(
79+
"supervisor.dialog.edit.title"
80+
);
81+
expect(intro?.querySelector(".supervisor-dialog-intro__description")).toHaveTextContent(
82+
"supervisor.dialog.edit.subtitle"
83+
);
84+
});
85+
86+
it("renders compact control classes instead of large form controls", () => {
87+
render(
88+
<ObjectiveDialogContent
89+
mode="edit"
90+
draftObjective="Investigate regressions"
91+
draftEvaluatorProviderId="claude"
92+
draftEvaluatorModel="sonnet"
93+
draftMaxSupervisionCount="3"
94+
draftScheduledAt=""
95+
disableObjective=""
96+
onDraftObjectiveChange={vi.fn()}
97+
onDraftEvaluatorProviderChange={vi.fn()}
98+
onDraftEvaluatorModelChange={vi.fn()}
99+
onDraftMaxSupervisionCountChange={vi.fn()}
100+
onDraftScheduledAtChange={vi.fn()}
101+
/>
102+
);
103+
48104
const textarea = screen.getByLabelText("supervisor.field.objective");
49-
expect(textarea).toHaveClass("input", "textarea", "textarea-lg");
105+
expect(textarea).toHaveClass("input", "textarea");
106+
expect(textarea).not.toHaveClass("textarea-lg");
50107
expect(textarea).toHaveAttribute("rows", "5");
51108
expect(textarea).toHaveValue("Investigate regressions");
52109
expect(textarea).toHaveAttribute("aria-describedby");
@@ -58,12 +115,25 @@ describe("ObjectiveDialogContent", () => {
58115
const trigger = screen.getByRole("button", {
59116
name: "supervisor.field.evaluator Claude",
60117
});
61-
expect(trigger).toHaveClass("input", "mobile-select-trigger");
118+
expect(trigger).toHaveClass("input", "mobile-select-trigger", "input-sm");
62119
expect(trigger).toHaveAttribute("aria-describedby");
63120
expect(screen.getByText("supervisor.field.evaluator_helper")).toHaveAttribute(
64121
"id",
65122
trigger.getAttribute("aria-describedby")
66123
);
124+
125+
expect(screen.getByLabelText("supervisor.field.evaluator_model")).toHaveClass(
126+
"input",
127+
"input-sm"
128+
);
129+
expect(screen.getByLabelText("supervisor.field.max_supervision_count")).toHaveClass(
130+
"input",
131+
"input-sm"
132+
);
133+
expect(screen.getByRole("button", { name: "supervisor.field.scheduled_at" })).toHaveClass(
134+
"input",
135+
"input-sm"
136+
);
67137
});
68138

69139
it("keeps objective editing behavior unchanged", () => {
@@ -222,6 +292,7 @@ describe("ObjectiveDialogContent", () => {
222292
/>
223293
);
224294

295+
expect(document.querySelector(".supervisor-dialog-intro")).toBeNull();
225296
expect(
226297
screen.getByRole("alert").querySelector('[data-icon-semantic="state.warning"]')
227298
).toBeTruthy();

packages/web/src/features/supervisor/views/shared/objective-dialog-content.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ export function ObjectiveDialogContent({
6464
const evaluatorModelHelperId = useId();
6565
const maxSupervisionCountHelperId = useId();
6666
const scheduledAtHelperId = useId();
67+
const introTitle = t(`supervisor.dialog.${mode}.title`);
68+
const introDescription = t(`supervisor.dialog.${mode}.subtitle`);
6769

6870
if (mode === "disable") {
6971
return (
@@ -90,11 +92,20 @@ export function ObjectiveDialogContent({
9092

9193
return (
9294
<>
95+
<div className="supervisor-dialog-intro">
96+
<div className="supervisor-dialog-intro__icon" aria-hidden="true">
97+
<ObjectiveDialogModeIcon mode={mode} />
98+
</div>
99+
<div className="supervisor-dialog-intro__copy">
100+
<p className="supervisor-dialog-intro__title">{introTitle}</p>
101+
<p className="supervisor-dialog-intro__description">{introDescription}</p>
102+
</div>
103+
</div>
104+
93105
<div className="form-group">
94106
<label htmlFor="objective">{t("supervisor.field.objective")}</label>
95107
<Textarea
96108
id="objective"
97-
size="lg"
98109
rows={5}
99110
value={draftObjective}
100111
onChange={(event) => onDraftObjectiveChange(event.target.value)}
@@ -113,6 +124,7 @@ export function ObjectiveDialogContent({
113124
</label>
114125
<Select
115126
id="evaluator-provider"
127+
size="sm"
116128
desktopMode="listbox"
117129
mobileSheetTitle={t("supervisor.field.evaluator")}
118130
mobileSheetPresentation="inline"
@@ -131,7 +143,7 @@ export function ObjectiveDialogContent({
131143
<label htmlFor="evaluator-model">{t("supervisor.field.evaluator_model")}</label>
132144
<Input
133145
id="evaluator-model"
134-
size="lg"
146+
size="sm"
135147
value={draftEvaluatorModel}
136148
onChange={(event) => onDraftEvaluatorModelChange(event.target.value)}
137149
aria-describedby={evaluatorModelHelperId}
@@ -146,7 +158,7 @@ export function ObjectiveDialogContent({
146158
<label htmlFor="max-supervision-count">{t("supervisor.field.max_supervision_count")}</label>
147159
<Input
148160
id="max-supervision-count"
149-
size="lg"
161+
size="sm"
150162
type="number"
151163
min={0}
152164
step={1}
@@ -165,6 +177,7 @@ export function ObjectiveDialogContent({
165177
<label htmlFor="scheduled-at">{t("supervisor.field.scheduled_at")}</label>
166178
<DateTimePicker
167179
label={t("supervisor.field.scheduled_at")}
180+
size="sm"
168181
value={draftScheduledAt}
169182
onValueChange={onDraftScheduledAtChange}
170183
placeholder={t("supervisor.field.scheduled_at_placeholder")}

0 commit comments

Comments
 (0)