diff --git a/packages/website/src/components/Scroller/index.module.css b/packages/website/src/components/Scroller/index.module.css index 5b5241677..32bd63955 100644 --- a/packages/website/src/components/Scroller/index.module.css +++ b/packages/website/src/components/Scroller/index.module.css @@ -1,4 +1,6 @@ .scroller { + --scroller-curtain-color: var(--gray-1); + display: flex; flex-direction: column; gap: var(--space-3); @@ -25,24 +27,74 @@ } } - .curtain { - width: min(25%, var(--space-7)); - height: calc(100% - var(--space-3) - 2 * var(--space-1)); + &[data-orientation="horizontal"] { + .curtain { + width: min(25%, var(--space-7)); + height: calc(100% - var(--space-3) - 2 * var(--space-1)); - position: absolute; - top: 0; + position: absolute; + top: 0; - opacity: 0; - pointer-events: none; + &[data-side="start"] { + left: 0; + background: linear-gradient( + 90deg, + var(--scroller-curtain-color), + transparent + ); + } - &[data-side="left"] { - left: 0; - background: linear-gradient(90deg, var(--gray-1), transparent); - } - - &[data-side="right"] { - right: 0; - background: linear-gradient(90deg, transparent, var(--gray-1)); + &[data-side="end"] { + right: 0; + background: linear-gradient( + 90deg, + transparent, + var(--scroller-curtain-color) + ); + } } } + + &[data-orientation="vertical"] { + min-height: 0; + + .content { + flex: 1 1 auto; + min-height: 0; + overflow-x: hidden; + overflow-y: auto; + padding-bottom: 0; + } + + .curtain { + width: calc(100% - var(--space-3) - 2 * var(--space-1)); + height: min(25%, var(--space-7)); + + position: absolute; + left: 0; + + &[data-side="start"] { + top: 0; + background: linear-gradient( + 180deg, + var(--scroller-curtain-color), + transparent + ); + } + + &[data-side="end"] { + bottom: 0; + background: linear-gradient( + 180deg, + transparent, + var(--scroller-curtain-color) + ); + } + } + } + + .curtain { + opacity: 0; + pointer-events: none; + } } diff --git a/packages/website/src/components/Scroller/index.tsx b/packages/website/src/components/Scroller/index.tsx index fdab6bebc..393dcbf91 100644 --- a/packages/website/src/components/Scroller/index.tsx +++ b/packages/website/src/components/Scroller/index.tsx @@ -3,66 +3,76 @@ import { clamp } from "three/src/math/MathUtils.js"; import { classNames } from "../../ui/classNames"; import styles from "./index.module.css"; -interface ScrollerProps extends ComponentProps<"div"> {} +interface ScrollerProps extends ComponentProps<"div"> { + orientation?: "horizontal" | "vertical"; +} -export function Scroller({ children, className, ...props }: ScrollerProps) { +export function Scroller({ + children, + className, + orientation = "horizontal", + ...props +}: ScrollerProps) { const content = useRef(null!); - const curtainLeft = useRef(null!); - const curtainRight = useRef(null!); + const curtainStart = useRef(null!); + const curtainEnd = useRef(null!); + + const isHorizontal = orientation === "horizontal"; useEffect(() => { function syncCurtains() { - const maxScroll = - content.current.scrollWidth - content.current.clientWidth; + const maxScroll = isHorizontal + ? content.current.scrollWidth - content.current.clientWidth + : content.current.scrollHeight - content.current.clientHeight; + const scrollPosition = isHorizontal + ? content.current.scrollLeft + : content.current.scrollTop; + if (maxScroll <= 0) { - curtainLeft.current.style.opacity = "0"; - curtainRight.current.style.opacity = "0"; + curtainStart.current.style.opacity = "0"; + curtainEnd.current.style.opacity = "0"; + return; } - const fadeDistance = Math.min(60, content.current.clientWidth * 0.15); - const leftOpacity = clamp( - content.current.scrollLeft / fadeDistance, - 0, - 1, - ); - const rightOpacity = clamp( - (maxScroll - content.current.scrollLeft) / fadeDistance, + const dimension = isHorizontal + ? content.current.clientWidth + : content.current.clientHeight; + const fadeDistance = Math.min(60, dimension * 0.15); + const startOpacity = clamp(scrollPosition / fadeDistance, 0, 1); + const endOpacity = clamp( + (maxScroll - scrollPosition) / fadeDistance, 0, 1, ); - curtainLeft.current.style.opacity = `${leftOpacity}`; - curtainRight.current.style.opacity = `${rightOpacity}`; - } - - function handleScroll() { - syncCurtains(); - } - - function handleResize() { - syncCurtains(); + curtainStart.current.style.opacity = `${startOpacity}`; + curtainEnd.current.style.opacity = `${endOpacity}`; } syncCurtains(); - window.addEventListener("resize", handleResize); - content.current.addEventListener("scroll", handleScroll); + window.addEventListener("resize", syncCurtains); + content.current.addEventListener("scroll", syncCurtains); return () => { - window.removeEventListener("resize", handleResize); - content.current.removeEventListener("scroll", handleScroll); + window.removeEventListener("resize", syncCurtains); + content.current.removeEventListener("scroll", syncCurtains); }; - }, []); + }, [orientation]); return ( -
+
{children}
-
-
+
+
); } diff --git a/packages/website/src/components/TankopediaLoadout/index.module.css b/packages/website/src/components/TankopediaLoadout/index.module.css index 96d214b6f..47583732e 100644 --- a/packages/website/src/components/TankopediaLoadout/index.module.css +++ b/packages/website/src/components/TankopediaLoadout/index.module.css @@ -1,6 +1,4 @@ .section { - max-width: 21rem; - display: flex; flex-direction: column; align-items: flex-start; @@ -80,8 +78,8 @@ } .consumables { - display: flex; - flex-wrap: wrap; + display: grid; + grid-template-columns: repeat(3, max-content); gap: var(--space-3); .consumable-wrapper { diff --git a/packages/website/src/components/TankopediaLoadout/index.tsx b/packages/website/src/components/TankopediaLoadout/index.tsx index 708eb96ba..65d42cd95 100644 --- a/packages/website/src/components/TankopediaLoadout/index.tsx +++ b/packages/website/src/components/TankopediaLoadout/index.tsx @@ -40,7 +40,7 @@ interface TankopediaLoadoutProps { } export function TankopediaLoadout({ characteristics }: TankopediaLoadoutProps) { - const tank = useDuel("protagonist", DuelModule.Tank); + // const tank = useDuel("protagonist", DuelModule.Tank); // const showModules = hasUpgrades(tank); return ( diff --git a/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.module.css b/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.module.css index 5dd7a7e03..acebceff1 100644 --- a/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.module.css +++ b/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.module.css @@ -13,11 +13,14 @@ display: flex; flex-direction: column; - gap: var(--space-5); - padding: var(--space-5); - - overflow-y: auto; - background-color: var(--gray-2); + + .content { + padding: var(--space-5); + + display: flex; + flex-direction: column; + gap: var(--space-5); + } } } diff --git a/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.tsx b/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.tsx index 85e9d06d7..cd62881c3 100644 --- a/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.tsx +++ b/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.tsx @@ -1,5 +1,6 @@ import { useMemo } from "react"; import { api } from "../../../../../api/dynamic"; +import { Scroller } from "../../../../../components/Scroller"; import type { ThicknessRange } from "../../../../../components/StaticArmor"; import { TankopediaCharacteristics } from "../../../../../components/TankopediaCharacteristics"; import { TankopediaGameModeAbilities } from "../../../../../components/TankopediaGameModeAbilities"; @@ -52,9 +53,11 @@ export const Page = withErrorWrapper( return (
-
- -
+ +
+ +
+
{/* {!skeleton && } */}