[Refactoring] seMarkScrolled → useScrollNotch: Use pseudo-element instead of border
This commit is contained in:
parent
2520dae3b7
commit
745f4c6ba2
@ -3,6 +3,10 @@
|
|||||||
#Settings {
|
#Settings {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
|
.with-notch::before {
|
||||||
|
top: var(--header-height);
|
||||||
|
}
|
||||||
|
|
||||||
> .Transition_slide {
|
> .Transition_slide {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -40,12 +44,6 @@
|
|||||||
.settings-content {
|
.settings-content {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
height: calc(100% - var(--header-height));
|
height: calc(100% - var(--header-height));
|
||||||
border-top: 1px solid transparent;
|
|
||||||
transition: border-top-color 0.2s ease-in-out;
|
|
||||||
|
|
||||||
&.scrolled {
|
|
||||||
border-top-color: var(--color-borders);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.password-form .input-group.error label::first-letter {
|
&.password-form .input-group.error label::first-letter {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { resolveTransitionName } from '../../../util/resolveTransitionName.ts';
|
|||||||
|
|
||||||
import useTwoFaReducer from '../../../hooks/reducers/useTwoFaReducer';
|
import useTwoFaReducer from '../../../hooks/reducers/useTwoFaReducer';
|
||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
import useMarkScrolled from '../../../hooks/useMarkScrolled/useMarkScrolled';
|
import useScrollNotch from '../../../hooks/useScrollNotch.ts';
|
||||||
|
|
||||||
import Transition from '../../ui/Transition';
|
import Transition from '../../ui/Transition';
|
||||||
import SettingsFolders from './folders/SettingsFolders';
|
import SettingsFolders from './folders/SettingsFolders';
|
||||||
@ -172,7 +172,7 @@ const Settings: FC<OwnProps> = ({
|
|||||||
const [twoFaState, twoFaDispatch] = useTwoFaReducer();
|
const [twoFaState, twoFaDispatch] = useTwoFaReducer();
|
||||||
const [privacyPasscode, setPrivacyPasscode] = useState<string>('');
|
const [privacyPasscode, setPrivacyPasscode] = useState<string>('');
|
||||||
|
|
||||||
useMarkScrolled({
|
useScrollNotch({
|
||||||
containerRef,
|
containerRef,
|
||||||
selector: '.settings-content',
|
selector: '.settings-content',
|
||||||
}, [currentScreen]);
|
}, [currentScreen]);
|
||||||
|
|||||||
@ -8,29 +8,6 @@
|
|||||||
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 1px;
|
|
||||||
|
|
||||||
opacity: 0;
|
|
||||||
background-color: var(--color-borders);
|
|
||||||
|
|
||||||
transition: opacity 0.2s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.scrolled {
|
|
||||||
&::before {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .profile-info > .ChatInfo {
|
> .profile-info > .ChatInfo {
|
||||||
grid-area: chat_info;
|
grid-area: chat_info;
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import useCurrentOrPrev from '../../hooks/useCurrentOrPrev';
|
|||||||
import useHistoryBack from '../../hooks/useHistoryBack';
|
import useHistoryBack from '../../hooks/useHistoryBack';
|
||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
import useLayoutEffectWithPrevDeps from '../../hooks/useLayoutEffectWithPrevDeps';
|
import useLayoutEffectWithPrevDeps from '../../hooks/useLayoutEffectWithPrevDeps';
|
||||||
import useMarkScrolled from '../../hooks/useMarkScrolled/useMarkScrolled';
|
import useScrollNotch from '../../hooks/useScrollNotch.ts';
|
||||||
import useWindowSize from '../../hooks/window/useWindowSize';
|
import useWindowSize from '../../hooks/window/useWindowSize';
|
||||||
|
|
||||||
import Transition from '../ui/Transition';
|
import Transition from '../ui/Transition';
|
||||||
@ -140,7 +140,7 @@ const RightColumn: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
const renderingContentKey = useCurrentOrPrev(contentKey, true, !isChatSelected) ?? -1;
|
const renderingContentKey = useCurrentOrPrev(contentKey, true, !isChatSelected) ?? -1;
|
||||||
|
|
||||||
useMarkScrolled({
|
useScrollNotch({
|
||||||
containerRef,
|
containerRef,
|
||||||
selector: ':scope .custom-scroll, :scope .panel-content',
|
selector: ':scope .custom-scroll, :scope .panel-content',
|
||||||
}, [contentKey, managementScreen, chatId, threadId]);
|
}, [contentKey, managementScreen, chatId, threadId]);
|
||||||
|
|||||||
@ -1,38 +0,0 @@
|
|||||||
import type { ElementRef } from '../../lib/teact/teact';
|
|
||||||
import { useEffect } from '../../lib/teact/teact';
|
|
||||||
|
|
||||||
import { requestMutation } from '../../lib/fasterdom/fasterdom';
|
|
||||||
import { throttle } from '../../util/schedulers';
|
|
||||||
|
|
||||||
const THROTTLE_DELAY = 100;
|
|
||||||
|
|
||||||
const useMarkScrolled = ({
|
|
||||||
containerRef, selector,
|
|
||||||
}: {
|
|
||||||
containerRef: ElementRef<HTMLDivElement>;
|
|
||||||
selector: string;
|
|
||||||
}, deps: unknown[]) => {
|
|
||||||
useEffect(() => {
|
|
||||||
const elements = containerRef?.current?.querySelectorAll(selector);
|
|
||||||
if (!elements?.length) return undefined;
|
|
||||||
|
|
||||||
const handleScroll = throttle((event: Event) => {
|
|
||||||
const target = event.target as HTMLElement;
|
|
||||||
const isScrolled = target.scrollTop > 0;
|
|
||||||
requestMutation(() => {
|
|
||||||
target.classList.toggle('scrolled', isScrolled);
|
|
||||||
});
|
|
||||||
}, THROTTLE_DELAY);
|
|
||||||
|
|
||||||
elements.forEach((el) => el.addEventListener('scroll', handleScroll, { passive: true }));
|
|
||||||
// Trigger the scroll handler immediately to apply the current state
|
|
||||||
elements.forEach((el) => el.dispatchEvent(new Event('scroll', { bubbles: false })));
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
elements.forEach((el) => el.removeEventListener('scroll', handleScroll));
|
|
||||||
};
|
|
||||||
// eslint-disable-next-line react-hooks-static-deps/exhaustive-deps
|
|
||||||
}, [containerRef, selector, ...deps]);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useMarkScrolled;
|
|
||||||
58
src/hooks/useScrollNotch.ts
Normal file
58
src/hooks/useScrollNotch.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import type { ElementRef } from '@teact';
|
||||||
|
import { useEffect, useLayoutEffect } from '@teact';
|
||||||
|
import { addExtraClass, removeExtraClass, toggleExtraClass } from '@teact/teact-dom.ts';
|
||||||
|
|
||||||
|
import { requestMutation } from '../lib/fasterdom/fasterdom.ts';
|
||||||
|
import { throttle } from '../util/schedulers.ts';
|
||||||
|
|
||||||
|
const THROTTLE_DELAY = 100;
|
||||||
|
|
||||||
|
const useScrollNotch = ({
|
||||||
|
containerRef,
|
||||||
|
selector,
|
||||||
|
}: {
|
||||||
|
containerRef: ElementRef<HTMLDivElement>;
|
||||||
|
selector: string;
|
||||||
|
}, deps: unknown[]) => {
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
const elements = containerRef.current?.querySelectorAll<HTMLElement>(selector);
|
||||||
|
if (!elements?.length) return undefined;
|
||||||
|
|
||||||
|
const handleScroll = throttle((event: Event) => {
|
||||||
|
const target = event.target as HTMLElement;
|
||||||
|
const isScrolled = target.scrollTop > 0;
|
||||||
|
|
||||||
|
requestMutation(() => {
|
||||||
|
toggleExtraClass(target, 'scrolled', isScrolled);
|
||||||
|
});
|
||||||
|
}, THROTTLE_DELAY);
|
||||||
|
|
||||||
|
elements.forEach((el) => {
|
||||||
|
addExtraClass(el, 'with-notch');
|
||||||
|
el.addEventListener('scroll', handleScroll, { passive: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
elements.forEach((el) => {
|
||||||
|
el.removeEventListener('scroll', handleScroll);
|
||||||
|
removeExtraClass(el, 'with-notch');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// eslint-disable-next-line react-hooks-static-deps/exhaustive-deps
|
||||||
|
}, [containerRef, selector, ...deps]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const elements = containerRef.current?.querySelectorAll<HTMLElement>(selector);
|
||||||
|
if (!elements?.length) return undefined;
|
||||||
|
|
||||||
|
elements.forEach((el) => {
|
||||||
|
const isScrolled = el.scrollTop > 0;
|
||||||
|
requestMutation(() => {
|
||||||
|
toggleExtraClass(el, 'scrolled', isScrolled);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// eslint-disable-next-line react-hooks-static-deps/exhaustive-deps
|
||||||
|
}, [containerRef, selector, ...deps]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useScrollNotch;
|
||||||
@ -359,6 +359,31 @@ body:not(.is-ios) {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.with-notch {
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
|
||||||
|
opacity: 0;
|
||||||
|
background-color: var(--color-borders);
|
||||||
|
|
||||||
|
transition: opacity 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.scrolled {
|
||||||
|
&::before {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes grow-icon {
|
@keyframes grow-icon {
|
||||||
0% {
|
0% {
|
||||||
transform: scale(0.5);
|
transform: scale(0.5);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user