Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion smart-accounts-kit/reference/glossary.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Fine-grained, wallet execution permissions that dapps can request from MetaMask

### Bundler

An ERC-4337 component that manages the alternate mempool: it collects user operations from smart accounts, bundles them into transactions, and submits them to the network.
An ERC-4337 component that manages the alternate mempool: it collects user operations from smart accounts, packages them, and submits them to the network.

### Caveat

Expand Down
58 changes: 46 additions & 12 deletions src/theme/GlossaryTerm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@
import glossaryData from '@site/src/lib/glossary.json';
import styles from './styles.module.css';

function useIsTouchDevice() {
const [isTouch, setIsTouch] = useState(false);
useEffect(() => {
setIsTouch(
'ontouchstart' in window &&
window.matchMedia('(pointer: coarse)').matches
);
Comment thread
alexandratran marked this conversation as resolved.
}, []);
return isTouch;
}

export default function GlossaryTerm({
term,
definition,
Expand All @@ -14,6 +25,7 @@
const [tooltipStyle, setTooltipStyle] = useState(null);
const wrapperRef = useRef(null);
const tooltipRef = useRef(null);
const isTouch = useIsTouchDevice();

const updatePosition = useCallback(() => {
if (!wrapperRef.current || !tooltipRef.current) return;
Expand All @@ -25,7 +37,6 @@

const preferredGap = 8; // px

// Decide top vs bottom based on available space
const hasSpaceAbove = wrapperRect.top >= tooltipRect.height + preferredGap;
const hasSpaceBelow = viewportHeight - wrapperRect.bottom >= tooltipRect.height + preferredGap;
const placeAbove = hasSpaceAbove || !hasSpaceBelow;
Expand All @@ -37,7 +48,6 @@
top = wrapperRect.bottom + preferredGap;
}

// Center horizontally on the wrapper, then clamp within viewport with margin
const horizontalMargin = 8;
let left = wrapperRect.left + wrapperRect.width / 2 - tooltipRect.width / 2;
left = Math.max(
Expand All @@ -51,8 +61,6 @@
useEffect(() => {
if (!showTooltip) return;

// Use double requestAnimationFrame to ensure DOM is fully rendered and layout is complete
// This ensures tooltipRef.current is available and has proper dimensions
let rafId2;
const rafId1 = requestAnimationFrame(() => {
rafId2 = requestAnimationFrame(() => {
Expand All @@ -72,7 +80,19 @@
};
}, [showTooltip, updatePosition]);

// Pull definition from local glossary data if not provided
// Close tooltip when tapping outside on touch devices
useEffect(() => {
if (!isTouch || !showTooltip) return;
const handleTouchOutside = (e) => {
if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
setShowTooltip(false);
setTooltipStyle(null);
}
};
document.addEventListener('touchstart', handleTouchOutside);
return () => document.removeEventListener('touchstart', handleTouchOutside);
}, [isTouch, showTooltip]);

const effectiveDefinition = useMemo(() => {
if (definition && typeof definition === 'string' && definition.length > 0) {
return definition;
Expand All @@ -95,15 +115,29 @@
return slugger.slug(String(term || ''));
}, [term]);

const glossaryHref = `${effectiveRoutePath}#${termId}`;

const handleClick = (e) => {
if (!isTouch) return;
e.preventDefault();
setShowTooltip((prev) => {
if (prev) setTooltipStyle(null);
return !prev;
});
};

const tooltipPositioned = showTooltip && tooltipStyle != null;

return (
<span ref={wrapperRef} className={styles.glossaryTermWrapper}>
<a

Check warning on line 133 in src/theme/GlossaryTerm/index.js

View workflow job for this annotation

GitHub Actions / Lint Code Base

Do not use an `<a>` element to navigate. Use the `<Link />` component from `@docusaurus/Link` instead. See: https://docusaurus.io/docs/docusaurus-core#link
href={`${effectiveRoutePath}#${termId}`}
href={glossaryHref}
className={styles.glossaryTerm}
onMouseEnter={() => setShowTooltip(true)}
onMouseLeave={() => setShowTooltip(false)}
onFocus={() => setShowTooltip(true)}
onBlur={() => setShowTooltip(false)}
onClick={handleClick}
onMouseEnter={isTouch ? undefined : () => setShowTooltip(true)}
onMouseLeave={isTouch ? undefined : () => { setShowTooltip(false); setTooltipStyle(null); }}
onFocus={isTouch ? undefined : () => setShowTooltip(true)}
onBlur={isTouch ? undefined : () => { setShowTooltip(false); setTooltipStyle(null); }}
aria-describedby={`tooltip-${termId}`}
>
{displayText}
Expand All @@ -112,10 +146,10 @@
<span
ref={tooltipRef}
id={`tooltip-${termId}`}
className={`${styles.tooltip} ${showTooltip ? styles.tooltipVisible : ''} ${styles.tooltipFloating}`}
className={`${styles.tooltip} ${tooltipPositioned ? styles.tooltipVisible : ''} ${styles.tooltipFloating}`}
role="tooltip"
style={
showTooltip && tooltipStyle
tooltipPositioned
? { top: `${tooltipStyle.top}px`, left: `${tooltipStyle.left}px` }
: undefined
}
Expand Down
Loading