Skip to content

Commit 29197c2

Browse files
Add predictive hover previews to concrete explorer
Add scoped desktop hover and focus previews for sliders, Material Source controls, and Pareto points. Smoothly arbitrate preview-to-commit posterior transitions, preserve categorical inputs, improve mobile slider touch targets, and add deterministic Playwright coverage for ownership, motion, accessibility, and interaction races.
1 parent 9ff838a commit 29197c2

9 files changed

Lines changed: 1570 additions & 80 deletions

File tree

docs/style.css

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,11 @@ h2 {
551551
Note: no `max-height` / `overflow-y` here — the panel grows to fit all
552552
ingredient rows naturally on desktop. The references panel in column 3 is
553553
typically taller, so the composition panel still ends within the page flow. */
554-
.sliders { grid-column: 1; position: relative; }
554+
.sliders {
555+
grid-column: 1;
556+
position: relative;
557+
transition: box-shadow 180ms ease-out;
558+
}
555559
.sliders-header {
556560
display: flex;
557561
align-items: center;
@@ -715,8 +719,8 @@ h2 {
715719
/* Half the rendered thumb width, exposed as a CSS variable so the JS
716720
marker-positioning math (`showSliderPreview` in ui.mjs) can derive
717721
the same value via `getComputedStyle(...).getPropertyValue('--thumb-half')`.
718-
Mobile overrides this to 8 px because the thumb is shrunk to 16 px
719-
in the @media block below; without that override, the preview marker
722+
Mobile overrides this to 11 px for its larger 22 px touch thumb;
723+
without that override, the preview marker
720724
sat 1 px off-track on mobile. */
721725
--thumb-half: 9px;
722726
}
@@ -793,12 +797,15 @@ h2 {
793797
transition: left 0.15s ease-out;
794798
animation: previewPulse 1.5s ease-in-out infinite;
795799
}
800+
.slider-preview-marker.tracking {
801+
transition: none;
802+
}
796803
@keyframes previewPulse {
797804
0%, 100% { opacity: 0.8; transform: translate(-9px, -9px) scale(1); }
798805
50% { opacity: 0.55; transform: translate(-9px, -9px) scale(1.15); }
799806
}
800807
.sliders.previewing {
801-
border-color: var(--accent);
808+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08), inset 0 0 0 1px var(--accent);
802809
}
803810
.info-row {
804811
display: flex;
@@ -864,6 +871,7 @@ h2 {
864871
margin-top: 4px;
865872
}
866873
.toggle-btn {
874+
position: relative;
867875
flex: 1;
868876
padding: 4px 8px;
869877
font-size: 0.78rem;
@@ -885,6 +893,20 @@ h2 {
885893
border-color: var(--accent);
886894
transform: translateY(-1px);
887895
}
896+
.toggle-btn[data-previewing]::after {
897+
content: "";
898+
position: absolute;
899+
inset: -3px;
900+
border: 2px solid var(--text);
901+
border-radius: 10px;
902+
pointer-events: none;
903+
opacity: 0.8;
904+
animation: togglePreviewPulse 1.5s ease-in-out infinite;
905+
}
906+
@keyframes togglePreviewPulse {
907+
0%, 100% { opacity: 0.8; transform: scale(1); }
908+
50% { opacity: 0.55; transform: scale(1.06); }
909+
}
888910

889911
/* Controls */
890912
.controls {
@@ -1594,30 +1616,28 @@ a.ref-link {
15941616
small breathing margin from the label above and info-row below. */
15951617
width: min(60vw, 220px);
15961618
display: block;
1597-
/* 44 px hit area (Apple HIG); the visible bar stays 6 px via the track
1619+
/* 56 px hit area; the visible bar stays 6 px via the track
15981620
pseudo-element. Margin drops to 0 so the row grows by less than the
15991621
full height increase -- the taller target absorbs the gap that used to
16001622
sit between the label row and the info-row. */
1601-
height: 44px;
1623+
height: 56px;
16021624
margin: 0 auto;
16031625
}
1604-
/* Smaller thumb on mobile reduces the intrinsic thumb-half-width inset
1605-
(was 9 px for the 18 px desktop thumb). 16 px is still a comfortable
1606-
touch target combined with the row's vertical generosity. The CSS
1607-
variable below keeps the JS slider-preview-marker math in sync —
1608-
`showSliderPreview` reads `--thumb-half` from the slider-group. */
1626+
/* The mobile thumb is larger than desktop for easier touch acquisition.
1627+
Keep the CSS variable synchronized with its half-width because the JS
1628+
preview-marker geometry reads it from the slider group. */
16091629
.mobile-sliders-view .slider-group {
1610-
--thumb-half: 8px;
1630+
--thumb-half: 11px;
16111631
}
16121632
.mobile-sliders-view .slider-group input[type=range]::-webkit-slider-thumb {
1613-
width: 16px;
1614-
height: 16px;
1615-
/* Re-center the smaller mobile thumb on the 6 px track. */
1616-
margin-top: -5px;
1633+
width: 22px;
1634+
height: 22px;
1635+
/* Re-center the mobile thumb on the 6 px track. */
1636+
margin-top: -8px;
16171637
}
16181638
.mobile-sliders-view .slider-group input[type=range]::-moz-range-thumb {
1619-
width: 16px;
1620-
height: 16px;
1639+
width: 22px;
1640+
height: 22px;
16211641
}
16221642
.mobile-sliders-view .slider-group .info-row {
16231643
/* Right-align the max-bound text to the same pixel column as the
@@ -1745,4 +1765,7 @@ a.ref-link {
17451765
animation is sufficient -- no transform override needed. */
17461766
animation: none !important;
17471767
}
1768+
.toggle-btn[data-previewing]::after {
1769+
animation: none !important;
1770+
}
17481771
}

0 commit comments

Comments
 (0)