mirror of
https://github.com/danilt2000/Alma-vid.git
synced 2026-02-04 17:54:12 +02:00
Add expandable content for Object component
Refactored the Object component to allow expandable/collapsible content when the description or address overflows the container. Added dynamic height detection and a gradient fade for collapsed state, with responsive max-height adjustments in SCSS. Improved user experience for long content display.
This commit is contained in:
@@ -1,26 +1,59 @@
|
||||
import "./Object.scss";
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
|
||||
function Object(props) {
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
const [needsExpansion, setNeedsExpansion] = useState(false);
|
||||
const contentRef = useRef(null);
|
||||
|
||||
const addressLimit = 30;
|
||||
const isAddressTooLong = props.address && props.address.length > addressLimit;
|
||||
const needsExpansion = isAddressTooLong;
|
||||
const checkIfContentOverflows = () => {
|
||||
if (contentRef.current) {
|
||||
// Временно убираем класс collapsed для измерения полной высоты
|
||||
const element = contentRef.current;
|
||||
const hadCollapsedClass = element.classList.contains(
|
||||
"item__content--collapsed"
|
||||
);
|
||||
|
||||
const truncateAddress = (text) => {
|
||||
if (!text) return "";
|
||||
if (isExpanded) return text;
|
||||
if (text.length <= addressLimit) return text;
|
||||
if (hadCollapsedClass) {
|
||||
element.classList.remove("item__content--collapsed");
|
||||
}
|
||||
|
||||
const truncated = text.substring(0, addressLimit);
|
||||
const lastSpaceIndex = truncated.lastIndexOf(" ");
|
||||
if (lastSpaceIndex > 0) {
|
||||
return truncated.substring(0, lastSpaceIndex) + "...";
|
||||
// Измеряем полную высоту
|
||||
const fullHeight = element.scrollHeight;
|
||||
|
||||
// Возвращаем класс обратно
|
||||
if (hadCollapsedClass) {
|
||||
element.classList.add("item__content--collapsed");
|
||||
}
|
||||
|
||||
// Измеряем высоту в свернутом состоянии
|
||||
const collapsedHeight = element.clientHeight;
|
||||
|
||||
// Проверяем, есть ли разница больше чем 20px (чтобы избежать ложных срабатываний)
|
||||
const heightDifference = fullHeight - collapsedHeight;
|
||||
setNeedsExpansion(heightDifference > 20);
|
||||
}
|
||||
return truncated + "...";
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// Задержка для правильного расчета после рендера
|
||||
const timeoutId = setTimeout(() => {
|
||||
checkIfContentOverflows();
|
||||
}, 200);
|
||||
|
||||
// Проверяем при изменении размера окна
|
||||
const handleResize = () => {
|
||||
setTimeout(checkIfContentOverflows, 100);
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeoutId);
|
||||
window.removeEventListener("resize", handleResize);
|
||||
};
|
||||
}, [props.desc, props.address]);
|
||||
|
||||
const toggleExpansion = () => {
|
||||
setIsExpanded(!isExpanded);
|
||||
};
|
||||
@@ -29,23 +62,31 @@ function Object(props) {
|
||||
<div className={`item ${isExpanded ? "item--expanded" : ""}`}>
|
||||
<img className="item__image" src={props.image} alt="квартира" />
|
||||
<div className="item__info font-inter-bold">
|
||||
<div className="item__content">
|
||||
<div
|
||||
className={`item__content ${
|
||||
!isExpanded ? "item__content--collapsed" : ""
|
||||
}`}
|
||||
ref={contentRef}
|
||||
>
|
||||
<p className="item__price">{props.price}</p>
|
||||
<p className="item__desc" title={props.desc}>
|
||||
{props.desc}
|
||||
</p>
|
||||
<p className="item__address font-inter-regular" title={props.address}>
|
||||
{truncateAddress(props.address)}
|
||||
{props.address}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{needsExpansion && (
|
||||
<button
|
||||
className="item__expand-btn"
|
||||
onClick={toggleExpansion}
|
||||
type="button"
|
||||
>
|
||||
{isExpanded ? "Скрыть" : "Показать больше"}
|
||||
</button>
|
||||
<div className="item__expand-wrapper">
|
||||
<button
|
||||
className="item__expand-btn"
|
||||
onClick={toggleExpansion}
|
||||
type="button"
|
||||
>
|
||||
{isExpanded ? "Скрыть" : "Показать больше"}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user