mirror of
https://github.com/danilt2000/Alma-vid.git
synced 2025-12-08 19:29:26 +02:00
Improve object card expansion and styling
Refactored the logic for determining when the object card content needs expansion, simplifying the overflow check and improving responsiveness. Updated SCSS to use 'height' instead of 'min-height' for better transitions, adjusted collapsed content max-heights, and enhanced the appearance and behavior of the expand button. Also updated sample addresses in SliderObjects.jsx to include more detailed location information.
This commit is contained in:
@@ -6,52 +6,29 @@ function Object(props) {
|
||||
const [needsExpansion, setNeedsExpansion] = useState(false);
|
||||
const contentRef = useRef(null);
|
||||
|
||||
const checkIfContentOverflows = () => {
|
||||
if (contentRef.current) {
|
||||
// Временно убираем класс collapsed для измерения полной высоты
|
||||
const element = contentRef.current;
|
||||
const hadCollapsedClass = element.classList.contains(
|
||||
"item__content--collapsed"
|
||||
);
|
||||
|
||||
if (hadCollapsedClass) {
|
||||
element.classList.remove("item__content--collapsed");
|
||||
}
|
||||
|
||||
// Измеряем полную высоту
|
||||
const fullHeight = element.scrollHeight;
|
||||
|
||||
// Возвращаем класс обратно
|
||||
if (hadCollapsedClass) {
|
||||
element.classList.add("item__content--collapsed");
|
||||
}
|
||||
|
||||
// Измеряем высоту в свернутом состоянии
|
||||
const collapsedHeight = element.clientHeight;
|
||||
|
||||
// Проверяем, есть ли разница больше чем 20px (чтобы избежать ложных срабатываний)
|
||||
const heightDifference = fullHeight - collapsedHeight;
|
||||
setNeedsExpansion(heightDifference > 20);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// Задержка для правильного расчета после рендера
|
||||
const timeoutId = setTimeout(() => {
|
||||
checkIfContentOverflows();
|
||||
}, 200);
|
||||
const checkExpansion = () => {
|
||||
if (!props.desc || !props.address || !contentRef.current) {
|
||||
setNeedsExpansion(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Проверяем при изменении размера окна
|
||||
const contentElement = contentRef.current;
|
||||
const contentHeight = contentElement.scrollHeight;
|
||||
const containerHeight = contentElement.clientHeight;
|
||||
|
||||
const needsExp = contentHeight > containerHeight;
|
||||
setNeedsExpansion(needsExp);
|
||||
};
|
||||
|
||||
setTimeout(checkExpansion, 100);
|
||||
|
||||
const handleResize = () => {
|
||||
setTimeout(checkIfContentOverflows, 100);
|
||||
setTimeout(checkExpansion, 100);
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeoutId);
|
||||
window.removeEventListener("resize", handleResize);
|
||||
};
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, [props.desc, props.address]);
|
||||
|
||||
const toggleExpansion = () => {
|
||||
@@ -78,11 +55,26 @@ function Object(props) {
|
||||
</div>
|
||||
|
||||
{needsExpansion && (
|
||||
<div className="item__expand-wrapper">
|
||||
<div className="item__expand-wrapper" style={{ display: 'block', visibility: 'visible', opacity: 1 }}>
|
||||
<button
|
||||
className="item__expand-btn"
|
||||
onClick={toggleExpansion}
|
||||
type="button"
|
||||
style={{
|
||||
display: 'block',
|
||||
visibility: 'visible',
|
||||
opacity: 1,
|
||||
color: '#007bff',
|
||||
background: 'none',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
padding: '2px 0',
|
||||
margin: '2px 0',
|
||||
fontSize: '11px',
|
||||
fontWeight: '500',
|
||||
textAlign: 'left',
|
||||
width: '100%'
|
||||
}}
|
||||
>
|
||||
{isExpanded ? "Скрыть" : "Показать больше"}
|
||||
</button>
|
||||
|
||||
@@ -10,112 +10,127 @@
|
||||
margin: 0 20px;
|
||||
border-radius: 15px;
|
||||
background-color: white;
|
||||
min-height: 450px;
|
||||
transition: height 0.3s ease;
|
||||
height: 450px;
|
||||
transition: height 0.6s cubic-bezier(0.4, 0, 0.2, 1), min-height 0.6s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
|
||||
&--expanded {
|
||||
height: auto;
|
||||
height: auto !important;
|
||||
min-height: 450px;
|
||||
transition: height 0.6s cubic-bezier(0.4, 0, 0.2, 1), min-height 0.6s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
@media (min-width: 1800px) {
|
||||
min-height: 480px;
|
||||
height: 480px;
|
||||
|
||||
&--expanded {
|
||||
height: auto !important;
|
||||
min-height: 480px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1300px) {
|
||||
min-height: 430px;
|
||||
height: 430px;
|
||||
|
||||
&--expanded {
|
||||
height: auto !important;
|
||||
min-height: 430px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
min-height: 410px;
|
||||
height: 410px;
|
||||
|
||||
&--expanded {
|
||||
height: auto !important;
|
||||
min-height: 410px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
min-height: 390px;
|
||||
height: 390px;
|
||||
|
||||
&--expanded {
|
||||
height: auto !important;
|
||||
min-height: 390px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $laptopWidth) {
|
||||
min-height: 370px;
|
||||
height: 370px;
|
||||
margin: 0 15px;
|
||||
|
||||
&--expanded {
|
||||
height: auto !important;
|
||||
min-height: 370px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $tabletWidth) {
|
||||
min-height: 500px;
|
||||
height: 500px;
|
||||
|
||||
&--expanded {
|
||||
height: auto !important;
|
||||
min-height: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 740px) {
|
||||
min-height: 480px;
|
||||
height: 480px;
|
||||
|
||||
&--expanded {
|
||||
height: auto !important;
|
||||
min-height: 480px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 690px) {
|
||||
min-height: 460px;
|
||||
height: 460px;
|
||||
|
||||
&--expanded {
|
||||
height: auto !important;
|
||||
min-height: 460px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 635px) {
|
||||
min-height: 440px;
|
||||
height: 440px;
|
||||
|
||||
&--expanded {
|
||||
height: auto !important;
|
||||
min-height: 440px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 570px) {
|
||||
min-height: 420px;
|
||||
height: 420px;
|
||||
|
||||
&--expanded {
|
||||
height: auto !important;
|
||||
min-height: 420px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $mobileWidth) {
|
||||
min-height: 400px;
|
||||
height: 400px;
|
||||
margin: 0 10px;
|
||||
|
||||
&--expanded {
|
||||
height: auto !important;
|
||||
min-height: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 420px) {
|
||||
min-height: 380px;
|
||||
height: 380px;
|
||||
|
||||
&--expanded {
|
||||
height: auto !important;
|
||||
min-height: 380px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item__image:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
@@ -181,6 +196,7 @@
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
|
||||
@media (max-width: $mobileWidth) {
|
||||
margin: 15px 15px 10px 15px;
|
||||
@@ -192,10 +208,10 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 10px;
|
||||
transition: max-height 0.3s ease, opacity 0.2s ease;
|
||||
transition: max-height 0.8s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
&--collapsed {
|
||||
max-height: 180px;
|
||||
max-height: 250px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
@@ -208,61 +224,46 @@
|
||||
height: 20px;
|
||||
background: linear-gradient(transparent, white);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (min-width: 1800px) {
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
@media (max-width: 1300px) {
|
||||
max-height: 170px;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
max-height: 160px;
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
max-height: 150px;
|
||||
}
|
||||
|
||||
@media (max-width: $laptopWidth) {
|
||||
max-height: 140px;
|
||||
}
|
||||
|
||||
@media (max-width: $tabletWidth) {
|
||||
max-height: 190px;
|
||||
}
|
||||
|
||||
@media (max-width: 740px) {
|
||||
max-height: 180px;
|
||||
}
|
||||
|
||||
@media (max-width: 690px) {
|
||||
max-height: 170px;
|
||||
}
|
||||
|
||||
@media (max-width: 635px) {
|
||||
max-height: 160px;
|
||||
}
|
||||
|
||||
@media (max-width: 570px) {
|
||||
max-height: 150px;
|
||||
transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
@media (max-width: $mobileWidth) {
|
||||
max-height: 160px;
|
||||
max-height: 200px !important;
|
||||
}
|
||||
|
||||
@media (max-width: 420px) {
|
||||
max-height: 150px;
|
||||
max-height: 180px !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.item__content--collapsed) {
|
||||
max-height: none !important;
|
||||
overflow: visible;
|
||||
|
||||
&::after {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item__expand-wrapper {
|
||||
margin-top: auto;
|
||||
padding-top: 5px;
|
||||
padding-top: 2px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
background: white;
|
||||
border-radius: 0 0 15px 15px;
|
||||
padding-bottom: 2px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-end;
|
||||
min-height: 20px;
|
||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
@media (max-width: $mobileWidth) {
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.item__price {
|
||||
@@ -315,20 +316,25 @@
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
padding: 4px 0;
|
||||
margin-bottom: 5px;
|
||||
padding: 2px 0;
|
||||
margin-bottom: 2px;
|
||||
text-align: left;
|
||||
transition: color 0.2s ease;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
font-family: inherit;
|
||||
flex-shrink: 0;
|
||||
max-width: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
position: relative;
|
||||
z-index: 15;
|
||||
display: block;
|
||||
width: 100%;
|
||||
|
||||
&:hover {
|
||||
color: #0056b3 !important;
|
||||
text-decoration: underline;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
@@ -342,16 +348,32 @@
|
||||
|
||||
@media (min-width: 1800px) {
|
||||
font-size: 13px;
|
||||
padding: 5px 0;
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
@media (min-width: 768.98px) and (max-width: $laptopWidth) {
|
||||
font-size: 10px;
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
@media (max-width: $tabletWidth) {
|
||||
font-size: 11px;
|
||||
padding: 3px 0;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
@media (max-width: $mobileWidth) {
|
||||
font-size: 11px;
|
||||
margin-bottom: 3px;
|
||||
margin-bottom: 1px;
|
||||
padding: 3px 0;
|
||||
min-height: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.item__expand-wrapper {
|
||||
display: block !important;
|
||||
visibility: visible !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
@@ -85,19 +85,19 @@ const SliderComponent = () => {
|
||||
image={objectPicOne}
|
||||
price="2 500 000 ₽"
|
||||
desc="2-комн. кв., 47 м², 1/2 этаж"
|
||||
address="Челябинская область, Челябинск, Лазурная улица, 14А"
|
||||
address="Челябинская область, Челябинск, Лазурная улица, 14А, район Металлургический, микрорайон Северо-Западный"
|
||||
/>
|
||||
<Object
|
||||
image={objectPicTwo}
|
||||
price="4 200 000 ₽"
|
||||
desc="3-комн. кв., 77 м², 4/4 этаж"
|
||||
address="Челябинская область, Челябинск, улица Ярослава Гашека, 20"
|
||||
address="Челябинская область, Челябинск, улица Ярослава Гашека, 20, район Ленинский, микрорайон Центральный"
|
||||
/>
|
||||
<Object
|
||||
image={objectPicThree}
|
||||
price="4 900 000 ₽"
|
||||
desc="Квартира-студия, 27,6 м², 19/25 этаж"
|
||||
address="Свердловская область, Екатеринбург, улица Студенческая, 80"
|
||||
address="Свердловская область, Екатеринбург, улица Студенческая, 80, район Верх-Исетский, микрорайон Уралмаш"
|
||||
/>
|
||||
</Slider>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user