mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
Implement unified scroll to download section
This commit is contained in:
@@ -3,7 +3,11 @@ import { MaterialIcon } from "@/utils/material";
|
|||||||
import { GitHubLink, GITHUB_WEB, GITHUB_APP, GITHUB_LICENSE } from "@/pages/home/homeLinks";
|
import { GitHubLink, GITHUB_WEB, GITHUB_APP, GITHUB_LICENSE } from "@/pages/home/homeLinks";
|
||||||
import styles from "@/pages/home/home-footer.module.scss";
|
import styles from "@/pages/home/home-footer.module.scss";
|
||||||
|
|
||||||
export function HomeFooter() {
|
interface HomeFooterProps {
|
||||||
|
onScrollToDownload?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function HomeFooter({ onScrollToDownload }: HomeFooterProps) {
|
||||||
return (
|
return (
|
||||||
<footer className={styles.homepageFooter}>
|
<footer className={styles.homepageFooter}>
|
||||||
<div className={styles.footerBrand}>
|
<div className={styles.footerBrand}>
|
||||||
@@ -15,10 +19,14 @@ export function HomeFooter() {
|
|||||||
</div>
|
</div>
|
||||||
<div className={styles.footerLinks}>
|
<div className={styles.footerLinks}>
|
||||||
<div className={styles.footerSection}>
|
<div className={styles.footerSection}>
|
||||||
<Link to="/#download" className={styles.footerLink}>
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onScrollToDownload}
|
||||||
|
className={styles.footerLink}
|
||||||
|
>
|
||||||
<MaterialIcon name="download" className={styles.footerLinkIcon} />
|
<MaterialIcon name="download" className={styles.footerLinkIcon} />
|
||||||
Скачать приложение
|
Скачать приложение
|
||||||
</Link>
|
</button>
|
||||||
<Link to="/login" className={styles.footerLink}>
|
<Link to="/login" className={styles.footerLink}>
|
||||||
<MaterialIcon name="language" className={styles.footerLinkIcon} />
|
<MaterialIcon name="language" className={styles.footerLinkIcon} />
|
||||||
Веб-версия
|
Веб-версия
|
||||||
|
|||||||
@@ -5,15 +5,23 @@ import { MaterialButton, MaterialIconButton } from "@/utils/material";
|
|||||||
import { GitHubLink, SupportLink } from "@/pages/home/homeLinks";
|
import { GitHubLink, SupportLink } from "@/pages/home/homeLinks";
|
||||||
import styles from "@/pages/home/home-header.module.scss";
|
import styles from "@/pages/home/home-header.module.scss";
|
||||||
|
|
||||||
export function HomeHeader() {
|
interface HomeHeaderProps {
|
||||||
|
onScrollToDownload?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function HomeHeader({ onScrollToDownload }: HomeHeaderProps) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { user } = useUserStore();
|
const { user } = useUserStore();
|
||||||
const { isMobile } = useDownloadAppScreen();
|
const { isMobile } = useDownloadAppScreen();
|
||||||
const isLoggedIn = user.authToken && user.currentUser;
|
const isLoggedIn = user.authToken && user.currentUser;
|
||||||
|
|
||||||
|
const handleMobileDownload = () => {
|
||||||
|
onScrollToDownload?.();
|
||||||
|
};
|
||||||
|
|
||||||
function handleGetStarted() {
|
function handleGetStarted() {
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
navigate("/download-app");
|
handleMobileDownload();
|
||||||
} else if (isLoggedIn) {
|
} else if (isLoggedIn) {
|
||||||
navigate("/chat");
|
navigate("/chat");
|
||||||
} else {
|
} else {
|
||||||
@@ -35,7 +43,7 @@ export function HomeHeader() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className={styles.homepageHeader}>
|
<header className={styles.homepageHeader} data-home-header>
|
||||||
<div className={styles.headerInner}>
|
<div className={styles.headerInner}>
|
||||||
<div className={styles.headerContent}>
|
<div className={styles.headerContent}>
|
||||||
<div className={styles.logo}>
|
<div className={styles.logo}>
|
||||||
@@ -55,7 +63,7 @@ export function HomeHeader() {
|
|||||||
{isMobile ? (
|
{isMobile ? (
|
||||||
<MaterialIconButton
|
<MaterialIconButton
|
||||||
variant="filled"
|
variant="filled"
|
||||||
onClick={() => navigate("/download-app")}
|
onClick={handleMobileDownload}
|
||||||
icon="download"
|
icon="download"
|
||||||
className={styles.headerSmallButton}
|
className={styles.headerSmallButton}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useState, type ReactNode } from "react";
|
import { useRef, useState, type ReactNode } from "react";
|
||||||
import styles from "@/pages/home/home.module.scss";
|
import styles from "@/pages/home/home.module.scss";
|
||||||
import useDownloadAppScreen from "@/core/hooks/useDownloadAppScreen";
|
import useDownloadAppScreen from "@/core/hooks/useDownloadAppScreen";
|
||||||
import { MaterialButton, MaterialIcon, MaterialIconButton, MaterialList, MaterialListItem } from "@/utils/material";
|
import { MaterialButton, MaterialIcon, MaterialIconButton, MaterialList, MaterialListItem } from "@/utils/material";
|
||||||
@@ -55,6 +55,16 @@ export default function HomePage() {
|
|||||||
const [dialogOpen, setDialogOpen] = useState(false);
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
const [dialogOs, setDialogOs] = useState<DownloadOs>(() => detectOs());
|
const [dialogOs, setDialogOs] = useState<DownloadOs>(() => detectOs());
|
||||||
const [menuOpen, setMenuOpen] = useState(false);
|
const [menuOpen, setMenuOpen] = useState(false);
|
||||||
|
const downloadSectionRef = useRef<HTMLElement>(null);
|
||||||
|
|
||||||
|
const scrollToDownload = () => {
|
||||||
|
const section = downloadSectionRef.current;
|
||||||
|
const header = document.querySelector<HTMLElement>("[data-home-header]");
|
||||||
|
if (!section) return;
|
||||||
|
const headerHeight = header?.getBoundingClientRect().height ?? 0;
|
||||||
|
const targetY = section.getBoundingClientRect().top + window.scrollY - headerHeight;
|
||||||
|
window.scrollTo({ top: targetY, behavior: "smooth" });
|
||||||
|
};
|
||||||
|
|
||||||
const triggerDownload = (os: DownloadOs): boolean => {
|
const triggerDownload = (os: DownloadOs): boolean => {
|
||||||
if (typeof document === "undefined") {
|
if (typeof document === "undefined") {
|
||||||
@@ -84,7 +94,7 @@ export default function HomePage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.homepage}>
|
<div className={styles.homepage}>
|
||||||
<HomeHeader />
|
<HomeHeader onScrollToDownload={scrollToDownload} />
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<section className={styles.title}>
|
<section className={styles.title}>
|
||||||
@@ -156,7 +166,7 @@ export default function HomePage() {
|
|||||||
</FeatureSection>
|
</FeatureSection>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="download" className={styles.download}>
|
<section ref={downloadSectionRef} className={styles.download}>
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<div className={styles.downloadContent}>
|
<div className={styles.downloadContent}>
|
||||||
<h3>Скачайте приложение</h3>
|
<h3>Скачайте приложение</h3>
|
||||||
@@ -259,7 +269,7 @@ export default function HomePage() {
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<DownloadDialog open={dialogOpen} onOpenChange={setDialogOpen} os={dialogOs} />
|
<DownloadDialog open={dialogOpen} onOpenChange={setDialogOpen} os={dialogOs} />
|
||||||
<HomeFooter />
|
<HomeFooter onScrollToDownload={scrollToDownload} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,11 @@
|
|||||||
color: $color-dark-on-surface-variant;
|
color: $color-dark-on-surface-variant;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: inherit;
|
||||||
transition: color 0.2s ease, transform 0.15s ease;
|
transition: color 0.2s ease, transform 0.15s ease;
|
||||||
-webkit-user-drag: none;
|
-webkit-user-drag: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@@ -86,6 +91,37 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
color: $color-dark-on-surface;
|
color: $color-dark-on-surface;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button.footerLink {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.footerLink {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.footerLink {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:is(button) {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
transform: scale(0.92);
|
transform: scale(0.92);
|
||||||
|
|||||||
Reference in New Issue
Block a user