Compare commits

..

No commits in common. "9561887e4b84babedf477cd9bf36b27c4d1bdd2d" and "32e085c1907aff907a567f0d9817f3a5aeca98b0" have entirely different histories.

8 changed files with 434 additions and 704 deletions

View File

@ -1,2 +1,2 @@
VITE_API_URL=https://dev.tombutcher.work/api VITE_API_URL=https://thehideout.tombutcher.work/api
VITE_TURNSTILE_KEY=0x4AAAAAAB2dBq6i8m4kYzDm VITE_TURNSTILE_KEY=0x4AAAAAAB2dBq6i8m4kYzDm

View File

@ -1,4 +1,4 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
@ -24,6 +24,7 @@
name="apple-mobile-web-app-status-bar-style" name="apple-mobile-web-app-status-bar-style"
content="black-translucent" content="black-translucent"
/> />
<link rel="stylesheet" href="/global.css" />
<link rel="stylesheet" href="/fonts.css" /> <link rel="stylesheet" href="/fonts.css" />
<link rel="manifest" href="/manifest.json" /> <link rel="manifest" href="/manifest.json" />
<title>The Hideout</title> <title>The Hideout</title>

View File

@ -29,7 +29,6 @@
"react-scroll": "^1.9.3", "react-scroll": "^1.9.3",
"react-turnstile": "^1.1.4", "react-turnstile": "^1.1.4",
"sass": "^1.86.3", "sass": "^1.86.3",
"simplebar-react": "^3.3.2",
"vite": "^6.2.5", "vite": "^6.2.5",
"vite-plugin-svgo": "^2.0.0", "vite-plugin-svgo": "^2.0.0",
"vite-plugin-svgr": "^4.5.0", "vite-plugin-svgr": "^4.5.0",

View File

