Skip to content

Commit e831a9f

Browse files
committed
fix: prevent long-press text selection and enlarge plan dropdown for touch UX
Add a shared .hold-press utility (user-select/touch-callout/touch-action/tap-highlight off) and apply it with select-none touch-manipulation + onContextMenu preventDefault to all hold-to-confirm buttons (Hold to Reset, Save/Reset Robot Config, Update/Reset All Parameters, ROS bridge refresh) so iOS/Android/Linux touch screens no longer trigger the text-selection cursor or context menu mid-press. Also detach the plan picker popover from the trigger width: w-[36rem], text-[1.625rem], min-h-[5rem] items, with max-h capped by --radix-popover-content-available-height so it fits any viewport.
1 parent cf53cbe commit e831a9f

4 files changed

Lines changed: 28 additions & 11 deletions

File tree

src/components/RosBridgeFloat.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ export function RosBridgeFloat() {
1616
<div
1717
className={`fixed ${
1818
isHalfScreen ? "bottom-30" : "bottom-20"
19-
} right-6 z-50 flex max-w-[min(100%,calc(100vw-1.5rem))] cursor-pointer select-none items-center gap-6 rounded-2xl border-2 border-[#444] bg-black/70 px-5 py-4 shadow-2xl backdrop-blur-md transition-all duration-300 sm:right-8 sm:gap-8 sm:px-8 sm:py-5`}
19+
} right-6 z-50 flex max-w-[min(100%,calc(100vw-1.5rem))] cursor-pointer select-none touch-manipulation hold-press items-center gap-6 rounded-2xl border-2 border-[#444] bg-black/70 px-5 py-4 shadow-2xl backdrop-blur-md transition-all duration-300 sm:right-8 sm:gap-8 sm:px-8 sm:py-5`}
2020
style={{
2121
background:
2222
pressProgress > 0
2323
? `linear-gradient(to right, rgba(76, 175, 80, 0.8) ${pressProgress}%, rgba(0, 0, 0, 0.7) ${pressProgress}%)`
2424
: "rgba(0, 0, 0, 0.7)",
2525
}}
26+
onContextMenu={(e) => e.preventDefault()}
2627
onMouseDown={() => {
2728
const timer = setInterval(() => {
2829
setPressProgress((prev: number) => {

src/components/playmat.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -623,9 +623,11 @@ export default function Playmat() {
623623
</Popover.Trigger>
624624
<Popover.Portal>
625625
<Popover.Content
626-
className="z-[200] w-[var(--radix-popover-trigger-width)] max-h-72 overflow-y-auto rounded-xl border border-[#333] bg-[#0a0a0a] p-1 shadow-2xl"
627-
sideOffset={4}
626+
className="z-[200] w-[36rem] max-w-[calc(100vw-2rem)] max-h-[min(34rem,var(--radix-popover-content-available-height))] overflow-y-auto overscroll-contain rounded-2xl border border-[#333] bg-[#0a0a0a] p-2 shadow-2xl"
627+
sideOffset={9}
628628
align="start"
629+
collisionPadding={16}
630+
avoidCollisions
629631
onOpenAutoFocus={(e) => e.preventDefault()}
630632
>
631633
{plans.map((plan: PlanSequence) => (
@@ -637,7 +639,7 @@ export default function Playmat() {
637639
setPlanMenuOpen(false);
638640
}}
639641
className={clsx(
640-
"w-full text-left px-3 py-3 text-lg rounded-lg transition-colors",
642+
"w-full text-left px-5 py-[1.375rem] min-h-[5rem] text-[1.625rem] rounded-xl transition-colors select-none touch-manipulation",
641643
selectedPlanId === plan.id
642644
? "text-white"
643645
: "text-[#ccc] hover:bg-[#1a1a1a] hover:text-white"
@@ -683,7 +685,8 @@ export default function Playmat() {
683685
<div className="flex items-center justify-between gap-4">
684686
{/* Reset Button */}
685687
<div
686-
className="flex-1 relative group"
688+
className="flex-1 relative group hold-press select-none touch-manipulation"
689+
onContextMenu={(e) => e.preventDefault()}
687690
onMouseDown={() => {
688691
const timer = setInterval(() => {
689692
setPressProgress((prev: number) => {

src/components/status.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,13 +1122,14 @@ export default function RobotDashboard() {
11221122
<div className="w-full max-w-2xl sm:max-w-none">
11231123
<button
11241124
type="button"
1125-
className="relative mt-8 block w-full overflow-hidden rounded-md px-5 py-4 text-center text-xl font-bold uppercase tracking-wider text-white transition-all duration-300"
1125+
className="relative mt-8 block w-full overflow-hidden rounded-md px-5 py-4 text-center text-xl font-bold uppercase tracking-wider text-white transition-all duration-300 hold-press select-none touch-manipulation"
11261126
style={{
11271127
background:
11281128
activeButton === "robotConfigSave" && buttonPressProgress > 0
11291129
? `linear-gradient(to right, #4caf50 ${buttonPressProgress}%, var(--theme-accent) ${buttonPressProgress}%)`
11301130
: "var(--theme-accent)",
11311131
}}
1132+
onContextMenu={(e) => e.preventDefault()}
11321133
onMouseDown={() => startLongPress("robotConfigSave")}
11331134
onMouseUp={cancelLongPress}
11341135
onMouseLeave={cancelLongPress}
@@ -1139,13 +1140,14 @@ export default function RobotDashboard() {
11391140
</button>
11401141
<button
11411142
type="button"
1142-
className="relative mt-2 block w-full overflow-hidden rounded-md px-5 py-4 text-center text-xl font-bold uppercase tracking-wider text-white transition-all duration-300"
1143+
className="relative mt-2 block w-full overflow-hidden rounded-md px-5 py-4 text-center text-xl font-bold uppercase tracking-wider text-white transition-all duration-300 hold-press select-none touch-manipulation"
11431144
style={{
11441145
background:
11451146
activeButton === "robotConfigReset" && buttonPressProgress > 0
11461147
? `linear-gradient(to right, #4caf50 ${buttonPressProgress}%, #333 ${buttonPressProgress}%)`
11471148
: "#333",
11481149
}}
1150+
onContextMenu={(e) => e.preventDefault()}
11491151
onMouseDown={() => startLongPress("robotConfigReset")}
11501152
onMouseUp={cancelLongPress}
11511153
onMouseLeave={cancelLongPress}
@@ -1707,12 +1709,13 @@ export default function RobotDashboard() {
17071709
</div>
17081710

17091711
<button
1710-
className="text-white text-xl font-bold py-4 px-5 rounded-md w-full block text-center uppercase tracking-wider transition-all duration-300 mt-8 relative overflow-hidden"
1712+
className="text-white text-xl font-bold py-4 px-5 rounded-md w-full block text-center uppercase tracking-wider transition-all duration-300 mt-8 relative overflow-hidden hold-press select-none touch-manipulation"
17111713
style={{
1712-
background: activeButton === 'update' && buttonPressProgress > 0
1714+
background: activeButton === 'update' && buttonPressProgress > 0
17131715
? `linear-gradient(to right, #4caf50 ${buttonPressProgress}%, var(--theme-accent) ${buttonPressProgress}%)`
17141716
: "var(--theme-accent)",
17151717
}}
1718+
onContextMenu={(e) => e.preventDefault()}
17161719
onMouseDown={() => startLongPress('update')}
17171720
onMouseUp={cancelLongPress}
17181721
onMouseLeave={cancelLongPress}
@@ -1724,12 +1727,13 @@ export default function RobotDashboard() {
17241727

17251728
{/* After the update button, add DEFAULT button */}
17261729
<button
1727-
className="text-white text-xl font-bold py-4 px-5 rounded-md w-full block text-center uppercase tracking-wider transition-all duration-300 mt-2 relative overflow-hidden"
1730+
className="text-white text-xl font-bold py-4 px-5 rounded-md w-full block text-center uppercase tracking-wider transition-all duration-300 mt-2 relative overflow-hidden hold-press select-none touch-manipulation"
17281731
style={{
1729-
background: activeButton === 'reset' && buttonPressProgress > 0
1732+
background: activeButton === 'reset' && buttonPressProgress > 0
17301733
? `linear-gradient(to right, #4caf50 ${buttonPressProgress}%, #333 ${buttonPressProgress}%)`
17311734
: '#333'
17321735
}}
1736+
onContextMenu={(e) => e.preventDefault()}
17331737
onMouseDown={() => startLongPress('reset')}
17341738
onMouseUp={cancelLongPress}
17351739
onMouseLeave={cancelLongPress}

src/index.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ input[type="range"] {
5353
touch-action: pan-x;
5454
}
5555

56+
/* Hold-to-confirm targets: suppress iOS callout, Android selection menu, and text selection magnifier on long press. Pair with Tailwind `select-none touch-manipulation`. */
57+
.hold-press {
58+
-webkit-touch-callout: none;
59+
-webkit-user-select: none;
60+
user-select: none;
61+
touch-action: manipulation;
62+
-webkit-tap-highlight-color: transparent;
63+
}
64+
5665
@theme inline {
5766
--radius-sm: calc(var(--radius) - 4px);
5867
--radius-md: calc(var(--radius) - 2px);

0 commit comments

Comments
 (0)