Skip to content

Commit 67501a0

Browse files
authored
Merge pull request #15 from boostorg/develop
Dev -> QA
2 parents fa382d7 + 67676ef commit 67501a0

13 files changed

Lines changed: 918 additions & 407 deletions

core/views.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,49 @@ def get_context_data(self, **kwargs):
11701170
{"value": "networking", "label": "Networking"},
11711171
]
11721172
)
1173+
badge_img = f"{settings.STATIC_URL}img/v3/badges"
1174+
context["badge_icon_srcs"] = [
1175+
f"{badge_img}/badge-first-place.png",
1176+
f"{badge_img}/badge-second-place.png",
1177+
f"{badge_img}/badge-bronze.png",
1178+
f"{badge_img}/badge-gold-medal.png",
1179+
f"{badge_img}/badge-military-star.png",
1180+
]
1181+
context["demo_badges"] = [
1182+
{
1183+
"icon_src": f"{badge_img}/badge-first-place.png",
1184+
"name": "Patch Wizard",
1185+
"earned_date": "08/08/2025",
1186+
},
1187+
{
1188+
"icon_src": f"{badge_img}/badge-gold-medal.png",
1189+
"name": "Standard Bearer",
1190+
"earned_date": "03/07/2025",
1191+
},
1192+
{
1193+
"icon_src": f"{badge_img}/badge-military-star.png",
1194+
"name": "Review Hawk",
1195+
"earned_date": "03/06/2025",
1196+
},
1197+
{
1198+
"icon_src": f"{badge_img}/badge-second-place.png",
1199+
"name": "Library Alchemist",
1200+
"earned_date": "03/04/2025",
1201+
},
1202+
{
1203+
"icon_src": f"{badge_img}/badge-first-place.png",
1204+
"name": "Bug Catcher",
1205+
"earned_date": "02/04/2025",
1206+
},
1207+
{
1208+
"icon_src": f"{badge_img}/badge-bronze.png",
1209+
"name": "Code Whisperer",
1210+
"earned_date": "01/01/2025",
1211+
},
1212+
]
1213+
1214+
context["demo_badges_few"] = context["demo_badges"][:2]
1215+
11731216
context["create_account_card_preview_url"] = (
11741217
f"{settings.STATIC_URL}img/checker.png"
11751218
)

libraries/utils.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,12 @@ def get_avatar(user):
495495
return url
496496
return getattr(user.commitauthor, "avatar_url", "") or ""
497497

498-
medals = ["🥇", "🥈", "🥉"]
498+
badge_img = f"{settings.STATIC_URL}img/v3/badges"
499+
medals = [
500+
f"{badge_img}/badge-first-place.png",
501+
f"{badge_img}/badge-second-place.png",
502+
f"{badge_img}/badge-bronze.png",
503+
]
499504

