sillsdev / sillsdev/TheCombine
[TreeView] Hover badge persists on touch-screen domain touch
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 22
- Forks
- 10
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 9
Description
#4046 causes an odd behavior on touch screen. Since hover isn't available, you can get the word-count badge to appear by tapping or press-and-hold-ing the button. In either case, the hover persists after the touch until something else is touched. This is good for press-and-hold, but bad for tap. When the button is tapped, that click navigates in the tree, so the hover shouldn't persist, but it does.
Claude's solution (to keep good press-and-hold hover and not have any tap hover) introduces too high a maintenance cost for the benefit:
import { useState, useRef } from 'react';
const badgeClass = "DomainCountBadge";
/** Style to show the child with given className only on hover of the parent */
const hoverSx = (className: string, showBadge: boolean): SxProps => ({
[`& .${className}`]: {
opacity: showBadge ? 1 : 0,
transition: "opacity .25s ease"
},
// Only apply CSS hover on devices that support hover
'@media (hover: hover)': {
[`&:hover .${className}`]: { opacity: 1 },
},
});
interface DomainTileButtonProps extends DomainTileProps {
onClick: (domain: SemanticDomain) => void;
}
export default function DomainTileButton(
props: DomainTileButtonProps
): ReactElement {
const { onClick, ...domainTileProps } = props;
const [showBadge, setShowBadge] = useState(false);
const touchStartTime = useRef<number | null>(null);
const handleTouchStart = () => {
touchStartTime.current = Date.now();
};
const handleTouchEnd = () => {
const touchDuration = touchStartTime.current
? Date.now() - touchStartTime.current
: 0;
// Show badge on long press (>500ms)
if (touchDuration >= 500) {
setShowBadge(true);
// Hide after a delay
setTimeout(() => setShowBadge(false), 1000);
}
touchStartTime.current = null;
};
return (
<Button
id={props.domain.id}
fullWidth
onClick={() => {
onClick(props.domain);
setShowBadge(false); // Clear badge on tap
}}
onTouchStart={handleTouchStart}
onTouchEnd={handleTouchEnd}
sx={{ height: "100%", ...hoverSx(badgeClass, showBadge) }}
tabIndex={-1}
variant="outlined"
>
<DomainTile {...domainTileProps} />
<DomainCountBadge className={badgeClass} domainId={props.domain.id} />
</Button>
);
}
But we could use
// Only apply CSS hover on devices that support hover
'@media (hover: hover)': {
[`&:hover .${className}`]: { opacity: 1 },
},
to disable the hover entirely on touch screen.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating the TreeView or DomainTileButton implementation and reproduce the badge behavior on a touch screen. Check the hover styling and tap handling described in the issue; done means a tap navigates without leaving the word-count badge visible, while the intended press-and-hold behavior remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100