feat: refresh BossAI console frontend

This commit is contained in:
boos
2026-06-06 15:25:04 +08:00
parent 45aa741d9c
commit dd874bae30
6 changed files with 1060 additions and 14 deletions
+120
View File
@@ -0,0 +1,120 @@
import React, { useEffect, useRef } from 'react';
import { gsap } from 'gsap';
type MotionVariant = 'page' | 'login';
interface MotionDivProps extends React.HTMLAttributes<HTMLDivElement> {
motionKey?: string;
motionVariant?: MotionVariant;
}
const PAGE_TARGET_SELECTOR = [
':scope > .console-hero',
':scope > .page-header',
':scope > .card',
':scope > .mobile-card',
':scope > .workflow-shell',
':scope > .picture-agent-shell',
':scope > .workspace-layout',
':scope > .dashboard-grid',
':scope > .digital-human-layout',
':scope > .money-printer-layout',
':scope > .about-page',
].join(', ');
const LOGIN_TARGET_SELECTOR = [
'.login-brand-header',
'.login-brand-copy-block',
'.login-compat-line',
'.login-capability-row',
'.login-auth-eyebrow',
'.login-auth-title',
'.login-auth-copy',
'.login-mode-tabs',
'.login-auth-panel form',
'.login-auth-footer',
].join(', ');
function selectMotionTargets(root: HTMLDivElement, variant: MotionVariant): Element[] {
const selector = variant === 'login' ? LOGIN_TARGET_SELECTOR : PAGE_TARGET_SELECTOR;
return Array.from(root.querySelectorAll(selector)).slice(0, variant === 'login' ? 14 : 18);
}
export default function MotionDiv({
children,
className,
motionKey,
motionVariant = 'page',
...props
}: MotionDivProps) {
const rootRef = useRef<HTMLDivElement>(null);
const resolvedMotionKey = motionKey || motionVariant;
useEffect(() => {
const root = rootRef.current;
if (!root) return undefined;
const mm = gsap.matchMedia();
mm.add(
{
reduceMotion: '(prefers-reduced-motion: reduce)',
isDesktop: '(min-width: 900px)',
},
(context) => {
const conditions = context.conditions || {};
if (conditions.reduceMotion) {
gsap.set(root, { autoAlpha: 1, clearProps: 'transform,opacity,visibility' });
return undefined;
}
const targets = selectMotionTargets(root, motionVariant);
const distance = motionVariant === 'login' ? 16 : 10;
const rootTween = gsap.fromTo(
root,
{ autoAlpha: 0, y: Math.max(6, distance - 4) },
{
autoAlpha: 1,
y: 0,
duration: motionVariant === 'login' ? 0.46 : 0.34,
ease: 'power2.out',
clearProps: 'transform,opacity,visibility',
},
);
const targetTween = targets.length
? gsap.fromTo(
targets,
{ autoAlpha: 0, y: distance },
{
autoAlpha: 1,
y: 0,
duration: motionVariant === 'login' ? 0.58 : 0.42,
ease: 'power2.out',
stagger: motionVariant === 'login' ? 0.045 : 0.025,
delay: 0.04,
clearProps: 'transform,opacity,visibility',
},
)
: null;
return () => {
rootTween.kill();
targetTween?.kill();
};
},
);
return () => mm.revert();
}, [resolvedMotionKey, motionVariant]);
return (
<div
ref={rootRef}
className={['motion-root', className].filter(Boolean).join(' ')}
{...props}
>
{children}
</div>
);
}