From 8a21500df5c2ddc48a6ac54d1b61fad0bb9777e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Bucquet?= Date: Sat, 10 Feb 2024 20:40:26 +0100 Subject: [PATCH 1/4] feat: adds pause button --- src/css/style.css | 60 ++++++++++++++++++++ src/icons/square-arrow-left-svgrepo-com.svg | 13 +++++ src/icons/square-arrow-right-svgrepo-com.svg | 13 +++++ src/icons/square-pause-svgrepo-com.svg | 13 +++++ src/index.html | 5 ++ src/modules/addRippleEffect.ts | 8 +++ src/modules/handleMenuButtons.ts | 16 ++++++ src/modules/index.ts | 1 + src/modules/rewindColors.ts | 9 ++- src/ts/index.ts | 3 +- 10 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 src/icons/square-arrow-left-svgrepo-com.svg create mode 100644 src/icons/square-arrow-right-svgrepo-com.svg create mode 100644 src/icons/square-pause-svgrepo-com.svg create mode 100644 src/modules/addRippleEffect.ts create mode 100644 src/modules/handleMenuButtons.ts diff --git a/src/css/style.css b/src/css/style.css index 2a5c446..a49a773 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -31,6 +31,7 @@ body { width: 300px; height: 300px; background-color: rgb(53, 45, 106); + transform: translateX(30px); } svg { @@ -125,3 +126,62 @@ path { transform: translate(-45px, -45px); background-color: yellow; } + +button { + width: 40px; + height: 40px; + border-radius: 8px; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + margin-bottom: 4px; + border: none; + background-color: white; + position: relative; + overflow: hidden; +} + +button:hover { + background-color: rgb(242, 242, 242); +} + +img { + height: 25px; + width: 25px; +} + +#menu { + display: flex; + flex-direction: column; + transform: translate(40px, -150px); +} + +button span { + position: absolute; + border-radius: 8px; + background-color: rgba(0, 0, 0, 0.2); + width: 40px; + height: 40px; + animation: ripple 1s; + opacity: 0; +} + +@keyframes ripple { + from { + opacity: 1; + transform: scale(0); + } + to { + opacity: 0; + transform: scale(10); + } +} + +.active { + background-color: rgb(236, 236, 236); +} + +.active:hover { + background-color: rgb(226, 226, 226); +} diff --git a/src/icons/square-arrow-left-svgrepo-com.svg b/src/icons/square-arrow-left-svgrepo-com.svg new file mode 100644 index 0000000..50e5a78 --- /dev/null +++ b/src/icons/square-arrow-left-svgrepo-com.svg @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/src/icons/square-arrow-right-svgrepo-com.svg b/src/icons/square-arrow-right-svgrepo-com.svg new file mode 100644 index 0000000..fed1cb9 --- /dev/null +++ b/src/icons/square-arrow-right-svgrepo-com.svg @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/src/icons/square-pause-svgrepo-com.svg b/src/icons/square-pause-svgrepo-com.svg new file mode 100644 index 0000000..3e8c8c1 --- /dev/null +++ b/src/icons/square-pause-svgrepo-com.svg @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/src/index.html b/src/index.html index 7c5bf08..4b83fce 100644 --- a/src/index.html +++ b/src/index.html @@ -35,6 +35,11 @@ + diff --git a/src/modules/addRippleEffect.ts b/src/modules/addRippleEffect.ts new file mode 100644 index 0000000..b6bd047 --- /dev/null +++ b/src/modules/addRippleEffect.ts @@ -0,0 +1,8 @@ +export const addRippleEffect = (button: HTMLButtonElement): void => { + const ripple = document.createElement('span'); + ripple.classList.add('ripple'); + button.appendChild(ripple); + setTimeout(() => { + ripple.remove(); + }, 600); +}; diff --git a/src/modules/handleMenuButtons.ts b/src/modules/handleMenuButtons.ts new file mode 100644 index 0000000..aefd66e --- /dev/null +++ b/src/modules/handleMenuButtons.ts @@ -0,0 +1,16 @@ +import { addRippleEffect } from './addRippleEffect'; +import { setPauseRewind } from './rewindColors'; + +export const handleMenuButtons = (): void => { + document.querySelectorAll('button').forEach((button) => { + button.addEventListener('click', (evt) => { + const button = evt.currentTarget as HTMLButtonElement; + addRippleEffect(button); + + if (button.id === 'pause') { + button.classList.toggle('active'); + setPauseRewind(); + } + }); + }); +}; diff --git a/src/modules/index.ts b/src/modules/index.ts index 2c13534..50f78f6 100644 --- a/src/modules/index.ts +++ b/src/modules/index.ts @@ -3,3 +3,4 @@ export * from './colorSVG'; export * from './colorReflection'; export * from './handleClickableElement'; export * from './recordColorChange'; +export * from './handleMenuButtons'; diff --git a/src/modules/rewindColors.ts b/src/modules/rewindColors.ts index bb29bc6..2429736 100644 --- a/src/modules/rewindColors.ts +++ b/src/modules/rewindColors.ts @@ -7,11 +7,12 @@ const TIMEOUT = 5000; let idleTime: NodeJS.Timeout; let interval: NodeJS.Timeout; let stopRewind = true; +let pauseRewind = false; let initialDelay: number; const rewind = (): void => { const removeStep = (): void => { - if (stopRewind) return; + if (stopRewind || pauseRewind) return; if (steps.length > 0) { console.log(steps.length); const removedStep = steps.pop(); @@ -29,8 +30,12 @@ export const setStopRewind = (arg: boolean): void => { stopRewind = arg; }; +export const setPauseRewind = (): void => { + pauseRewind = !pauseRewind; +}; + export const resetTimer = (): void => { - if (stopRewind) return; + if (stopRewind || pauseRewind) return; clearTimeout(idleTime); clearTimeout(interval); initialDelay = DELAY; diff --git a/src/ts/index.ts b/src/ts/index.ts index 0b8d928..c0f48ea 100644 --- a/src/ts/index.ts +++ b/src/ts/index.ts @@ -1,5 +1,6 @@ -import { handleClickableElement } from '../modules'; +import { handleClickableElement, handleMenuButtons } from '../modules'; ((): void => { handleClickableElement(); + handleMenuButtons(); })(); From 56979351e3da20fe9eca17d8668a5c356afeaece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Bucquet?= Date: Sat, 10 Feb 2024 21:28:20 +0100 Subject: [PATCH 2/4] feat: adds undo/redo functionality --- src/index.html | 6 ++++++ src/modules/handleClickableElement.ts | 6 ------ src/modules/handleMenuButtons.ts | 12 +++++++++++- src/modules/recordColorChange.ts | 4 +++- src/modules/rewindColors.ts | 25 ++++++++++++++++++++++++- src/modules/scrollThroughSteps.ts | 2 +- 6 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/index.html b/src/index.html index 4b83fce..3495eae 100644 --- a/src/index.html +++ b/src/index.html @@ -39,6 +39,12 @@ + + diff --git a/src/modules/handleClickableElement.ts b/src/modules/handleClickableElement.ts index d4ce065..ce22afc 100644 --- a/src/modules/handleClickableElement.ts +++ b/src/modules/handleClickableElement.ts @@ -5,13 +5,7 @@ import { recordColorChange } from './recordColorChange'; import { resetTimer, setStopRewind } from './rewindColors'; import { scrollThroughSteps } from './scrollThroughSteps'; -export type StepType = { - target: string; - color: string; -}; - let isScroll = false; -export const steps: StepType[] = []; type ClickableElement = HTMLElement & { id: string }; diff --git a/src/modules/handleMenuButtons.ts b/src/modules/handleMenuButtons.ts index aefd66e..28b1bf6 100644 --- a/src/modules/handleMenuButtons.ts +++ b/src/modules/handleMenuButtons.ts @@ -1,5 +1,9 @@ import { addRippleEffect } from './addRippleEffect'; -import { setPauseRewind } from './rewindColors'; +import { + redoColorChange, + setPauseRewind, + undoColorChange, +} from './rewindColors'; export const handleMenuButtons = (): void => { document.querySelectorAll('button').forEach((button) => { @@ -11,6 +15,12 @@ export const handleMenuButtons = (): void => { button.classList.toggle('active'); setPauseRewind(); } + if (button.id === 'redo') { + redoColorChange(); + } + if (button.id === 'undo') { + undoColorChange(); + } }); }); }; diff --git a/src/modules/recordColorChange.ts b/src/modules/recordColorChange.ts index 24d259f..4189c17 100644 --- a/src/modules/recordColorChange.ts +++ b/src/modules/recordColorChange.ts @@ -1,4 +1,4 @@ -import { type StepType, steps } from './handleClickableElement'; +import { type StepType, steps, updateStepIndex } from './rewindColors'; const pushStep = (step: StepType): void => { steps.push(step); @@ -11,6 +11,7 @@ export const recordColorChange = (target: Element): void => { target: target.id, color: computedStyle.backgroundColor, }); + updateStepIndex(); } if (target instanceof SVGElement) { const computedStyle = window.getComputedStyle(target); @@ -18,5 +19,6 @@ export const recordColorChange = (target: Element): void => { target: target.id, color: computedStyle.fill, }); + updateStepIndex(); } }; diff --git a/src/modules/rewindColors.ts b/src/modules/rewindColors.ts index 2429736..7d44cbb 100644 --- a/src/modules/rewindColors.ts +++ b/src/modules/rewindColors.ts @@ -1,6 +1,13 @@ -import { steps } from './handleClickableElement'; import { applyColorFromStep } from './applyColorFromStep'; +export type StepType = { + target: string; + color: string; +}; + +export const steps: StepType[] = []; +let stepIndex = steps.length - 1; + const DELAY = 1000; const TIMEOUT = 5000; @@ -10,6 +17,22 @@ let stopRewind = true; let pauseRewind = false; let initialDelay: number; +export const updateStepIndex = (): void => { + stepIndex = stepIndex + 1; +}; + +export const undoColorChange = (): void => { + if (stepIndex < 0) return; + applyColorFromStep(steps[stepIndex]); + stepIndex = stepIndex - 1; +}; + +export const redoColorChange = (): void => { + if (stepIndex > steps.length - 1) return; + applyColorFromStep(steps[stepIndex]); + stepIndex = stepIndex + 1; +}; + const rewind = (): void => { const removeStep = (): void => { if (stopRewind || pauseRewind) return; diff --git a/src/modules/scrollThroughSteps.ts b/src/modules/scrollThroughSteps.ts index cd5214d..28119af 100644 --- a/src/modules/scrollThroughSteps.ts +++ b/src/modules/scrollThroughSteps.ts @@ -1,5 +1,5 @@ import { applyColorFromStep } from './applyColorFromStep'; -import { steps } from './handleClickableElement'; +import { steps } from './rewindColors'; let scrollIndex = 0; From 42d3d58abc2d79d40c5c24512565b50b209c0898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Bucquet?= Date: Sat, 10 Feb 2024 21:31:10 +0100 Subject: [PATCH 3/4] chore: update README.md --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b13e8cc..badb828 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,9 @@ Visit the [life demo](sirpixiejerry.github.io/dop-eye/) to try it yourself. - [x] change element color - [x] rewind to original color - [x] scroll steps -- [ ] improve scroll steps feature and cleanup event listeners -- [ ] add user menu +- [x] add pause button +- [x] add undo button +- [x] add redo button +- [x] add info button +- [ ] add save button - [ ] optimization for mobile devices From 5440338e8070fce67c5ff58b62c848e1ffb7f112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Bucquet?= Date: Sat, 10 Feb 2024 21:38:36 +0100 Subject: [PATCH 4/4] fix: fix applyColorFromStep import and test --- src/modules/applyColorFromStep.test.ts | 3 ++- src/modules/applyColorFromStep.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/applyColorFromStep.test.ts b/src/modules/applyColorFromStep.test.ts index c5c999b..595450a 100644 --- a/src/modules/applyColorFromStep.test.ts +++ b/src/modules/applyColorFromStep.test.ts @@ -20,6 +20,7 @@ describe('applyColorFromStep', () => { it('should apply color to the specified element', () => { const mockTarget = document.getElementById(mockStep.target); applyColorFromStep(mockStep); - expect(mockTarget!.style.backgroundColor).to.equal(mockStep.color); + if (!mockTarget) throw new Error('mockTarget not found'); + expect(mockTarget.style.backgroundColor).to.equal(mockStep.color); }); }); diff --git a/src/modules/applyColorFromStep.ts b/src/modules/applyColorFromStep.ts index 9b2b078..208ffde 100644 --- a/src/modules/applyColorFromStep.ts +++ b/src/modules/applyColorFromStep.ts @@ -1,6 +1,6 @@ import { colorReflection } from './colorReflection'; import { colorSVG } from './colorSVG'; -import type { StepType } from './handleClickableElement'; +import type { StepType } from './rewindColors'; export const applyColorFromStep = (step: StepType | undefined): void => { if (step === undefined) return;