Skip to content

Commit 561842f

Browse files
Merge pull request #343 from DevLoversTeam/feature/leaderboard-logic-update
feat: update sponsor button style and improve leaderboard display logic
2 parents 6a9a01c + 8e3fed8 commit 561842f

10 files changed

Lines changed: 178 additions & 85 deletions

File tree

frontend/app/globals.css

Lines changed: 96 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@
7070

7171
--accent-primary: #1e5eff;
7272
--accent-hover: #174ad6;
73+
74+
--sponsor: #bf3989;
75+
--sponsor-hover: #9a2f6e;
7376
}
7477

7578
.dark {
@@ -108,6 +111,43 @@
108111

109112
--accent-primary: #ff2d55;
110113
--accent-hover: #e0264b;
114+
115+
--sponsor: #db61a2;
116+
--sponsor-hover: #bf3989;
117+
}
118+
119+
html {
120+
overflow-x: hidden;
121+
}
122+
123+
*::-webkit-scrollbar {
124+
width: 6px;
125+
height: 6px;
126+
}
127+
128+
*::-webkit-scrollbar-track {
129+
background: transparent;
130+
}
131+
132+
*::-webkit-scrollbar-thumb {
133+
background: rgba(0, 0, 0, 0.25);
134+
border-radius: 3px;
135+
}
136+
137+
:is(.dark) *::-webkit-scrollbar-thumb,
138+
.dark::-webkit-scrollbar-thumb {
139+
background: rgba(255, 255, 255, 0.2);
140+
}
141+
142+
@supports (-moz-appearance: none) {
143+
* {
144+
scrollbar-width: thin;
145+
scrollbar-color: rgba(0, 0, 0, 0.25) transparent;
146+
}
147+
148+
:is(.dark) * {
149+
scrollbar-color: rgba(255, 255, 255, 0.2) transparent;
150+
}
111151
}
112152

113153
@layer base {
@@ -130,6 +170,7 @@
130170
.btn {
131171
background-color: var(--accent-primary);
132172
}
173+
133174
.btn:hover {
134175
background-color: var(--accent-hover);
135176
}
@@ -158,6 +199,7 @@
158199
from {
159200
width: 100%;
160201
}
202+
161203
to {
162204
width: 0%;
163205
}
@@ -167,45 +209,45 @@
167209
from {
168210
transform: scaleX(1);
169211
}
212+
170213
to {
171214
transform: scaleX(0);
172215
}
173216
}
174217

175218
@keyframes wave-clip {
219+
176220
0%,
177221
100% {
178-
clip-path: polygon(
179-
0% 50%,
180-
15% 48%,
181-
32% 52%,
182-
54% 60%,
183-
70% 62%,
184-
84% 60%,
185-
100% 55%,
186-
100% 100%,
187-
0% 100%
188-
);
222+
clip-path: polygon(0% 50%,
223+
15% 48%,
224+
32% 52%,
225+
54% 60%,
226+
70% 62%,
227+
84% 60%,
228+
100% 55%,
229+
100% 100%,
230+
0% 100%);
189231
}
232+
190233
50% {
191-
clip-path: polygon(
192-
0% 65%,
193-
16% 70%,
194-
34% 72%,
195-
51% 68%,
196-
67% 58%,
197-
84% 52%,
198-
100% 48%,
199-
100% 100%,
200-
0% 100%
201-
);
234+
clip-path: polygon(0% 65%,
235+
16% 70%,
236+
34% 72%,
237+
51% 68%,
238+
67% 58%,
239+
84% 52%,
240+
100% 48%,
241+
100% 100%,
242+
0% 100%);
202243
}
203244
}
204245

205246
@keyframes slide-up-gradient {
206247
0% {
207248
clip-path: inset(100% 0 0 0);
208249
}
250+
209251
100% {
210252
clip-path: inset(0 0 0 0);
211253
}
@@ -215,10 +257,11 @@
215257
0% {
216258
transform: translate(0, 0) scale(1) rotate(var(--card-rotate, 0deg));
217259
}
260+
218261
50% {
219-
transform: translate(var(--card-x, 0), var(--card-y, 0)) scale(1.05)
220-
rotate(calc(var(--card-rotate, 0deg) + var(--card-rotate-offset, 0deg)));
262+
transform: translate(var(--card-x, 0), var(--card-y, 0)) scale(1.05) rotate(calc(var(--card-rotate, 0deg) + var(--card-rotate-offset, 0deg)));
221263
}
264+
222265
100% {
223266
transform: translate(0, 0) scale(1) rotate(var(--card-rotate, 0deg));
224267
}
@@ -293,10 +336,12 @@
293336
}
294337

