diff --git a/public/images/butterfly_dock.webp b/public/images/butterfly_dock.webp index 00a01ee..0db339d 100644 Binary files a/public/images/butterfly_dock.webp and b/public/images/butterfly_dock.webp differ diff --git a/public/images/contributors/aura.webp b/public/images/contributors/aura.webp new file mode 100644 index 0000000..87698c2 Binary files /dev/null and b/public/images/contributors/aura.webp differ diff --git a/public/images/contributors/chiimera.webp b/public/images/contributors/chiimera.webp new file mode 100644 index 0000000..b0703a4 Binary files /dev/null and b/public/images/contributors/chiimera.webp differ diff --git a/public/images/contributors/eiren.webp b/public/images/contributors/eiren.webp deleted file mode 100644 index dc74634..0000000 Binary files a/public/images/contributors/eiren.webp and /dev/null differ diff --git a/public/images/contributors/elle.webp b/public/images/contributors/elle.webp new file mode 100644 index 0000000..5bdcc19 Binary files /dev/null and b/public/images/contributors/elle.webp differ diff --git a/public/images/contributors/em.webp b/public/images/contributors/em-1.webp similarity index 100% rename from public/images/contributors/em.webp rename to public/images/contributors/em-1.webp diff --git a/public/images/contributors/em-2.webp b/public/images/contributors/em-2.webp new file mode 100644 index 0000000..c936a9d Binary files /dev/null and b/public/images/contributors/em-2.webp differ diff --git a/public/images/contributors/fate.webp b/public/images/contributors/fate.webp new file mode 100644 index 0000000..c1709ba Binary files /dev/null and b/public/images/contributors/fate.webp differ diff --git a/public/images/contributors/futura.webp b/public/images/contributors/futura.webp new file mode 100644 index 0000000..74cfbe9 Binary files /dev/null and b/public/images/contributors/futura.webp differ diff --git a/public/images/contributors/hannahpadd.webp b/public/images/contributors/hannahpadd.webp new file mode 100644 index 0000000..fe12086 Binary files /dev/null and b/public/images/contributors/hannahpadd.webp differ diff --git a/public/images/contributors/hina.webp b/public/images/contributors/hina.webp new file mode 100644 index 0000000..d45a64e Binary files /dev/null and b/public/images/contributors/hina.webp differ diff --git a/public/images/contributors/jovannmc.webp b/public/images/contributors/jovannmc-1.webp similarity index 100% rename from public/images/contributors/jovannmc.webp rename to public/images/contributors/jovannmc-1.webp diff --git a/public/images/contributors/jovannmc-2.webp b/public/images/contributors/jovannmc-2.webp new file mode 100644 index 0000000..735f85b Binary files /dev/null and b/public/images/contributors/jovannmc-2.webp differ diff --git a/public/images/contributors/platinum.webp b/public/images/contributors/platinum.webp new file mode 100644 index 0000000..feb0dcc Binary files /dev/null and b/public/images/contributors/platinum.webp differ diff --git a/public/images/contributors/polymoria.webp b/public/images/contributors/polymoria-1.webp similarity index 100% rename from public/images/contributors/polymoria.webp rename to public/images/contributors/polymoria-1.webp diff --git a/public/images/contributors/polymoria-2.webp b/public/images/contributors/polymoria-2.webp new file mode 100644 index 0000000..a45dee6 Binary files /dev/null and b/public/images/contributors/polymoria-2.webp differ diff --git a/public/images/contributors/sebby.webp b/public/images/contributors/sebby.webp new file mode 100644 index 0000000..47c34b1 Binary files /dev/null and b/public/images/contributors/sebby.webp differ diff --git a/public/images/contributors/shine bright.webp b/public/images/contributors/shine.webp similarity index 100% rename from public/images/contributors/shine bright.webp rename to public/images/contributors/shine.webp diff --git a/public/images/contributors/sky.webp b/public/images/contributors/sky.webp new file mode 100644 index 0000000..e29a230 Binary files /dev/null and b/public/images/contributors/sky.webp differ diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 58148e8..4a22208 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -18,7 +18,8 @@ }, "shop": { "title": "Shop", - "official": "Official ", + "og": "SlimeVR Trackers", + "butterfly": "Butterfly Trackers", "spare-parts": "Spare parts" }, "social": { diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index e651e9a..28fbc50 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -87,12 +87,20 @@ export const Footer: Component = (props) => { />
- + + + + {
{props.children}
-
- + +
+
); diff --git a/src/components/commons/Drawer.tsx b/src/components/commons/Drawer.tsx index 6809dd6..51f95d2 100644 --- a/src/components/commons/Drawer.tsx +++ b/src/components/commons/Drawer.tsx @@ -27,7 +27,7 @@ interface DrawerProps { } export const Drawer: ParentComponent = (props) => { - let drawerContainerRef: HTMLDivElement; + let drawerContainerRef!: HTMLDivElement; let context: DrawerContextData = { events: new TypedEventTarget(), @@ -61,14 +61,14 @@ interface DrawerItemProps { export const DrawerItem: ParentComponent = (props) => { const context = useContext(DrawerContext); - let itemRef: HTMLDivElement; - let itemContentRef: HTMLDivElement; + let itemRef!: HTMLDivElement; + let itemContentRef!: HTMLDivElement; let itemIndex: number; - let contentSizeObserver; + let contentSizeObserver!: ResizeObserver; if (!context) throw new Error("no context for the drawer found!"); - const [contentSize, setContentSize] = createSignal(null); + const [contentSize, setContentSize] = createSignal(); const [isOpen, setOpen] = createSignal(props.open); const onResize = () => { @@ -104,7 +104,7 @@ export const DrawerItem: ParentComponent = (props) => { if (isServer) return { height: "inherit" }; if (!contentSize() || !isOpen()) return { height: `0px` }; - return { height: `${contentSize().height}px` }; + return { height: `${contentSize()?.height}px` }; }); return ( diff --git a/src/components/commons/icons/socials/BoothIcon.tsx b/src/components/commons/icons/socials/BoothIcon.tsx new file mode 100644 index 0000000..96c955f --- /dev/null +++ b/src/components/commons/icons/socials/BoothIcon.tsx @@ -0,0 +1,44 @@ +import { Component } from "solid-js"; + +export const BoothIcon: Component = (props) => { + return ( + + + + + + + + + + + ); +}; diff --git a/src/components/commons/icons/socials/SoundCloudIcon.tsx b/src/components/commons/icons/socials/SoundCloudIcon.tsx new file mode 100644 index 0000000..2936f01 --- /dev/null +++ b/src/components/commons/icons/socials/SoundCloudIcon.tsx @@ -0,0 +1,36 @@ +import { Component } from "solid-js"; + +export const SoundCloudIcon: Component = (props) => { + return ( + + + + + + + + + + + ); +}; diff --git a/src/components/commons/icons/socials/VGenIcon.tsx b/src/components/commons/icons/socials/VGenIcon.tsx new file mode 100644 index 0000000..67ce147 --- /dev/null +++ b/src/components/commons/icons/socials/VGenIcon.tsx @@ -0,0 +1,181 @@ +import { Component } from "solid-js"; + +export const VGenIcon: Component = (props) => { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/src/components/contributors/Card.tsx b/src/components/contributors/Card.tsx index 449e836..4d68a8e 100644 --- a/src/components/contributors/Card.tsx +++ b/src/components/contributors/Card.tsx @@ -28,6 +28,9 @@ import { RedditIcon } from "../commons/icons/socials/RedditIcon"; import { Typography } from "../commons/Typography"; import CircularIcon from "./CircularIcon"; import { PatreonIcon } from "../commons/icons/socials/PatreonIcon"; +import { VGenIcon } from "../commons/icons/socials/VGenIcon"; +import { BoothIcon } from "../commons/icons/socials/BoothIcon"; +import { getCardIndex, getCardName, getContentSize } from "~/utils/dom"; // constants const FALLBACK_COLOR = "#d9d9d9"; // fallback color for cards without a background or border set @@ -52,6 +55,8 @@ const SOCIAL_ICONS: Record< discord: { icon: DiscordIcon, size: 20 }, tiktok: { icon: TiktokIcon, size: 20 }, printables: { icon: PrintablesIcon, size: 18 }, + vgen: { icon: VGenIcon, size: 20 }, + booth: { icon: BoothIcon, size: 22 }, steam: { icon: SteamIcon, size: 18 }, matrix: { icon: MatrixIcon, size: 16 }, website: { icon: WebsiteIcon, size: 20 }, @@ -78,9 +83,18 @@ interface CardProps extends Contributor { } export const Card: ParentComponent = (props) => { - const { name, roles, socials, tags, classes, color, onClick, cachedImage } = - props; + const { + display, + roles, + socials, + tags, + classes, + color, + onClick, + cachedImage, + } = props; const borderColor = color || FALLBACK_COLOR; + const name = getCardName(display); let card: HTMLDivElement = null as any; let placeholder: HTMLDivElement = null as any; // placeholder for the card when focused to keep its position in list @@ -89,7 +103,7 @@ export const Card: ParentComponent = (props) => { const [imageError, setImageError] = createSignal(cachedImage?.error ?? false); const [imageLoading, setImageLoading] = createSignal(!cachedImage); const [imgSrc, setImgSrc] = createSignal( - cachedImage?.src ?? `/images/contributors/jovannmc.webp` + cachedImage?.src ?? `/images/contributors/jovannmc-1.webp` ); const [imgClasses, setImgClasses] = createSignal( cachedImage?.classes ?? @@ -130,7 +144,7 @@ export const Card: ParentComponent = (props) => { ) => { if (transitioning()) return; - const rect = cachedRect || card.getBoundingClientRect(); + const rect = cachedRect || getContentSize(card); const x = clientX - rect.left; const y = clientY - rect.top; const centerX = rect.width / 2; @@ -176,7 +190,7 @@ export const Card: ParentComponent = (props) => { }; const isMouseOverCard = (e: PointerEvent) => { - const rect = cachedRect || card.getBoundingClientRect(); + const rect = cachedRect || getContentSize(card); // allow extra pixels of tolerance to prevent glitching on edges return ( e.clientX >= rect.left - CARD_TOLERANCE && @@ -193,7 +207,7 @@ export const Card: ParentComponent = (props) => { const cardHoverEnter = (e: PointerEvent) => { if (props.isFocused || transitioning() || e.pointerType === "touch") return; - cachedRect = card.getBoundingClientRect(); + cachedRect = getContentSize(card); card.style.transition = `transform ${HOVER_TRANSITION_DURATION}ms ease`; card.style.willChange = "transform"; document.addEventListener("pointermove", cardHoverTilt, { passive: true }); @@ -247,7 +261,7 @@ export const Card: ParentComponent = (props) => { setCardVars(); card.offsetHeight; // force reflow - const rect = card.getBoundingClientRect(); + const rect = getContentSize(card); originalPosition = { top: rect.top, left: rect.left }; placeholder.style.display = "block"; @@ -407,7 +421,14 @@ export const Card: ParentComponent = (props) => { // only load via network request if not cached setImageLoading(true); const image = new Image(); - image.src = `/images/contributors/${name.toLowerCase()}.webp`; + + if (display.length > 1) { + const i = getCardIndex(display.length) - 1; + image.src = display[i].src; + } else { + image.src = display[0].src; + } + image.onload = () => { setImgSrc(image.src); setImgClasses( @@ -446,7 +467,7 @@ export const Card: ParentComponent = (props) => { aria-hidden="true" /> - {/* the actual card*/} + {/* the actual card */}
@@ -25,42 +25,45 @@ const TrackerCard: Component<{ tag="h1" textAlign="text-center" key={props.titleKey} - class="text-[2.25rem] font-bold" + class="text-[24px] lg:text-[28px] xl:text-[32px] font-bold" /> -
+
SlimeVR tracker image
{/* regular version of order button */} -