Debuggler LogoDebuggler
All challenges
The Teleporting PopoverDashboardFloating UI
import { useState, useEffect, useRef } from "react";

export default function App() {
  const [isOpen, setIsOpen] = useState(false);
  const [coords, setCoords] = useState({ top: 0, left: 0 });
  
  const triggerRef = useRef(null);
  
  // BUG: Using a standard useRef for a conditionally rendered DOM element.
  // When isOpen becomes true, the popover div mounts and the popoverRef is updated.
  // However, updating a ref does NOT trigger a re-render. Thus, the positioning
  // logic (which measures the popover node) doesn't run until the next render,
  // causing the popover to temporarily render at (0, 0).
  //
  // The fix is to use a callback ref (e.g. useState) for the popover element
  // so that React re-renders and positions the popover as soon as it mounts.
  const popoverRef = useRef(null);

  useEffect(() => {
    const b = document.body;
    b.style.background = "#fafafa"; b.style.margin = "0";
    return () => { b.style.background = ""; b.style.margin = ""; };
  }, []);

  useEffect(() => {
    if (!isOpen || !triggerRef.current || !popoverRef.current) return;

    const triggerRect = triggerRef.current.getBoundingClientRect();
    const popoverRect = popoverRef.current.getBoundingClientRect();
    
    // Position popover directly below the trigger button, centered
    const top = triggerRect.bottom + window.scrollY + 8;
    const left = triggerRect.left + window.scrollX + (triggerRect.width - popoverRect.width) / 2;
    
    setCoords({ top, left });
  }, [isOpen, triggerRef.current, popoverRef.current]); // BUG: Ref mutations don't trigger effect runs!

  return (
    <div style={styles.page}>
      <div style={styles.card}>
        <h1 style={styles.h1}>System Status</h1>
        <p style={styles.sub}>Check system health metrics and view detailed logs.</p>
        
        <div style={styles.metricsGrid}>
          <div style={styles.metricCard}>
            <div style={styles.metricLabel}>API Gateway</div>
            <div style={styles.metricValue}>99.9%</div>
          </div>
          <div style={styles.metricCard}>
            <div style={styles.metricLabel}>Database Load</div>
            <div style={styles.metricValue}>12%</div>
          </div>
        </div>

        <div style={styles.actions}>
          <button
            ref={triggerRef}
            data-testid="view-details-btn"
            onClick={() => setIsOpen(!isOpen)}
            style={styles.button}
          >
            {isOpen ? "Hide Details" : "View Details"}
          </button>
        </div>

        {isOpen && (
          <div
            ref={popoverRef}
            data-testid="popover"
            style={{
              ...styles.popover,
              top: `${coords.top}px`,
              left: `${coords.left}px`
            }}
          >
            <h3 style={styles.popoverTitle}>Service Details</h3>
            <p style={styles.popoverText}>All 14 microservices are operating within normal latency parameters (&lt;50ms).</p>
            <div style={styles.badge}>Healthy</div>
          </div>
        )}
      </div>
    </div>
  );
}

const styles = {
  page: { display: "flex", justifyContent: "center", padding: "40px 20px", fontFamily: "system-ui, sans-serif" },
  card: { background: "#fff", borderRadius: 12, padding: "24px", width: "100%", maxWidth: 440, boxShadow: "0 4px 6px -1px rgba(0,0,0,0.1)" },
  h1: { margin: "0 0 6px", fontSize: 20, fontWeight: 600, color: "#111827" },
  sub: { margin: "0 0 20px", fontSize: 14, color: "#6B7280" },
  metricsGrid: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 20 },
  metricCard: { background: "#F9FAFB", border: "1px solid #E5E7EB", borderRadius: 8, padding: "12px 16px" },
  metricLabel: { fontSize: 12, color: "#6B7280", marginBottom: 4 },
  metricValue: { fontSize: 18, fontWeight: 600, color: "#10B981" },
  actions: { display: "flex", justifyContent: "flex-end" },
  button: { background: "#4F46E5", color: "#fff", border: "none", padding: "8px 16px", borderRadius: 6, fontSize: 14, fontWeight: 500, cursor: "pointer", outline: "none" },
  popover: {
    position: "absolute",
    width: 260,
    background: "#fff",
    border: "1px solid #E5E7EB",
    borderRadius: 8,
    padding: "16px",
    boxShadow: "0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05)",
    zIndex: 50,
    boxSizing: "border-box"
  },
  popoverTitle: { margin: "0 0 8px", fontSize: 14, fontWeight: 600, color: "#111827" },
  popoverText: { margin: "0 0 12px", fontSize: 12, color: "#4B5563", lineHeight: 1.4 },
  badge: { display: "inline-block", background: "#D1FAE5", color: "#065F46", fontSize: 11, fontWeight: 600, padding: "2px 8px", borderRadius: 9999 }
};

Click the 'View Details' button. The popover initially appears at the top-left of the screen (0, 0) instead of below the button. Find out why it renders incorrectly on first mount.

After you fix it

  • Clicking 'View Details' should instantly position the popover directly below the button.
  • The popover should never render at (0, 0) top-left.

Click "Run checks" to verify your solution.