Fix tutorial spotlight behind sticky header and crosslink nav attributes

Tutorial: account for sticky header height in needsScroll check so
the spotlight doesn't render behind the header at narrow viewports.

Crosslinks: fix data attribute mismatches in two navigateToCard calls
— capture template used 'data-id' instead of 'data-template-id', and
PP template used 'data-id' instead of 'data-pp-template-id'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 23:15:40 +03:00
parent a89b3a25d0
commit 6a7826e550
2 changed files with 5 additions and 4 deletions

View File

@@ -1162,7 +1162,7 @@ function renderPictureSourcesList(streams) {
detailsHtml = `<div class="stream-card-props"> detailsHtml = `<div class="stream-card-props">
<span class="stream-card-prop" title="${t('streams.display')}">${ICON_MONITOR} ${stream.display_index ?? 0}</span> <span class="stream-card-prop" title="${t('streams.display')}">${ICON_MONITOR} ${stream.display_index ?? 0}</span>
<span class="stream-card-prop" title="${t('streams.target_fps')}">${ICON_FPS} ${stream.target_fps ?? 30}</span> <span class="stream-card-prop" title="${t('streams.target_fps')}">${ICON_FPS} ${stream.target_fps ?? 30}</span>
${capTmplName ? `<span class="stream-card-prop stream-card-link" title="${t('streams.capture_template')}" onclick="event.stopPropagation(); navigateToCard('streams','raw','raw-templates','data-id','${stream.capture_template_id}')">${ICON_TEMPLATE} ${capTmplName}</span>` : ''} ${capTmplName ? `<span class="stream-card-prop stream-card-link" title="${t('streams.capture_template')}" onclick="event.stopPropagation(); navigateToCard('streams','raw','raw-templates','data-template-id','${stream.capture_template_id}')">${ICON_TEMPLATE} ${capTmplName}</span>` : ''}
</div>`; </div>`;
} else if (stream.stream_type === 'processed') { } else if (stream.stream_type === 'processed') {
const sourceStream = _cachedStreams.find(s => s.id === stream.source_stream_id); const sourceStream = _cachedStreams.find(s => s.id === stream.source_stream_id);
@@ -1176,7 +1176,7 @@ function renderPictureSourcesList(streams) {
} }
detailsHtml = `<div class="stream-card-props"> detailsHtml = `<div class="stream-card-props">
<span class="stream-card-prop stream-card-link" title="${t('streams.source')}" onclick="event.stopPropagation(); navigateToCard('streams','${sourceSubTab}','${sourceSection}','data-stream-id','${stream.source_stream_id}')">${ICON_LINK_SOURCE} ${sourceName}</span> <span class="stream-card-prop stream-card-link" title="${t('streams.source')}" onclick="event.stopPropagation(); navigateToCard('streams','${sourceSubTab}','${sourceSection}','data-stream-id','${stream.source_stream_id}')">${ICON_LINK_SOURCE} ${sourceName}</span>
${ppTmplName ? `<span class="stream-card-prop stream-card-link" title="${t('streams.pp_template')}" onclick="event.stopPropagation(); navigateToCard('streams','processed','proc-templates','data-id','${stream.postprocessing_template_id}')">${ICON_TEMPLATE} ${ppTmplName}</span>` : ''} ${ppTmplName ? `<span class="stream-card-prop stream-card-link" title="${t('streams.pp_template')}" onclick="event.stopPropagation(); navigateToCard('streams','processed','proc-templates','data-pp-template-id','${stream.postprocessing_template_id}')">${ICON_TEMPLATE} ${ppTmplName}</span>` : ''}
</div>`; </div>`;
} else if (stream.stream_type === 'static_image') { } else if (stream.stream_type === 'static_image') {
const src = stream.image_source || ''; const src = stream.image_source || '';

View File

@@ -314,9 +314,10 @@ function showTutorialStep(index, direction = 1) {
target.classList.add('tutorial-target'); target.classList.add('tutorial-target');
if (isFixed) target.style.zIndex = '10001'; if (isFixed) target.style.zIndex = '10001';
// Scroll target into view if off-screen (smooth animation) // Scroll target into view if off-screen or behind sticky header
const preRect = target.getBoundingClientRect(); const preRect = target.getBoundingClientRect();
const needsScroll = preRect.bottom > window.innerHeight || preRect.top < 0; const headerH = isFixed ? (parseInt(getComputedStyle(document.documentElement).getPropertyValue('--header-height')) || 0) : 0;
const needsScroll = preRect.bottom > window.innerHeight || preRect.top < headerH;
if (needsScroll) { if (needsScroll) {
target.scrollIntoView({ behavior: 'smooth', block: 'center' }); target.scrollIntoView({ behavior: 'smooth', block: 'center' });