295338
@keyframes float {
339+
296340
0%,
297341
100% {
298342
transform: translateY(0);
299343
}
344+
300345
50% {
301346
transform: translateY(-8px);
302347
}
@@ -306,6 +351,7 @@
306351
0% {
307352
stroke-dashoffset: 0;
308353
}
354+
309355
100% {
310356
stroke-dashoffset: 20;
311357
}
@@ -359,16 +405,12 @@
359405
0 0 0 2px rgba(0, 0, 0, 0.4), 0 0 0 7px rgba(0, 0, 0, 0.1),
360406
0 22px 60px rgba(0, 0, 0, 0.28);
361407

362-
--shop-hero-btn-success-bg: color-mix(
363-
in oklab,
364-
var(--shop-hero-btn-bg) 88%,
365-
white
366-
);
367-
--shop-hero-btn-success-bg-hover: color-mix(
368-
in oklab,
369-
var(--shop-hero-btn-bg) 80%,
370-
white
371-
);
408+
--shop-hero-btn-success-bg: color-mix(in oklab,
409+
var(--shop-hero-btn-bg) 88%,
410+
white);
411+
--shop-hero-btn-success-bg-hover: color-mix(in oklab,
412+
var(--shop-hero-btn-bg) 80%,
413+
white);
372414
--shop-hero-btn-success-shadow: 0 22px 60px rgba(0, 0, 0, 0.25);
373415
--shop-hero-btn-success-shadow-hover: 0 28px 80px rgba(0, 0, 0, 0.32);
374416
}
@@ -421,16 +463,12 @@
421463
0 0 0 2px rgba(255, 45, 85, 0.7), 0 0 0 7px rgba(255, 45, 85, 0.22),
422464
0 22px 70px rgba(255, 45, 85, 0.38);
423465

424-
--shop-hero-btn-success-bg: color-mix(
425-
in oklab,
426-
var(--accent-primary) 82%,
427-
black
428-
);
429-
--shop-hero-btn-success-bg-hover: color-mix(
430-
in oklab,
431-
var(--accent-primary) 72%,
432-
black
433-
);
466+
--shop-hero-btn-success-bg: color-mix(in oklab,
467+
var(--accent-primary) 82%,
468+
black);
469+
--shop-hero-btn-success-bg-hover: color-mix(in oklab,
470+
var(--accent-primary) 72%,
471+
black);
434472
--shop-hero-btn-success-shadow: 0 22px 60px rgba(255, 45, 85, 0.45);
435473
--shop-hero-btn-success-shadow-hover: 0 28px 80px rgba(255, 45, 85, 0.6);
436474
}
@@ -440,6 +478,7 @@
440478
from {
441479
transform: translateX(0);
442480
}
481+
443482
to {
444483
transform: translateX(-100%);
445484
}
@@ -458,9 +497,12 @@
458497
0% {
459498
transform: translateY(0);
460499
}
500+
461501
100% {
462502
transform: translateY(-50%);
463-
} /* Рухаємось на 50%, бо контент дубльовано */
503+
}
504+
505+
/* Рухаємось на 50%, бо контент дубльовано */
464506
}
465507

466508
.animate-marquee-vertical {
@@ -474,18 +516,23 @@
474516

475517
/* Hide scrollbar for horizontal scroll containers */
476518
.scrollbar-hide {
477-
-ms-overflow-style: none; /* IE and Edge */
478-
scrollbar-width: none; /* Firefox */
519+
-ms-overflow-style: none;
520+
/* IE and Edge */
521+
scrollbar-width: none;
522+
/* Firefox */
479523
}
524+
480525
.scrollbar-hide::-webkit-scrollbar {
481-
display: none; /* Chrome, Safari and Opera */
526+
display: none;
527+
/* Chrome, Safari and Opera */
482528
}
483529

484530
@media (prefers-reduced-motion: reduce) {
531+
485532
.animate-float,
486533
.animate-spin-slow,
487534
.animate-spin-slower,
488535
.animate-dash-flow {
489536
animation: none !important;
490537
}
491-
}
538+
}

