From 56c300f368d05484d76a6d5be9b2a3dd3d8f411d Mon Sep 17 00:00:00 2001 From: pradeepkumar Date: Wed, 15 Apr 2026 11:47:40 +0530 Subject: [PATCH] feat: implement dynamic row-based tag clipping in TopProfessionals and fix typo in CommonHeader --- src/components/home/TopProfessionals.tsx | 53 +++++++++++++++++++++--- src/components/layout/CommonHeader.tsx | 2 +- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/components/home/TopProfessionals.tsx b/src/components/home/TopProfessionals.tsx index 4f1a878..bb26f15 100644 --- a/src/components/home/TopProfessionals.tsx +++ b/src/components/home/TopProfessionals.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useLayoutEffect, useRef } from 'react'; import Link from 'next/link'; import Image from 'next/image'; import { uploadService } from '@/services/upload.service'; @@ -32,7 +32,47 @@ function ProfessionalCard({ const [imgError, setImgError] = useState(false); const placeholder = '/assets/icons/user-placeholder-icon.svg'; const isPlaceholder = imageUrl === placeholder; - const INITIAL_TAG_COUNT = 4; + + // Dynamic row-based tag clipping: show as many tags as fit in 2 rows, with "+N more" if overflow + const tagContainerRef = useRef(null); + const [visibleTagCount, setVisibleTagCount] = useState(expertise.length); + + useLayoutEffect(() => { + const container = tagContainerRef.current; + if (!container) return; + + const measure = () => { + const items = Array.from(container.querySelectorAll('[data-tag]')); + if (items.length === 0) return; + + const firstTop = items[0].offsetTop; + let secondTop: number | null = null; + let rowBreakIndex = items.length; + + for (let i = 0; i < items.length; i++) { + const top = items[i].offsetTop; + if (top > firstTop) { + if (secondTop === null) secondTop = top; + if (top > secondTop) { + rowBreakIndex = i; + break; + } + } + } + + const hasOverflow = rowBreakIndex < items.length; + // If overflow, drop one tag to reserve space for "+N more" chip + const finalCount = hasOverflow ? Math.max(1, rowBreakIndex - 1) : rowBreakIndex; + setVisibleTagCount(finalCount); + }; + + measure(); + const ro = new ResizeObserver(measure); + ro.observe(container); + return () => ro.disconnect(); + }, [expertise]); + + const hiddenCount = expertise.length - visibleTagCount; return (
@@ -112,18 +152,19 @@ function ProfessionalCard({

Expertise:

-
- {expertise.slice(0, INITIAL_TAG_COUNT).map((tag, index) => ( +
+ {expertise.slice(0, visibleTagCount).map((tag, index) => ( {tag} ))} - {expertise.length > INITIAL_TAG_COUNT && ( + {hiddenCount > 0 && ( - +{expertise.length - INITIAL_TAG_COUNT} more + +{hiddenCount} more )}
diff --git a/src/components/layout/CommonHeader.tsx b/src/components/layout/CommonHeader.tsx index 41fcf47..82ac1f8 100644 --- a/src/components/layout/CommonHeader.tsx +++ b/src/components/layout/CommonHeader.tsx @@ -254,7 +254,7 @@ export function CommonHeader() { Sign in - Sign into connect + Sign in to Connect