Skip to content

Commit

Permalink
fix(core): impl ai-island animation via css transform (#7458)
Browse files Browse the repository at this point in the history
  • Loading branch information
CatsJuice authored Jul 9, 2024
1 parent cf7b026 commit 22187f9
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 51 deletions.
31 changes: 8 additions & 23 deletions packages/frontend/core/src/components/pure/ai-island/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,9 @@ import {
aiIslandAnimationBg,
aiIslandBtn,
aiIslandWrapper,
borderAngle1,
borderAngle2,
borderAngle3,
gradient,
} from './styles.css';

if (
typeof window !== 'undefined' &&
window.CSS &&
window.CSS.registerProperty
) {
const getName = (nameWithVar: string) => nameWithVar.slice(4, -1);
const registerAngle = (varName: string, initialValue: number) => {
window.CSS.registerProperty({
name: getName(varName),
syntax: '<angle>',
inherits: false,
initialValue: `${initialValue}deg`,
});
};
registerAngle(borderAngle1, 0);
registerAngle(borderAngle2, 90);
registerAngle(borderAngle3, 180);
}

export const AIIsland = () => {
// to make sure ai island is hidden first and animate in
const [hide, setHide] = useState(true);
Expand All @@ -52,7 +31,13 @@ export const AIIsland = () => {
data-hide={hide}
data-animation={!aiChatHasEverOpened}
>
<div className={aiIslandAnimationBg} />
{aiChatHasEverOpened ? null : (
<div className={aiIslandAnimationBg}>
<div className={gradient} />
<div className={gradient} />
<div className={gradient} />
</div>
)}
<button
className={aiIslandBtn}
data-testid="ai-island"
Expand Down
65 changes: 41 additions & 24 deletions packages/frontend/core/src/components/pure/ai-island/styles.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,8 @@ const brightGreen = createVar('bright-green');
const brightRed = createVar('bright-red');
const borderWidth = createVar('border-width');

const rotateBg1 = keyframes({
to: { [borderAngle1.slice(4, -1)]: '360deg' },
});
const rotateBg2 = keyframes({
to: { [borderAngle2.slice(4, -1)]: '450deg' },
});
const rotateBg3 = keyframes({
to: { [borderAngle3.slice(4, -1)]: '540deg' },
const rotateBg = keyframes({
to: { transform: 'rotate(360deg)' },
});

export const aiIslandAnimationBg = style({
Expand All @@ -68,6 +62,7 @@ export const aiIslandAnimationBg = style({
left: 0,
position: 'absolute',
borderRadius: '50%',
overflow: 'hidden',

vars: {
[borderAngle1]: '0deg',
Expand All @@ -79,29 +74,51 @@ export const aiIslandAnimationBg = style({
[borderWidth]: '1.5px',
},
backgroundColor: 'transparent',
backgroundImage: `conic-gradient(from ${borderAngle1} at 50% 50%,
transparent,
${brightBlue} 10%,
transparent 30%,
transparent),
conic-gradient(from ${borderAngle2} at 50% 50%,
transparent,
${brightGreen} 10%,
transparent 60%,
transparent),
conic-gradient(from ${borderAngle3} at 50% 50%,
transparent,
${brightRed} 10%,
transparent 50%,
transparent)`,

selectors: {
[`${aiIslandWrapper}[data-animation="true"] &`]: {
width: `calc(100% + 2 * ${borderWidth})`,
height: `calc(100% + 2 * ${borderWidth})`,
top: `calc(-1 * ${borderWidth})`,
left: `calc(-1 * ${borderWidth})`,
animation: `${rotateBg1} 3s linear infinite, ${rotateBg2} 8s linear infinite, ${rotateBg3} 13s linear infinite`,
},
},
});

export const gradient = style({
position: 'absolute',
width: '100%',
height: '100%',
borderRadius: 'inherit',
animationName: rotateBg,
animationIterationCount: 'infinite',
animationTimingFunction: 'linear',
pointerEvents: 'none',
willChange: 'transform',
selectors: {
[`&:nth-of-type(1)`]: {
animationDuration: '3s',
backgroundImage: `conic-gradient(from ${borderAngle1} at 50% 50%,
transparent, ${brightBlue} 10%,
transparent 30%,
transparent
)`,
},
[`&:nth-of-type(2)`]: {
animationDuration: '8s',
backgroundImage: `conic-gradient(from ${borderAngle2} at 50% 50%,
transparent, ${brightGreen} 10%,
transparent 60%,
transparent
)`,
},
[`&:nth-of-type(3)`]: {
animationDuration: '13s',
backgroundImage: `conic-gradient(from ${borderAngle3} at 50% 50%,
transparent, ${brightRed} 10%,
transparent 50%,
transparent
)`,
},
},
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { GlobalState } from '@toeverything/infra';
import { Entity, LiveData } from '@toeverything/infra';
import { combineLatest } from 'rxjs';

import type { SidebarTabName } from '../../multi-tab-sidebar';
import { RightSidebarView } from './right-sidebar-view';
Expand All @@ -14,11 +15,13 @@ export class RightSidebar extends Entity {
constructor(private readonly globalState: GlobalState) {
super();

const sub = this.activeTabName$.subscribe(name => {
if (name === 'chat') {
this.globalState.set(RIGHT_SIDEBAR_AI_HAS_EVER_OPENED_KEY, true);
const sub = combineLatest([this.activeTabName$, this.isOpen$]).subscribe(
([name, open]) => {
if (name === 'chat' && open) {
this.globalState.set(RIGHT_SIDEBAR_AI_HAS_EVER_OPENED_KEY, true);
}
}
});
);
this._disposables.push(() => sub.unsubscribe());
}

Expand Down

0 comments on commit 22187f9

Please sign in to comment.