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

View File

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

View File

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

View File

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

View File

@ -19,7 +19,6 @@ import {
useSettingsContext,
} from "./contexts/SettingsContext";
const apiUrl = import.meta.env.VITE_API_URL;
import "./global.css";
// Component that handles image loading after API data is fetched
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 { Layout } from "antd";
import ContentRenderer from "./ContentRenderer";
import HeaderLogo from "./HeaderLogo";
import ScrollIcon from "../icons/ScrollIcon";
@ -8,8 +9,8 @@ import ImageCarousel from "./ImageCarousel";
import CloseButton from "./CloseButton";
import MenuButton from "./MenuButton";
import { useSettingsContext } from "../contexts/SettingsContext";
import Simplebar from "simplebar-react";
import "simplebar-react/dist/simplebar.min.css";
const { Content } = Layout;
const Page = ({
pageData,
@ -28,11 +29,10 @@ const Page = ({
!pageData.showProperties &&
!pageData.showContactForm &&
!pageData.hideMobileImage;
const scrollRef = useRef(null);
const contentRef = useRef(null);
const [isImageShrunk, setIsImageShrunk] = useState(false);
const [safariBlurToggle, setSafariBlurToggle] = useState(false);
const shrinkDistance = 1;
const [hasVerticalScrollbar, setHasVerticalScrollbar] = useState(false);
const settings = useSettingsContext();
const themes = settings?.themes || [];
@ -43,9 +43,8 @@ const Page = ({
// Reset scroll position and image state when visible becomes false
useEffect(() => {
if (!visible && scrollRef.current) {
const el = scrollRef.current.getScrollElement();
el.scrollTop = 0;
if (!visible && contentRef.current) {
contentRef.current.scrollTop = 0;
setIsImageShrunk(false);
}
}, [visible]);
@ -84,50 +83,14 @@ const Page = ({
};
}, [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(() => {
checkOverflow();
}, [
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;
if (!contentRef.current || !mobileImage) return;
const handleScroll = () => {
// Don't shrink image if page is not visible
if (!visible) return;
const el = scrollRef.current.getScrollElement();
const el = contentRef.current;
const scrollTop = el.scrollTop;
const scrollHeight = el.scrollHeight;
const clientHeight = el.clientHeight;
@ -155,7 +118,7 @@ const Page = ({
}
};
const el = scrollRef.current.getScrollElement();
const el = contentRef.current;
el.addEventListener("scroll", handleScroll);
return () => {
@ -209,23 +172,13 @@ const Page = ({
<ImageCarousel page={pageData} className="th-mobile-image" />
</div>
)}
<div
<Content
className={`th-page-content${
visible == false ? " th-page-content-hidden" : ""
}${isLargeMobile ? " th-page-content-mobile" : ""}`}
ref={contentRef}
>
<Simplebar
className="th-content-scroll"
ref={scrollRef}
forceVisible="y"
autoHide={false}
>
<div
className={`th-content-container-wrapper${
hasVerticalScrollbar ? " th-content-container-wrapper-scroll" : ""
}`}
>
<div className="th-content-container-wrapper">
<div
className={`th-content-container ${
mobileImage ? " th-content-container-mobile-image" : ""
@ -234,9 +187,7 @@ const Page = ({
<ContentRenderer content={pageData?.content} />
</div>
</div>
</Simplebar>
</div>
</Content>
{pageData?.showScroll == true && <ScrollIcon visible={visible} />}
</div>
);

View File

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

935
yarn.lock

File diff suppressed because it is too large Load Diff