Skip to content

Commit 5647b04

Browse files
author
iitzIrFan
committed
feat: enhance ShowcaseCard with clickable overlay and improved styles
1 parent 986f220 commit 5647b04

File tree

2 files changed

+265
-4
lines changed

2 files changed

+265
-4
lines changed

src/pages/showcase/_components/ShowcaseCard/index.tsx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,29 @@ function ShowcaseCardTag({tags}: {tags: TagType[]}) {
4848
}
4949

5050
function ShowcaseCard({user}: {user: User}) {
51+
const handleCardClick = () => {
52+
window.open(user.website, '_blank');
53+
};
54+
55+
const handleSourceClick = (e: React.MouseEvent) => {
56+
e.stopPropagation();
57+
// The link will handle the navigation
58+
};
59+
5160
return (
52-
<li key={user.title} className="card shadow--md">
61+
<li key={user.title} className={clsx('card shadow--md', styles.card)}>
62+
<div className={styles.cardLink} onClick={handleCardClick} />
5363
<div className={clsx('card__image', styles.showcaseCardImage)}>
5464
<IdealImage img={user.preview} alt={user.title} />
5565
</div>
5666
<div className="card__body">
57-
<div className={clsx(styles.showcaseCardHeader)}>
67+
<div className={styles.showcaseCardHeader}>
5868
<h4 className={styles.showcaseCardTitle}>
59-
<Link href={user.website} className={styles.showcaseCardLink}>
69+
<Link
70+
href={user.website}
71+
className={styles.showcaseCardLink}
72+
target="_blank"
73+
>
6074
{user.title}
6175
</Link>
6276
</h4>
@@ -70,6 +84,9 @@ function ShowcaseCard({user}: {user: User}) {
7084
'button button--secondary button--sm',
7185
styles.showcaseCardSrcBtn,
7286
)}
87+
target="_blank"
88+
rel="noopener noreferrer"
89+
onClick={handleSourceClick}
7390
>
7491
<Translate id="showcase.card.sourceLink">source</Translate>
7592
</Link>

src/pages/showcase/_components/ShowcaseCard/styles.module.css

Lines changed: 245 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
overflow: hidden;
33
height: 150px;
44
border-bottom: 2px solid var(--ifm-color-emphasis-200);
5+
transition: transform var(--ifm-transition-fast) ease;
56
}
67

78
.showcaseCardHeader {
@@ -22,11 +23,14 @@
2223
var(--ifm-color-primary)
2324
)
2425
0% 100% / 0% 1px no-repeat;
25-
transition: background-size ease-out 200ms;
26+
transition: all var(--ifm-transition-fast) ease;
27+
position: relative;
28+
z-index: 2;
2629
}
2730

2831
.showcaseCardTitle a:not(:focus):hover {
2932
background-size: 100% 1px;
33+
color: var(--ifm-link-hover-color);
3034
}
3135

3236
.showcaseCardTitle,
@@ -66,6 +70,8 @@
6670
.cardFooter {
6771
display: flex;
6872
flex-wrap: wrap;
73+
position: relative;
74+
z-index: 2;
6975
}
7076

