fix(vision): move undock button to vision status bar

Move the undock button into the DockedVisionFeed status bar alongside
the disable-vision button. This prevents the buttons from overlapping.

When vision is enabled, the dock-controls overlay is now hidden since
all controls are in the unified status bar.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock 2026-01-08 10:23:48 -06:00
parent fbf4aa449c
commit e685f10aff
2 changed files with 114 additions and 75 deletions

View File

@ -510,54 +510,56 @@ export function MyAbacus() {
position: 'relative',
})}
>
{/* Control buttons - stacked vertically on right side to avoid blocking beads */}
<div
data-element="dock-controls"
style={{
position: 'absolute',
bottom: 0,
right: 0,
margin: '4px',
display: 'flex',
flexDirection: 'column',
gap: '4px',
alignItems: 'flex-end',
}}
>
<VisionIndicator size="small" position="inline" />
<button
data-action="undock-abacus"
onClick={(e) => {
e.stopPropagation()
handleUndockClick()
}}
title="Undock abacus"
className={css({
w: '24px',
h: '24px',
{/* Control buttons - only show when NOT using vision feed (vision has its own status bar) */}
{!(visionConfig.enabled && isVisionSetupComplete) && (
<div
data-element="dock-controls"
style={{
position: 'absolute',
bottom: 0,
right: 0,
margin: '4px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
bg: 'rgba(0, 0, 0, 0.5)',
backdropFilter: 'blur(4px)',
border: '1px solid rgba(255, 255, 255, 0.3)',
borderRadius: 'md',
color: 'white',
fontSize: 'xs',
cursor: 'pointer',
transition: 'all 0.2s',
zIndex: 10,
opacity: 0.7,
_hover: {
bg: 'rgba(0, 0, 0, 0.7)',
opacity: 1,
transform: 'scale(1.1)',
},
})}
flexDirection: 'column',
gap: '4px',
alignItems: 'flex-end',
}}
>
</button>
</div>
<VisionIndicator size="small" position="inline" />
<button
data-action="undock-abacus"
onClick={(e) => {
e.stopPropagation()
handleUndockClick()
}}
title="Undock abacus"
className={css({
w: '24px',
h: '24px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
bg: 'rgba(0, 0, 0, 0.5)',
backdropFilter: 'blur(4px)',
border: '1px solid rgba(255, 255, 255, 0.3)',
borderRadius: 'md',
color: 'white',
fontSize: 'xs',
cursor: 'pointer',
transition: 'all 0.2s',
zIndex: 10,
opacity: 0.7,
_hover: {
bg: 'rgba(0, 0, 0, 0.7)',
opacity: 1,
transform: 'scale(1.1)',
},
})}
>
</button>
</div>
)}
<div
data-element="abacus-display"
className={css({
@ -584,6 +586,7 @@ export function MyAbacus() {
dock.onValueChange(value)
}
}}
onUndock={handleUndockClick}
/>
) : (
<AbacusReact

View File

@ -31,6 +31,8 @@ interface DockedVisionFeedProps {
onValueDetected?: (value: number) => void
/** Number of columns to detect */
columnCount?: number
/** Called when user wants to undock the abacus */
onUndock?: () => void
}
/**
@ -41,7 +43,7 @@ interface DockedVisionFeedProps {
* - For remote camera: Receives frames from phone, runs detection
* - Shows the video feed with detection overlay
*/
export function DockedVisionFeed({ onValueDetected, columnCount = 5 }: DockedVisionFeedProps) {
export function DockedVisionFeed({ onValueDetected, columnCount = 5, onUndock }: DockedVisionFeedProps) {
const {
visionConfig,
setDockedValue,
@ -843,34 +845,68 @@ export function DockedVisionFeed({ onValueDetected, columnCount = 5 }: DockedVis
)}
</div>
{/* Right side: Close button */}
<button
type="button"
data-action="disable-vision"
onClick={handleDisableVision}
title="Turn off camera"
className={css({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
w: '24px',
h: '24px',
bg: 'transparent',
border: '1px solid rgba(255, 255, 255, 0.3)',
borderRadius: 'md',
color: 'gray.400',
fontSize: 'xs',
cursor: 'pointer',
transition: 'all 0.15s',
_hover: {
bg: 'red.600',
borderColor: 'red.600',
color: 'white',
},
})}
>
</button>
{/* Right side: Undock + Close buttons */}
<div className={css({ display: 'flex', alignItems: 'center', gap: 1 })}>
{onUndock && (
<button
type="button"
data-action="undock-abacus"
onClick={(e) => {
e.stopPropagation()
onUndock()
}}
title="Undock abacus"
className={css({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
w: '24px',
h: '24px',
bg: 'transparent',
border: '1px solid rgba(255, 255, 255, 0.3)',
borderRadius: 'md',
color: 'gray.400',
fontSize: 'xs',
cursor: 'pointer',
transition: 'all 0.15s',
_hover: {
bg: 'blue.600',
borderColor: 'blue.600',
color: 'white',
},
})}
>
</button>
)}
<button
type="button"
data-action="disable-vision"
onClick={handleDisableVision}
title="Turn off camera"
className={css({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
w: '24px',
h: '24px',
bg: 'transparent',
border: '1px solid rgba(255, 255, 255, 0.3)',
borderRadius: 'md',
color: 'gray.400',
fontSize: 'xs',
cursor: 'pointer',
transition: 'all 0.15s',
_hover: {
bg: 'red.600',
borderColor: 'red.600',
color: 'white',
},
})}
>
</button>
</div>
</div>
)}
</div>