h1 + ExpandableContent + ...
This commit is contained in:
@@ -17,7 +17,7 @@ const DanakSuggestedService: FC = () => {
|
||||
{
|
||||
data?.data?.danakSuggestServices?.map((item) => {
|
||||
return (
|
||||
<ServiceItem key={item.id} item={item} />
|
||||
<ServiceItem isShort key={item.id} item={item} />
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
'use client'
|
||||
import { FC, Fragment } from 'react'
|
||||
import ExpandableContent from '@/components/ExpandableContent'
|
||||
import { useGetProductBySlug } from './hooks/useProductData'
|
||||
import ServiceHeader from './components/ServiceHeader'
|
||||
import moment from 'moment-jalaali'
|
||||
@@ -94,8 +95,7 @@ const DetailService: FC<{ id: string }> = ({ id }) => {
|
||||
توضیحات کامل
|
||||
</div>
|
||||
{getDetailService.data?.data?.danakService?.metaDescription && (
|
||||
<p dangerouslySetInnerHTML={{ __html: getDetailService.data.data.danakService.metaDescription }} className='text-[13px] text-description mt-4 leading-6'>
|
||||
</p>
|
||||
<ExpandableContent html={getDetailService.data.data.danakService.metaDescription} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -40,9 +40,9 @@ const ServiceHeader: FC<Props> = (props: Props) => {
|
||||
<Image alt='icon' width={70} height={70} src={data?.icon} className='w-full h-full rounded-xl' />
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<h1>
|
||||
{data?.name}
|
||||
</div>
|
||||
</h1>
|
||||
|
||||
<p className='text-description mt-1 text-[11px]'>
|
||||
{data?.description}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
'use client'
|
||||
import { FC, memo, useEffect, useRef, useState } from 'react'
|
||||
import Button from '@/components/Button'
|
||||
import { clx } from '@/helpers/utils'
|
||||
|
||||
type Props = {
|
||||
html: string;
|
||||
collapsedHeightClass?: string; // e.g. 'max-h-36' for ~6 lines with leading-6
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const ExpandableContent: FC<Props> = memo(({ html, collapsedHeightClass = 'max-h-36', className }) => {
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
const [isOverflowing, setIsOverflowing] = useState(false)
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const el = containerRef.current
|
||||
if (!el) return
|
||||
if (expanded) {
|
||||
setIsOverflowing(false)
|
||||
return
|
||||
}
|
||||
setIsOverflowing(el.scrollHeight > el.clientHeight + 1)
|
||||
}, [html, expanded])
|
||||
|
||||
return (
|
||||
<div className={clx('mt-4', className)}>
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={clx(
|
||||
'relative text-[13px] text-description leading-6',
|
||||
!expanded && 'overflow-hidden',
|
||||
!expanded && collapsedHeightClass,
|
||||
)}
|
||||
>
|
||||
<div dangerouslySetInnerHTML={{ __html: html }} />
|
||||
{!expanded && isOverflowing && (
|
||||
<div className='pointer-events-none absolute inset-x-0 bottom-0 h-16 bg-gradient-to-t from-white to-transparent' />
|
||||
)}
|
||||
</div>
|
||||
{isOverflowing || expanded ? (
|
||||
<div className='mt-3'>
|
||||
<Button
|
||||
type='button'
|
||||
onClick={() => setExpanded((s) => !s)}
|
||||
className='h-8 w-fit px-3 text-xs rounded-lg'
|
||||
label={expanded ? 'بستن' : 'مشاهده بیشتر'}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
ExpandableContent.displayName = 'ExpandableContent'
|
||||
|
||||
export default ExpandableContent
|
||||
|
||||
|
||||
Reference in New Issue
Block a user