diff --git a/src/components/GlobalScrollListener.tsx b/src/components/GlobalScrollListener.tsx index 869d759785..1463606ebf 100644 --- a/src/components/GlobalScrollListener.tsx +++ b/src/components/GlobalScrollListener.tsx @@ -4,7 +4,10 @@ import { useDispatch } from 'react-redux'; import useScrollDirection, { ScrollDirection } from '@/hooks/useScrollDirection'; import { setIsVisible } from '@/redux/slices/navbar'; -import { setIsExpanded } from '@/redux/slices/QuranReader/contextMenu'; +import { + setIsExpanded, + setShowReadingPreferenceSwitcher, +} from '@/redux/slices/QuranReader/contextMenu'; const GlobalScrollListener = () => { const dispatch = useDispatch(); @@ -23,6 +26,11 @@ const GlobalScrollListener = () => { dispatch({ type: setIsExpanded.type, payload: true }); dispatch({ type: setIsVisible.type, payload: true }); } + if (newYPosition > 150 && direction === ScrollDirection.Down) { + dispatch({ type: setShowReadingPreferenceSwitcher.type, payload: true }); + } else if (newYPosition <= 150 && direction === ScrollDirection.Up) { + dispatch({ type: setShowReadingPreferenceSwitcher.type, payload: false }); + } }, [dispatch], ); diff --git a/src/components/QuranReader/ContextMenu.module.scss b/src/components/QuranReader/ContextMenu.module.scss index 9d38a34c33..22b4e122dd 100644 --- a/src/components/QuranReader/ContextMenu.module.scss +++ b/src/components/QuranReader/ContextMenu.module.scss @@ -75,10 +75,15 @@ } } +.halfSection { + width: 50%; // when reading preference toggle is hidden +} + .section { - width: 50%; - display: flex; - align-items: center; + width: calc(100% / 3); + @include breakpoints.smallerThanTablet { + width: 50%; + } } .alignStart { diff --git a/src/components/QuranReader/ContextMenu.tsx b/src/components/QuranReader/ContextMenu.tsx index 2dc4ac5252..dd87170728 100644 --- a/src/components/QuranReader/ContextMenu.tsx +++ b/src/components/QuranReader/ContextMenu.tsx @@ -7,7 +7,11 @@ import useTranslation from 'next-translate/useTranslation'; import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import styles from './ContextMenu.module.scss'; +import ReadingPreferenceSwitcher, { + ReadingPreferenceSwitcherType, +} from './ReadingPreferenceSwitcher'; +import { SwitchSize } from '@/dls/Switch/Switch'; import ChevronDownIcon from '@/icons/chevron-down.svg'; import { selectNavbar } from '@/redux/slices/navbar'; import { selectContextMenu } from '@/redux/slices/QuranReader/contextMenu'; @@ -31,7 +35,10 @@ const ContextMenu = () => { const isSidebarNavigationVisible = useSelector(selectIsSidebarNavigationVisible); const { t, lang } = useTranslation('common'); const isSideBarVisible = useSelector(selectNotes, shallowEqual).isVisible; - const { isExpanded } = useSelector(selectContextMenu, shallowEqual); + const { isExpanded, showReadingPreferenceSwitcher } = useSelector( + selectContextMenu, + shallowEqual, + ); const isNavbarVisible = useSelector(selectNavbar, shallowEqual).isVisible; const { verseKey, chapterId, page, hizb } = useSelector(selectLastReadVerseKey, shallowEqual); const chapterData = useMemo(() => { @@ -66,7 +73,7 @@ const ContextMenu = () => { style={{ '--progress': `${progress}%` }} // this is to pass the value to css so it can be used to show the progress bar. >
-
+

{

-
+ {showReadingPreferenceSwitcher && ( +
+ +
+ )} +

svg { + width: 15px; + display: block; + margin: auto; + } + + @include breakpoints.smallerThanTablet { + & > svg { + -webkit-margin-end: 0; + margin-inline-end: 0; + } + } +} diff --git a/src/components/QuranReader/ReadingPreferenceSwitcher/ReadingPreferenceOption.tsx b/src/components/QuranReader/ReadingPreferenceSwitcher/ReadingPreferenceOption.tsx index db537cb44c..bca037014c 100644 --- a/src/components/QuranReader/ReadingPreferenceSwitcher/ReadingPreferenceOption.tsx +++ b/src/components/QuranReader/ReadingPreferenceSwitcher/ReadingPreferenceOption.tsx @@ -1,20 +1,30 @@ import React from 'react'; +import classNames from 'classnames'; import useTranslation from 'next-translate/useTranslation'; import styles from '@/components/QuranReader/ReadingPreferenceSwitcher/ReadingPreference.module.scss'; import Spinner from '@/dls/Spinner/Spinner'; +import BookIcon from '@/icons/book.svg'; +import ReaderIcon from '@/icons/reader.svg'; import { ReadingPreference } from 'types/QuranReader'; type Props = { readingPreference: ReadingPreference; selectedReadingPreference: ReadingPreference; + isIconsOnly?: boolean; isLoading: boolean; }; +export const readingPreferenceIcons = { + [ReadingPreference.Reading]: , + [ReadingPreference.Translation]: , +}; + const LoadingSwitcher: React.FC = ({ readingPreference, selectedReadingPreference, + isIconsOnly = false, isLoading, }) => { const { t } = useTranslation('common'); @@ -23,10 +33,23 @@ const LoadingSwitcher: React.FC = ({ - {t(`reading-preference.${readingPreference}`)} + {!isIconsOnly && ( + + {t(`reading-preference.${selectedReadingPreference}`)} + + )}

) : ( - t(`reading-preference.${selectedReadingPreference}`) +
+ + {readingPreferenceIcons[selectedReadingPreference]} + + {!isIconsOnly && ( + + {t(`reading-preference.${selectedReadingPreference}`)} + + )} +
); }; diff --git a/src/components/QuranReader/ReadingPreferenceSwitcher/ReadingPreferenceSwitcher.module.scss b/src/components/QuranReader/ReadingPreferenceSwitcher/ReadingPreferenceSwitcher.module.scss index 42e4f8c902..eacb816d13 100644 --- a/src/components/QuranReader/ReadingPreferenceSwitcher/ReadingPreferenceSwitcher.module.scss +++ b/src/components/QuranReader/ReadingPreferenceSwitcher/ReadingPreferenceSwitcher.module.scss @@ -1,8 +1,7 @@ $readingPreferenceMaxWidth: calc(20 * var(--spacing-large)); +$contextMenuReadingPreferenceMaxWidth: calc(10 * var(--spacing-large)); .container { max-width: $readingPreferenceMaxWidth; - margin-block-start: var(--spacing-small); - margin-block-end: var(--spacing-xxsmall); margin-inline-start: auto; margin-inline-end: auto; padding-block-start: 0; @@ -10,3 +9,12 @@ $readingPreferenceMaxWidth: calc(20 * var(--spacing-large)); padding-inline-start: var(--spacing-small); padding-inline-end: var(--spacing-small); } + +.surahHeaderContainer { + margin-block-start: var(--spacing-small); + margin-block-end: var(--spacing-xxsmall); +} + +.contextMenuContainer { + max-width: $contextMenuReadingPreferenceMaxWidth; +} diff --git a/src/components/QuranReader/ReadingPreferenceSwitcher/index.tsx b/src/components/QuranReader/ReadingPreferenceSwitcher/index.tsx index 86289f2ec1..80797a6f85 100644 --- a/src/components/QuranReader/ReadingPreferenceSwitcher/index.tsx +++ b/src/components/QuranReader/ReadingPreferenceSwitcher/index.tsx @@ -1,21 +1,40 @@ +import classNames from 'classnames'; import { useRouter } from 'next/router'; import { useSelector } from 'react-redux'; import LoadingSwitcher from './ReadingPreferenceOption'; import styles from './ReadingPreferenceSwitcher.module.scss'; -import Switch from '@/dls/Switch/Switch'; +import Switch, { SwitchSize } from '@/dls/Switch/Switch'; import usePersistPreferenceGroup from '@/hooks/auth/usePersistPreferenceGroup'; import { selectReadingPreferences, setReadingPreference, } from '@/redux/slices/QuranReader/readingPreferences'; +import { selectLastReadVerseKey } from '@/redux/slices/QuranReader/readingTracker'; import { logValueChange } from '@/utils/eventLogger'; import PreferenceGroup from 'types/auth/PreferenceGroup'; import { ReadingPreference } from 'types/QuranReader'; -const ReadingPreferenceSwitcher = () => { +export enum ReadingPreferenceSwitcherType { + SurahHeader = 'surah_header', + ContextMenu = 'context_menu', +} + +interface Props { + size?: SwitchSize; + isIconsOnly?: boolean; + type?: ReadingPreferenceSwitcherType; +} + +const ReadingPreferenceSwitcher: React.FC = ({ + size, + isIconsOnly = false, + type = ReadingPreferenceSwitcherType.SurahHeader, +}) => { const readingPreferences = useSelector(selectReadingPreferences); + const lastReadVerseKey = useSelector(selectLastReadVerseKey); + const lastReadVerse = lastReadVerseKey.verseKey?.split(':')[1]; const { readingPreference } = readingPreferences; const { actions: { onSettingsChange }, @@ -30,6 +49,7 @@ const ReadingPreferenceSwitcher = () => { readingPreference={readingPreference} selectedReadingPreference={ReadingPreference.Translation} isLoading={isLoading} + isIconsOnly={isIconsOnly} /> ), value: ReadingPreference.Translation, @@ -40,6 +60,7 @@ const ReadingPreferenceSwitcher = () => { readingPreference={readingPreference} selectedReadingPreference={ReadingPreference.Reading} isLoading={isLoading} + isIconsOnly={isIconsOnly} /> ), value: ReadingPreference.Reading, @@ -47,11 +68,20 @@ const ReadingPreferenceSwitcher = () => { ]; const onViewSwitched = (view: ReadingPreference) => { - logValueChange('reading_preference', readingPreference, view); + logValueChange(`${type}_reading_preference`, readingPreference, view); - // drop `startingVerse` from query params const newQueryParams = { ...router.query }; - delete newQueryParams.startingVerse; + + // Track `startingVerse` once we're past the start of the page so we can + // continue from the same ayah when switching views. Without the > 1 check, + // switching views at the start of the page causes unnecessary scrolls + + if (type === ReadingPreferenceSwitcherType.SurahHeader) { + delete newQueryParams.startingVerse; + } else if (parseInt(lastReadVerse, 10) > 1) { + newQueryParams.startingVerse = lastReadVerse; + } + const newUrlObject = { pathname: router.pathname, query: newQueryParams, @@ -69,11 +99,17 @@ const ReadingPreferenceSwitcher = () => { }; return ( -
+
); diff --git a/src/components/dls/Switch/Switch.module.scss b/src/components/dls/Switch/Switch.module.scss index 6744cd6364..38255e6f3f 100644 --- a/src/components/dls/Switch/Switch.module.scss +++ b/src/components/dls/Switch/Switch.module.scss @@ -17,6 +17,13 @@ $separatorOpacity: 0.2; ); // use grid to prevent layout shift when `font-family: bold` on item selected https://css-tricks.com/bold-on-hover-without-the-layout-shift/ } +.xSmallContainer { + padding-block-start: 0; + padding-block-end: 0; + padding-inline-start: 0; + padding-inline-end: 0; +} + .item { cursor: pointer; color: var(--color-text-default); @@ -94,3 +101,10 @@ $background-container: calc(0.8 * var(--spacing-xxsmall)); padding-inline-start: var(--spacing-small); padding-inline-end: var(--spacing-small); } + +.itemXSmall { + padding-block-start: var(--spacing-micro); + padding-block-end: var(--spacing-micro); + padding-inline-start: var(--spacing-micro); + padding-inline-end: var(--spacing-micro); +} diff --git a/src/components/dls/Switch/Switch.tsx b/src/components/dls/Switch/Switch.tsx index ee3df858f9..230352abfd 100644 --- a/src/components/dls/Switch/Switch.tsx +++ b/src/components/dls/Switch/Switch.tsx @@ -14,6 +14,7 @@ type Item = { disabled?: boolean; }; export enum SwitchSize { + XSmall = 'xsmall', Small = 'small', Normal = 'normal', Large = 'large', @@ -29,7 +30,11 @@ const Switch = ({ items, onSelect, selected, size = SwitchSize.Normal }: SwitchP const selectedIndex = items.findIndex((item) => item.value === selected); const { locale } = useRouter(); return ( -
+
{items.map((item) => (