From 2b23bb7e2a75bbf72788d154dd2388ced7bcaa53 Mon Sep 17 00:00:00 2001 From: peptiderepo <273788462+peptiderepo@users.noreply.github.com> Date: Wed, 29 Apr 2026 13:29:04 +0700 Subject: [PATCH] feat: RCT inline abbreviation tooltip on verdict legend strip (v2.2.1) (#53) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI green (PHP Lint 8.1/8.2/8.3 ✓, PHPCS ✓, PHPUnit 8.1/8.2/8.3 ✓). QA: PASS. --- CHANGELOG.md | 24 +++++++ assets/js/abbr-tooltip.js | 134 ++++++++++++++++++++++++++++++++++++++ footer.php | 2 +- front-page.php | 2 +- functions.php | 7 +- inc/verdict-helpers.php | 49 +++++++++++++- style.css | 54 ++++++++++++++- 7 files changed, 267 insertions(+), 5 deletions(-) create mode 100644 assets/js/abbr-tooltip.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 8374ceb..88fb9c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Peptide Starter Theme - Changelog +## [2.2.1] - 2026-04-29 — RCT inline abbreviation tooltip + +### Added + +- `.pr-abbr` tap-target on the term "RCT" in the Established verdict card on + the verdict legend strip (homepage). Tapping/clicking opens a small inline + popover with the full definition: "Randomized Controlled Trial — the gold + standard for clinical evidence." Closes on outside click, Escape key, or + focus leaving the element. +- `assets/js/abbr-tooltip.js` — new JS module (~130 lines) for popover open/ + close, outside-click dismissal, keyboard accessibility (Enter/Space/Escape), + and ARIA attributes (`aria-expanded`, `aria-describedby`, `role="tooltip"`). + Enqueued on front page only (`is_front_page()`). +- `peptide_starter_render_desc( string $text, array $abbrs ): string` helper in + `inc/verdict-helpers.php`. Builds safe HTML from `esc_html`/`esc_attr` + components; verdict taxonomy items carry an optional `abbrs` map. +- `.pr-abbr` and `.pr-abbr-popover` CSS in `style.css` — dashed underline + affordance, fade-in animation, dark-mode-safe surface variables. + +### Fixed + +- `PEPTIDE_STARTER_VERSION` constant in `functions.php` was stale at + `2.0.0-alpha.3`; realigned to `2.2.1` to match `style.css` Version header. + ## [2.1.8] - 2026-04-28 — Homepage verdict section spacing fix ### Fixed diff --git a/assets/js/abbr-tooltip.js b/assets/js/abbr-tooltip.js new file mode 100644 index 0000000..0284868 --- /dev/null +++ b/assets/js/abbr-tooltip.js @@ -0,0 +1,134 @@ +/** + * abbr-tooltip.js — Inline abbreviation popover for verdict legend screen. + * + * What: Opens a small popover anchored to any .pr-abbr element when tapped, + * clicked, or activated via keyboard. Closes on outside click or Escape. + * Who triggers: Enqueued by functions.php on is_front_page() requests only. + * Depends on: .pr-abbr elements in the DOM with data-def attributes; CSS in + * style.css (.pr-abbr-popover). + * + * @see inc/verdict-helpers.php — peptide_starter_render_desc() emits .pr-abbr elements + * @see style.css — .pr-abbr, .pr-abbr-popover visual styles + * @package peptide-starter + */ + +( function () { + 'use strict'; + + var POPOVER_CLASS = 'pr-abbr-popover'; + var ACTIVE_CLASS = 'pr-abbr--active'; + var activePopover = null; + var activeAbbr = null; + + /** + * Remove the currently open popover, if any. + * + * @return {void} + */ + function closePopover() { + if ( activePopover ) { + activePopover.remove(); + activePopover = null; + } + if ( activeAbbr ) { + activeAbbr.classList.remove( ACTIVE_CLASS ); + activeAbbr.removeAttribute( 'aria-expanded' ); + activeAbbr = null; + } + } + + /** + * Create and position a popover anchored to the given abbr element. + * + * @param {HTMLElement} abbr - The .pr-abbr element that was activated. + * @return {void} + */ + function openPopover( abbr ) { + closePopover(); + + var def = abbr.getAttribute( 'data-def' ); + if ( ! def ) { + return; + } + + var popover = document.createElement( 'div' ); + popover.className = POPOVER_CLASS; + popover.textContent = def; + popover.setAttribute( 'role', 'tooltip' ); + popover.setAttribute( 'id', POPOVER_CLASS + '-' + Date.now() ); + + document.body.appendChild( popover ); + + // Position below the abbr, clamped to viewport width. + var rect = abbr.getBoundingClientRect(); + var scrollTop = window.pageYOffset || document.documentElement.scrollTop; + var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; + var top = rect.bottom + scrollTop + 6; + var left = rect.left + scrollLeft; + var maxLeft = window.innerWidth - popover.offsetWidth - 16; + + popover.style.top = top + 'px'; + popover.style.left = Math.max( 8, Math.min( left, maxLeft ) ) + 'px'; + + abbr.classList.add( ACTIVE_CLASS ); + abbr.setAttribute( 'aria-expanded', 'true' ); + abbr.setAttribute( 'aria-describedby', popover.id ); + + activePopover = popover; + activeAbbr = abbr; + } + + /** + * Toggle the popover for an abbr element (open if closed, close if open). + * + * @param {HTMLElement} abbr - The .pr-abbr element that was activated. + * @return {void} + */ + function togglePopover( abbr ) { + if ( activeAbbr === abbr ) { + closePopover(); + } else { + openPopover( abbr ); + } + } + + // ------------------------------------------------------------------------- + // Event listeners + // ------------------------------------------------------------------------- + + document.addEventListener( 'click', function ( e ) { + var abbr = e.target.closest( '.pr-abbr' ); + if ( abbr ) { + e.stopPropagation(); + togglePopover( abbr ); + return; + } + // Click outside any abbr — close. + closePopover(); + } ); + + document.addEventListener( 'keydown', function ( e ) { + if ( e.key === 'Escape' ) { + closePopover(); + return; + } + if ( e.key === 'Enter' || e.key === ' ' ) { + var abbr = e.target.closest( '.pr-abbr' ); + if ( abbr ) { + e.preventDefault(); + togglePopover( abbr ); + } + } + } ); + + // Close when focus leaves the popover+abbr pair entirely. + document.addEventListener( 'focusin', function ( e ) { + if ( + activeAbbr && + ! activeAbbr.contains( e.target ) && + ( ! activePopover || ! activePopover.contains( e.target ) ) + ) { + closePopover(); + } + } ); +} )(); diff --git a/footer.php b/footer.php index e5b2bbe..ee06f41 100644 --- a/footer.php +++ b/footer.php @@ -57,7 +57,7 @@ echo '