diff --git a/ak/views.py b/ak/views.py index 5a4541f36..10d73664c 100644 --- a/ak/views.py +++ b/ak/views.py @@ -8,22 +8,26 @@ from django.views.generic import TemplateView from core.calendar import extract_calendar_events, events_by_month, get_calendar +from core.mixins import V3Mixin from libraries.constants import LATEST_RELEASE_URL_PATH_STR from libraries.mixins import ContributorMixin from news.models import Entry from testimonials.models import Testimonial +from core.mock_data import SharedResources logger = structlog.get_logger() -class HomepageView(ContributorMixin, TemplateView): +class HomepageView(V3Mixin, ContributorMixin, TemplateView): """ Define all the pieces that will be displayed on the home page """ template_name = "homepage.html" + v3_template_name = "v3/homepage.html" + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["entries"] = Entry.objects.published().order_by("-publish_at")[:3] @@ -67,6 +71,107 @@ def get_events(self): return dict(sorted_events) + def get_v3_context_data(self, **kwargs): + ctx = super().get_context_data(**kwargs) + ctx["install_card_pkg_managers"] = SharedResources.install_card_pkg_managers + ctx["install_card_system_install"] = SharedResources.install_card_system_install + + demo_cards = [ + { + "title": "Performant", + "description": "Optimized for production at any scale, Boost outperforms many standard benchmarks.", + "icon_name": "bullseye-arrow", + }, + { + "title": "Peer-reviewed", + "description": "Well tested by members of the C++ standards committee.", + "icon_name": "get-help", + }, + { + "title": "Portable", + "description": "Works across all platforms, compilers, and C++ standards.", + "icon_name": "link", + }, + { + "title": "Innovative", + "description": "Over 40 Boost libraries have become part of the C++ standard over the past 25 years.", + "icon_name": "bullseye-arrow", + }, + { + "title": "Community-powered", + "description": "Contributing to Boost builds credibility, sharpens skills, and advances careers.", + "icon_name": "human", + }, + { + "title": "Known worldwide", + "description": "Used in countless projects, you've probably encountered Boost without realizing it.", + "icon_name": "link", + }, + { + "title": "Free", + "description": "Open source now and always, thanks to the Boost Software License.", + "icon_name": "check", + }, + { + "title": "Production-ready", + "description": "Battle-tested in critical systems across industries around the globe.", + "icon_name": "bullseye-arrow", + }, + ] + + ctx["library_cards"] = demo_cards + ctx["why_boost_cards"] = demo_cards[:8] + ctx["calendar_card"] = { + "title": "Boost is released three times a year", + "text": "Each release has updates to existing libraries, and any new libraries that have passed the rigorous acceptance process.", + "primary_button_url": "www.example.com", + "primary_button_label": "View the Release Calendar", + "secondary_button_url": "www.example.com", + "secondary_button_label": "Secondary Button", + "image": f"{settings.STATIC_URL}/img/v3/demo_page/Calendar.png", + } + ctx["info_card"] = { + "title": "How we got here", + "text": "Since 1998, Boost has been where C++ innovation happens. What started with three developers has grown into the foundation of modern C++ development.", + "primary_button_url": "www.example.com", + "primary_button_label": "Explore Our History", + } + ctx["posts_from_the_boost_community"] = { + "heading": "Posts from the Boost Community", + "primary_cta_label": "View all posts", + "primary_cta_url": "#", + "variant": "card", + "theme": "teal", + "items": SharedResources.demo_posts[:5], + } + ctx["join_developers_building_the_future_of_cpp"] = { + "items": SharedResources.demo_join_community_links[:5] + } + ctx["boost_community_data"] = { + "heading": "The Boost community", + "view_all_url": "#", + "view_all_label": "Explore the community", + "posts": SharedResources.demo_posts, + } + ctx["popular_terms"] = SharedResources.popular_terms + ctx["demo_events_with_links"] = SharedResources.demo_events_with_links[:4] + ctx["code_demo_hello"] = SharedResources.code_demo_hello + ctx["stats_in_numbers"] = { + "example_library_commits_bars": SharedResources.example_library_commits_bars + } + ctx["testimonial_data"] = {"testimonials": SharedResources.testimonials} + + ctx["library_intro"] = SharedResources.library_intro + + ctx["build_anything_with_boost"] = SharedResources.build_anything_with_boost + + ctx["hero_legacy_image_url_light"] = SharedResources.hero_legacy_image_url_light + ctx["hero_legacy_image_url_dark"] = SharedResources.hero_legacy_image_url_dark + ctx["hero_image_url"] = SharedResources.hero_image_url + ctx["hero_image_url_light"] = SharedResources.hero_image_url_light + ctx["hero_image_url_dark"] = SharedResources.hero_image_url_dark + return ctx + class ForbiddenView(View): """ diff --git a/core/mock_data.py b/core/mock_data.py new file mode 100644 index 000000000..5991c4258 --- /dev/null +++ b/core/mock_data.py @@ -0,0 +1,291 @@ +from datetime import date + +from django.conf import settings + +from libraries.utils import commit_data_to_stats_bars + + +class SharedResources: + badge_img = f"{settings.STATIC_URL}img/v3/badges" + + demo_posts = [ + { + "title": "A talk by Richard Thomson at the Utah C++ Programmers Group", + "url": "#", + "date": date(2025, 3, 3), + "category": "Issues", + "tag": "beast", + "author": { + "name": "Richard Thomson", + "profile_url": "#", + "role": "Contributor", + "avatar_url": "https://ui-avatars.com/api/?name=Richard+Thomson&size=48", + "badge_url": f"{badge_img}/badge-first-place.png", + }, + }, + { + "title": "A talk by Richard Thomson at the Utah C++ Programmers Group", + "url": "#", + "date": date(2025, 3, 3), + "category": "Issues", + "tag": "beast", + "author": { + "name": "Peter Dimov", + "profile_url": "#", + "role": "Maintainer", + "avatar_url": "https://ui-avatars.com/api/?name=Peter+Dimov&size=48", + "badge_url": f"{badge_img}/badge-bronze.png", + }, + }, + { + "title": "Boost.Bind and modern C++: a quick overview", + "url": "#", + "date": date(2025, 2, 15), + "category": "Releases", + "tag": "bind", + "author": { + "name": "Alex Morgan", + "profile_url": "#", + "role": "Contributor", + "avatar_url": "https://thispersondoesnotexist.com/", + }, + }, + { + "title": "Boost.Bind and modern C++: a quick overview again", + "url": "#", + "date": date(2025, 2, 15), + "category": "Releases", + "tag": "bind", + "author": { + "name": "Alex Morgan", + "profile_url": "#", + "role": "Contributor", + "avatar_url": "https://thispersondoesnotexist.com/", + }, + }, + { + "title": "utility::string_view and core::detail::string_view", + "url": "#", + "date": date(2025, 2, 15), + "category": "Releases", + "tag": "bind", + "author": { + "name": "Alex Morgan", + "profile_url": "#", + "role": "Contributor", + "avatar_url": "https://thispersondoesnotexist.com/", + }, + }, + ] + + install_card_pkg_managers = [ + {"label": "Conan", "value": "conan", "command": "conan install boost"}, + {"label": "Vcpkg", "value": "vcpkg", "command": "vcpkg install boost"}, + ] + + install_card_system_install = [ + { + "label": "Ubuntu", + "value": "ubuntu", + "command": "sudo apt install libboost-all-dev", + }, + { + "label": "Fedora", + "value": "fedora", + "command": "sudo dnf install boost-devel", + }, + { + "label": "CentOS", + "value": "centos", + "command": "sudo yum install boost-devel", + }, + {"label": "Arch", "value": "arch", "command": "sudo pacman -S boost"}, + {"label": "Homebrew", "value": "homebrew", "command": "brew install boost"}, + ] + + popular_terms = [ + {"label": "Networking"}, + {"label": "Math"}, + {"label": "Data processing"}, + {"label": "Concurrency"}, + {"label": "File systems"}, + {"label": "Testing"}, + ] + + demo_events = [ + { + "title": "Boost 1.90.0 closed for major changes", + "description": "Release closed for major code changes. " + "Still open for serious problem fixes.", + "date": "29/10/25", + "datetime": "2025-10-29", + }, + { + "title": "C++ Now 2025 call for submissions", + "description": "C++ Now conference is accepting talk proposals " + "until March 15.", + "date": "12/02/25", + "datetime": "2025-02-12", + }, + { + "title": "Boost 1.89.0 released", + "description": "Boost 1.89.0 is available with updates to Asio, " + "Beast, and several other libraries.", + "date": "15/01/25", + "datetime": "2025-01-15", + }, + { + "title": "Boost 1.89.0 released", + "description": "Boost 1.89.0 is available with updates to Asio, " + "Beast, and several other libraries.", + "date": "15/01/25", + "datetime": "2025-01-15", + }, + ] + + demo_events_with_links = [ + { + **event, + "card_url": f"#event-{i}", + "card_aria_label": event["title"], + } + for i, event in enumerate(demo_events) + ] + + code_demo_hello = """#include +int main() +{ + std::cout << "Hello, Boost."; +}""" + + demo_join_community_links = 4 * [ + { + "title": "Get help", + "url": "#", + "description": "Tap into quick answers, networking, and chat with 24,000+ members.", + "icon_name": "github", + } + ] + + example_commit_data = [ + {"release": "1.71.0", "commit_count": 106}, + {"release": "1.72.0", "commit_count": 70}, + {"release": "1.73.0", "commit_count": 65}, + {"release": "1.74.0", "commit_count": 60}, + {"release": "1.75.0", "commit_count": 36}, + {"release": "1.76.0", "commit_count": 31}, + {"release": "1.77.0", "commit_count": 15}, + {"release": "1.78.0", "commit_count": 17}, + {"release": "1.79.0", "commit_count": 22}, + {"release": "1.80.0", "commit_count": 2}, + {"release": "1.81.0", "commit_count": 76}, + {"release": "1.82.0", "commit_count": 32}, + {"release": "1.83.0", "commit_count": 3}, + {"release": "1.84.0", "commit_count": 35}, + {"release": "1.85.0", "commit_count": 41}, + {"release": "1.86.0", "commit_count": 42}, + {"release": "1.87.0", "commit_count": 27}, + {"release": "1.88.0", "commit_count": 28}, + {"release": "1.89.0", "commit_count": 15}, + {"release": "1.90.0", "commit_count": 18}, + ] + + example_library_commits_bars = commit_data_to_stats_bars( + example_commit_data[-10:] + if len(example_commit_data) > 10 + else example_commit_data + ) + + testimonials = [ + { + "quote": "I use Boost daily. I absolutely love it. It's wonderful. I could not do my job w/o it. Much of it is in the new C++11 standard too.", + "author": { + "name": "Name Surname", + "profile_url": "#", + "avatar_url": "/static/img/v3/demo_page/Avatar.png", + "role": "Contributor", + "badge_url": "/static/img/v3/demo_page/Badge.svg", + }, + }, + { + "quote": "I use Boost daily. I absolutely love it. It's wonderful. I could not do my job w/o it. Much of it is in the new C++11 standard too.", + "author": { + "name": "Name Surname", + "profile_url": "#", + "avatar_url": "/static/img/v3/demo_page/Avatar.png", + "role": "Contributor", + "badge_url": "/static/img/v3/demo_page/Badge.svg", + }, + }, + { + "quote": "I use Boost d1aily. I absolutely love it. It's wonderful. I could not do my job w/o it. Much of it is in the new C++11 standard too.", + "author": { + "name": "Name Surname", + "profile_url": "#", + "avatar_url": "/static/img/v3/demo_page/Avatar.png", + "role": "Contributor", + "badge_url": "/static/img/v3/demo_page/Badge.svg", + }, + }, + { + "quote": "I use Boost daily. I absolutely love it. It's wonderful. I could not do my job w/o it. Much of it is in the new C++11 standard too.", + "author": { + "name": "Name Surname", + "profile_url": "#", + "avatar_url": "/static/img/v3/demo_page/Avatar.png", + "role": "Contributor", + "badge_url": "/static/img/v3/demo_page/Badge.svg", + }, + }, + ] + + library_intro = { + "library_name": "Boost.Core.", + "description": "Lightweight utilities that power dozens of other Boost libraries", + "authors": [ + { + "name": "Vinnie Falco", + "role": "Author", + "avatar_url": f"{settings.STATIC_URL}img/v3/demo_page/Avatar.png", + "badge_url": f"{settings.STATIC_URL}img/v3/demo_page/Badge.svg", + "bio": "Big C++ fan. Not quite kidney-donation level, but close.", + }, + { + "name": "Alex Wells", + "role": "Contributor", + "avatar_url": f"{settings.STATIC_URL}img/v3/demo_page/Avatar.png", + "bio": "C++ enthusiast who has worked at Intel and Microsoft.", + }, + { + "name": "Dave Abrahams", + "role": "Maintainer", + "avatar_url": f"{settings.STATIC_URL}img/v3/demo_page/Avatar.png", + "badge_url": f"{settings.STATIC_URL}img/v3/demo_page/Badge.svg", + "bio": "Contributor to Boost since 2009.", + }, + ], + "cta_url": "#", + } + + build_anything_with_boost = { + "title": "Build anything with Boost", + "text": "Use, modify, and distribute Boost libraries freely. No binary attribution needed.", + "image_url": f"{settings.STATIC_URL}img/checker.png", + "image_alt": "This is a placeholder image", + "button_url": "#", + "button_label": "See license details", + } + + hero_legacy_image_url_light = f"{settings.STATIC_URL}img/v3/home-page/heros.png" + + hero_legacy_image_url_dark = ( + f"{settings.STATIC_URL}img/v3/home-page/heros_light.png" + ) + + hero_image_url = f"{settings.STATIC_URL}img/v3/home-page/home-page-foreground.png" + hero_image_url_light = ( + f"{settings.STATIC_URL}img/v3/home-page/home-page-foreground.png" + ) + hero_image_url_dark = ( + f"{settings.STATIC_URL}img/v3/home-page/home-page-foreground.png" + ) diff --git a/core/views.py b/core/views.py index 03c841091..3daf2d875 100644 --- a/core/views.py +++ b/core/views.py @@ -1,5 +1,3 @@ -from datetime import date - import os import re @@ -84,6 +82,15 @@ save_rendered_content, ) +from libraries.models import Library, LibraryVersion +from libraries.utils import ( + build_library_intro_context, + get_commit_data_by_release_for_library, + commit_data_to_stats_bars, +) + +from .mock_data import SharedResources # noqa: F401 + logger = structlog.get_logger() @@ -1247,11 +1254,7 @@ class V3ComponentDemoView(TemplateView): def get_context_data(self, **kwargs): from django.urls import reverse - from libraries.models import Library, LibraryVersion from libraries.utils import ( - build_library_intro_context, - get_commit_data_by_release_for_library, - commit_data_to_stats_bars, patch_commit_authors, ) @@ -1275,12 +1278,6 @@ def get_context_data(self, **kwargs): std::cout << res << std::endl; }""" - CODE_DEMO_HELLO = """#include - int main() - { - std::cout << "Hello, Boost."; - }""" - CODE_DEMO_INSTALL = """brew install openssl export OPENSSL_ROOT=$(brew --prefix openssl) @@ -1288,47 +1285,18 @@ def get_context_data(self, **kwargs): # Install bjam tool user config: https://www.bfgroup.xyz/b2/manual/release/index.html cp ./libs/beast/tools/user-config.jam $HOME""" - INSTALL_CARD_PKG_MANAGERS = [ - {"label": "Conan", "value": "conan", "command": "conan install boost"}, - {"label": "Vcpkg", "value": "vcpkg", "command": "vcpkg install boost"}, - ] - INSTALL_CARD_SYSTEM_INSTALL = [ - { - "label": "Ubuntu", - "value": "ubuntu", - "command": "sudo apt install libboost-all-dev", - }, - { - "label": "Fedora", - "value": "fedora", - "command": "sudo dnf install boost-devel", - }, - { - "label": "CentOS", - "value": "centos", - "command": "sudo yum install boost-devel", - }, - {"label": "Arch", "value": "arch", "command": "sudo pacman -S boost"}, - {"label": "Homebrew", "value": "homebrew", "command": "brew install boost"}, - ] - context = super().get_context_data(**kwargs) context["code_demo_beast"] = CODE_DEMO_BEAST - context["code_demo_hello"] = CODE_DEMO_HELLO + context["code_demo_hello"] = SharedResources.code_demo_hello context["code_demo_install"] = CODE_DEMO_INSTALL context["install_card_title"] = ( "Install Boost and get started in your terminal." ) - context["install_card_pkg_managers"] = INSTALL_CARD_PKG_MANAGERS - context["install_card_system_install"] = INSTALL_CARD_SYSTEM_INSTALL - context["popular_terms"] = [ - {"label": "Networking"}, - {"label": "Math"}, - {"label": "Data processing"}, - {"label": "Concurrency"}, - {"label": "File systems"}, - {"label": "Testing"}, - ] + context["install_card_pkg_managers"] = SharedResources.install_card_pkg_managers + context["install_card_system_install"] = ( + SharedResources.install_card_system_install + ) + context["popular_terms"] = SharedResources.popular_terms context["demo_libs"] = [ ("asio", "Asio"), ("beast", "Beast"), @@ -1412,50 +1380,10 @@ def get_context_data(self, **kwargs): {"label": "Issues", "value": "issues"}, ] - context["demo_posts"] = [ - { - "title": "A talk by Richard Thomson at the Utah C++ Programmers Group", - "url": "#", - "date": date(2025, 3, 3), - "category": "Issues", - "tag": "beast", - "author": { - "name": "Richard Thomson", - "profile_url": "#", - "role": "Contributor", - "avatar_url": "https://ui-avatars.com/api/?name=Richard+Thomson&size=48", - "badge_url": f"{badge_img}/badge-first-place.png", - }, - }, - { - "title": "A talk by Richard Thomson at the Utah C++ Programmers Group", - "url": "#", - "date": date(2025, 3, 3), - "category": "Issues", - "tag": "beast", - "author": { - "name": "Peter Dimov", - "profile_url": "#", - "role": "Maintainer", - "avatar_url": "https://ui-avatars.com/api/?name=Peter+Dimov&size=48", - "badge_url": f"{badge_img}/badge-bronze.png", - }, - }, - { - "title": "Boost.Bind and modern C++: a quick overview", - "url": "#", - "date": date(2025, 2, 15), - "category": "Releases", - "tag": "bind", - "author": { - "name": "Alex Morgan", - "profile_url": "#", - "role": "Contributor", - "avatar_url": "https://thispersondoesnotexist.com/", - }, - }, - ] - context["demo_post"] = context["demo_posts"][0] + context["demo_posts"] = SharedResources.demo_posts + context["demo_post"] = SharedResources.demo_posts[0] + + context["demo_join_community_links"] = SharedResources.demo_join_community_links context["demo_user_card"] = { "username": "vinniefalco", @@ -1577,38 +1505,9 @@ def get_context_data(self, **kwargs): }, ] - context["demo_events"] = [ - { - "title": "Boost 1.90.0 closed for major changes", - "description": "Release closed for major code changes. " - "Still open for serious problem fixes.", - "date": "29/10/25", - "datetime": "2025-10-29", - }, - { - "title": "C++ Now 2025 call for submissions", - "description": "C++ Now conference is accepting talk proposals " - "until March 15.", - "date": "12/02/25", - "datetime": "2025-02-12", - }, - { - "title": "Boost 1.89.0 released", - "description": "Boost 1.89.0 is available with updates to Asio, " - "Beast, and several other libraries.", - "date": "15/01/25", - "datetime": "2025-01-15", - }, - ] + context["demo_events"] = SharedResources.demo_events - context["demo_events_with_links"] = [ - { - **event, - "card_url": f"#event-{i}", - "card_aria_label": event["title"], - } - for i, event in enumerate(context["demo_events"]) - ] + context["demo_events_with_links"] = SharedResources.demo_events_with_links[:3] context["create_account_card_preview_url"] = ( f"{settings.STATIC_URL}img/checker.png" @@ -1617,20 +1516,14 @@ def get_context_data(self, **kwargs): f"{settings.STATIC_URL}img/v3/home-page/home-page-background.png" ) context["hero_legacy_image_url_light"] = ( - f"{settings.STATIC_URL}img/v3/home-page/heros.png" + SharedResources.hero_legacy_image_url_light ) context["hero_legacy_image_url_dark"] = ( - f"{settings.STATIC_URL}img/v3/home-page/heros_light.png" - ) - context["hero_image_url"] = ( - f"{settings.STATIC_URL}img/v3/home-page/home-page-foreground.png" - ) - context["hero_image_url_light"] = ( - f"{settings.STATIC_URL}img/v3/home-page/home-page-foreground.png" - ) - context["hero_image_url_dark"] = ( - f"{settings.STATIC_URL}img/v3/home-page/home-page-foreground.png" + SharedResources.hero_legacy_image_url_dark ) + context["hero_image_url"] = SharedResources.hero_image_url + context["hero_image_url_light"] = SharedResources.hero_image_url_light + context["hero_image_url_dark"] = SharedResources.hero_image_url_dark context["basic_card_data"] = { "title": "Found a Bug?", "text": "We rely on developers like you to keep Boost solid. Here's how to report issues that help the whole comm", @@ -1641,14 +1534,7 @@ def get_context_data(self, **kwargs): "image": "/static/img/v3/demo_page/Calendar.png", } - context["horizontal_card_data"] = { - "title": "Build anything with Boost", - "text": "Use, modify, and distribute Boost libraries freely. No binary attribution needed.", - "image_url": f"{settings.STATIC_URL}img/checker.png", - "image_alt": "This is a placeholder image", - "button_url": "#", - "button_label": "See license details", - } + context["horizontal_card_data"] = SharedResources.build_anything_with_boost context["demo_cards_carousel_cards"] = [ { @@ -1738,48 +1624,7 @@ def get_context_data(self, **kwargs): context["testimonial_data"] = { "heading": "What Engineers are saying", - "testimonials": [ - { - "quote": "I use Boost daily. I absolutely love it. It's wonderful. I could not do my job w/o it. Much of it is in the new C++11 standard too.", - "author": { - "name": "Name Surname", - "profile_url": "#", - "avatar_url": "/static/img/v3/demo_page/Avatar.png", - "role": "Contributor", - "badge_url": "/static/img/v3/demo_page/Badge.svg", - }, - }, - { - "quote": "I use Boost daily. I absolutely love it. It's wonderful. I could not do my job w/o it. Much of it is in the new C++11 standard too.", - "author": { - "name": "Name Surname", - "profile_url": "#", - "avatar_url": "/static/img/v3/demo_page/Avatar.png", - "role": "Contributor", - "badge_url": "/static/img/v3/demo_page/Badge.svg", - }, - }, - { - "quote": "I use Boost d1aily. I absolutely love it. It's wonderful. I could not do my job w/o it. Much of it is in the new C++11 standard too.", - "author": { - "name": "Name Surname", - "profile_url": "#", - "avatar_url": "/static/img/v3/demo_page/Avatar.png", - "role": "Contributor", - "badge_url": "/static/img/v3/demo_page/Badge.svg", - }, - }, - { - "quote": "I use Boost daily. I absolutely love it. It's wonderful. I could not do my job w/o it. Much of it is in the new C++11 standard too.", - "author": { - "name": "Name Surname", - "profile_url": "#", - "avatar_url": "/static/img/v3/demo_page/Avatar.png", - "role": "Contributor", - "badge_url": "/static/img/v3/demo_page/Badge.svg", - }, - }, - ], + "testimonials": SharedResources.testimonials, } context["achievements_data"] = { diff --git a/static/css/v3/card.css b/static/css/v3/card.css index a56d2fc0f..fc7804d92 100644 --- a/static/css/v3/card.css +++ b/static/css/v3/card.css @@ -128,6 +128,14 @@ display: block; } +@media (max-width: 767px) { + .horizontal-card__text, + .horizontal-card__image { + flex: 1 1 0; + min-width: 0; + } +} + .square-card-image { flex: 1 0 0; aspect-ratio: 1/1; diff --git a/static/css/v3/code-block.css b/static/css/v3/code-block.css index e96888c92..e162f211a 100644 --- a/static/css/v3/code-block.css +++ b/static/css/v3/code-block.css @@ -52,7 +52,6 @@ font-family: var(--font-sans); color: var(--color-text-primary); border-radius: var(--code-block-card-radius); - box-shadow: var(--card-shadow-value); } .code-block-card .code-block { diff --git a/static/css/v3/components.css b/static/css/v3/components.css index 45e5661dd..8c3c45a08 100644 --- a/static/css/v3/components.css +++ b/static/css/v3/components.css @@ -45,5 +45,6 @@ @import "./card-group.css"; @import "./post-card.css"; @import "./event-card.css"; +@import "./join-card.css"; @import "./badge-button.css"; @import "./library-item.css"; diff --git a/static/css/v3/content.css b/static/css/v3/content.css index f8c1cbc01..06308048c 100644 --- a/static/css/v3/content.css +++ b/static/css/v3/content.css @@ -1,9 +1,15 @@ +.content-card-link { + display: block; + text-decoration: none; + color: inherit; +} + .content-detail-icon { font-family: var(--font-sans); color: var(--color-text-primary); margin: 0; padding: var(--space-card); - border-radius: var(--border-radius-xxl); + border-radius: var(--border-radius-l); background: var(--color-bg-secondary); border: 1px solid var(--color-border); display: flex; @@ -13,6 +19,7 @@ box-sizing: border-box; align-self: start; transition: background-color 0.2s ease, border-color 0.2s ease; + height: 100%; } a:hover .content-detail-icon:not(.content-detail-icon--contained) { diff --git a/static/css/v3/heros.css b/static/css/v3/heros.css index c6b46e4ea..396798d54 100644 --- a/static/css/v3/heros.css +++ b/static/css/v3/heros.css @@ -55,13 +55,14 @@ .hero-home__block { width: 100%; max-width: 1440px; - height: 480px; + min-height: 480px; position: relative; display: flex; align-items: center; flex-direction: row; padding: calc(var(--space-medium) + var(--space-default)); align-items: end; + padding-top: 60px; } .hero-home--no-image .hero-home__block { @@ -132,7 +133,11 @@ } /* Hide card on tablet and mobile; only show on desktop */ - @media (max-width: 1024px) { + @media (max-width: 1279px) { + .hero-home__content { + width: 100%; + } + .hero-home__card { display: none; } @@ -258,7 +263,7 @@ } /* ----- Hero home: mobile ----- */ - @media (max-width: 700px) { + @media (max-width: 767px) { .hero-home__block { height: auto; min-height: 600px; @@ -362,7 +367,7 @@ .hero-library__block { width: 100%; max-width: 1440px; - height: 480px; + min-height: 480px; display: flex; align-items: center; justify-content: space-between; @@ -507,7 +512,7 @@ } /* ----- Hero library: mobile ----- */ - @media (max-width: 700px) { + @media (max-width: 767px) { .hero-library__block { height: 600px; diff --git a/static/css/v3/install-card.css b/static/css/v3/install-card.css index 1476019fe..1434c70b7 100644 --- a/static/css/v3/install-card.css +++ b/static/css/v3/install-card.css @@ -60,7 +60,6 @@ flex-direction: column; gap: var(--space-medium); width: 100%; - padding-bottom: var(--space-large); box-sizing: border-box; min-width: 0; } diff --git a/static/css/v3/join-card.css b/static/css/v3/join-card.css new file mode 100644 index 000000000..04238f821 --- /dev/null +++ b/static/css/v3/join-card.css @@ -0,0 +1,68 @@ +/* + Join Card + Individual join-card item styles. + For card group containers, see card-group.css. +*/ + +.join-card { + display: flex; + flex-direction: column; + padding: var(--space-large); + box-sizing: border-box; + width: 100%; + gap: var(--space-large); +} + +.join-card__content { + display: flex; + flex-direction: row; +} + +.join-card__start-here { + font-size: var(--font-size-xs); + font-weight: var(--font-weight-medium); + font-style: normal; + line-height: 100%; + letter-spacing: -0.12px; + text-decoration-line: underline; + text-decoration-style: solid; + text-decoration-skip-ink: none; + text-decoration-thickness: auto; + text-underline-offset: auto; + text-underline-position: from-font; +} + +.join-card__title-block { + display: flex; + flex-direction: column; + gap: var(--space-default); + flex: 1; + padding-right: var(--space-large); +} + +.join-card__description { + margin: 0; + font-family: var(--font-sans); + font-size: var(--font-size-small); + font-weight: var(--font-weight-regular); + line-height: var(--line-height-default); + letter-spacing: -0.14px; + color: var(--color-text-secondary); + min-height: 34px; + padding: 0; +} + +.join-card__title { + margin: 0; + font-family: var(--font-sans); + font-size: var(--font-size-base); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-default); + letter-spacing: -0.16px; + color: var(--color-text-primary); + text-decoration: none; +} + +.join-card__title:hover { + text-decoration: none; +} diff --git a/static/css/v3/stats.css b/static/css/v3/stats.css index fcdfc8e2e..f21169e26 100644 --- a/static/css/v3/stats.css +++ b/static/css/v3/stats.css @@ -71,9 +71,9 @@ --stats-bar-gap: 2px; width: 100%; min-height: 360px; - height: 360px; - container-type: size; + container-type: inline-size; box-sizing: border-box; + overflow: hidden; } .stats--in-numbers .stats__description { @@ -140,7 +140,7 @@ .stats__cta { display: flex; gap: var(--space-default); - padding: var(--stats-space); + padding: var(--space-large); flex-shrink: 0; } diff --git a/static/css/v3/testimonial-card.css b/static/css/v3/testimonial-card.css index 48fd37fff..e08c51338 100644 --- a/static/css/v3/testimonial-card.css +++ b/static/css/v3/testimonial-card.css @@ -36,7 +36,7 @@ .testimonial-card__tail-wrapper { display: flex; - padding: 0 var(--Chat-bubble-tail-left-padding, 60px); + padding: 0 var(--space-xxl); align-items: center; } @@ -100,6 +100,8 @@ overflow-y: hidden; -webkit-overflow-scrolling: touch; min-width: 0; + -ms-overflow-style: none; + scrollbar-width: none; } .testimonial-card__list-item { diff --git a/static/css/v3/v3-examples-section.css b/static/css/v3/v3-examples-section.css index 359094cc5..9cf4ef9ec 100644 --- a/static/css/v3/v3-examples-section.css +++ b/static/css/v3/v3-examples-section.css @@ -2,7 +2,7 @@ max-width: 80rem; margin-left: auto; margin-right: auto; - padding: var(--space-xl, 32px) var(--space-default, 8px); + padding: 10% var(--space-default, 8px); color: var(--color-text-primary); } @@ -45,6 +45,20 @@ border-radius: 8px; } +.v3-examples-section__example-box--full-width { + padding: 0; + background: none; + border: none; + border-radius: 0; + width: 100vw; + position: relative; + left: 50%; + right: 50%; + margin-left: -50vw; + margin-right: -50vw; + box-sizing: border-box; +} + html.dark .v3-examples-section__example-box { background: var(--color-surface-mid); } diff --git a/static/css/v3/v3-homepage.css b/static/css/v3/v3-homepage.css new file mode 100644 index 000000000..533e31059 --- /dev/null +++ b/static/css/v3/v3-homepage.css @@ -0,0 +1,243 @@ +body:has(.homepage-v3) .header { + position: absolute; + z-index: 10; + left: 0; + right: 0; +} + +.homepage-container .hero-home { + border: none; + border-radius: 0; + width: 100vw; + position: relative; + left: 50%; + right: 50%; + margin-left: -50vw; + margin-right: -50vw; + box-sizing: border-box; +} + +.homepage-container { + max-width: 1440px; + margin: 0 auto; + padding: 0 var(--space-large); +} + +.four-column .why-boost-cards__grid { + grid-template-columns: repeat(4, 1fr); +} + +.card-masonry-top { + padding-bottom: var(--space-large); + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-template-areas: + "a c d" + "b c d" + "b c e" + "b c e" + "b c e" + ; + row-gap: var(--space-card); + column-gap: var(--space-card); +} + +.card-masonry-top .item-a { + grid-area: a; +} + +.card-masonry-top .item-b { + grid-area: b; +} + +.card-masonry-top .item-c { + grid-area: c; +} + +.card-masonry-top .item-d { + grid-area: d; +} + +.card-masonry-top .item-e { + grid-area: e; +} + +.card-masonry-top .item-f { + display: none; +} + +.card-masonry-bottom { + display: grid; + grid-template-columns: repeat(6, 1fr); + grid-template-areas: + "a a a c c c" + "b b d d d d"; + row-gap: var(--space-card); + column-gap: var(--space-card); +} + +.card-masonry-bottom .card-group { + max-width: 100%; + width: 100%; +} + +.license-card .horizontal-card { + max-width: 100%; +} + +@media (min-width: 768px) { + .license-card .horizontal-card { + min-height: 358px; + } + + .license-card .horizontal-card .horizontal-card__image { + flex: 0 0 205px; + aspect-ratio: 1 / 1; + } +} + +@media (max-width: 1279px) { + .responsive-limit-5-items .stats__bar-wrap:nth-child(n+6) { + display: none; + } +} + + +@media (min-width: 768px) and (max-width: 1279px) { + .responsive-limit-3-items .card-group__item:nth-child(n+4) { + display: none; + } + + .responsive-limit-2-items .card-group__item:nth-child(n+3) { + display: none; + } + + .homepage-container { + max-width: 1024px; + } + + .search-card { + max-width: 100%; + } + + .homepage-join-card .card-group { + max-width: 100%; + } + + .card-masonry-top { + grid-template-columns: repeat(2, 1fr); + grid-template-areas: + "a f" + "a c" + "d c" + "e c" + "e b" + "e b" + "e ." + ; + } + + .card-masonry-top .item-f { + display: contents; + grid-area: f; + } + + .card-masonry-bottom { + grid-template-columns: repeat(2, minmax(0, 1fr)); + grid-template-areas: + "a c" + "b d"; + } + + .card-masonry-bottom > div { + min-width: 0; + } + + .card-masonry-bottom > div > * { + max-width: 100%; + } + + .four-column .why-boost-cards__grid { + grid-template-columns: repeat(6, 1fr); + } + + .four-column .why-boost-cards__grid > * { + grid-column: span 2; + } + + .four-column .why-boost-cards__grid > :nth-last-child(2):nth-child(3n+1), + .four-column .why-boost-cards__grid > :last-child:nth-child(3n+2) { + grid-column: span 3; + } + + .four-column .why-boost-cards__grid > :last-child:nth-child(3n+1) { + grid-column: span 6; + } +} + +@media (max-width: 767px) { + .homepage-container .hero-home { + padding-left: var(--space-default); + padding-right: var(--space-default); + } + + .homepage-container { + max-width: 390px; + } + + .four-column .why-boost-cards__grid { + grid-template-columns: repeat(1, 1fr); + } + + .card-masonry-top { + grid-template-columns: 1fr; + grid-template-areas: + "a" + "f" + "c" + "d" + "b" + "e" + ; + } + + .card-masonry-bottom { + grid-template-columns: 1fr; + grid-template-areas: + "a" + "c" + "b" + "d" + ; + } + + .card-masonry-bottom > div { + min-width: 0; + } + + .card-masonry-top .item-f { + display: contents; + grid-area: f; + } +} + +.card-masonry-bottom .item-a { + grid-area: a; + display: flex; +} + +.card-masonry-bottom .item-a .stats { + flex: 1; +} + +.card-masonry-bottom .item-b { + grid-area: b; +} + +.card-masonry-bottom .item-c { + grid-area: c; +} + +.card-masonry-bottom .item-d { + grid-area: d; +} diff --git a/static/img/v3/home-page/heros_light.png b/static/img/v3/home-page/heros_light.png index 3fd89b311..458ac31a5 100644 Binary files a/static/img/v3/home-page/heros_light.png and b/static/img/v3/home-page/heros_light.png differ diff --git a/templates/base.html b/templates/base.html index fbcf94b00..fe642f32d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -363,22 +363,10 @@ {% flag "v3" %}
v3 flag enabled
{% endflag %} - {% flag "v3" %} - {% include "v3/includes/_header_v3.html" %} - {% if request.resolver_match.url_name == 'v3-demo-components' %} - {% include "v3/includes/_hero_home.html" with install_card_id="hero-home-1" hero_background_image_url="" hero_image_url_light=hero_legacy_image_url_light hero_image_url_dark=hero_legacy_image_url_dark %} - {% include "v3/includes/_hero_home.html" with install_card_id="hero-home-2" hero_image_url=hero_image_url %} - {% include "v3/includes/_hero_home.html" with install_card_id="hero-home-3" hero_image_url="" hero_image_url_light="" hero_image_url_dark="" %} -
- {% include "v3/includes/_hero_library.html" with hero_background_image_url="" title="Boost.Beast" description="Portable HTTP, WebSocket, and network operations using only C++11 and Boost.Asio" doc_url="#" source_url="#" slack_url="#" github_url="#" version_tag="C++ 03" added_text="Added in 1.66.0" hero_image_url_light=hero_legacy_image_url_light hero_image_url_dark=hero_legacy_image_url_dark is_flagship_lib=True %} -
- {% include "v3/includes/_hero_library.html" with title="Boost.Beast" description="Portable HTTP, WebSocket, and network operations using only C++11 and Boost.Asio" doc_url="#" source_url="#" slack_url="#" github_url="#" version_tag="C++ 03" added_text="Added in 1.66.0" hero_image_url=hero_image_url is_flagship_lib=True %} - {% include "v3/includes/_hero_library.html" with title="Boost.Beast" description="Portable HTTP, WebSocket, and network operations using only C++11 and Boost.Asio" doc_url="#" source_url="#" slack_url="#" github_url="#" version_tag="C++ 03" added_text="Added in 1.66.0" hero_image_url="" hero_image_url_light="" hero_image_url_dark="" %} - {% endif %} - {% endflag %} {% block main_content_wrapper %}
{% endblock %} {% block content_header %} {% flag "v3" %} + {% include "v3/includes/_header_v3.html" %} {% else %} {% include "includes/_header.html" %} {% endflag %} diff --git a/templates/v3/examples/_v3_example_section.html b/templates/v3/examples/_v3_example_section.html index b5acf9daf..e68563aac 100644 --- a/templates/v3/examples/_v3_example_section.html +++ b/templates/v3/examples/_v3_example_section.html @@ -40,6 +40,22 @@

