Skip to content

Commit 20a185a

Browse files
authored
Fix theme card scroll (#4281)
* fix theme card scroll * review feedback: preserve hash updates
1 parent 26b9417 commit 20a185a

1 file changed

Lines changed: 47 additions & 4 deletions

File tree

packages/base/default-templates/theme-dashboard.gts

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,43 @@ import {
1717
} from '@cardstack/boxel-ui/components';
1818
import { bool, cn } from '@cardstack/boxel-ui/helpers';
1919

20+
function scrollToSection(sectionId: string, event: Event) {
21+
event.preventDefault();
22+
let navEl = event.currentTarget as HTMLElement;
23+
let card = navEl.closest('.detailed-style-reference');
24+
let section = card?.querySelector(
25+
`[id="${sectionId}"]`,
26+
) as HTMLElement | null;
27+
if (!section) {
28+
return;
29+
}
30+
let scrollContainer = findScrollableParent(navEl);
31+
if (!scrollContainer) {
32+
return;
33+
}
34+
let stickyNavHeight = navEl.closest('nav')?.clientHeight ?? 0;
35+
let delta =
36+
section.getBoundingClientRect().top -
37+
scrollContainer.getBoundingClientRect().top -
38+
stickyNavHeight;
39+
scrollContainer.scrollBy({ top: delta, behavior: 'smooth' });
40+
history.pushState(null, '', `#${sectionId}`);
41+
}
42+
43+
function findScrollableParent(el: HTMLElement): HTMLElement | null {
44+
let parent = el.parentElement;
45+
while (parent && parent !== document.documentElement) {
46+
if (parent.scrollHeight > parent.clientHeight) {
47+
let { overflowY } = window.getComputedStyle(parent);
48+
if (overflowY === 'auto' || overflowY === 'scroll') {
49+
return parent;
50+
}
51+
}
52+
parent = parent.parentElement;
53+
}
54+
return null;
55+
}
56+
2057
export interface SectionSignature {
2158
id: string;
2259
navTitle: string;
@@ -199,9 +236,10 @@ export class NavSection extends GlimmerComponent<{
199236
@action
200237
private scrollToTop(event: Event) {
201238
event.preventDefault();
202-
document
203-
.querySelector('#top')
204-
?.scrollIntoView({ behavior: 'smooth', block: 'start' });
239+
let scrollContainer = findScrollableParent(
240+
event.currentTarget as HTMLElement,
241+
);
242+
scrollContainer?.scrollTo({ top: 0, behavior: 'smooth' });
205243
}
206244
}
207245

@@ -222,6 +260,7 @@ export class SimpleNavBar extends GlimmerComponent<{
222260
@kind='secondary'
223261
@size='small'
224262
class='boxel-ellipsize'
263+
{{on 'click' (fn scrollToSection navItem.id)}}
225264
>
226265
{{navItem.navTitle}}
227266
</Button>
@@ -269,7 +308,11 @@ export class NavBar extends GlimmerComponent<{
269308
<div class='nav-container'>
270309
<div class='nav-grid'>
271310
{{#each @sections as |section|}}
272-
<a href='#{{section.id}}' class='nav-item'>{{section.navTitle}}</a>
311+
<a
312+
href='#{{section.id}}'
313+
class='nav-item'
314+
{{on 'click' (fn scrollToSection section.id)}}
315+
>{{section.navTitle}}</a>
273316
{{/each}}
274317
</div>
275318
</div>

0 commit comments

Comments
 (0)