Refactor grid button styles for improved visibility and interaction
This commit is contained in:
@@ -4177,7 +4177,7 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
|
|||||||
<button
|
<button
|
||||||
style={{
|
style={{
|
||||||
position: "relative",
|
position: "relative",
|
||||||
top: gridBtnActive ? "0" : "-22px",
|
top: gridBtnActive ? "0" : "-43px",
|
||||||
opacity: gridBtnActive ? 1 : 0.5,
|
opacity: gridBtnActive ? 1 : 0.5,
|
||||||
transition: "top 0.25s cubic-bezier(.4,2,.6,1), opacity 0.2s",
|
transition: "top 0.25s cubic-bezier(.4,2,.6,1), opacity 0.2s",
|
||||||
padding: "6px 16px",
|
padding: "6px 16px",
|
||||||
@@ -4191,11 +4191,13 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
|
|||||||
marginLeft: "4px",
|
marginLeft: "4px",
|
||||||
marginRight: "8px",
|
marginRight: "8px",
|
||||||
boxShadow: "0 2px 8px rgba(0,0,0,0.2)",
|
boxShadow: "0 2px 8px rgba(0,0,0,0.2)",
|
||||||
pointerEvents: gridBtnActive ? "auto" : "none",
|
pointerEvents: "auto",
|
||||||
zIndex: 2,
|
zIndex: 2,
|
||||||
display: gridBtnActive ? "block" : "none",
|
display: "block",
|
||||||
}}
|
}}
|
||||||
title="Toggle Fullscreen"
|
title="Toggle Fullscreen"
|
||||||
|
onMouseEnter={() => setGridBtnActive(true)}
|
||||||
|
onMouseLeave={() => setGridBtnActive(false)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const root = document.querySelector(".dicom-viewer-root") as HTMLElement;
|
const root = document.querySelector(".dicom-viewer-root") as HTMLElement;
|
||||||
if (!root) return;
|
if (!root) return;
|
||||||
@@ -4216,7 +4218,7 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
|
|||||||
className="grid-menu-btn"
|
className="grid-menu-btn"
|
||||||
style={{
|
style={{
|
||||||
position: "relative",
|
position: "relative",
|
||||||
top: gridBtnActive ? "0" : "-22px",
|
top: gridBtnActive ? "0" : "-43px",
|
||||||
opacity: gridBtnActive ? 1 : 0.5,
|
opacity: gridBtnActive ? 1 : 0.5,
|
||||||
transition: "top 0.25s cubic-bezier(.4,2,.6,1), opacity 0.2s",
|
transition: "top 0.25s cubic-bezier(.4,2,.6,1), opacity 0.2s",
|
||||||
padding: "6px 16px",
|
padding: "6px 16px",
|
||||||
@@ -4229,10 +4231,11 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
|
|||||||
fontSize: "15px",
|
fontSize: "15px",
|
||||||
marginRight: "8px",
|
marginRight: "8px",
|
||||||
boxShadow: "0 2px 8px rgba(0,0,0,0.2)",
|
boxShadow: "0 2px 8px rgba(0,0,0,0.2)",
|
||||||
pointerEvents: gridBtnActive ? "auto" : "none", // Only clickable when active
|
pointerEvents: "auto",
|
||||||
zIndex: 2,
|
zIndex: 2,
|
||||||
display: gridBtnActive ? "block" : "none",
|
display: "block",
|
||||||
}}
|
}}
|
||||||
|
onMouseEnter={() => setGridBtnActive(true)}
|
||||||
onMouseLeave={() => setGridBtnActive(false)}
|
onMouseLeave={() => setGridBtnActive(false)}
|
||||||
onBlur={() => setGridBtnActive(false)}
|
onBlur={() => setGridBtnActive(false)}
|
||||||
onClick={() => setViewportMenuOpen(open => !open)}
|
onClick={() => setViewportMenuOpen(open => !open)}
|
||||||
@@ -4350,6 +4353,9 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
|
|||||||
>
|
>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '8px 12px', borderBottom: '1px solid #2b2f31' }}>
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '8px 12px', borderBottom: '1px solid #2b2f31' }}>
|
||||||
<div style={{ fontWeight: 700 }}>Stacks</div>
|
<div style={{ fontWeight: 700 }}>Stacks</div>
|
||||||
|
<div style={{ fontSize: 12, color: '#9bb4c8' }}>
|
||||||
|
Active VP: {activeViewport !== null ? activeViewport + 1 : '-'}
|
||||||
|
</div>
|
||||||
<div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
|
<div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
|
||||||
<button
|
<button
|
||||||
title="Close"
|
title="Close"
|
||||||
@@ -4372,6 +4378,7 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
|
|||||||
const count = imageIds.length;
|
const count = imageIds.length;
|
||||||
const invalid = !Array.isArray(imageIds) || count === 0;
|
const invalid = !Array.isArray(imageIds) || count === 0;
|
||||||
const isSelected = selectedStackIdx.includes(idx);
|
const isSelected = selectedStackIdx.includes(idx);
|
||||||
|
const isActiveViewportStack = activeViewport !== null && selectedStackIdx[activeViewport] === idx;
|
||||||
// Prefer the middle image for a representative thumbnail, fallback to first
|
// Prefer the middle image for a representative thumbnail, fallback to first
|
||||||
const midIndex = Math.floor(imageIds.length / 2);
|
const midIndex = Math.floor(imageIds.length / 2);
|
||||||
const chosenImage = imageIds[midIndex] || imageIds[0];
|
const chosenImage = imageIds[midIndex] || imageIds[0];
|
||||||
@@ -4387,14 +4394,19 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
|
|||||||
e.dataTransfer.setData('text/stack-idx', String(idx));
|
e.dataTransfer.setData('text/stack-idx', String(idx));
|
||||||
e.dataTransfer.effectAllowed = 'copy';
|
e.dataTransfer.effectAllowed = 'copy';
|
||||||
}}
|
}}
|
||||||
onClick={() => { if (!invalid) handleLoadStack(0, idx); }}
|
onClick={() => {
|
||||||
|
if (invalid) return;
|
||||||
|
const targetViewport = activeViewport ?? 0;
|
||||||
|
handleLoadStack(targetViewport, idx);
|
||||||
|
}}
|
||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
padding: '8px 10px',
|
padding: '8px 10px',
|
||||||
background: isSelected ? '#1976d2' : 'transparent',
|
background: isActiveViewportStack ? '#0d47a1' : (isSelected ? '#1976d2' : 'transparent'),
|
||||||
color: isSelected ? '#fff' : '#ddd',
|
color: isSelected ? '#fff' : '#ddd',
|
||||||
|
border: isActiveViewportStack ? '1px solid #64b5f6' : '1px solid transparent',
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
cursor: invalid ? 'not-allowed' : 'pointer',
|
cursor: invalid ? 'not-allowed' : 'pointer',
|
||||||
}}
|
}}
|
||||||
@@ -4426,7 +4438,12 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
|
|||||||
<div style={{ fontSize: 12, opacity: 0.7 }}>{count} img{count === 1 ? '' : 's'}</div>
|
<div style={{ fontSize: 12, opacity: 0.7 }}>{count} img{count === 1 ? '' : 's'}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 4 }}>
|
||||||
<div style={{ fontSize: 12, opacity: 0.8 }}>{stack.studyId || ''}</div>
|
<div style={{ fontSize: 12, opacity: 0.8 }}>{stack.studyId || ''}</div>
|
||||||
|
{isActiveViewportStack && (
|
||||||
|
<div style={{ fontSize: 11, color: '#bbdefb', fontWeight: 700 }}>ACTIVE</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
Reference in New Issue
Block a user