frontend/components/dashboard/ProfileCard.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,16 @@ export function ProfileCard({
6464
</p>
6565

6666
<div className="mt-3 flex flex-wrap items-center gap-2">
67-
{isSponsor ? (
67+
<span className="inline-flex items-center rounded-full bg-(--accent-primary)/10 px-3 py-1 text-xs font-bold tracking-wider text-(--accent-primary) uppercase">
68+
{user.role || t('defaultRole')}
69+
</span>
70+
{isSponsor && (
6871
<span
69-
className="inline-flex items-center gap-1.5 rounded-full bg-amber-100 px-3 py-1 text-xs font-bold tracking-wider text-amber-700 uppercase dark:bg-amber-500/15 dark:text-amber-400"
72+
className="inline-flex items-center gap-1.5 rounded-full bg-(--sponsor)/10 px-3 py-1 text-xs font-bold tracking-wider text-(--sponsor) uppercase dark:bg-(--sponsor)/15 dark:text-(--sponsor)"
7073
>
7174
<Heart className="h-3 w-3 fill-current" />
7275
{t('sponsor')}
7376
</span>
74-
) : (
75-
<span className="inline-flex items-center rounded-full bg-(--accent-primary)/10 px-3 py-1 text-xs font-bold tracking-wider text-(--accent-primary) uppercase">
76-
{user.role || t('defaultRole')}
77-
</span>
7877
)}
7978
</div>
8079
</div>
@@ -107,10 +106,12 @@ export function ProfileCard({
107106
href="https://github.com/sponsors/DevLoversTeam"
108107
target="_blank"
109108
rel="noopener noreferrer"
110-
className="group relative inline-flex items-center justify-center gap-2 overflow-hidden rounded-full border border-emerald-200 bg-emerald-50 px-8 py-3 text-sm font-semibold tracking-widest uppercase text-emerald-700 transition-all hover:scale-105 hover:border-(--accent-primary) hover:bg-(--accent-primary) hover:text-white dark:border-emerald-500/20 dark:bg-emerald-500/10 dark:text-emerald-400 dark:hover:border-(--accent-primary) dark:hover:bg-(--accent-primary) dark:hover:text-white"
109+
className="group relative inline-flex items-center justify-center gap-2 overflow-hidden rounded-full border border-(--sponsor)/30 bg-(--sponsor)/10 px-8 py-3 text-sm font-semibold tracking-widest uppercase text-(--sponsor) transition-all hover:scale-105 hover:border-(--accent-primary)/30 hover:bg-(--accent-primary) hover:text-white dark:border-(--sponsor)/30 dark:bg-(--sponsor)/15 dark:text-(--sponsor) dark:hover:border-(--accent-primary)/30 dark:hover:bg-(--accent-primary) dark:hover:text-white"
111110
>
112111
<Heart className="h-4 w-4 fill-current group-hover:fill-none" />
113-
<span className="grid">
112+
{/* Mobile: static text, Desktop: text swap on hover */}
113+
<span className="sm:hidden">{t('sponsorThanks')}</span>
114+
<span className="hidden sm:grid">
114115
<span className="col-start-1 row-start-1 transition-all group-hover:translate-y-full group-hover:opacity-0">
115116
{t('sponsorThanks')}
116117
</span>
@@ -124,7 +125,8 @@ export function ProfileCard({
124125
href="https://github.com/sponsors/DevLoversTeam"
125126
target="_blank"
126127
rel="noopener noreferrer"
127-
className="group relative inline-flex items-center justify-center gap-2 rounded-full px-8 py-3 text-sm font-semibold tracking-widest uppercase text-white bg-(--accent-primary) hover:bg-(--accent-hover) transition-all hover:scale-105"
128+
className="group relative inline-flex items-center justify-center gap-2 rounded-full bg-(--accent-primary) px-8 py-3 text-sm font-semibold tracking-widest uppercase text-white transition-all hover:scale-105 hover:bg-(--accent-hover)"
129+
128130
>
129131
<Heart className="h-4 w-4" />
130132
<span className="relative z-10">{t('becomeSponsor')}</span>

frontend/components/home/WelcomeHeroSection.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ export default function WelcomeHeroSection() {
2424
</span>
2525
<div className="relative">
2626
<h1 className="select-none text-5xl font-extrabold tracking-tight sm:text-6xl md:text-7xl lg:text-8xl">
27-
<span className="relative inline-block bg-gradient-to-r from-[var(--accent-primary)]/70 via-[color-mix(in_srgb,var(--accent-primary)_70%,white)]/70 to-[var(--accent-hover)]/70 bg-clip-text text-transparent">
27+
<span className="relative inline-block bg-linear-to-r from-(--accent-primary)/70 via-[color-mix(in_srgb,var(--accent-primary)_70%,white)]/70 to-(--accent-hover)/70 bg-clip-text text-transparent">
2828
DevLovers
2929
</span>
3030

3131
<span
32-
className="wave-text-gradient absolute inset-0 inline-block bg-gradient-to-r from-[var(--accent-primary)] via-[color-mix(in_srgb,var(--accent-primary)_70%,white)] to-[var(--accent-hover)] bg-clip-text text-transparent"
32+
className="wave-text-gradient absolute inset-0 inline-block bg-linear-to-r from-(--accent-primary) via-[color-mix(in_srgb,var(--accent-primary)_70%,white)] to-(--accent-hover) bg-clip-text text-transparent"
3333
aria-hidden="true"
3434
>
3535
DevLovers
@@ -48,26 +48,32 @@ export default function WelcomeHeroSection() {
4848

4949
<OnlineCounterPopup ctaRef={ctaRef} />
5050

51-
<motion.div
51+
<motion.button
52+
type="button"
53+
onClick={() => {
54+
const steps = document.querySelectorAll<HTMLElement>('[data-home-step]');
55+
if (steps[1]) steps[1].scrollIntoView({ behavior: 'smooth' });
56+
}}
5257
initial={{ opacity: 0, y: 20 }}
5358
animate={{ opacity: 1, y: 0 }}
5459
transition={{ delay: 1, duration: 1 }}
55-
className="absolute bottom-8 left-1/2 -translate-x-1/2 flex flex-col items-center gap-2 text-gray-400 dark:text-white/50"
60+
className="absolute bottom-8 left-1/2 -translate-x-1/2 flex cursor-pointer flex-col items-center gap-2 text-gray-400 transition-colors hover:text-(--accent-primary) dark:text-white/50 dark:hover:text-(--accent-primary)"
61+
aria-label={t('scrollToNextSection')}
5662
>
57-
<div className="relative h-8 w-5 rounded-full border-2 border-gray-300 p-1 dark:border-white/30">
58-
<motion.div
63+
<div className="relative h-8 w-5 rounded-full border-2 border-current p-1 opacity-75">
64+
<motion.div
5965
animate={{ y: [0, 8, 0] }}
6066
transition={{ duration: 1.5, repeat: Infinity, ease: "easeInOut" }}
61-
className="mx-auto h-1.5 w-1 rounded-full bg-gray-400 dark:bg-white/70"
67+
className="mx-auto h-1.5 w-1 rounded-full bg-current"
6268
/>
6369
</div>
6470
<motion.div
6571
animate={{ y: [0, 4, 0] }}
6672
transition={{ duration: 1.5, repeat: Infinity, ease: "easeInOut", delay: 0.2 }}
6773
>
68-
<ChevronDown className="h-4 w-4 text-gray-400 dark:text-white/50" />
74+
<ChevronDown className="h-4 w-4" />
6975
</motion.div>
70-
</motion.div>
76+
</motion.button>
7177
</section>
7278
);
7379
}

frontend/components/leaderboard/LeaderboardPodium.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export function LeaderboardPodium({ topThree }: { topThree: User[] }) {
117117
target="_blank"
118118
rel="noopener noreferrer"
119119
aria-label={t('sponsor')}
120-
className="mt-0.5 inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-0.5 text-[10px] font-bold text-amber-700 transition-colors hover:bg-amber-200 dark:bg-amber-500/15 dark:text-amber-400 dark:hover:bg-amber-500/25"
120+
className="mt-0.5 inline-flex items-center gap-1 rounded-full bg-(--sponsor)/10 px-2 py-0.5 text-[10px] font-bold text-(--sponsor) transition-colors hover:bg-(--sponsor)/20 dark:bg-(--sponsor)/15 dark:text-(--sponsor) dark:hover:bg-(--sponsor)/25"
121121
>
122122
<Heart className="h-2.5 w-2.5 fill-current" aria-hidden="true" />
123123
<span className="hidden md:inline">{t('sponsor')}</span>

0 commit comments

Comments
 (0)