diff --git a/src/features/StreetcodePage/TextBlock/ReadMore/ReadMore.component.tsx b/src/features/StreetcodePage/TextBlock/ReadMore/ReadMore.component.tsx index f89e88043..9010b69b6 100644 --- a/src/features/StreetcodePage/TextBlock/ReadMore/ReadMore.component.tsx +++ b/src/features/StreetcodePage/TextBlock/ReadMore/ReadMore.component.tsx @@ -1,65 +1,38 @@ /* eslint-disable react/jsx-no-useless-fragment */ import './ReadMore.styles.scss'; -import { CSSProperties, useEffect, useRef, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; +import { useMediaQuery } from 'react-responsive'; import SearchTerms from '@streetcode/TextBlock/SearchTerms/SearchTerms.component'; -import classnames from 'classnames'; -import * as lodash from 'lodash'; -import useWindowSize from '@/app/common/hooks/stateful/useWindowSize.hook'; interface Props { text: string; - maxLines?: number; } -const ReadMore = ({ text, maxLines = 25 }: Props) => { - const [clamped, setClamped] = useState(true); - const [showButtons, setShowButtons] = useState(false); - const containerRef = useRef(null); - const readMoreRef = useRef(null); - const firstRender = useRef(true); - const windowSize = useWindowSize(); - - const handleClick = () => setClamped(!clamped); +const MAX_LENGTH_DESKTOP = 2000; +const MAX_LENGTH_TABLET = 1600; +const MAX_LENGTH_MOBILE = 900; - useEffect(() => { - const hasClamping = (el: HTMLDivElement) => { - const { clientHeight, scrollHeight } = el; - return clientHeight !== scrollHeight; - }; - - const checkButtonAvailability = () => { - if (containerRef.current) { - const hadClampClass = containerRef.current.classList.contains('clamp'); - if (!hadClampClass) containerRef.current.classList.add('clamp'); - if (hasClamping(containerRef.current)) { - setShowButtons(hasClamping(containerRef.current)); - } - if (!hadClampClass) containerRef.current.classList.remove('clamp'); - } - }; - - const debouncedCheck = lodash.debounce(checkButtonAvailability, 50); - - checkButtonAvailability(); - window.addEventListener('resize', debouncedCheck); +const ReadMore = ({ text }: Props) => { + const [isExpanded, setIsExpanded] = useState(false); + const readMoreRef = useRef(null); - return () => { - window.removeEventListener('resize', debouncedCheck); - }; - }, [containerRef]); + const isMobile = useMediaQuery({ + query: '(max-width: 480px)', + }); + const isDesktop = useMediaQuery({ + query: '(min-width: 1025px)', + }); + const isTablet = useMediaQuery({ + query: '(min-width: 481px) and (max-width: 1023px)', + }); - const textContainerStyle: CSSProperties = { - display: '-webkit-box', - WebkitBoxOrient: 'vertical' as const, - WebkitLineClamp: maxLines, - overflow: 'hidden', - textOverflow: 'ellipsis', - overflowWrap: 'normal', - }; + const isTextLong = (isDesktop && text.length > MAX_LENGTH_DESKTOP) + || (isTablet && text.length > MAX_LENGTH_TABLET) + || (isMobile && text.length > MAX_LENGTH_MOBILE); useEffect(() => { - if (clamped && readMoreRef.current && !firstRender.current) { + if (!isExpanded && isTextLong && readMoreRef.current) { const screenHeight = window.innerHeight; const rect = readMoreRef.current.getBoundingClientRect(); @@ -69,41 +42,43 @@ const ReadMore = ({ text, maxLines = 25 }: Props) => { window.scrollTo({ top: scrollPosition, behavior: 'smooth' }); } - if (firstRender.current) { - firstRender.current = false; + }, [isExpanded]); + + // eslint-disable-next-line @typescript-eslint/no-shadow + function getTrunculatedText(text: string) { + let maxLength = text.length; + + if (isDesktop) { + maxLength = MAX_LENGTH_DESKTOP; + } else if (isTablet) { + maxLength = MAX_LENGTH_TABLET; + } else if (isMobile) { + maxLength = MAX_LENGTH_MOBILE; } - }, [clamped]); - const className = classnames('long-text', clamped && 'clamp'); + + return `${text.substring(0, maxLength)}...`; + } return ( <>
-
- -
- {showButtons && windowSize.width > 480 && ( -
- - {clamped ? 'Трохи ще' : 'Дещо менше'} - -
- )} - {showButtons && windowSize.width <= 480 && ( -
+ + + {isTextLong && ( +
setIsExpanded((prev) => !prev)} > - {clamped ? 'Трохи ще' : 'Згорнути текст'} + {!isExpanded ? 'Трохи ще' : isMobile ? 'Згорнути текст' : 'Дещо менше'}
)} diff --git a/src/features/StreetcodePage/TextBlock/ReadMore/ReadMore.styles.scss b/src/features/StreetcodePage/TextBlock/ReadMore/ReadMore.styles.scss index aa23caeb2..6acb4f1bf 100644 --- a/src/features/StreetcodePage/TextBlock/ReadMore/ReadMore.styles.scss +++ b/src/features/StreetcodePage/TextBlock/ReadMore/ReadMore.styles.scss @@ -2,28 +2,30 @@ @use "@sass/variables/_variables.colors.scss" as c; @use "@sass/_utils.functions.scss" as f; -.readMore { - color: c.$dark-red-color; - cursor: pointer; - &:hover{ - text-decoration: underline; +@media screen and (min-width: 481px) { + .readMore { + color: c.$dark-red-color; + cursor: pointer; + &:hover{ + text-decoration: underline; + } } -} -.readMoreContainer { - @include mut.rem-margined($top: 35px); - @include mut.with-font($font-weight: 500); -} + .readMoreContainer { + @include mut.rem-margined($top: 35px); + @include mut.with-font($font-weight: 500); + } -.mainTextContent { - white-space: pre-line; - @include mut.rem-margined($bottom: 35px); -} + .mainTextContent { + white-space: pre-line; + @include mut.rem-margined($bottom: 35px); + } -.text { - white-space: pre-line; - margin-right: f.pxToRem(10px); - margin-left: f.pxToRem(10px); + .text { + white-space: pre-line; + margin-right: f.pxToRem(10px); + margin-left: f.pxToRem(10px); + } } @media screen and (max-width: 1024px) { @@ -46,6 +48,7 @@ @media screen and (max-width: 480px){ .readMore{ + color: c.$dark-red-color; display: flex; justify-content: center; } @@ -65,7 +68,7 @@ border-style: solid; border-width: 2px; width: 252px; - color: #E04031; + color: #E04031!important; margin: auto; font-size: 14px; font-weight: 500;