added background to panel itself

This commit is contained in:
onysd 2026-09-08 02:02:18 +03:00
parent 87173ae43f
commit f7b3af48de
8 changed files with 122 additions and 58 deletions

View file

@ -1,7 +1,7 @@
import type { FormEvent } from "react";
import { useEffect, useRef, useState } from "react";
import { useEffect, useState } from "react";
import { api, errorMessage } from "../api";
import { BgIcons } from "../components/BgIcons";
import { AppBackground } from "../components/AppBackground";
import { Alert } from "../components/ui";
import { ThemeSwitch } from "../theme";
import type { AdminSession, PublicBranding } from "../types";
@ -19,34 +19,11 @@ export function LoginPage({ onLogin }: { onLogin: (session: AdminSession) => voi
// failure so the panel simply keeps its own branding.
const [branding, setBranding] = useState<PublicBranding | null>(null);
const [iconFailed, setIconFailed] = useState(false);
const orbsRef = useRef<HTMLDivElement>(null);
useEffect(() => {
api.publicBranding().then(setBranding).catch(() => undefined);
}, []);
// The orbs drift with the pointer, the same 30px parallax the marketing site
// uses. Written straight to the node instead of through state: this fires on
// every mouse move, and re-rendering the whole form for a background offset
// would be a lot of work to move three blurred circles.
useEffect(() => {
// Someone who asked the system for less motion gets none of this: the CSS
// drift is already disabled for them, and a JS-driven transform would walk
// straight past that preference.
if (window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) {
return;
}
function onMove(event: MouseEvent) {
const node = orbsRef.current;
if (!node) return;
const x = (event.clientX / window.innerWidth - 0.5) * 30;
const y = (event.clientY / window.innerHeight - 0.5) * 30;
node.style.transform = `translate(${x}px, ${y}px)`;
}
window.addEventListener("mousemove", onMove);
return () => window.removeEventListener("mousemove", onMove);
}, []);
const serverName = branding?.name?.trim() || "OwpenGram";
const iconSrc = branding?.has_icon && !iconFailed ? api.publicIconURL() : "/logo.png";
@ -68,12 +45,7 @@ export function LoginPage({ onLogin }: { onLogin: (session: AdminSession) => voi
return (
<main className="login-page">
<div className="bg-orbs" aria-hidden="true" ref={orbsRef}>
<div className="bg-orb bg-orb--1" />
<div className="bg-orb bg-orb--2" />
<div className="bg-orb bg-orb--3" />
</div>
<BgIcons />
<AppBackground />
<section className="login-panel">
<div className="login-head">
<div className="brand brand-elevated">