Make image dimensions and font properties collapsible sections
- Add expandedSections state to track which sections are open - Image Dimensions section now collapses by default (click to expand) - Font Properties section now collapses by default (click to expand) - Shows count of items in each section - Dramatically reduces vertical scrolling on the right sidebar - More compact layout with accordion-style sections Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 4.5
parent
5efc1155b9
commit
95c1255811
@@ -505,6 +505,11 @@ export default function DesignCanvas({ product }: { product: ProductDTO }) {
|
|||||||
const [designApprovalId, setDesignApprovalId] = useState<string | null>(null);
|
const [designApprovalId, setDesignApprovalId] = useState<string | null>(null);
|
||||||
const [submissionMessage, setSubmissionMessage] = useState<string | null>(null);
|
const [submissionMessage, setSubmissionMessage] = useState<string | null>(null);
|
||||||
const [imageDimensions, setImageDimensions] = useState<Record<string, { widthCm: number | null; heightCm: number | null }>>({});
|
const [imageDimensions, setImageDimensions] = useState<Record<string, { widthCm: number | null; heightCm: number | null }>>({});
|
||||||
|
const [expandedSections, setExpandedSections] = useState<Record<string, boolean>>({});
|
||||||
|
|
||||||
|
const toggleSection = (section: string) => {
|
||||||
|
setExpandedSections((prev) => ({ ...prev, [section]: !prev[section] }));
|
||||||
|
};
|
||||||
|
|
||||||
const stageFrontRef = useRef<Konva.Stage | null>(null);
|
const stageFrontRef = useRef<Konva.Stage | null>(null);
|
||||||
const stageBackRef = useRef<Konva.Stage | null>(null);
|
const stageBackRef = useRef<Konva.Stage | null>(null);
|
||||||
@@ -1177,11 +1182,20 @@ export default function DesignCanvas({ product }: { product: ProductDTO }) {
|
|||||||
{(() => {
|
{(() => {
|
||||||
const images = view === 'front' ? elementsFront.filter(el => el.type === 'image') : elementsBack.filter(el => el.type === 'image');
|
const images = view === 'front' ? elementsFront.filter(el => el.type === 'image') : elementsBack.filter(el => el.type === 'image');
|
||||||
return images.length > 0 ? (
|
return images.length > 0 ? (
|
||||||
<div className="mb-3 grid gap-3">
|
<div className="mb-2 border border-line bg-surface">
|
||||||
{images.map((img, idx) => (
|
<button
|
||||||
<div key={img.id} className="border border-line bg-surface p-2">
|
onClick={() => toggleSection('imageDimensions')}
|
||||||
<p className="text-xs font-semibold mb-2">Image {idx + 1}</p>
|
className="w-full px-3 py-2 flex items-center justify-between text-sm font-semibold hover:bg-ink/5"
|
||||||
<div className="flex gap-2">
|
>
|
||||||
|
<span>Image Dimensions ({images.length})</span>
|
||||||
|
<span>{expandedSections.imageDimensions ? '−' : '+'}</span>
|
||||||
|
</button>
|
||||||
|
{expandedSections.imageDimensions && (
|
||||||
|
<div className="border-t border-line p-2 space-y-2">
|
||||||
|
{images.map((img, idx) => (
|
||||||
|
<div key={img.id} className="text-xs">
|
||||||
|
<p className="font-semibold mb-1">Image {idx + 1}</p>
|
||||||
|
<div className="flex gap-2">
|
||||||
<label className="flex flex-col gap-1 flex-1">
|
<label className="flex flex-col gap-1 flex-1">
|
||||||
<span className="text-xs text-muted">Width (cm)</span>
|
<span className="text-xs text-muted">Width (cm)</span>
|
||||||
<input
|
<input
|
||||||
@@ -1218,9 +1232,11 @@ export default function DesignCanvas({ product }: { product: ProductDTO }) {
|
|||||||
className="border border-line bg-paper px-3 py-2 text-sm"
|
className="border border-line bg-paper px-3 py-2 text-sm"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
))}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : null;
|
) : null;
|
||||||
})()}
|
})()}
|
||||||
@@ -1229,11 +1245,20 @@ export default function DesignCanvas({ product }: { product: ProductDTO }) {
|
|||||||
{(() => {
|
{(() => {
|
||||||
const texts = view === 'front' ? elementsFront.filter(el => el.type === 'text') : elementsBack.filter(el => el.type === 'text');
|
const texts = view === 'front' ? elementsFront.filter(el => el.type === 'text') : elementsBack.filter(el => el.type === 'text');
|
||||||
return texts.length > 0 ? (
|
return texts.length > 0 ? (
|
||||||
<div className="mb-2 space-y-2">
|
<div className="mb-2 border border-line bg-surface">
|
||||||
{texts.map((text, idx) => (
|
<button
|
||||||
<div key={text.id} className="border border-line bg-surface p-2">
|
onClick={() => toggleSection('fontProperties')}
|
||||||
<p className="text-xs font-semibold mb-2">Font {idx + 1}</p>
|
className="w-full px-3 py-2 flex items-center justify-between text-sm font-semibold hover:bg-ink/5"
|
||||||
<div className="space-y-2">
|
>
|
||||||
|
<span>Font Properties ({texts.length})</span>
|
||||||
|
<span>{expandedSections.fontProperties ? '−' : '+'}</span>
|
||||||
|
</button>
|
||||||
|
{expandedSections.fontProperties && (
|
||||||
|
<div className="border-t border-line p-2 space-y-3">
|
||||||
|
{texts.map((text, idx) => (
|
||||||
|
<div key={text.id} className="border-b border-line pb-3 last:border-0 last:pb-0">
|
||||||
|
<p className="text-xs font-semibold mb-2">Font {idx + 1}</p>
|
||||||
|
<div className="space-y-2">
|
||||||
<label className="flex flex-col gap-1">
|
<label className="flex flex-col gap-1">
|
||||||
<span className="text-xs text-muted">Text</span>
|
<span className="text-xs text-muted">Text</span>
|
||||||
<input
|
<input
|
||||||
@@ -1353,10 +1378,12 @@ export default function DesignCanvas({ product }: { product: ProductDTO }) {
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
))}
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : null;
|
) : null;
|
||||||
})()}
|
})()}
|
||||||
|
|||||||
Reference in New Issue
Block a user