Skip to content

Commit 8d7d145

Browse files
authored
feat: show lock on embed while scrolling (#38)
* feat: add clickable hint option set to false for embeddables * fix: increase debounce time for scroll end event in CustomEmbeddableRenderer * feat: add lock indicator for scrolling in CustomEmbeddableRenderer - Introduced a LockIndicator component that displays a lock icon when the user is scrolling. - Updated styles to enhance the visibility and positioning of the lock icon. - Implemented event listeners to manage the visibility of the lock icon based on scroll state. * feat: enhance LockIndicator with countdown timer - Added a countdown timer to the LockIndicator component that activates when scrolling stops. - Updated styles for the lock icon and countdown timer to improve visibility and positioning. - Implemented polling and event listeners to manage the countdown state effectively. * refactor: simplify LockIndicator by removing countdown timer - Removed the countdown timer functionality from the LockIndicator component, streamlining its behavior to only show the lock icon when scrolling. - Updated styles to reflect the removal of the countdown timer and adjusted the lock icon's size for better integration. - Cleaned up the useEffect hook to eliminate unnecessary state management related to the countdown.
1 parent 0191304 commit 8d7d145

File tree

3 files changed

+57
-4
lines changed

3 files changed

+57
-4
lines changed

src/frontend/src/CustomEmbeddableRenderer.scss

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,28 @@
99
position: absolute;
1010
top: -30px;
1111
pointer-events: none;
12+
display: flex;
13+
align-items: center;
1214

1315
&__text {
1416
font-family: 'Roboto', sans-serif;
1517
color: #d3d3d3;
1618
pointer-events: none;
1719
font-size: 18px;
20+
margin-right: 8px;
21+
}
22+
}
23+
24+
&__lock-icon {
25+
display: flex;
26+
align-items: center;
27+
justify-content: center;
28+
color: #d3d3d3;
29+
opacity: 0;
30+
transition: opacity 0.3s ease-in-out;
31+
32+
&.visible {
33+
opacity: 1;
1834
}
1935
}
2036

@@ -31,4 +47,4 @@
3147
border-bottom-right-radius: var(--embeddable-radius);
3248
}
3349
}
34-
}
50+
}

src/frontend/src/CustomEmbeddableRenderer.tsx

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import React from 'react';
1+
import React, { useEffect, useState } from 'react';
2+
import { Lock } from 'lucide-react';
23
import { debounce } from './utils/debounce';
34
import type { NonDeleted, ExcalidrawEmbeddableElement } from '@atyrode/excalidraw/element/types';
45
import type { AppState } from '@atyrode/excalidraw/types';
@@ -65,6 +66,7 @@ export const renderCustomEmbeddable = (
6566
<div className="custom-embed">
6667
<div className="custom-embed__title-bar">
6768
<div className="custom-embed__title-bar__text">{title}</div>
69+
<LockIndicator />
6870
</div>
6971
<div className="custom-embed__content">
7072
{content}
@@ -78,6 +80,7 @@ export const renderCustomEmbeddable = (
7880
<div className="custom-embed">
7981
<div className="custom-embed__title-bar">
8082
<div className="custom-embed__title-bar__text">{title}</div>
83+
<LockIndicator />
8184
</div>
8285
<div className="custom-embed__content">
8386
<iframe className="custom-embed__content--iframe" src={element.link} />
@@ -87,14 +90,44 @@ export const renderCustomEmbeddable = (
8790
}
8891
};
8992

93+
// Lock icon component that shows when scrolling
94+
const LockIndicator = () => {
95+
const [visible, setVisible] = useState(false);
96+
97+
useEffect(() => {
98+
const handleScrollStateChange = (event: CustomEvent<{ isScrolling: boolean }>) => {
99+
setVisible(event.detail.isScrolling);
100+
};
101+
102+
// Add event listener for scroll state changes
103+
document.addEventListener('scrollStateChange', handleScrollStateChange as EventListener);
104+
105+
// Clean up
106+
return () => {
107+
document.removeEventListener('scrollStateChange', handleScrollStateChange as EventListener);
108+
};
109+
}, []);
110+
111+
return (
112+
<div className={`custom-embed__lock-icon ${visible ? 'visible' : ''}`}>
113+
<Lock size={16} />
114+
</div>
115+
);
116+
};
117+
90118
// Track scrolling state
91119
let isScrolling = false;
120+
// Create a custom event for scrolling state changes
121+
const scrollStateChangeEvent = new CustomEvent('scrollStateChange', { detail: { isScrolling: false } });
92122

93123
export const lockEmbeddables = () => {
94124
if (!isScrolling) {
95125
isScrolling = true;
96126
// Set pointer-events to none during scrolling
97127
document.documentElement.style.setProperty('--embeddable-pointer-events', 'none');
128+
// Dispatch event with updated scrolling state
129+
scrollStateChangeEvent.detail.isScrolling = true;
130+
document.dispatchEvent(scrollStateChangeEvent);
98131
}
99132

100133
// Reset the pointer-events after scrolling stops
@@ -106,4 +139,7 @@ const debouncedScrollEnd = debounce(() => {
106139
isScrolling = false;
107140
// Set pointer-events back to all when not scrolling
108141
document.documentElement.style.setProperty('--embeddable-pointer-events', 'all');
109-
}, 150); // 150ms debounce seems reasonable, but can be adjusted as needed
142+
// Dispatch event with updated scrolling state
143+
scrollStateChangeEvent.detail.isScrolling = false;
144+
document.dispatchEvent(scrollStateChangeEvent);
145+
}, 350);

src/frontend/src/lib/ExcalidrawElementFactory.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ export class ExcalidrawElementFactory {
121121
type: "embeddable",
122122
link: options.link,
123123
customData: {
124-
showHyperlinkIcon: false
124+
showHyperlinkIcon: false,
125+
showClickableHint: false
125126
}
126127
};
127128
}

0 commit comments

Comments
 (0)