diff --git a/src/App.module.css b/src/App.module.css
index feb0a54..6fe48e1 100644
--- a/src/App.module.css
+++ b/src/App.module.css
@@ -49,7 +49,8 @@
--radius-xxl: 12px;
/* Z-index */
- --z-modal: 1000;
+ --z-modal: 10000;
+ --z-tooltip: 50000;
}
body {
background-color: var(--color-bg);
diff --git a/src/components/httprequestviewer/RequestRowSummary.module.css b/src/components/httprequestviewer/RequestRowSummary.module.css
index 018e882..8d725c9 100644
--- a/src/components/httprequestviewer/RequestRowSummary.module.css
+++ b/src/components/httprequestviewer/RequestRowSummary.module.css
@@ -25,10 +25,11 @@ tr {
border: 1px solid #ffffff;
}
-tr:hover, tr:hover td {
+/* Only apply hover effects to data rows, not header rows */
+tbody tr:hover, tbody tr:hover td {
border: 1px dashed var(--color-bg-hover);
}
-tr:hover {
+tbody tr:hover {
filter: brightness(290%);
}
a {
diff --git a/src/components/httprequestviewer/RequestsTable.module.css b/src/components/httprequestviewer/RequestsTable.module.css
new file mode 100644
index 0000000..b6776ef
--- /dev/null
+++ b/src/components/httprequestviewer/RequestsTable.module.css
@@ -0,0 +1,73 @@
+/* Table styles using CSS variables from App.module.css */
+
+.tableContainer {
+ background: var(--color-bg-secondary);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-lg);
+ overflow: hidden;
+ /* Allow tooltips to show above table */
+ position: relative;
+}
+
+.table {
+ width: 100%;
+ border-collapse: collapse;
+}
+
+.tableHeader {
+ background: var(--color-bg-light);
+}
+
+/* Ensure header row doesn't inherit hover effects */
+.tableHeader tr:hover {
+ filter: none !important;
+ background: var(--color-bg-light) !important;
+ border: none !important;
+}
+
+.tableHeader tr:hover td,
+.tableHeader tr:hover th {
+ border: 1px solid var(--color-border) !important;
+ filter: none !important;
+}
+
+/* Ensure tooltips in header work properly */
+.tableHeader .tooltipContainer {
+ position: relative;
+ z-index: 10;
+}
+
+.tableHeaderCell {
+ padding: var(--spacing-sm);
+ font-size: var(--font-size-md);
+ font-weight: bold;
+ border-bottom: 1px solid var(--color-border);
+ color: var(--color-text);
+ /* Ensure tooltip positioning context */
+ position: relative;
+ overflow: visible;
+}
+
+.tableHeaderCell.center {
+ text-align: center;
+}
+
+.tableHeaderCell.left {
+ text-align: left;
+}
+
+.tableHeaderCell.right {
+ text-align: right;
+}
+
+.tableHeaderCell.expandColumn {
+ width: 30px;
+}
+
+/* No results message */
+.noResults {
+ text-align: center;
+ color: var(--color-text-muted);
+ padding: 40px;
+ font-size: var(--font-size-xl);
+}
\ No newline at end of file
diff --git a/src/components/httprequestviewer/RequestsTable.tsx b/src/components/httprequestviewer/RequestsTable.tsx
index 21f2117..e4ba0c9 100644
--- a/src/components/httprequestviewer/RequestsTable.tsx
+++ b/src/components/httprequestviewer/RequestsTable.tsx
@@ -3,7 +3,7 @@ import RequestRowSummary from './RequestRowSummary'
import ScreenshotRow from './ScreenshotRow'
import { Tooltip } from '../shared/Tooltip'
import { TooltipType } from '../shared/tooltipDefinitions'
-import styles from './HTTPRequestViewer.module.css'
+import styles from './RequestsTable.module.css'
import type { HTTPRequest, ScreenshotEvent } from './types/httpRequest'
interface RequestsTableProps {
diff --git a/src/components/shared/Modal.module.css b/src/components/shared/Modal.module.css
new file mode 100644
index 0000000..5e13e00
--- /dev/null
+++ b/src/components/shared/Modal.module.css
@@ -0,0 +1,71 @@
+/* Modal component styles using CSS variables from App.module.css */
+
+.modalOverlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.5);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: var(--z-modal);
+ padding: var(--spacing-lg);
+}
+
+.modalContainer {
+ background-color: var(--color-bg-secondary);
+ border-radius: var(--radius-lg);
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
+ max-width: 600px;
+ max-height: 80vh;
+ width: 100%;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ border: 1px solid var(--color-border);
+}
+
+.modalHeader {
+ padding: var(--spacing-lg);
+ border-bottom: 1px solid var(--color-border);
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background-color: var(--color-bg-light);
+}
+
+.modalTitle {
+ margin: 0;
+ color: var(--color-text);
+ font-size: var(--font-size-xxl);
+ font-weight: bold;
+}
+
+.modalCloseButton {
+ background: none;
+ border: none;
+ font-size: 24px;
+ cursor: pointer;
+ color: var(--color-text-muted);
+ padding: 0;
+ width: 30px;
+ height: 30px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: background-color 0.2s ease;
+}
+
+.modalCloseButton:hover {
+ background-color: var(--color-bg-hover);
+ color: var(--color-text);
+}
+
+.modalBody {
+ padding: var(--spacing-lg);
+ overflow: auto;
+ flex: 1;
+}
\ No newline at end of file
diff --git a/src/components/shared/Modal.tsx b/src/components/shared/Modal.tsx
index 9704b4c..089c8fa 100644
--- a/src/components/shared/Modal.tsx
+++ b/src/components/shared/Modal.tsx
@@ -1,4 +1,5 @@
import { useEffect } from 'react'
+import styles from './Modal.module.css'
interface ModalProps {
isOpen: boolean
@@ -32,85 +33,28 @@ export function Modal({ isOpen, onClose, title, children }: ModalProps) {
return (
e.stopPropagation()}
>
{/* Modal Header */}
-
-
+
+
{title}
{/* Modal Content */}
-
diff --git a/src/components/shared/Tooltip.module.css b/src/components/shared/Tooltip.module.css
new file mode 100644
index 0000000..c1569a4
--- /dev/null
+++ b/src/components/shared/Tooltip.module.css
@@ -0,0 +1,174 @@
+/* Tooltip component styles using CSS variables from App.module.css */
+
+.tooltipContainer {
+ position: relative;
+ display: inline-flex;
+ align-items: center;
+ gap: var(--spacing-xs);
+ /* Ensure tooltip positioning context */
+ z-index: 1;
+}
+
+.tooltipIcon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 16px;
+ height: 16px;
+ background-color: var(--color-primary);
+ color: white;
+ border-radius: 50%;
+ font-size: var(--font-size-xs);
+ font-weight: bold;
+ cursor: help;
+ transition: all 0.2s ease;
+ user-select: none;
+}
+
+.tooltipIcon:hover {
+ background-color: var(--color-text);
+ transform: scale(1.1);
+}
+
+/* Hover tooltip */
+.hoverTooltip {
+ position: absolute;
+ top: auto;
+ bottom: calc(100% + var(--spacing-xs));
+ left: 50%;
+ transform: translateX(-50%);
+ background-color: var(--color-bg-secondary);
+ color: var(--color-text);
+ padding: var(--spacing-sm) var(--spacing-md);
+ border-radius: var(--radius-md);
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
+ font-size: var(--font-size-sm);
+ z-index: var(--z-tooltip);
+ max-width: 300px;
+ word-wrap: break-word;
+ white-space: normal;
+ /* Ensure tooltip doesn't get clipped by containers */
+ pointer-events: none;
+ /* Prevent text selection */
+ user-select: none;
+}
+
+.hoverTooltip::after {
+ content: '';
+ position: absolute;
+ top: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 0;
+ height: 0;
+ border-left: 6px solid transparent;
+ border-right: 6px solid transparent;
+ border-top: 6px solid var(--color-bg-secondary);
+ /* Ensure arrow is also on top */
+ z-index: calc(var(--z-tooltip) + 1);
+ pointer-events: none;
+}
+
+/* Fixed positioned tooltip for better visibility */
+.hoverTooltipFixed {
+ position: fixed;
+ transform: translateX(-50%) translateY(-100%);
+ background-color: var(--color-bg-secondary);
+ color: var(--color-text);
+ padding: var(--spacing-sm) var(--spacing-md);
+ border-radius: var(--radius-md);
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
+ font-size: var(--font-size-sm);
+ z-index: var(--z-tooltip);
+ max-width: 300px;
+ word-wrap: break-word;
+ white-space: normal;
+ pointer-events: none;
+ user-select: none;
+ border: 1px solid var(--color-border);
+ margin-top: -8px;
+}
+
+.hoverTooltipFixed::after {
+ content: '';
+ position: absolute;
+ top: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 0;
+ height: 0;
+ border-left: 6px solid transparent;
+ border-right: 6px solid transparent;
+ border-top: 6px solid var(--color-bg-secondary);
+ z-index: calc(var(--z-tooltip) + 1);
+ pointer-events: none;
+}
+
+.tooltipTitle {
+ font-weight: bold;
+ margin-bottom: var(--spacing-xs);
+ color: var(--color-text-highlight);
+}
+
+.tooltipDescription {
+ margin-bottom: var(--spacing-xs);
+ line-height: 1.4;
+}
+
+.tooltipHint {
+ font-size: var(--font-size-xs);
+ color: var(--color-text-muted);
+ font-style: italic;
+}
+
+/* Modal content styling */
+.modalContent {
+ line-height: 1.6;
+}
+
+.modalDescription {
+ margin-bottom: var(--spacing-lg);
+ color: var(--color-text);
+}
+
+.modalSection {
+ margin-bottom: var(--spacing-lg);
+ padding: var(--spacing-md);
+ background-color: var(--color-bg-light);
+ border-radius: var(--radius-md);
+ border-left: 4px solid var(--color-primary);
+}
+
+.modalSectionTitle {
+ font-weight: bold;
+ margin-bottom: var(--spacing-sm);
+ color: var(--color-text);
+ display: flex;
+ align-items: center;
+ gap: var(--spacing-xs);
+}
+
+.modalSectionContent {
+ color: var(--color-text);
+ line-height: 1.5;
+}
+
+.modalLinks {
+ display: flex;
+ flex-direction: column;
+ gap: var(--spacing-xs);
+}
+
+.modalLink {
+ color: var(--color-primary);
+ text-decoration: none;
+ display: flex;
+ align-items: center;
+ gap: var(--spacing-xs);
+ transition: color 0.2s ease;
+}
+
+.modalLink:hover {
+ color: var(--color-text-highlight);
+ text-decoration: underline;
+}
\ No newline at end of file
diff --git a/src/components/shared/Tooltip.tsx b/src/components/shared/Tooltip.tsx
index d195da5..c985d7f 100644
--- a/src/components/shared/Tooltip.tsx
+++ b/src/components/shared/Tooltip.tsx
@@ -2,6 +2,7 @@ import { useState } from 'react'
import { Modal } from './Modal'
import { TOOLTIP_DEFINITIONS } from './tooltipDefinitions'
import type { TooltipTypeValues } from './tooltipDefinitions'
+import styles from './Tooltip.module.css'
// Tooltip component for field explanations
interface TooltipProps {
@@ -13,6 +14,7 @@ export function Tooltip({ children, type }: TooltipProps) {
const { title, description, lighthouseRelation, calculation, links } = TOOLTIP_DEFINITIONS[type]
const [isHovered, setIsHovered] = useState(false)
const [isModalOpen, setIsModalOpen] = useState(false)
+ const [tooltipPosition, setTooltipPosition] = useState({ top: 0, left: 0 })
const handleIconClick = (e: React.MouseEvent) => {
e.preventDefault()
@@ -21,29 +23,51 @@ export function Tooltip({ children, type }: TooltipProps) {
setIsModalOpen(true)
}
+ const handleMouseEnter = (e: React.MouseEvent) => {
+ const rect = (e.target as HTMLElement).getBoundingClientRect()
+ setTooltipPosition({
+ top: rect.top - 10, // Position above the icon
+ left: rect.left + rect.width / 2 // Center horizontally
+ })
+ setIsHovered(true)
+ }
+
return (
<>
-
+
{children}
+ className={styles.tooltipIcon}
+ onClick={handleIconClick}
+ onMouseEnter={handleMouseEnter}
+ onMouseLeave={() => setIsHovered(false)}
+ >
?
-
- {/* Hover tooltip - only show when not modal open */}
- {isHovered && !isModalOpen && (
-
-
- {title}
-
-
- {description}
-
-
- Click for detailed information
-
+
+
+ {/* Hover tooltip - rendered as fixed positioned element */}
+ {isHovered && !isModalOpen && (
+
+
+ {title}
- )}
+
+ {description}
+
+
+ Click for detailed information
+
+
+ )}
+
+
{/* Modal with detailed content */}
@@ -52,45 +76,47 @@ export function Tooltip({ children, type }: TooltipProps) {
onClose={() => setIsModalOpen(false)}
title={title}
>
-
-
+
+
{description}
{lighthouseRelation && (
-
-
+
+
🎯 Lighthouse Relationship
-
)}
{calculation && (
-
-
+
+
🧮 Calculation
-
)}
{links && links.length > 0 && (
-