@ -303,8 +303,7 @@ hr.th-divider {
flex-grow: 3; flex-grow: 3;
padding: 0 var(--th-page-padding); padding: 0 var(--th-page-padding);
margin: 0; margin: 0;
height: 100%; /* Use fixed height instead of min-height */ height: var(--unit-100vh); /* Use fixed height instead of min-height */
min-height: 0;
width: 100%; width: 100%;
color: var(--th-textColor); color: var(--th-textColor);
display: flex; display: flex;
@ -312,36 +311,9 @@ hr.th-divider {
align-items: start; align-items: start;
text-align: left; text-align: left;
transition: opacity 0.3s ease-in-out; transition: opacity 0.3s ease-in-out;
} /* Prevent layout shifts */
contain: layout style;
.th-content-scroll { overflow-y: scroll;
height: 100%;
width: 100%;
flex: 1 1 auto;
}
.simplebar-scrollbar:before {
background: var(--th-textColor);
}
.simplebar-track.simplebar-vertical {
width: 6px;
}
.simplebar-scrollbar.simplebar-visible:before {
opacity: 1;
}
/* Ensure Simplebar fills and scrolls correctly */
.th-content-scroll .simplebar-content-wrapper {
height: 100%;
overflow-y: auto;
}
.th-content-scroll .simplebar-content {
min-height: 100%;
display: flex;
flex-direction: column;
} }
.th-page-content-mobile { .th-page-content-mobile {
@ -478,10 +450,6 @@ hr.th-divider {
flex-grow: 1; flex-grow: 1;
} }
.th-content-container-wrapper-scroll {
padding-right: 20px;
}
/* App component styles */ /* App component styles */
.th-app-container { .th-app-container {
height: var(--unit-100vh); height: var(--unit-100vh);
@ -787,10 +755,8 @@ hr.th-divider {
overflow: hidden; /* Prevent overflow */ overflow: hidden; /* Prevent overflow */
border-bottom: 1px solid var(--th-textColor); border-bottom: 1px solid var(--th-textColor);
transition: opacity 0.3s ease-in-out, transition: opacity 0.3s ease-in-out,
max-height 0.75s cubic-bezier(0, 0.5, 0.5, 1), max-height 0.75s cubic-bezier(0, 0.5, 0.5, 1);
min-height 0.75s cubic-bezier(0, 0.5, 0.5, 1);
opacity: 1; opacity: 1;
min-height: 260px;
max-height: 260px; max-height: 260px;
} }
@ -799,7 +765,6 @@ hr.th-divider {
} }
.th-page-mobile-image-wrapper-shrunk { .th-page-mobile-image-wrapper-shrunk {
min-height: 110px;
max-height: 110px; max-height: 110px;
} }

View File

@ -19,7 +19,6 @@ import {
useSettingsContext, useSettingsContext,
} from "./contexts/SettingsContext"; } from "./contexts/SettingsContext";
const apiUrl = import.meta.env.VITE_API_URL; const apiUrl = import.meta.env.VITE_API_URL;
import "./global.css";
// Component that handles image loading after API data is fetched // Component that handles image loading after API data is fetched
const AppContent = ({ pages, properties, images }) => { const AppContent = ({ pages, properties, images }) => {

View File

@ -1,5 +1,6 @@
import { useEffect, useRef, useState, useCallback } from "react"; import { useEffect, useRef, useState } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { Layout } from "antd";
import ContentRenderer from "./ContentRenderer"; import ContentRenderer from "./ContentRenderer";
import HeaderLogo from "./HeaderLogo"; import HeaderLogo from "./HeaderLogo";
import ScrollIcon from "../icons/ScrollIcon"; import ScrollIcon from "../icons/ScrollIcon";
@ -8,8 +9,8 @@ import ImageCarousel from "./ImageCarousel";
import CloseButton from "./CloseButton"; import CloseButton from "./CloseButton";
import MenuButton from "./MenuButton"; import MenuButton from "./MenuButton";
import { useSettingsContext } from "../contexts/SettingsContext"; import { useSettingsContext } from "../contexts/SettingsContext";
import Simplebar from "simplebar-react";
import "simplebar-react/dist/simplebar.min.css"; const { Content } = Layout;
const Page = ({ const Page = ({
pageData, pageData,
@ -28,11 +29,10 @@ const Page = ({
!pageData.showProperties && !pageData.showProperties &&
!pageData.showContactForm && !pageData.showContactForm &&
!pageData.hideMobileImage; !pageData.hideMobileImage;
const scrollRef = useRef(null); const contentRef = useRef(null);
const [isImageShrunk, setIsImageShrunk] = useState(false); const [isImageShrunk, setIsImageShrunk] = useState(false);
const [safariBlurToggle, setSafariBlurToggle] = useState(false); const [safariBlurToggle, setSafariBlurToggle] = useState(false);
const shrinkDistance = 1; const shrinkDistance = 1;
const [hasVerticalScrollbar, setHasVerticalScrollbar] = useState(false);
const settings = useSettingsContext(); const settings = useSettingsContext();
const themes = settings?.themes || []; const themes = settings?.themes || [];
@ -43,9 +43,8 @@ const Page = ({
// Reset scroll position and image state when visible becomes false // Reset scroll position and image state when visible becomes false
useEffect(() => { useEffect(() => {
if (!visible && scrollRef.current) { if (!visible && contentRef.current) {
const el = scrollRef.current.getScrollElement(); contentRef.current.scrollTop = 0;
el.scrollTop = 0;
setIsImageShrunk(false); setIsImageShrunk(false);
} }
}, [visible]); }, [visible]);
@ -84,50 +83,14 @@ const Page = ({
}; };
}, [isImageShrunk, mobileImage]); }, [isImageShrunk, mobileImage]);
const checkOverflow = useCallback(() => {
if (!scrollRef.current) return;
const el = scrollRef.current.getScrollElement();
if (!el) return;
const canScroll = el.scrollHeight > el.clientHeight;
setHasVerticalScrollbar(canScroll);
}, []);
// Recalculate overflow on mount, when layout/content changes, and on resize
useEffect(() => { useEffect(() => {
checkOverflow(); if (!contentRef.current || !mobileImage) return;
}, [
checkOverflow,
pageData?.content,
visible,
isLargeMobile,
isMobile,
mobileImage,
]);
// Observe size changes of the scroll container
useEffect(() => {
if (!scrollRef.current) return;
const el = scrollRef.current.getScrollElement();
if (!el) return;
const resizeObserver = new ResizeObserver(() => {
checkOverflow();
});
resizeObserver.observe(el);
window.addEventListener("resize", checkOverflow);
return () => {
resizeObserver.disconnect();
window.removeEventListener("resize", checkOverflow);
};
}, [checkOverflow]);
useEffect(() => {
if (!scrollRef.current || !mobileImage) return;
const handleScroll = () => { const handleScroll = () => {
// Don't shrink image if page is not visible // Don't shrink image if page is not visible
if (!visible) return; if (!visible) return;
const el = scrollRef.current.getScrollElement(); const el = contentRef.current;
const scrollTop = el.scrollTop; const scrollTop = el.scrollTop;
const scrollHeight = el.scrollHeight; const scrollHeight = el.scrollHeight;
const clientHeight = el.clientHeight; const clientHeight = el.clientHeight;
@ -155,7 +118,7 @@ const Page = ({
} }
}; };
const el = scrollRef.current.getScrollElement(); const el = contentRef.current;
el.addEventListener("scroll", handleScroll); el.addEventListener("scroll", handleScroll);
return () => { return () => {
@ -209,23 +172,13 @@ const Page = ({
<ImageCarousel page={pageData} className="th-mobile-image" /> <ImageCarousel page={pageData} className="th-mobile-image" />
</div> </div>
)} )}
<Content
<div
className={`th-page-content${ className={`th-page-content${
visible == false ? " th-page-content-hidden" : "" visible == false ? " th-page-content-hidden" : ""
}${isLargeMobile ? " th-page-content-mobile" : ""}`} }${isLargeMobile ? " th-page-content-mobile" : ""}`}
ref={contentRef}
> >
<Simplebar <div className="th-content-container-wrapper">
className="th-content-scroll"
ref={scrollRef}
forceVisible="y"
autoHide={false}
>
<div
className={`th-content-container-wrapper${
hasVerticalScrollbar ? " th-content-container-wrapper-scroll" : ""
}`}
>
<div <div
className={`th-content-container ${ className={`th-content-container ${
mobileImage ? " th-content-container-mobile-image" : "" mobileImage ? " th-content-container-mobile-image" : ""
@ -234,9 +187,7 @@ const Page = ({
<ContentRenderer content={pageData?.content} /> <ContentRenderer content={pageData?.content} />
</div> </div>
</div> </div>
</Simplebar> </Content>
</div>
{pageData?.showScroll == true && <ScrollIcon visible={visible} />} {pageData?.showScroll == true && <ScrollIcon visible={visible} />}
</div> </div>
); );

View File

@ -8,7 +8,7 @@ export default defineConfig({
plugins: [react(), svgo(), svgr()], plugins: [react(), svgo(), svgr()],
server: { server: {
host: "0.0.0.0", host: "0.0.0.0",
allowedHosts: ["dev.tombutcher.work"], allowedHosts: ["thehideout.tombutcher.work"],
}, },
base: "/", base: "/",
}); });

935
yarn.lock

File diff suppressed because it is too large Load Diff