| 1 |
/** |
| 2 |
* Tooltip — the single, canonical tooltip for the admin component system. |
| 3 |
* |
| 4 |
* CSS-only, driven by a `data-tip` attribute. Works two ways: |
| 5 |
* |
| 6 |
* 1. Wrap any element (e.g. a button): |
| 7 |
* <span class="wpsubs-tooltip" data-tip="Regenerate API Key"><button>…</button></span> |
| 8 |
* |
| 9 |
* 2. Inline help icon beside a label (see wpsubs_render_tooltip()): |
| 10 |
* <span class="wpsubs-tooltip" data-tip="…" role="img" aria-label="…"> |
| 11 |
* <span class="dashicons dashicons-editor-help wpsubs-tooltip__icon" aria-hidden="true"></span> |
| 12 |
* </span> |
| 13 |
* |
| 14 |
* The bubble (::after) shows above the trigger with a downward caret (::before), |
| 15 |
* only while the trigger is hovered/focused. Long text wraps (max-width). The |
| 16 |
* trigger is a non-labelable <span>, so nesting it inside a <label> never makes |
| 17 |
* label-hover reveal the bubble. Place it inside an overflow:visible container. |
| 18 |
* |
| 19 |
* Placement is orthogonal — combine one direction with one alignment: |
| 20 |
* Direction (which side): --top (default), --bottom, --left, --right |
| 21 |
* Alignment (offset along the cross-axis): --start, --center (default), --end |
| 22 |
* e.g. `wpsubs-tooltip--bottom wpsubs-tooltip--end`. The caret always points at |
| 23 |
* the trigger regardless of alignment. |
| 24 |
*/ |
| 25 |
|
| 26 |
.wpsubs-tooltip { |
| 27 |
position: relative; |
| 28 |
display: inline-flex; |
| 29 |
align-items: center; |
| 30 |
vertical-align: text-bottom; |
| 31 |
} |
| 32 |
|
| 33 |
/* Bubble. */ |
| 34 |
.wpsubs-tooltip[data-tip]::after { |
| 35 |
content: attr(data-tip); |
| 36 |
position: absolute; |
| 37 |
bottom: calc(100% + 9px); |
| 38 |
left: 50%; |
| 39 |
transform: translateX(-50%); |
| 40 |
z-index: 9999; |
| 41 |
width: max-content; |
| 42 |
max-width: 240px; |
| 43 |
padding: 8px 11px; |
| 44 |
border-radius: 7px; |
| 45 |
background: var(--wpsubs-text, #1f2327); |
| 46 |
color: #fff; |
| 47 |
font-size: 12px; |
| 48 |
font-weight: 400; |
| 49 |
line-height: 1.5; |
| 50 |
text-align: left; |
| 51 |
text-transform: none; |
| 52 |
letter-spacing: normal; |
| 53 |
white-space: normal; |
| 54 |
box-shadow: |
| 55 |
0 8px 24px rgba(0, 0, 0, 0.16), |
| 56 |
0 3px 8px rgba(0, 0, 0, 0.1); |
| 57 |
opacity: 0; |
| 58 |
pointer-events: none; |
| 59 |
} |
| 60 |
|
| 61 |
/* Caret — a rotated square. It sits ABOVE the bubble (higher z-index) and |
| 62 |
overlaps its edge, so the bubble's edge/shadow never draws a seam across the |
| 63 |
arrow: the arrow and bubble read as one solid shape. */ |
| 64 |
.wpsubs-tooltip[data-tip]::before { |
| 65 |
content: ""; |
| 66 |
position: absolute; |
| 67 |
bottom: calc(100% + 9px); |
| 68 |
left: 50%; |
| 69 |
width: 9px; |
| 70 |
height: 9px; |
| 71 |
background: var(--wpsubs-text, #1f2327); |
| 72 |
transform: translate(-50%, 40%) rotate(45deg); |
| 73 |
z-index: 10000; |
| 74 |
opacity: 0; |
| 75 |
pointer-events: none; |
| 76 |
} |
| 77 |
|
| 78 |
.wpsubs-tooltip[data-tip]:hover::after, |
| 79 |
.wpsubs-tooltip[data-tip]:hover::before, |
| 80 |
.wpsubs-tooltip[data-tip]:focus-visible::after, |
| 81 |
.wpsubs-tooltip[data-tip]:focus-visible::before { |
| 82 |
opacity: 1; |
| 83 |
} |
| 84 |
|
| 85 |
/* Help-icon usage (wpsubs_render_hint): the --hint modifier carries the gap |
| 86 |
from the preceding label text, so the trigger span stays exactly icon-width |
| 87 |
and the caret centres on the icon. */ |
| 88 |
.wpsubs-tooltip--hint { |
| 89 |
margin-left: 5px; |
| 90 |
} |
| 91 |
|
| 92 |
.wpsubs-tooltip__icon.dashicons { |
| 93 |
font-size: 15px; |
| 94 |
width: 15px; |
| 95 |
height: 15px; |
| 96 |
line-height: 1; |
| 97 |
color: var(--wpsubs-text-subtle); |
| 98 |
cursor: help; |
| 99 |
transition: color 0.12s ease; |
| 100 |
} |
| 101 |
|
| 102 |
.wpsubs-tooltip:hover .wpsubs-tooltip__icon.dashicons { |
| 103 |
color: var(--wpsubs-brand, #2271b1); |
| 104 |
} |
| 105 |
|
| 106 |
/* ========================================================================== |
| 107 |
Directional placement — which side the bubble is on. Default (no class) is |
| 108 |
--top. The caret always sits over the trigger's centre and points at it. |
| 109 |
========================================================================== */ |
| 110 |
|
| 111 |
/* Bottom: bubble below, caret on its top edge. */ |
| 112 |
.wpsubs-tooltip--bottom[data-tip]::after { |
| 113 |
bottom: auto; |
| 114 |
top: calc(100% + 9px); |
| 115 |
} |
| 116 |
.wpsubs-tooltip--bottom[data-tip]::before { |
| 117 |
bottom: auto; |
| 118 |
top: calc(100% + 9px); |
| 119 |
transform: translate(-50%, -40%) rotate(45deg); |
| 120 |
} |
| 121 |
|
| 122 |
/* Left: bubble to the left, vertically centred, caret on its right edge. */ |
| 123 |
.wpsubs-tooltip--left[data-tip]::after { |
| 124 |
bottom: auto; |
| 125 |
left: auto; |
| 126 |
right: calc(100% + 9px); |
| 127 |
top: 50%; |
| 128 |
transform: translateY(-50%); |
| 129 |
} |
| 130 |
.wpsubs-tooltip--left[data-tip]::before { |
| 131 |
bottom: auto; |
| 132 |
left: auto; |
| 133 |
right: calc(100% + 9px); |
| 134 |
top: 50%; |
| 135 |
transform: translate(40%, -50%) rotate(45deg); |
| 136 |
} |
| 137 |
|
| 138 |
/* Right: bubble to the right, vertically centred, caret on its left edge. */ |
| 139 |
.wpsubs-tooltip--right[data-tip]::after { |
| 140 |
bottom: auto; |
| 141 |
left: calc(100% + 9px); |
| 142 |
top: 50%; |
| 143 |
transform: translateY(-50%); |
| 144 |
} |
| 145 |
.wpsubs-tooltip--right[data-tip]::before { |
| 146 |
bottom: auto; |
| 147 |
left: calc(100% + 9px); |
| 148 |
top: 50%; |
| 149 |
transform: translate(-40%, -50%) rotate(45deg); |
| 150 |
} |
| 151 |
|
| 152 |
/* ========================================================================== |
| 153 |
Alignment — where the bubble sits along the axis perpendicular to the |
| 154 |
direction. Default is --center. The caret does NOT move (it stays over the |
| 155 |
trigger), only the bubble shifts. |
| 156 |
========================================================================== */ |
| 157 |
|
| 158 |
/* Horizontal align for top/bottom directions (i.e. not left/right). */ |
| 159 |
.wpsubs-tooltip--start:not(.wpsubs-tooltip--left):not(.wpsubs-tooltip--right)[data-tip]::after { |
| 160 |
left: -8px; |
| 161 |
right: auto; |
| 162 |
transform: none; |
| 163 |
} |
| 164 |
.wpsubs-tooltip--end:not(.wpsubs-tooltip--left):not(.wpsubs-tooltip--right)[data-tip]::after { |
| 165 |
left: auto; |
| 166 |
right: -8px; |
| 167 |
transform: none; |
| 168 |
} |
| 169 |
|
| 170 |
/* Vertical align for left/right directions. */ |
| 171 |
.wpsubs-tooltip--left.wpsubs-tooltip--start[data-tip]::after, |
| 172 |
.wpsubs-tooltip--right.wpsubs-tooltip--start[data-tip]::after { |
| 173 |
top: -8px; |
| 174 |
bottom: auto; |
| 175 |
transform: none; |
| 176 |
} |
| 177 |
.wpsubs-tooltip--left.wpsubs-tooltip--end[data-tip]::after, |
| 178 |
.wpsubs-tooltip--right.wpsubs-tooltip--end[data-tip]::after { |
| 179 |
top: auto; |
| 180 |
bottom: -8px; |
| 181 |
transform: none; |
| 182 |
} |
| 183 |
|