From 9045955842d29f238927ee0be656423f967870bd Mon Sep 17 00:00:00 2001 From: weareoutman Date: Thu, 16 Nov 2023 12:27:42 +0800 Subject: [PATCH] fix(main-view): show footer shadow only when it's pinned --- .../containers/src/main-view/index.spec.tsx | 35 +++++++++++++++++-- bricks/containers/src/main-view/index.tsx | 31 ++++++++++++++-- .../src/main-view/styles.shadow.css | 9 +++-- 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/bricks/containers/src/main-view/index.spec.tsx b/bricks/containers/src/main-view/index.spec.tsx index 22fdd15f1..68f3cf170 100644 --- a/bricks/containers/src/main-view/index.spec.tsx +++ b/bricks/containers/src/main-view/index.spec.tsx @@ -5,8 +5,16 @@ import { EoMainView } from "./index.js"; jest.mock("@next-core/theme", () => ({})); +const disconnect = jest.fn(); +(global.IntersectionObserver as any) = jest.fn((callback: any) => ({ + observe() { + callback([{ intersectionRatio: 0.99 }]); + }, + disconnect, +})); + describe("eo-main-view", () => { - test("basic usage", async () => { + test("basic usage", () => { const element = document.createElement("eo-main-view") as EoMainView; expect(element.shadowRoot).toBeFalsy(); @@ -26,7 +34,7 @@ describe("eo-main-view", () => { expect(element.shadowRoot?.childNodes.length).toBe(0); }); - test("narrow", async () => { + test("narrow", () => { const element = document.createElement("eo-main-view") as EoMainView; element.narrow = "medium"; @@ -43,7 +51,7 @@ describe("eo-main-view", () => { }); }); - test("banner alone", async () => { + test("banner alone", () => { const element = document.createElement("eo-main-view") as EoMainView; element.bannerAlone = true; element.bannerTitle = "Hello"; @@ -65,4 +73,25 @@ describe("eo-main-view", () => { document.body.removeChild(element); }); }); + + test("footer", async () => { + const element = document.createElement("eo-main-view") as EoMainView; + + act(() => { + document.body.appendChild(element); + }); + expect( + element.shadowRoot?.querySelector(".footer").classList.contains("pinned") + ).toBe(false); + + element.showFooter = true; + await act(() => (global as any).flushPromises()); + expect( + element.shadowRoot?.querySelector(".footer").classList.contains("pinned") + ).toBe(true); + + act(() => { + document.body.removeChild(element); + }); + }); }); diff --git a/bricks/containers/src/main-view/index.tsx b/bricks/containers/src/main-view/index.tsx index 39399c452..71dbc832d 100644 --- a/bricks/containers/src/main-view/index.tsx +++ b/bricks/containers/src/main-view/index.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect, useLayoutEffect, useRef, useState } from "react"; import { createDecorators } from "@next-core/element"; import { ReactNextElement, @@ -13,6 +13,7 @@ import type { } from "../narrow-view/index.js"; import { BannerProps, EoBanner } from "../banner/index.js"; import styleText from "./styles.shadow.css"; +import classNames from "classnames"; const { defineElement, property } = createDecorators(); @@ -111,6 +112,7 @@ class EoMainView extends ReactNextElement { bannerTitle={this.bannerTitle} bannerDescription={this.bannerDescription} bannerImage={this.bannerImage} + showFooter={this.showFooter} /> ); } @@ -122,9 +124,31 @@ export function EoMainViewComponent({ bannerTitle, bannerDescription, bannerImage, + showFooter, }: MainViewProps) { const narrow = _narrow ?? "full"; const bannerConfig = bannerAlone ? { bannerTitle, bannerDescription } : null; + const footerRef = useRef(null); + const [footerPinned, setFooterPinned] = useState(false); + + useEffect(() => { + const footer = footerRef.current; + if (showFooter && footer) { + const observer = new IntersectionObserver( + ([e]) => { + setFooterPinned(e.intersectionRatio < 1); + }, + { + rootMargin: "0px 0px -1px 0px", + threshold: [1], + } + ); + observer.observe(footer); + return () => { + observer.disconnect(); + }; + } + }, [showFooter]); return ( <> @@ -153,7 +177,10 @@ export function EoMainViewComponent({ -
+
diff --git a/bricks/containers/src/main-view/styles.shadow.css b/bricks/containers/src/main-view/styles.shadow.css index feb16ef25..4ee0fb25c 100644 --- a/bricks/containers/src/main-view/styles.shadow.css +++ b/bricks/containers/src/main-view/styles.shadow.css @@ -80,9 +80,6 @@ eo-banner { position: sticky; bottom: 0; width: 100%; - background: var(--color-fill-global-bg-2); - /* box-shadow: 0px -4px 16px 0px rgba(0,0,0,0.08); */ - box-shadow: var(--slide-up-shadow); margin-left: calc(-1 * var(--page-padding-left)); margin-right: calc(-1 * var(--page-padding-right)); margin-bottom: calc(-1 * var(--page-padding-bottom)); @@ -90,6 +87,12 @@ eo-banner { padding-right: var(--page-padding-right); } +.pinned { + background: var(--color-fill-global-bg-2); + /* box-shadow: 0px -4px 16px 0px rgba(0,0,0,0.08); */ + box-shadow: var(--slide-up-shadow); +} + .footer > eo-narrow-view { padding: 20px 0; }