Skip to content

Commit f86ed08

Browse files
mrkeshav-05kasya
andauthored
Refactor layout and styling of Leaders and UserCard components for im… (#2501)
* Refactor layout and styling of Leaders and UserCard components for improved responsiveness and visual consistency * fix: correct class names for text wrapping in UserCard component * fix: improve layout and styling of UserCard component for better responsiveness * refactor: improve layout and styling of Leaders and UserCard components * Update layout for UserCard * Apply make-check * Fix tests * Fix truncate on User card for members page * Fix alignment for longer names --------- Co-authored-by: Kate <kate@kgthreads.com>
1 parent dffea35 commit f86ed08

File tree

4 files changed

+59
-35
lines changed

4 files changed

+59
-35
lines changed

frontend/__tests__/unit/components/UserCard.test.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ jest.mock('@fortawesome/react-fontawesome', () => ({
6565
}) => <span data-testid={`icon-${icon.iconName}`} className={className} {...props} />,
6666
}))
6767

68+
jest.mock('@heroui/tooltip', () => ({
69+
Tooltip: ({ children, content }: { children: React.ReactNode; content: string }) => (
70+
<div data-testid="tooltip" data-tooltip-content={content}>
71+
{children}
72+
</div>
73+
),
74+
}))
75+
6876
jest.mock('millify', () => ({
6977
__esModule: true,
7078
default: (value: number) => {
@@ -131,7 +139,7 @@ describe('UserCard', () => {
131139
render(<UserCard {...fullProps} />)
132140

133141
expect(screen.getByText('John Doe')).toBeInTheDocument()
134-
expect(screen.getByText('Tech Corp')).toBeInTheDocument()
142+
expect(screen.getByText(/Tech Corp/)).toBeInTheDocument()
135143
expect(screen.getByText('Software Developer')).toBeInTheDocument()
136144
expect(screen.getByTestId('user-avatar')).toHaveAttribute(
137145
'src',
@@ -162,7 +170,7 @@ describe('UserCard', () => {
162170
it('renders company information when provided', () => {
163171
render(<UserCard {...defaultProps} company="Tech Corp" />)
164172

165-
expect(screen.getByText('Tech Corp')).toBeInTheDocument()
173+
expect(screen.getByText(/Tech Corp/)).toBeInTheDocument()
166174
})
167175

168176
it('renders location when company is not provided', () => {
@@ -340,7 +348,15 @@ describe('UserCard', () => {
340348
render(<UserCard {...defaultProps} />)
341349

342350
const button = screen.getByRole('button')
343-
expect(button).toHaveClass('group', 'flex', 'flex-col', 'items-center', 'rounded-lg', 'p-6')
351+
expect(button).toHaveClass(
352+
'group',
353+
'flex',
354+
'flex-col',
355+
'items-center',
356+
'rounded-lg',
357+
'px-6',
358+
'py-6'
359+
)
344360
})
345361
})
346362

frontend/__tests__/unit/pages/Users.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ describe('UsersPage Component', () => {
8888
expect(screen.getByText('Security Co')).toBeInTheDocument()
8989
})
9090

91-
const viewButtons = screen.getAllByText('View Profile')
91+
const viewButtons = screen.getAllByText('View Details')
9292
expect(viewButtons).toHaveLength(2)
9393
})
9494

@@ -121,11 +121,11 @@ describe('UsersPage Component', () => {
121121
})
122122
})
123123

124-
test('navigates to user details on View Profile button click', async () => {
124+
test('navigates to user details on View Details button click', async () => {
125125
render(<UsersPage />)
126126

127127
await waitFor(() => {
128-
const viewDetailsButtons = screen.getAllByText('View Profile')
128+
const viewDetailsButtons = screen.getAllByText('View Details')
129129
expect(viewDetailsButtons[0]).toBeInTheDocument()
130130
fireEvent.click(viewDetailsButtons[0])
131131
})

frontend/src/components/Leaders.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const Leaders: React.FC<LeadersProps> = ({ users }) => {
2424

2525
return (
2626
<SecondaryCard icon={faPersonWalkingArrowRight} title={<AnchorTitle title="Leaders" />}>
27-
<div className="flex w-full flex-col items-center justify-around overflow-hidden md:flex-row">
27+
<div className="flex w-full flex-wrap items-stretch justify-center gap-4 p-2">
2828
{users.map((user) => (
2929
<UserCard
3030
key={user.member?.login || user.memberName}
@@ -34,7 +34,7 @@ const Leaders: React.FC<LeadersProps> = ({ users }) => {
3434
label: 'View Profile',
3535
onclick: () => handleButtonClick(user),
3636
}}
37-
className="h-64 w-44 bg-inherit"
37+
className="h-auto w-full max-w-[280px] bg-inherit"
3838
description={user.description}
3939
name={user.member?.name || user.memberName}
4040
/>

frontend/src/components/UserCard.tsx

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
} from '@fortawesome/free-solid-svg-icons'
88
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
99
import { Button } from '@heroui/button'
10+
import { Tooltip } from '@heroui/tooltip'
1011
import millify from 'millify'
1112
import Image from 'next/image'
1213
import type { UserCardProps } from 'types/card'
@@ -28,10 +29,10 @@ const UserCard = ({
2829
return (
2930
<Button
3031
onPress={button.onclick}
31-
className={`group flex flex-col items-center rounded-lg p-6 ${className}`}
32+
className={`group flex flex-col items-center rounded-lg px-6 py-6 ${className}`}
3233
>
33-
<div className="flex w-full flex-col items-center gap-4">
34-
<div className="relative h-20 w-20 overflow-hidden rounded-full ring-2 ring-gray-100 group-hover:ring-blue-400 dark:ring-gray-700">
34+
<div className="flex w-full flex-col items-center gap-3">
35+
<div className="relative h-20 w-20 shrink-0 overflow-hidden rounded-full ring-2 ring-gray-100 transition-all group-hover:ring-blue-400 dark:ring-gray-700">
3536
{avatar ? (
3637
<Image fill src={`${avatar}&s=160`} alt={name || 'user'} objectFit="cover" />
3738
) : (
@@ -44,43 +45,50 @@ const UserCard = ({
4445
)}
4546
</div>
4647

47-
<div className="text-center">
48-
<h3 className="max-w-[250px] truncate text-lg font-semibold text-gray-900 sm:text-xl dark:text-white">
49-
{name}
50-
</h3>
51-
<p className="mt-1 max-w-[250px] truncate text-sm text-gray-600 sm:text-base dark:text-gray-400">
52-
{company || location || email || login}
53-
</p>
48+
<div className="w-full max-w-[250px] min-w-0 text-center">
49+
<Tooltip content={name} delay={100} closeDelay={100} showArrow placement="top">
50+
<h3 className="w-full truncate text-lg font-semibold text-gray-900 sm:text-xl dark:text-white">
51+
{name}
52+
</h3>
53+
</Tooltip>
54+
{(company || location || email || login) && (
55+
<p className="mt-1.5 truncate px-3 text-xs text-gray-600 sm:text-sm dark:text-gray-400">
56+
{company || location || email || login}
57+
</p>
58+
)}
5459
{description && (
55-
<p className="mt-1 max-w-[250px] truncate text-sm text-gray-600 sm:text-base dark:text-gray-400">
60+
<p className="mt-1.5 truncate px-3 text-xs text-gray-600 sm:text-sm dark:text-gray-400">
5661
{description}
5762
</p>
5863
)}
59-
<div className="flex justify-center gap-3">
64+
</div>
65+
66+
{(followersCount > 0 || repositoriesCount > 0 || badgeCount > 0) && (
67+
<div className="flex flex-wrap justify-center gap-3 px-2">
6068
{followersCount > 0 && (
61-
<p className="mt-1 max-w-[250px] truncate text-sm text-gray-600 sm:text-base dark:text-gray-400">
62-
<FontAwesomeIcon icon={faUsers} className="mr-1 h-4 w-4" />
63-
{millify(followersCount, { precision: 1 })}
64-
</p>
69+
<div className="flex items-center gap-1 text-xs text-gray-600 sm:text-sm dark:text-gray-400">
70+
<FontAwesomeIcon icon={faUsers} className="h-3.5 w-3.5" />
71+
<span>{millify(followersCount, { precision: 1 })}</span>
72+
</div>
6573
)}
6674
{repositoriesCount > 0 && (
67-
<p className="mt-1 max-w-[250px] truncate text-sm text-gray-600 sm:text-base dark:text-gray-400">
68-
<FontAwesomeIcon icon={faFolderOpen} className="mr-1 h-4 w-4" />
69-
{millify(repositoriesCount, { precision: 1 })}
70-
</p>
75+
<div className="flex items-center gap-1 text-xs text-gray-600 sm:text-sm dark:text-gray-400">
76+
<FontAwesomeIcon icon={faFolderOpen} className="h-3.5 w-3.5" />
77+
<span>{millify(repositoriesCount, { precision: 1 })}</span>
78+
</div>
7179
)}
7280
{badgeCount > 0 && (
73-
<p className="mt-1 max-w-[250px] truncate text-sm text-gray-600 sm:text-base dark:text-gray-400">
74-
<FontAwesomeIcon icon={faMedal} className="mr-1 h-4 w-4" aria-label="badges" />
75-
{millify(badgeCount, { precision: 1 })}{' '}
76-
</p>
81+
<div className="flex items-center gap-1 text-xs text-gray-600 sm:text-sm dark:text-gray-400">
82+
<FontAwesomeIcon icon={faMedal} className="h-3.5 w-3.5" aria-label="badges" />
83+
<span>{millify(badgeCount, { precision: 1 })}</span>
84+
</div>
7785
)}
7886
</div>
79-
</div>
87+
)}
8088
</div>
8189

82-
<div className="inline-flex items-center text-sm font-medium text-blue-400">
83-
View Profile
90+
<div className="flex items-center justify-center text-sm font-medium text-blue-400">
91+
{button.label}
8492
<FontAwesomeIcon
8593
icon={faChevronRight}
8694
className="ml-2 h-4 w-4 transform transition-transform group-hover:translate-x-1"

0 commit comments

Comments
 (0)