feat: improve and fix animations

This commit is contained in:
Zamitto
2025-05-16 18:12:30 -03:00
parent bc06ae5c03
commit e4f7747200
5 changed files with 198 additions and 84 deletions

View File

@@ -64,6 +64,26 @@ $margin-vertical: 52px;
}
}
@keyframes chip-stand-by {
0% {
opacity: 0;
}
100% {
opacity: 0;
}
}
@keyframes chip-in {
0% {
transform: translateY(20px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
@keyframes title-in {
0% {
transform: translateY(10px);
@@ -110,82 +130,91 @@ $margin-vertical: 52px;
}
.achievement-notification {
position: relative;
display: grid;
width: calc(360px - $margin-horizontal);
height: 140px;
overflow: hidden;
animation:
content-in 450ms ease-in-out,
content-wait 450ms ease-in-out 450ms,
content-expand 450ms ease-in-out 900ms;
width: 360px;
height: 192px;
&::before {
content: "";
position: absolute;
top: 8px;
left: 8px;
width: 64px;
height: 64px;
opacity: 0;
z-index: 1;
background: url("/src/assets/icons/ellipses.png");
background-size: contain;
animation: ellipses-out 900ms ease-in-out;
}
.achievement-notification__outer-container {
position: relative;
display: grid;
width: calc(360px - $margin-horizontal);
overflow: clip;
border: 1px solid #ffffff1a;
animation:
content-in 450ms ease-in-out,
content-wait 450ms ease-in-out 450ms,
content-expand 450ms ease-in-out 900ms;
box-shadow: 0px 2px 16px 0px rgba(0, 0, 0, 0.25);
&::after {
content: "";
position: absolute;
top: 0px;
width: 80px;
height: 80px;
opacity: 0;
background: url("/src/assets/icons/trophy.png") no-repeat center;
animation: trophy-out 900ms ease-in-out;
}
&::before {
content: "";
position: absolute;
top: 8px;
left: 8px;
width: 64px;
height: 64px;
z-index: 2;
opacity: 0;
background: url("/src/assets/icons/ellipses.png");
background-size: contain;
animation: ellipses-out 900ms ease-in-out;
}
&.top_left {
margin: $margin-vertical 0 0 $margin-horizontal;
}
&::after {
content: "";
position: absolute;
top: 0px;
width: 80px;
height: 80px;
opacity: 0;
background: url("/src/assets/icons/trophy.png") no-repeat center;
animation: trophy-out 900ms ease-in-out;
}
&.top_center {
margin: $margin-vertical 0 0 $margin-horizontal;
}
&.top_left {
margin: $margin-vertical 0 0 $margin-horizontal;
}
&.top_right {
margin: $margin-vertical $margin-horizontal 0 0;
align-self: end;
}
&.top_center {
margin: $margin-vertical 0 0 $margin-horizontal;
}
&.bottom_left {
margin: 0 0 $margin-vertical $margin-horizontal;
}
&.top_right {
margin: $margin-vertical $margin-horizontal 0 0;
align-self: end;
}
&.bottom_center {
margin: 0 0 $margin-vertical $margin-horizontal;
}
&.bottom_left {
margin: 0 0 $margin-vertical $margin-horizontal;
}
&.bottom_right {
margin: 0 $margin-horizontal $margin-vertical 0;
align-self: end;
}
&.bottom_center {
margin: 0 0 $margin-vertical $margin-horizontal;
}
&.closing {
transform: translateY(-20px);
opacity: 0;
animation: content-out 450ms ease-in-out;
&.bottom_right {
margin: 0 $margin-horizontal $margin-vertical 0;
align-self: end;
}
&.closing {
animation: content-out 450ms ease-in-out;
animation-fill-mode: forwards;
&::before {
animation: none;
}
&::after {
animation: none;
}
}
}
&__container {
width: calc(360px - $margin-horizontal);
max-width: 100%;
border: 1px solid #ffffff1a;
display: flex;
padding: 8px 16px 8px 8px;
background: globals.$background-color;
transform: translateY(0);
box-shadow: 0px 2px 16px 0px rgba(0, 0, 0, 0.25);
&.top_left {
align-self: flex-start;
@@ -243,7 +272,6 @@ $margin-vertical: 52px;
min-height: 64px;
border-radius: 2px;
flex: 1;
position: relative;
}
&__text-container {
@@ -273,4 +301,71 @@ $margin-vertical: 52px;
color: globals.$body-color;
animation: description-in 450ms ease-in-out 900ms;
}
&__chip-container {
position: relative;
z-index: 2;
animation:
chip-stand-by 900ms,
chip-in 300ms ease-in-out 900ms;
&.closing {
animation: content-out 450ms ease-in-out;
animation-fill-mode: forwards;
}
&.top_left {
margin: $margin-vertical 0 0 $margin-horizontal;
}
&.top_center {
margin: $margin-vertical 0 0 $margin-horizontal;
}
&.top_right {
margin: $margin-vertical $margin-horizontal 0 0;
}
&.bottom_left {
margin: 0 0 $margin-vertical $margin-horizontal;
}
&.bottom_center {
margin: 0 0 $margin-vertical $margin-horizontal;
}
&.bottom_right {
margin: 0 $margin-horizontal $margin-vertical 0;
}
}
&__chip {
position: absolute;
top: -12px;
right: 8px;
display: flex;
gap: 4px;
padding: 0 8px;
border-radius: 300px;
align-items: center;
background: globals.$muted-color;
height: 24px;
animation:
chip-stand-by 900ms ease-in-out,
chip-in 450ms ease-in-out 900ms;
&__icon {
width: 16px;
height: 16px;
path {
fill: globals.$background-color;
}
}
&__label {
color: globals.$background-color;
font-weight: 700;
}
}
}

View File

@@ -4,16 +4,17 @@ import {
} from "@types";
import cn from "classnames";
import "./achievement-notification.scss";
import HydraIcon from "@renderer/assets/icons/hydra.svg?react";
interface AchievementNotificationProps {
position: AchievementCustomNotificationPosition;
currentAchievement: AchievementNotificationInfo;
achievement: AchievementNotificationInfo;
isClosing: boolean;
}
export function AchievementNotificationItem({
position,
currentAchievement,
achievement,
isClosing,
}: Readonly<AchievementNotificationProps>) {
return (
@@ -23,25 +24,48 @@ export function AchievementNotificationItem({
closing: isClosing,
})}
>
{achievement.points && (
<div
className={cn("achievement-notification__chip-container", {
[position]: true,
closing: isClosing,
})}
>
<div className="achievement-notification__chip">
<HydraIcon className="achievement-notification__chip__icon" />
<span className="achievement-notification__chip__label">
+{achievement.points}
</span>
</div>
</div>
)}
<div
className={cn("achievement-notification__container", {
className={cn("achievement-notification__outer-container", {
[position]: true,
closing: isClosing,
})}
>
<div className="achievement-notification__content">
<img
src={currentAchievement.iconUrl}
alt={currentAchievement.title}
className="achievement-notification__icon"
/>
<div className="achievement-notification__text-container">
<p className="achievement-notification__title">
{currentAchievement.title}
</p>
<p className="achievement-notification__description">
{currentAchievement.description}
</p>
<div
className={cn("achievement-notification__container", {
[position]: true,
closing: isClosing,
})}
>
<div className="achievement-notification__content">
<img
src={achievement.iconUrl}
alt={achievement.title}
className="achievement-notification__icon"
/>
<div className="achievement-notification__text-container">
<p className="achievement-notification__title">
{achievement.title}
</p>
<p className="achievement-notification__description">
{achievement.description}
</p>
</div>
</div>
</div>
</div>

View File

@@ -155,7 +155,7 @@ export function AchievementNotification() {
return (
<AchievementNotificationItem
currentAchievement={currentAchievement}
achievement={currentAchievement}
isClosing={isClosing}
position={position}
/>

View File

@@ -158,7 +158,7 @@ export default function ThemeEditor() {
<AchievementNotificationItem
position={achievementPreview.position}
currentAchievement={achievementPreview.achievement}
achievement={achievementPreview.achievement}
isClosing={isClosingNotifications}
/>
</div>

View File

@@ -1,8 +1,3 @@
import {
AchievementCustomNotificationPosition,
AchievementNotificationInfo,
} from "@types";
export enum Downloader {
RealDebrid,
Torrent,