Skip to content

Commit a233603

Browse files
committed
feat(storyboard): improve board settings toggle
1 parent 38a5352 commit a233603

2 files changed

Lines changed: 70 additions & 6 deletions

File tree

web/src/components/storyboard/StoryboardBoard.tsx

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
Box,
3838
Card,
3939
Caption,
40+
CloseButton,
4041
Collapse,
4142
Dialog,
4243
Divider,
@@ -50,6 +51,7 @@ import {
5051
LoadingSpinner,
5152
Panel,
5253
ScrollArea,
54+
SectionHeader,
5355
SelectField,
5456
Skeleton,
5557
Text,
@@ -347,6 +349,8 @@ const StoryboardBoardInner: React.FC<StoryboardBoardProps> = ({
347349
() => setSettingsOpen((open) => !open),
348350
[]
349351
);
352+
const closeSettings = useCallback(() => setSettingsOpen(false), []);
353+
const settingsPanelId = `storyboard-board-settings-${boardId}`;
350354

351355
// The inspector docks under the grid, so on a board of more than a row or
352356
// two it opens below the fold. A selection the user makes here scrolls it
@@ -553,10 +557,19 @@ const StoryboardBoardInner: React.FC<StoryboardBoardProps> = ({
553557
: null;
554558
const stillStepActive = nextRenderStep === "stills";
555559
const clipStepActive = nextRenderStep === "clips";
556-
const missingNextModel =
557-
(stillStepActive && !imageModel?.id) ||
558-
(clipStepActive && !videoModel?.id);
559-
const settingsVisible = settingsOpen || missingNextModel;
560+
const missingModelStep = stillStepActive
561+
? imageModel?.id
562+
? null
563+
: "stills"
564+
: clipStepActive && !videoModel?.id
565+
? "clips"
566+
: null;
567+
useEffect(() => {
568+
if (missingModelStep) {
569+
setSettingsOpen(true);
570+
}
571+
}, [missingModelStep]);
572+
const settingsVisible = settingsOpen;
560573

561574
// The toolbar's one-line summary: how big the board is, how it looks, and
562575
// who is in it — the fields the folded form would otherwise hide.
@@ -682,10 +695,11 @@ const StoryboardBoardInner: React.FC<StoryboardBoardProps> = ({
682695
Change Style
683696
</EditorButton>
684697
<EditorButton
685-
variant="outlined"
698+
variant={settingsVisible ? "contained" : "outlined"}
686699
startIcon={<TuneIcon fontSize="small" />}
687700
onClick={toggleSettings}
688701
aria-expanded={settingsVisible}
702+
aria-controls={settingsPanelId}
689703
>
690704
Board settings
691705
</EditorButton>
@@ -723,8 +737,22 @@ const StoryboardBoardInner: React.FC<StoryboardBoardProps> = ({
723737

724738
{!readOnly && (
725739
<Collapse in={settingsVisible} timeout="auto" unmountOnExit>
726-
<Panel padding={SPACING.xl} sx={{ maxWidth: "1100px" }}>
740+
<Panel
741+
id={settingsPanelId}
742+
padding={SPACING.xl}
743+
sx={{ maxWidth: "1100px" }}
744+
>
727745
<FlexColumn gap={SPACING.xl}>
746+
<SectionHeader
747+
title="Board settings"
748+
size="small"
749+
action={
750+
<CloseButton
751+
tooltip="Close board settings"
752+
onClick={closeSettings}
753+
/>
754+
}
755+
/>
728756
<FormGrid stackBelow={FORM_STACK_BELOW}>
729757
<FormSection label="Screenplay">
730758
<FormField label="Title">

web/src/components/storyboard/__tests__/StoryboardBoard.test.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,42 @@ describe("StoryboardBoard toolbar", () => {
445445
expect(screen.getByText("0 shots")).toBeInTheDocument();
446446
});
447447

448+
it("closes board settings from the settings panel", async () => {
449+
mockShots = [makeShot("s1")];
450+
const user = userEvent.setup();
451+
renderBoard(jest.fn());
452+
453+
await user.click(screen.getByRole("button", { name: /Board settings/ }));
454+
await user.click(
455+
screen.getByRole("button", { name: "Close board settings" })
456+
);
457+
458+
expect(
459+
screen.queryByRole("combobox", { name: "Still model" })
460+
).not.toBeInTheDocument();
461+
expect(
462+
screen.getByRole("button", { name: "Board settings" })
463+
).toHaveAttribute("aria-expanded", "false");
464+
});
465+
466+
it("lets the user close settings after a missing model reveals them", async () => {
467+
boardModels = { imageModel: null, videoModel: null };
468+
mockShots = [makeShot("s1")];
469+
const user = userEvent.setup();
470+
renderBoard(jest.fn());
471+
472+
expect(screen.getByRole("alert")).toHaveTextContent(
473+
"Choose a still model before rendering stills."
474+
);
475+
await user.click(
476+
screen.getByRole("button", { name: "Close board settings" })
477+
);
478+
479+
expect(
480+
screen.queryByRole("combobox", { name: "Still model" })
481+
).not.toBeInTheDocument();
482+
});
483+
448484
it("renders the render actions on the toolbar", () => {
449485
mockShots = [makeShot("s1")];
450486
renderBoard(jest.fn());

0 commit comments

Comments
 (0)