7177
.tag {
@@ -90,3 +96,241 @@
9096
margin-left: 6px;
9197
margin-right: 6px;
9298
}
99+
100+
/* Card Styles */
101+
.card {
102+
--card-scale: 1;
103+
--card-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.1);
104+
--card-border: 1px solid var(--ifm-color-emphasis-200);
105+
106+
position: relative;
107+
overflow: hidden;
108+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
109+
border: var(--card-border);
110+
border-radius: 8px;
111+
height: 100%;
112+
display: flex;
113+
flex-direction: column;
114+
cursor: pointer;
115+
background: var(--ifm-card-background-color);
116+
transform: scale(var(--card-scale)) translateZ(0);
117+
will-change: transform, box-shadow, border-color;
118+
}
119+
120+
.card:hover {
121+
--card-scale: 1.02;
122+
--card-shadow: 0 12px 28px 0 rgba(0, 0, 0, 0.15);
123+
--card-border: 1px solid var(--ifm-color-primary);
124+
transform: translateY(-6px) scale(var(--card-scale)) translateZ(0);
125+
box-shadow: var(--card-shadow);
126+
border-color: var(--ifm-color-primary);
127+
}
128+
129+
/* Card clickable overlay */
130+
.cardLink {
131+
position: absolute;
132+
top: 0;
133+
left: 0;
134+
right: 0;
135+
bottom: 0;
136+
z-index: 1;
137+
opacity: 0;
138+
background: linear-gradient(135deg, rgba(var(--ifm-color-primary-rgb), 0.1) 0%, rgba(var(--ifm-color-primary-rgb), 0) 100%);
139+
transition: opacity 0.3s ease;
140+
}
141+
142+
.card:hover .cardLink {
143+
opacity: 1;
144+
}
145+
146+
/* Card content */
147+
.card__body {
148+
position: relative;
149+
z-index: 2;
150+
flex-grow: 1;
151+
display: flex;
152+
flex-direction: column;
153+
pointer-events: none;
154+
padding: 1.5rem 1.5rem 0.5rem;
155+
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
156+
}
157+
158+
.card:hover .card__body {
159+
transform: translateY(-4px);
160+
}
161+
162+
.card__body > * {
163+
pointer-events: auto;
164+
}
165+
166+
.card__footer {
167+
position: relative;
168+
z-index: 2;
169+
padding: 0.5rem 1.5rem 1.5rem;
170+
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
171+
}
172+
173+
.card:hover .card__footer {
174+
transform: translateY(4px);
175+
}
176+
177+
/* Source button */
178+
.showcaseCardSrcBtn {
179+
position: relative;
180+
z-index: 3;
181+
pointer-events: auto;
182+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
183+
transform: translateY(2px);
184+
opacity: 0.9;
185+
border-radius: 20px;
186+
font-weight: 500;
187+
letter-spacing: 0.5px;
188+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
189+
background: var(--ifm-color-primary);
190+
color: white !important;
191+
border: none;
192+
}
193+
194+
.showcaseCardSrcBtn:hover {
195+
transform: translateY(-1px) scale(1.03);
196+
opacity: 1;
197+
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
198+
background: var(--ifm-color-primary-dark);
199+
}
200+
201+
.showcaseCardSrcBtn:active {
202+
transform: translateY(1px) scale(0.98);
203+
}
204+
205+
/* Title styles */
206+
.showcaseCardTitle {
207+
position: relative;
208+
display: inline-block;
209+
margin: 0;
210+
}
211+
212+
.showcaseCardTitle a {
213+
position: relative;
214+
z-index: 2;
215+
pointer-events: auto;
216+
display: inline-block;
217+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
218+
font-weight: 600;
219+
color: var(--ifm-heading-color);
220+
text-decoration: none;
221+
background: linear-gradient(
222+
var(--ifm-color-primary),
223+
var(--ifm-color-primary)
224+
)
225+
0% 100% / 0% 2px no-repeat;
226+
padding-bottom: 2px;
227+
}
228+
229+
.showcaseCardTitle a:hover {
230+
background-size: 100% 2px;
231+
color: var(--ifm-color-primary);
232+
}
233+
234+
/* Image hover effect */
235+
.card__image,
236+
.showcaseCardImage {
237+
position: relative;
238+
z-index: 2;
239+
overflow: hidden;
240+
transform: translateZ(0);
241+
}
242+
243+
.showcaseCardImage img {
244+
transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
245+
transform: scale(1);
246+
will-change: transform;
247+
}
248+
249+
.card:hover .showcaseCardImage img {
250+
transform: scale(1.05);
251+
}
252+
253+
.showcaseCardImage::after {
254+
content: '';
255+
position: absolute;
256+
top: 0;
257+
left: 0;
258+
right: 0;
259+
bottom: 0;
260+
background: linear-gradient(
261+
to bottom,
262+
rgba(0, 0, 0, 0) 0%,
263+
rgba(0, 0, 0, 0.2) 100%
264+
);
265+
opacity: 0.5;
266+
transition: opacity 0.3s ease;
267+
mix-blend-mode: multiply;
268+
}
269+
270+
.card:hover .showcaseCardImage::after {
271+
opacity: 0.8;
272+
}
273+
274+
/* Tag styles */
275+
.tag {
276+
--tag-scale: 1;
277+
--tag-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
278+
279+
position: relative;
280+
overflow: hidden;
281+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
282+
transform: scale(var(--tag-scale)) translateZ(0);
283+
will-change: transform, box-shadow;
284+
border-radius: 12px;
285+
background: var(--ifm-color-emphasis-100);
286+
border: 1px solid var(--ifm-color-emphasis-200);
287+
box-shadow: var(--tag-shadow);
288+
}
289+
290+
.tag:hover {
291+
--tag-scale: 1.05;
292+
--tag-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
293+
transform: translateY(-2px) scale(var(--tag-scale)) translateZ(0);
294+
z-index: 1;
295+
}
296+
297+
.tag::before {
298+
content: '';
299+
position: absolute;
300+
top: 0;
301+
left: 0;
302+
width: 100%;
303+
height: 100%;
304+
background: linear-gradient(
305+
135deg,
306+
rgba(255, 255, 255, 0.2) 0%,
307+
rgba(255, 255, 255, 0) 100%
308+
);
309+
transform: translateX(-100%) skewX(-20deg);
310+
transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
311+
pointer-events: none;
312+
}
313+
314+
.tag:hover::before {
315+
transform: translateX(200%) skewX(-20deg);
316+
}
317+
318+
/* Favorite icon animation */
319+
.svgIconFavorite {
320+
transition: transform 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
321+
}
322+
323+
.card:hover .svgIconFavorite {
324+
transform: scale(1.2) rotate(8deg);
325+
filter: drop-shadow(0 2px 4px rgba(255, 0, 0, 0.3));
326+
}
327+
328+
/* Card description */
329+
.showcaseCardBody {
330+
transition: all 0.3s ease;
331+
opacity: 0.9;
332+
}
333+
334+
.card:hover .showcaseCardBody {
335+
opacity: 1;
336+
}

0 commit comments

Comments
 (0)