From b3418e3c96e391394eab7c593c759b33c0e49a2e Mon Sep 17 00:00:00 2001 From: Ender Date: Fri, 24 Oct 2025 20:51:11 +0200 Subject: [PATCH] feat: add collapsible sections to StepGenerate component with reusable CollapsibleSection --- .../components/steps/CollapsibleSection.tsx | 44 +++++++++++++++++++ .../src/components/steps/SelectedImages.tsx | 23 +++++----- .../src/components/steps/StepGenerate.tsx | 19 ++++---- 3 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 apps/admin/src/components/steps/CollapsibleSection.tsx diff --git a/apps/admin/src/components/steps/CollapsibleSection.tsx b/apps/admin/src/components/steps/CollapsibleSection.tsx new file mode 100644 index 0000000..049fe87 --- /dev/null +++ b/apps/admin/src/components/steps/CollapsibleSection.tsx @@ -0,0 +1,44 @@ +import { Box, Collapse, IconButton, Stack, Typography, type SxProps, type Theme } from '@mui/material'; +import ExpandMore from '@mui/icons-material/ExpandMore'; +import { useState, type PropsWithChildren } from 'react'; + +export default function CollapsibleSection({ title, defaultCollapsed = true, right, sx, children }: PropsWithChildren<{ + title: string; + defaultCollapsed?: boolean; + right?: React.ReactNode; + sx?: SxProps; +}>) { + const [open, setOpen] = useState(!defaultCollapsed); + + return ( + + setOpen(v => !v)} + > + + { + e.stopPropagation(); + setOpen(v => !v); + }} + sx={{ transform: open ? 'rotate(180deg)' : 'rotate(0deg)', transition: 'transform 150ms ease' }} + > + + + {title} + + {right} + + + + {children} + + + + ); +} diff --git a/apps/admin/src/components/steps/SelectedImages.tsx b/apps/admin/src/components/steps/SelectedImages.tsx index 08a9cd2..8c80cc9 100644 --- a/apps/admin/src/components/steps/SelectedImages.tsx +++ b/apps/admin/src/components/steps/SelectedImages.tsx @@ -8,19 +8,16 @@ export default function SelectedImages({ onRemove: (key: string) => void; }) { return ( - - Selected Images - - {imageKeys.map((k) => ( - - {k.split('/').slice(-1)[0]} - - - ))} - {imageKeys.length === 0 && ( - (No images selected) - )} - + + {imageKeys.map((k) => ( + + {k.split('/').slice(-1)[0]} + + + ))} + {imageKeys.length === 0 && ( + (No images selected) + )} ); } diff --git a/apps/admin/src/components/steps/StepGenerate.tsx b/apps/admin/src/components/steps/StepGenerate.tsx index 7cf048f..d257cf7 100644 --- a/apps/admin/src/components/steps/StepGenerate.tsx +++ b/apps/admin/src/components/steps/StepGenerate.tsx @@ -1,6 +1,7 @@ import { Box, Stack, TextField, Typography } from '@mui/material'; import MediaLibrary from '../MediaLibrary'; import SelectedImages from './SelectedImages'; +import CollapsibleSection from './CollapsibleSection'; import type { Clip } from './StepAssets'; export default function StepGenerate({ @@ -24,8 +25,7 @@ export default function StepGenerate({ {/* Audio transcriptions in order */} - - Audio Transcriptions + {[...postClips] .sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()) @@ -39,17 +39,20 @@ export default function StepGenerate({ (No audio clips) )} - + {/* Selected images */} - + + + {/* Media library */} - + + + {/* Prompt */} - - AI Prompt + - + ); }