Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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