feat: refresh BossAI console frontend
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user