Skip to content

Commit b8996ed

Browse files
committed
Add dfw-scroll-visibility component: implement visibility control based on scroll position, enhance styles for visibility transitions, and update main layout to include the new component for improved user experience.
1 parent 6545260 commit b8996ed

5 files changed

Lines changed: 88 additions & 2 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
dfw-scroll-visibility {
2+
display: block;
3+
/* No size in flow; fixed child is out of flow. visibility on host hides the button. */
4+
}
5+
6+
dfw-scroll-visibility[data-visible="false"] {
7+
visibility: hidden;
8+
opacity: 0;
9+
pointer-events: none;
10+
transition: opacity 0.2s ease, visibility 0.2s ease;
11+
}
12+
13+
dfw-scroll-visibility[data-visible="true"] {
14+
transition: opacity 0.2s ease, visibility 0.2s ease;
15+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { Component } from "@ribajs/core";
2+
import { hasChildNodesTrim } from "@ribajs/utils/src/dom.js";
3+
4+
const VISIBLE_SCROLL_START = 0.1; // show after 10% from top
5+
const VISIBLE_SCROLL_END = 0.9; // hide again in last 10%
6+
7+
/**
8+
* Wrapper component that shows its child content only when the page is scrolled
9+
* in the "middle" 80% (between 10% and 90% of scroll range). Use for fixed
10+
* elements like a call button that should be hidden near the top and bottom.
11+
* Pass the content as child nodes (like dfw-contact-map).
12+
*/
13+
export class DfwScrollVisibilityComponent extends Component {
14+
public static tagName = "dfw-scroll-visibility";
15+
16+
protected autobind = true;
17+
18+
static get observedAttributes(): string[] {
19+
return [];
20+
}
21+
22+
private rafId: number | null = null;
23+
private readonly boundUpdateVisibility = () => this.updateVisibility();
24+
25+
protected connectedCallback() {
26+
super.connectedCallback();
27+
this.setAttribute("data-visible", "false");
28+
this.init(DfwScrollVisibilityComponent.observedAttributes);
29+
}
30+
31+
protected async afterBind() {
32+
await super.afterBind();
33+
this.updateVisibility();
34+
window.addEventListener("scroll", this.boundUpdateVisibility, { passive: true });
35+
}
36+
37+
protected disconnectedCallback() {
38+
window.removeEventListener("scroll", this.boundUpdateVisibility);
39+
if (this.rafId !== null) {
40+
cancelAnimationFrame(this.rafId);
41+
}
42+
super.disconnectedCallback();
43+
}
44+
45+
private updateVisibility(): void {
46+
if (this.rafId !== null) return;
47+
this.rafId = requestAnimationFrame(() => {
48+
this.rafId = null;
49+
const maxScroll = document.documentElement.scrollHeight - window.innerHeight;
50+
const visible =
51+
maxScroll <= 0 ||
52+
(window.scrollY >= maxScroll * VISIBLE_SCROLL_START &&
53+
window.scrollY <= maxScroll * VISIBLE_SCROLL_END);
54+
this.setAttribute("data-visible", visible ? "true" : "false");
55+
});
56+
}
57+
58+
protected requiredAttributes(): string[] {
59+
return [];
60+
}
61+
62+
protected template(): string | null {
63+
if (hasChildNodesTrim(this)) {
64+
return null;
65+
}
66+
return `<p>Provide child content to show in the middle 80% scroll range.</p>`;
67+
}
68+
}

src/ts/components/index.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
@import './dfw-background-gears/dfw-background-gears.component';
22
@import './dfw-contact-map/dfw-contact-map.component';
33
@import './dfw-gallery/dfw-gallery.component';
4+
@import './dfw-scroll-visibility/dfw-scroll-visibility.component';

src/ts/components/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export { DfwBackgroundGearsComponent } from "./dfw-background-gears/dfw-background-gears.component.js";
22
export { DfwContactMapComponent } from "./dfw-contact-map/dfw-contact-map.component.js";
3-
export { DfwGalleryComponent } from "./dfw-gallery/dfw-gallery.component.js";
3+
export { DfwGalleryComponent } from "./dfw-gallery/dfw-gallery.component.js";
4+
export { DfwScrollVisibilityComponent } from "./dfw-scroll-visibility/dfw-scroll-visibility.component.js";

src/views/layouts/main.pug

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ html(lang='de')
1818
router-view#main(listen-all-links='true')
1919
block content
2020
include ../partials/footer.pug
21-
include ../partials/fixed-call-button.pug
21+
dfw-scroll-visibility
22+
include ../partials/fixed-call-button.pug
2223
script(src=basePath + '/ts/main.ts', type='module')

0 commit comments

Comments
 (0)