Skip to content

Commit

Permalink
Merge pull request #16 from youngkyo0504/refactor/motion-one
Browse files Browse the repository at this point in the history
fix: motion one 적용및 element가 간헐적으로 계속 만들어지는 이슈
  • Loading branch information
youngkyo0504 authored Oct 10, 2024
2 parents b293e18 + 88a860b commit ca8c108
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 211 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "chrome-extension-boilerplate-react-vite",
"version": "1.0.2",
"version": "1.0.4",
"description": "chrome extension boilerplate",
"license": "MIT",
"repository": {
Expand Down
59 changes: 31 additions & 28 deletions pages/content/lib/animation/animations.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
import { SpringPhysics } from './physics';
import { animate, timeline } from 'motion';

Check failure on line 1 in pages/content/lib/animation/animations.ts

View workflow job for this annotation

GitHub Actions / eslint

timeline not found in 'motion'

export const showing = new SpringPhysics({
startAt: 0,
options: {
namespace: '--copy-url',
mass: 1,
tension: 200,
friction: 100,
start_velocity: 0,
},
update: ({ namespace, value }) => {
document.documentElement.style.setProperty(namespace + '-y', `${10 - value * 10}%`);
document.documentElement.style.setProperty(namespace + '-opacity', `${value}`);
},
});
const keyframesLikeSpring = [0.32, 0.72, 0, 1] as const;

export const scale = new SpringPhysics({
startAt: 1,
options: {
namespace: '--copy-url',
mass: 1,
tension: 200,
friction: 100,
start_velocity: 0,
},
update: ({ namespace, value }) => {
document.documentElement.style.setProperty(namespace + '-scale', `${value}`);
},
});
export const dismiss = (selector: string) => {
return animate(selector, { y: 10, opacity: 0, filter: 'blur(2px)' }, { duration: 0.3 });
};

export const scaleAndShrink = (selector: string) =>
timeline([
[selector, { scale: 1.1 }, { duration: 0.7, easing: keyframesLikeSpring }],
[selector, { scale: 1 }, { duration: 0.6, easing: 'ease-in-out' }],
]);

export const open = (selector: string) => {

Check failure on line 15 in pages/content/lib/animation/animations.ts

View workflow job for this annotation

GitHub Actions / eslint

'selector' is defined but never used
return animate(
'.copy-url-content',
{ y: '0px', opacity: 1, filter: 'blur(0px)' },
{
y: {
easing: keyframesLikeSpring,
duration: 0.5,
},
filter: {
duration: 0.3,
},
opacity: {
easing: 'ease-in-out',
duration: 0.3,
},
},
);
};
114 changes: 0 additions & 114 deletions pages/content/lib/animation/physics.ts

This file was deleted.

3 changes: 3 additions & 0 deletions pages/content/lib/dom/css.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any
/**
* NOTE: css함수 안에 주석을 넣지 마시오. 템플릿 리터럴은 주석을 문자열로 취급함
*/
export function css(strings: TemplateStringsArray, ...values: any[]) {

Check failure on line 5 in pages/content/lib/dom/css.ts

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type
let str = '';
strings.forEach((string, i) => {
Expand Down
2 changes: 1 addition & 1 deletion pages/content/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ runAtDocumentEnd(async () => {
const copyHandler = async (event: KeyboardEvent) => {
if (!matchShortcut(event)) return;
event.preventDefault();
toastUI.createToast({ message: chrome.i18n.getMessage('whenAction'), duration: 1000 });
toastUI.showToast({ message: chrome.i18n.getMessage('whenAction'), duration: 1000 });
const link = await getLink(await getSelectorFunc(rules));
await copyHTML(link);
};
Expand Down
101 changes: 37 additions & 64 deletions pages/content/lib/ui/toast.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { css } from '../dom/css';
import { linkIcon } from './linkIcon';
import { text } from '../dom/text';
import { scale, showing } from '@lib/animation/animations';
import * as animation from '@lib/animation/animations';

interface Toast {
message: string;
Expand All @@ -12,6 +12,7 @@ export class ToastUI {
private container: HTMLElement;
private existToastId: string | null = null;
private timer: number | null = null;
private state: 'open' | 'close' = 'close';

constructor() {
this.container = document.createElement('div');
Expand All @@ -38,21 +39,34 @@ export class ToastUI {
}, duration);
}

createToast({ message, duration = 2000 }: Toast) {
if (this.existToastId && typeof this.timer === 'number') {
this.scale();
showToast({ message, duration = 2000 }: Toast) {
if (this.existToastId) {
if (this.state === 'open') {
this.scale();
}

if (this.state === 'close') {
this.open();
}

this.queueDismiss(duration, this.existToastId);
return;
}

this.createToast({
message,
duration,
});
}

createToast({ message, duration = 2000 }: Toast) {
const id = `toast-${Math.random().toString(36).substr(2, 9)}`;
const toastEl = this.buildDom(message);
toastEl.id = id;
this.existToastId = id;
this.container.appendChild(toastEl);

this.open();
this.queueDismiss(duration, this.existToastId);
this.open();
}

buildDom(message: string) {
Expand All @@ -63,30 +77,36 @@ export class ToastUI {
toastElementContent.appendChild(linkIcon());
toastElementContent.appendChild(text(message));
toastElementContent.className = 'copy-url-content';

// toastElementContent.style.setProperty('--motion-translateY', '10px');
return toastElement;
}

private open() {
showing.to(1);
this.state = 'open';
animation.open('.copy-url-content');
}

private scale() {
scale.to(1.1, () => {
scale.to(1);
});
private async scale() {
animation.scaleAndShrink('.copy-url-content');
}

dismiss(id: string) {
const toastElement = document.getElementById(id);
if (toastElement) {
showing.to(0, () => {
toastElement.remove();
this.state = 'close';
animation.dismiss('.copy-url-content').finished.then(() => {
if (this.state === 'open') return;
this.existToastId = null;
toastElement.remove();
});
}
}
}

// NOTE: Motion-One에서 translateY는 individual transform을 지원해야하기때문에 css variable을 이용한다. 참고할것
// @see (https://motion.dev/docs/improvements-to-the-web-animations-api-dx#individual-transforms)
// buildDom에서 --motion-translateY를 설정해주었기때문에 css에는 translateY를 적지않는다.
const toastCSS = css`
.copy-url-toast {
position: fixed;
Expand All @@ -112,60 +132,13 @@ const toastCSS = css`
line-height: 1;
user-select: none;
will-change: transform, opacity;
scale: var(--copy-url-scale, 1);
transform: translateY(var(--copy-url-y, 100px));
opacity: var(--copy-url-opacity, 1);
--motion-translateY: 10px;
filter: blur(1px);
scale: 1;
opacity: 0;
}
.copy-url-content span {
color: hsl(0 0% 93.333%);
}
.copy-url-toast[data-side='top'] {
animation: slideUpAndFade 0.3s ease-out forwards;
}
.copy-url-toast[data-side='down'] {
animation: slideDownAndFade 0.3s ease-out forwards;
}
.copy-url-content[data-scale='true'] {
transform-origin: center;
animation: scale 0.3s ease-out forwards;
}
@keyframes slideDownAndFade {
from {
opacity: 1;
transform: translate(-50%, 0%);
}
to {
opacity: 0;
transform: translate(-50%, 10%);
}
}
@keyframes slideUpAndFade {
from {
opacity: 0;
transform: translate(-50%, 10%);
}
to {
opacity: 1;
transform: translate(-50%, 0%);
}
}
@keyframes scale {
from {
opacity: 0;
scale: 1;
transform: translate(-50%, 0);
}
to {
opacity: 1;
scale: 1.5;
transform: translate(-50%, 0);
}
}
`;
7 changes: 4 additions & 3 deletions pages/content/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
},
"dependencies": {
"@chrome-extension-boilerplate/shared": "workspace:*",
"@chrome-extension-boilerplate/storage": "workspace:*"
"@chrome-extension-boilerplate/storage": "workspace:*",
"motion": "^10.18.0"
},
"devDependencies": {
"@chrome-extension-boilerplate/tsconfig": "workspace:*",
"@chrome-extension-boilerplate/hmr": "workspace:*"
"@chrome-extension-boilerplate/hmr": "workspace:*",
"@chrome-extension-boilerplate/tsconfig": "workspace:*"
}
}
Loading

0 comments on commit ca8c108

Please sign in to comment.