500505
author_dicts = []
501506
for user in combined:
@@ -504,7 +509,7 @@ def get_avatar(user):
504509
"name": user.display_name or user.get_full_name(),
505510
"role": roles[user.id],
506511
"avatar_url": get_avatar(user),
507-
"badge": (
512+
"badge_url": (
508513
medals[len(author_dicts)] if len(author_dicts) < len(medals) else ""
509514
),
510515
"bio": "",
@@ -516,7 +521,7 @@ def get_avatar(user):
516521
"name": ca.display_name,
517522
"role": "Contributor",
518523
"avatar_url": ca.avatar_url or "",
519-
"badge": (
524+
"badge_url": (
520525
medals[len(author_dicts)] if len(author_dicts) < len(medals) else ""
521526
),
522527
"bio": "",

static/css/v3/badges-card.css

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
.badges-card {
2+
box-sizing: border-box;
3+
max-width: 696px;
4+
padding: var(--space-large, 16px) 0;
5+
}
6+
7+
/* Filled state — 3-column badge grid */
8+
.badges-card__grid {
9+
display: grid;
10+
grid-template-columns: repeat(3, 1fr);
11+
gap: var(--space-large, 16px);
12+
padding: 0 var(--space-large, 16px);
13+
margin: 0;
14+
list-style: none;
15+
}
16+
17+
.badges-card__entry {
18+
display: flex;
19+
flex-direction: row;
20+
align-items: center;
21+
gap: var(--space-default, 8px);
22+
}
23+
24+
.badges-card__icon {
25+
display: flex;
26+
align-items: center;
27+
justify-content: center;
28+
flex-shrink: 0;
29+
}
30+
31+
.badges-card__text {
32+
display: flex;
33+
flex-direction: column;
34+
gap: var(--space-xs);
35+
min-width: 0;
36+
}
37+
38+
.badges-card__name {
39+
color: var(--color-text-primary, #050816);
40+
font-size: var(--font-size-base, 16px);
41+
font-weight: var(--font-weight-regular, 400);
42+
line-height: var(--line-height-default, 1.2);
43+
}
44+
45+
.badges-card__date {
46+
color: var(--color-text-secondary, #585a64);
47+
font-size: var(--font-size-small, 14px);
48+
font-weight: var(--font-weight-regular, 400);
49+
line-height: var(--line-height-default, 1.2);
50+
}
51+
52+
/* Empty state */
53+
.badges-card__empty {
54+
display: flex;
55+
flex-direction: column;
56+
gap: var(--space-medium);
57+
padding: 0 var(--space-large, 16px);
58+
}
59+
60+
.badges-card__icon-row {
61+
display: flex;
62+
gap: var(--space-default, 8px);
63+
}
64+
65+
.badges-card__description {
66+
margin: 0;
67+
padding: var(--space-medium);
68+
padding-left: 0;
69+
padding-bottom: 0;
70+
color: var(--color-text-secondary, #585a64);
71+
font-size: var(--font-size-base, 16px);
72+
font-weight: var(--font-weight-semibold, 600);
73+
line-height: var(--line-height-default, 1.2);
74+
letter-spacing: -0.01em;
75+
}
76+
77+
.badges-card .btn-row {
78+
padding: 0 var(--space-large, 16px);
79+
}
80+
81+
/* Responsive — 2-column grid on mobile */
82+
@media (max-width: 696px) {
83+
.badges-card__grid {
84+
grid-template-columns: repeat(2, 1fr);
85+
}
86+
}

static/css/v3/components.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
@import "./wysiwyg-editor.css";
2222
@import "./search-card.css";
2323
@import "./create-account-card.css";
24+
@import "./badges-card.css";
2425
@import "./privacy-policy.css";
2526
@import "./library-intro-card.css";
2627
@import "./learn-cards.css";

static/css/v3/v3-examples-section.css

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,22 @@
2020
margin-bottom: 0;
2121
}
2222

23-
.v3-examples-section__block .block-title {
23+
.v3-examples-section__block > h3 {
2424
font-size: var(--font-size-base, 16px);
2525
font-weight: var(--font-weight-medium, 500);
2626
margin-bottom: var(--space-default, 8px);
2727
}
2828

29+
.v3-examples-section__anchor-link {
30+
margin-left: var(--space-s, 4px);
31+
color: var(--color-text-secondary);
32+
vertical-align: middle;
33+
}
34+
35+
.v3-examples-section__anchor-link:hover {
36+
color: var(--color-text-primary);
37+
}
38+
2939
.v3-examples-section__example-box {
3040
box-sizing: border-box;
3141
width: 100%;
@@ -218,3 +228,100 @@ html.dark .v3-examples-section__example-box {
218228
font-weight: var(--font-weight-medium);
219229
color: var(--color-text-secondary);
220230
}
231+
232+
/* ── Table of contents ─────────────────────────── */
233+
234+
.v3-examples-section__toc {
235+
margin-bottom: var(--space-xl, 32px);
236+
padding: var(--space-large, 16px) var(--space-xl, 32px);
237+
background: var(--color-surface-weak);
238+
border: 1px solid var(--color-border);
239+
border-radius: var(--border-radius-l, 8px);
240+
}
241+
242+
html.dark .v3-examples-section__toc {
243+
background: var(--color-surface-mid);
244+
}
245+
246+
.v3-examples-section__toc-heading {
247+
font-size: var(--font-size-base, 16px);
248+
font-weight: var(--font-weight-medium, 500);
249+
margin: 0 0 var(--space-default, 8px);
250+
color: var(--color-text-primary);
251+
}
252+
253+
.v3-examples-section__toc-list {
254+
list-style: none;
255+
margin: 0;
256+
padding: 0;
257+
display: grid;
258+
grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
259+
gap: var(--space-s, 4px) var(--space-xl, 32px);
260+
}
261+
262+
.v3-examples-section__toc-link {
263+
display: inline-block;
264+
padding: var(--space-s, 4px) 0;
265+
font-size: var(--font-size-small, 14px);
266+
color: var(--color-text-link-accent);
267+
text-decoration: none;
268+
}
269+
270+
.v3-examples-section__toc-link:hover {
271+
text-decoration: underline;
272+
}
273+
274+
/* ── Scroll offset for anchor links ────────────── */
275+
276+
.v3-examples-section__block[id] {
277+
scroll-margin-top: var(--space-xl, 32px);
278+
}
279+
280+
/* ── Fixed dark mode toggle ────────────────────── */
281+
282+
.v3-examples-section__theme-toggle {
283+
position: fixed;
284+
bottom: var(--space-xl, 32px);
285+
right: var(--space-xl, 32px);
286+
z-index: 100;
287+
display: inline-flex;
288+
align-items: center;
289+
justify-content: center;
290+
width: 50px;
291+
height: 50px;
292+
padding: 0 var(--space-l, 16px);
293+
border: 1px solid var(--color-border);
294+
border-radius: var(--border-radius-xl, 12px);
295+
background: var(--color-surface-brand-accent-hovered);
296+
color: var(--color-text-primary);
297+
cursor: pointer;
298+
box-shadow: 0 2px 8px rgb(0 0 0 / 0.12);
299+
}
300+
301+
.v3-examples-section__theme-toggle:hover {
302+
background: var(--color-navigation-hover);
303+
}
304+
305+
.v3-examples-section__theme-toggle-sun,
306+
.v3-examples-section__theme-toggle-moon {
307+
display: inline-flex;
308+
align-items: center;
309+
}
310+
311+
/* Light mode: show moon (switch to dark) */
312+
.v3-examples-section__theme-toggle-sun {
313+
display: none;
314+
}
315+
316+
.v3-examples-section__theme-toggle-moon {
317+
display: inline-flex;
318+
}
319+
320+
/* Dark mode: show sun (switch to light) */
321+
html.dark .v3-examples-section__theme-toggle-sun {
322+
display: inline-flex;
323+
}
324+
325+
html.dark .v3-examples-section__theme-toggle-moon {
326+
display: none;
327+
}
4.88 KB
Loading
4.52 KB
Loading
5.25 KB
Loading
3.98 KB
Loading
3.71 KB
Loading

0 commit comments

Comments
 (0)