Table of Contents

    + {% with section_title="Hero Cards" %} +
    +

    {{ section_title }}

    +
    + {% include "v3/includes/_hero_home.html" with hero_background_image_url="" install_card_id="hero-home-1" hero_image_url_light=hero_legacy_image_url_light hero_image_url_dark=hero_legacy_image_url_dark %} + {% include "v3/includes/_hero_home.html" with install_card_id="hero-home-2" hero_image_url=hero_image_url %} + {% include "v3/includes/_hero_home.html" with install_card_id="hero-home-3" hero_image_url="" hero_image_url_light="" hero_image_url_dark="" %} +
    + {% include "v3/includes/_hero_library.html" with hero_background_image_url="" title="Boost.Beast" description="Portable HTTP, WebSocket, and network operations using only C++11 and Boost.Asio" doc_url="#" source_url="#" slack_url="#" github_url="#" version_tag="C++ 03" added_text="Added in 1.66.0" hero_image_url_light=hero_legacy_image_url_light hero_image_url_dark=hero_legacy_image_url_dark is_flagship_lib=True %} +
    + {% include "v3/includes/_hero_library.html" with title="Boost.Beast" description="Portable HTTP, WebSocket, and network operations using only C++11 and Boost.Asio" doc_url="#" source_url="#" slack_url="#" github_url="#" version_tag="C++ 03" added_text="Added in 1.66.0" hero_image_url=hero_image_url is_flagship_lib=True %} + {% include "v3/includes/_hero_library.html" with title="Boost.Beast" description="Portable HTTP, WebSocket, and network operations using only C++11 and Boost.Asio" doc_url="#" source_url="#" slack_url="#" github_url="#" version_tag="C++ 03" added_text="Added in 1.66.0" hero_image_url="" hero_image_url_light="" hero_image_url_dark="" %} +
    +
    + {% endwith %} + {% with section_title="Buttons" %}

    {{ section_title }}

    @@ -576,6 +592,27 @@

    {{ section_title }}

    {% endwith %} + {% with section_title="Join Cards — list (this only have 1 theme)" %} +
    +

    {{ section_title }}

    +
    + {% include "v3/includes/_join_card.html" with heading="Join developers building the future of C++ " items=demo_join_community_links variant="list" primary_cta_label="Button" primary_cta_url="#" secondary_cta_label="Button" secondary_cta_url="#" %} +
    +
    + {% endwith %} + + {% with section_title="Join Cards — card variant with different themes - default, teal, yellow, green" %} +
    +

    {{ section_title }}

    +
    + {% include "v3/includes/_join_card.html" with heading="Join developers building the future of C++ " items=demo_join_community_links variant="card" primary_cta_label="Button" primary_cta_url="#" secondary_cta_label="Button" secondary_cta_url="#" %} + {% include "v3/includes/_join_card.html" with heading="Join developers building the future of C++ " items=demo_join_community_links variant="card" theme="teal" primary_cta_label="Button" primary_cta_url="#" secondary_cta_label="Button" secondary_cta_url="#" %} + {% include "v3/includes/_join_card.html" with heading="Join developers building the future of C++ " items=demo_join_community_links variant="card" theme="yellow" primary_cta_label="Button" primary_cta_url="#" secondary_cta_label="Button" secondary_cta_url="#" %} + {% include "v3/includes/_join_card.html" with heading="Join developers building the future of C++ " items=demo_join_community_links variant="card" theme="green" primary_cta_label="Button" primary_cta_url="#" secondary_cta_label="Button" secondary_cta_url="#" %} +
    +
    + {% endwith %} + {% with section_title="Post Cards — list (this only have 1 theme)" %}

    {{ section_title }}

    @@ -607,6 +644,18 @@

    {{ section_title }}

    {% endwith %} {% with section_title="Event Cards — list (this only have 1 theme)" %} +
    +

    {{ section_title }}

    +
    + {% include "v3/includes/_event_card.html" with heading="Upcoming Events" items=demo_events_with_links variant="card" primary_cta_label="View events" primary_cta_url="#" secondary_cta_label="View calendar" secondary_cta_url="#" %} + {% include "v3/includes/_event_card.html" with heading="Upcoming Events" items=demo_events_with_links variant="card" theme="yellow" primary_cta_label="View events" primary_cta_url="#" secondary_cta_label="View calendar" secondary_cta_url="#" %} + {% include "v3/includes/_event_card.html" with heading="Upcoming Events" items=demo_events_with_links variant="card" theme="green" primary_cta_label="View events" primary_cta_url="#" secondary_cta_label="View calendar" secondary_cta_url="#" %} + {% include "v3/includes/_event_card.html" with heading="Upcoming Events" items=demo_events_with_links variant="card" theme="teal" primary_cta_label="View events" primary_cta_url="#" secondary_cta_label="View calendar" secondary_cta_url="#" %} +
    +
    + {% endwith %} + + {% with section_title="Achievement cards" %}

    {{ section_title }}

    diff --git a/templates/v3/homepage.html b/templates/v3/homepage.html new file mode 100644 index 000000000..84e7d6a1b --- /dev/null +++ b/templates/v3/homepage.html @@ -0,0 +1,65 @@ +{% extends "base.html" %} +{% load static %} +{% load waffle_tags %} + +{% block main_content_wrapper %}
    {% endblock %} +{% block title %}Boost C++ Homepage{% endblock %} +{% block extra_head %} + {{ block.super }} + +{% endblock %} + +{% block content %} +
    + {% include "v3/includes/_hero_home.html" with hero_background_image_url="" install_card_id="hero-home-1" hero_image_url_light=hero_legacy_image_url_light hero_image_url_dark=hero_legacy_image_url_dark %} +
    +
    + {% include "v3/includes/_search_card.html" with heading="What are you trying to find?" action_url="#" popular_terms=popular_terms %} +
    +
    + {% include "v3/includes/_event_card.html" with heading="Upcoming Events" items=demo_events_with_links variant="list" primary_cta_label="Download latest release" primary_cta_url="#" secondary_cta_label="View events calendar" secondary_cta_url="#" %} +
    +
    + {% with data=posts_from_the_boost_community %} + {% include "v3/includes/_post_card.html" with heading=data.heading items=data.items variant=data.variant theme=data.theme primary_cta_label=data.primary_cta_label primary_cta_url=data.primary_cta_url %} + {% endwith %} +
    +
    + {% include "v3/includes/_code_block_card.html" with heading="Get started with our libraries" code=code_demo_hello block_variant="grey-bg" button_text="Explore examples" language="cpp" button_aria_label="Explore examples" %} +
    +
    + {% with data=join_developers_building_the_future_of_cpp %} + {% include "v3/includes/_join_card.html" with heading="Join developers building the future of C++" items=data.items variant="card" theme="yellow" primary_cta_label="Explore the community" primary_cta_url="#" %} + {% endwith %} +
    +
    + {% include "v3/includes/_install_card.html" with title=install_card_title|default:"Install Boost and get started in your terminal." card_id=install_card_id|default:"hero-home-install" %} +
    +
    +
    + {% include 'v3/includes/_why_boost_cards.html' with why_boost_cards=why_boost_cards %} +
    +
    +
    + {% with data=stats_in_numbers %} + {% include "v3/includes/_stats_in_numbers.html" with heading="Commits per release" description="Commit count by Boost release for this library." bars=data.example_library_commits_bars theme="default" primary_cta_label="View library" primary_cta_url="#" %} + {% endwith %} +
    +
    + {% with data=library_intro %} + {% include "v3/includes/_library_intro_card.html" with library_name=data.library_name description=data.description authors=data.authors cta_url=data.cta_url %} + {% endwith %} +
    +
    + {% with data=testimonial_data %} + {% include "v3/includes/_testimonial_card.html" with heading="What engineers" testimonials=data.testimonials %} + {% endwith %} +
    +
    + {% with data=build_anything_with_boost %} + {% include "v3/includes/_horizontal_card.html" with title=data.title text=data.text image_url=data.image_url button_url=data.button_url button_label=data.button_label image_alt=data.image_alt %} + {% endwith %} +
    +
    +
    +{% endblock %} diff --git a/templates/v3/includes/_content_detail_card_item.html b/templates/v3/includes/_content_detail_card_item.html index 1916eef25..260efee1b 100644 --- a/templates/v3/includes/_content_detail_card_item.html +++ b/templates/v3/includes/_content_detail_card_item.html @@ -7,8 +7,9 @@ If omitted (and badge_count not set), card is rendered without icon and modifier --has-icon is not applied. badge_count (optional) — when set (e.g. in carousel), shows a non-clickable count badge instead of icon. title_url (optional) — if set, title is wrapped in a link - cta_label (optional) — if set with cta_href, renders a CTA link below description + cta_label (optional) — if set with cta_href, renders a CTA link below description (or span if cta_as_span) cta_href (optional) — used with cta_label for the CTA link + cta_as_span (optional) — if truthy, CTA is rendered as (use when the whole card is wrapped in a link) Usage: {% include "v3/includes/_content_detail_card_item.html" with title="Get help" description="Tap into quick answers..." icon_name="bullseye-arrow" %} With badge (e.g. carousel): {% include "..." with title="..." description="..." badge_count=1 %} @@ -27,7 +28,11 @@

    {% if title_url %}{% endif %}{{ title }}{% if title_url %}{% endif %}

    {{ description }}

    - {% if cta_label and cta_href %} + {% if cta_label %} + {% if cta_as_span %} + {{ cta_label }} + {% elif cta_href %} {{ cta_label }} {% endif %} + {% endif %} diff --git a/templates/v3/includes/_join_card.html b/templates/v3/includes/_join_card.html new file mode 100644 index 000000000..0956aabd5 --- /dev/null +++ b/templates/v3/includes/_join_card.html @@ -0,0 +1,53 @@ +{% extends "v3/includes/_card_group.html" %} +{% comment %} + Join Card — extends _card_group.html to render join card items. + + Variables (passed to _card_group.html): + heading (string, optional) — section heading text + heading_url (string, optional) — if set, heading becomes a link + items (list, optional) — list of objects with: + - title (string, optional) — title + - url (string, optional) — link URL + - description (string, optional) — link description + - icon_name (string, optional) — optional icon + variant (string, optional) — "list" or "card", defaults to "list" + theme (string, optional) — only for variant "card": "default", "grey", "yellow", "green", "teal" + layout (string, optional) — "vertical" or "horizontal", defaults to "vertical" + primary_cta_label (string, optional) — primary CTA button label + primary_cta_url (string, optional) — primary CTA button URL + secondary_cta_label (string, optional) — secondary CTA button label + secondary_cta_url (string, optional) — secondary CTA button URL + + Usage: + {% include "v3/includes/_join_card.html" with heading="Join" items=ctas variant="card" theme="teal" primary_cta_label="Explore the community" primary_cta_url="/community/" %} +{% endcomment %} +{% block card_list %} + {% if items %} +
      + {% for item in items %} +
    • +
      +
      +
      + {% if item.title and item.url %} + {{ item.title }} + {% elif item.title %} +

      {{ item.title }}

      + {% endif %} + {% if item.description %} +

      {{ item.description }}

      + {% endif %} +
      + {% if item.icon_name %} + {% include 'includes/icon.html' with icon_name=item.icon_name icon_size=16 %} + {% endif %} +
      + {% if item.url %} + Start here + {% endif %} +
      +
    • + {% endfor %} +
    + {% endif %} +{% endblock %}