diff --git a/client/src/components/Leaderboard.css b/client/src/components/Leaderboard.css index 0dda857a..f05e2a9b 100644 --- a/client/src/components/Leaderboard.css +++ b/client/src/components/Leaderboard.css @@ -59,6 +59,7 @@ h2 { width: 100%; flex-grow: 1; overflow-y: auto; + overflow-x: visible; border-radius: 8px; background-color: rgba(30, 30, 30, 0.4); /* Slightly darker but still transparent */ border: 1px solid rgba(255, 255, 255, 0.05); @@ -176,6 +177,39 @@ h2 { border-radius: 4px; } +/* Title tooltip styles */ +.title-with-tooltip { + position: relative; + cursor: help; +} + +.title-tooltip { + visibility: hidden; + opacity: 0; + position: fixed; + background-color: rgba(20, 20, 20, 0.98); + color: #fff; + padding: 0.6rem 0.9rem; + border-radius: 6px; + font-size: 0.85rem; + max-width: 280px; + text-align: left; + z-index: 10000; + box-shadow: 0 6px 20px rgba(0, 0, 0, 0.6); + border: 1px solid rgba(245, 128, 37, 0.4); + pointer-events: none; + transition: opacity 0.2s ease, visibility 0.2s ease; + line-height: 1.4; + white-space: normal; + word-wrap: break-word; + transform: translateY(8px); +} + +.title-with-tooltip:hover .title-tooltip { + visibility: visible; + opacity: 1; +} + .leaderboard-stats { display: flex; gap: 1.5rem; diff --git a/client/src/components/Leaderboard.jsx b/client/src/components/Leaderboard.jsx index 46c6b001..94566458 100644 --- a/client/src/components/Leaderboard.jsx +++ b/client/src/components/Leaderboard.jsx @@ -425,8 +425,21 @@ function Leaderboard({ defaultDuration = 15, defaultPeriod = 'alltime', layoutMo const titleToShow = titles?.find(t => t.is_equipped); return titleToShow ? (
- + { + const tooltip = e.currentTarget.querySelector('.title-tooltip'); + if (tooltip) { + const rect = e.currentTarget.getBoundingClientRect(); + tooltip.style.top = `${rect.bottom + 8}px`; + tooltip.style.left = `${rect.left}px`; + } + }} + > {titleToShow.name} + {titleToShow.description && ( + {titleToShow.description} + )}
) : null; diff --git a/client/src/components/ProfileModal.css b/client/src/components/ProfileModal.css index a794ee43..1fe205c4 100644 --- a/client/src/components/ProfileModal.css +++ b/client/src/components/ProfileModal.css @@ -950,6 +950,38 @@ color: var(--text-color-highlight); } +/* Title tooltip styles for profile modal */ +.displayed-title-name.title-with-tooltip { + position: relative; + cursor: help; +} + +.displayed-title-name.title-with-tooltip .title-tooltip { + visibility: hidden; + opacity: 0; + position: fixed; + background-color: rgba(20, 20, 20, 0.98); + color: #fff; + padding: 0.6rem 0.9rem; + border-radius: 6px; + font-size: 0.85rem; + max-width: 280px; + text-align: left; + z-index: 10001; + box-shadow: 0 6px 20px rgba(0, 0, 0, 0.6); + border: 1px solid rgba(245, 128, 37, 0.4); + pointer-events: none; + transition: opacity 0.2s ease, visibility 0.2s ease; + line-height: 1.4; + white-space: normal; + word-wrap: break-word; +} + +.displayed-title-name.title-with-tooltip:hover .title-tooltip { + visibility: visible; + opacity: 1; +} + .no-title-display { font-style: italic; color: #888888; diff --git a/client/src/components/ProfileModal.jsx b/client/src/components/ProfileModal.jsx index 6106cd6b..d856e03b 100644 --- a/client/src/components/ProfileModal.jsx +++ b/client/src/components/ProfileModal.jsx @@ -757,12 +757,52 @@ function ProfileModal({ isOpen, onClose, netid }) {
{loadingTitles ? ( Loading title... - ) : displayUser && displayUser.selected_title_id && userTitles.find(t => String(t.id) === String(displayUser.selected_title_id))?.name ? ( + ) : displayUser && displayUser.selected_title_id && userTitles.find(t => String(t.id) === String(displayUser.selected_title_id)) ? ( // Display the equipped title if available - {userTitles.find(t => String(t.id) === String(displayUser.selected_title_id)).name} - ) : userTitles.find(t => t.is_equipped)?.name ? ( + (() => { + const equippedTitle = userTitles.find(t => String(t.id) === String(displayUser.selected_title_id)); + return ( + { + const tooltip = e.currentTarget.querySelector('.title-tooltip'); + if (tooltip) { + const rect = e.currentTarget.getBoundingClientRect(); + tooltip.style.top = `${rect.bottom + 8}px`; + tooltip.style.left = `${rect.left}px`; + } + }} + > + {equippedTitle.name} + {equippedTitle.description && ( + {equippedTitle.description} + )} + + ); + })() + ) : userTitles.find(t => t.is_equipped) ? ( // Alternatively check for is_equipped flag from the API response - {userTitles.find(t => t.is_equipped).name} + (() => { + const equippedTitle = userTitles.find(t => t.is_equipped); + return ( + { + const tooltip = e.currentTarget.querySelector('.title-tooltip'); + if (tooltip) { + const rect = e.currentTarget.getBoundingClientRect(); + tooltip.style.top = `${rect.bottom + 8}px`; + tooltip.style.left = `${rect.left}px`; + } + }} + > + {equippedTitle.name} + {equippedTitle.description && ( + {equippedTitle.description} + )} + + ); + })() ) : ( // Display message if no title is equipped User has no title selected