mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Mobile: tour bottom-sheet + measured sizing; tidy profile tab-grid tiles
Onboarding tour (tourEngine.js): - On narrow viewports (<640px) dock the popover as a fixed BOTTOM SHEET instead of anchoring it — kills the off-screen/jump-to-center glitches caused by short viewports, wrapping buttons and URL-bar resize. The spotlight still highlights the target, scrolled to center so it sits above the sheet. - On desktop, measure the ACTUAL popover size (getBoundingClientRect) and feed it to computeTourPlacement, instead of the fixed 240/336 guesses that pushed tall popovers off-screen. Profile modal mobile tab grid (CSS): - Equal-height tiles via a min-height token + centered content, so long labels no longer leave a ragged grid. - Move the unread dot to the tile's top-right corner (was landing in the grid gutter at the vertical-nav left edge). - Tighter line-height/padding + non-shrinking glyph. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
55db677637
commit
0e2f81d222
3 files changed
+54
-4
No files matched your search
+17
-3
@@ -3668,12 +3668,16 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
gap: var(--space-2xs);
|
||||
width: 100%;
|
||||
padding-block: var(--space-sm);
|
||||
padding-inline: var(--space-2xs);
|
||||
/* equal-height tiles: a consistent floor so short and 2-line labels align
|
||||
(grid rows stretch to the tallest tile, so within a row they match) */
|
||||
min-block-size: var(--profile-modal-nav-tile-min-height);
|
||||
padding-block: var(--space-xs);
|
||||
padding-inline: var(--space-3xs);
|
||||
line-height: 1.15;
|
||||
/* wrap labels at spaces, not mid-word */
|
||||
overflow-wrap: break-word;
|
||||
word-break: normal;
|
||||
@@ -3684,6 +3688,16 @@
|
||||
.profile-modal__nav > button svg {
|
||||
width: var(--space-lg);
|
||||
height: var(--space-lg);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* In the tile grid the unread dot rides the tile's top-right corner instead
|
||||
of the vertical-nav left edge (where it landed in the grid gutter). */
|
||||
.profile-modal__nav > button .profile-nav__unread-dot {
|
||||
top: var(--space-2xs);
|
||||
left: auto;
|
||||
right: var(--space-2xs);
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -359,6 +359,8 @@
|
||||
--notification-banner-max-inline: var(--size-28rem);
|
||||
--profile-modal-nav-min-width: max-content;
|
||||
--profile-modal-nav-max-width: max-content;
|
||||
/* Equal-height floor for the mobile tab-grid tiles. */
|
||||
--profile-modal-nav-tile-min-height: 4.75rem;
|
||||
--profile-modal-scrollbar-offset: var(--space-2xs);
|
||||
--modal-embed-height: 80vh;
|
||||
--profile-history-max-height: 26.25rem;
|
||||
|
||||
@@ -57,6 +57,20 @@ const TOUR_CSS = `
|
||||
padding: 1rem;
|
||||
transition: left 0.28s ease, top 0.28s ease;
|
||||
}
|
||||
/* Mobile: dock the popover as a bottom sheet instead of anchoring it to the
|
||||
target. Anchored placement is fragile on phones (short viewports, wrapping
|
||||
buttons, URL-bar resize) — a fixed sheet is always in a predictable spot and
|
||||
the spotlight still highlights the (centered-scrolled) target above it. */
|
||||
.bv-tour-popover.bv-tour-popover--sheet {
|
||||
left: 0.75rem;
|
||||
right: 0.75rem;
|
||||
top: auto;
|
||||
bottom: max(0.75rem, env(safe-area-inset-bottom, 0px));
|
||||
transform: none;
|
||||
width: auto;
|
||||
max-width: 32rem;
|
||||
margin-inline: auto;
|
||||
}
|
||||
.bv-tour-popover h3 { font-size: 1rem; font-weight: 700; margin: 0 0 0.375rem; }
|
||||
.bv-tour-popover p { font-size: 0.875rem; margin: 0 0 0.75rem; opacity: 0.9; }
|
||||
.bv-tour-dots { display: flex; gap: 0.375rem; margin-bottom: 0.75rem; }
|
||||
@@ -171,10 +185,13 @@ export function createTour({
|
||||
}
|
||||
};
|
||||
|
||||
const isMobileViewport = () => (doc.defaultView?.innerWidth || 1200) < 640;
|
||||
|
||||
function measure(step) {
|
||||
const target = step.target ? doc.querySelector(step.target) : null;
|
||||
if (!target) {
|
||||
// Centered card: zero-size cutout in the middle (pure dim).
|
||||
state.popover.classList.remove("bv-tour-popover--sheet");
|
||||
setVar(state.scrim, "--bv-tour-x", "50vw");
|
||||
setVar(state.scrim, "--bv-tour-y", "50vh");
|
||||
setVar(state.scrim, "--bv-tour-w", "0px");
|
||||
@@ -187,8 +204,13 @@ export function createTour({
|
||||
return;
|
||||
}
|
||||
|
||||
const mobile = isMobileViewport();
|
||||
try {
|
||||
target.scrollIntoView({ block: "nearest", inline: "nearest" });
|
||||
// Center the target on mobile so it sits above the bottom sheet.
|
||||
target.scrollIntoView({
|
||||
block: mobile ? "center" : "nearest",
|
||||
inline: "nearest",
|
||||
});
|
||||
} catch (error) {
|
||||
// older engines
|
||||
}
|
||||
@@ -200,11 +222,23 @@ export function createTour({
|
||||
setVar(state.scrim, "--bv-tour-w", `${rect.width + pad * 2}px`);
|
||||
setVar(state.scrim, "--bv-tour-h", `${rect.height + pad * 2}px`);
|
||||
|
||||
if (mobile) {
|
||||
// Bottom sheet — no anchored-placement math to get wrong.
|
||||
state.popover.classList.add("bv-tour-popover--sheet");
|
||||
return;
|
||||
}
|
||||
|
||||
// Desktop: anchor, but measure the ACTUAL popover so the fit checks are
|
||||
// accurate (the old 240px/336px guesses pushed tall popovers off-screen).
|
||||
state.popover.classList.remove("bv-tour-popover--sheet");
|
||||
const popRect = state.popover.getBoundingClientRect();
|
||||
const placementResult = computeTourPlacement({
|
||||
rect,
|
||||
viewportWidth: doc.defaultView?.innerWidth || 1200,
|
||||
viewportHeight: doc.defaultView?.innerHeight || 800,
|
||||
preferred: step.placement || "",
|
||||
popWidth: popRect.width || 336,
|
||||
popHeight: popRect.height || 240,
|
||||
});
|
||||
setVar(state.popover, "--bv-tour-px", `${placementResult.px}px`);
|
||||
setVar(state.popover, "--bv-tour-py", `${placementResult.py}px`);
|
||||
|
||||
Reference in new issue
Block a user