Skip to content

Commit

Permalink
Improved topic cards now show three articles, with new design (mozill…
Browse files Browse the repository at this point in the history
…a#6408)

* Improved topic card now show three top articles
* Alter the help_topics macro to support showing three articles
* Add show more section with sectional line above
* Add logic to the product_landing view to return docs and counts
* A utility function builds the topics_context for the cards
* Fix card scroll for topic cards on mobile
  • Loading branch information
smithellis committed Jan 23, 2025
1 parent 2188154 commit f17ff85
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 37 deletions.
47 changes: 30 additions & 17 deletions kitsune/products/jinja2/products/includes/topic_macros.html
Original file line number Diff line number Diff line change
@@ -1,32 +1,45 @@
{% macro help_topics(topics, product_slug=None, new_tab=False) -%}
<div class="sumo-card-grid">
<div class="scroll-wrap">
{% for topic in topics %}
{% set topic_url = url('products.documents', product_slug=product_slug or product.slug, topic_slug=topic.slug) %}
<div class="card card--topic">
{# topics: List of topic_data dicts containing:
- topic: Topic model instance
- topic_url: URL to topic page
- title: Topic title
- total_articles: Number of articles
- image_url: URL to topic icon
- documents: three documents for the topic
#}
<div class="topics-section">
<div class="topics-grid">
{% for topic_data in topics %}
<div class="card--topic">
<div class="topic-header">
<img
class="card--icon"
src="{{ topic.image_url }}"
alt="{{ pgettext('DB: products.Topic.title', topic.title) }} icon"
src="{{ topic_data.image_url }}"
alt="{{ pgettext('DB: products.Topic.title', topic_data.title) }} icon"
/>
<div class="card--details">
<h3 class="card--title">
<a class="expand-this-link" href="{{ topic_url }}" data-on-hover="{{ _('See all') }}" {% if new_tab %} target="_blank" {% endif %}
data-event-name="link_click"
data-event-parameters='{
"link_name": "product-and-topic-home",
"link_detail": "{{ (product_slug or product.slug) + '/' + topic.slug }}"
}'>
{{ pgettext('DB: products.Topic.title', topic.title) }}
<a href="{{ topic_data.topic_url }}">
{{ pgettext('DB: products.Topic.title', topic_data.title) }}
</a>
</h3>
</div>
</div>
{% endfor %}
<ul class="article-list">
{% for document in topic_data.documents %}
<li>
<a href="{{ document.get_absolute_url() }}">
{{ document.title }}</a>
</li>
{% endfor %}
</ul>
<a class="view-all-link" href="{{ topic_data.topic_url }}">View All {{ topic_data.total_articles }} Articles</a>
</div>
{% endfor %}
</div>
</div>
{%- endmacro %}



{% macro topic_metadata(topics, product=None) %}
{% if product and has_aaq_config and not settings.READ_ONLY %}
<section class="support-callouts mzp-l-content sumo-page-section--inner">
Expand Down
2 changes: 1 addition & 1 deletion kitsune/products/jinja2/products/product.html
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ <h1 class="sumo-page-heading-xl">
<div class="sumo-page-subheader">
<div class="sumo-page-subheader--text">
<div class="text-center-to-left-on-large">
<h2 class="sumo-page-subheading">{{ _('Frequent Topics') }}</h2>
<h2 class="sumo-page-subheading">{{ _('Topics') }}</h2>
<p class="sumo-page-intro">{{ _('Explore the knowledge base.') }}</p>
</div>
</div>
Expand Down
21 changes: 17 additions & 4 deletions kitsune/products/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from kitsune.wiki.decorators import check_simple_wiki_locale
from kitsune.wiki.facets import documents_for, topics_for
from kitsune.wiki.models import Document, Revision
from kitsune.wiki.utils import get_featured_articles
from kitsune.wiki.utils import build_topics_data, get_featured_articles


@check_simple_wiki_locale
Expand All @@ -23,8 +23,19 @@ def product_list(request):


@check_simple_wiki_locale
def product_landing(request, slug):
"""The product landing page."""
def product_landing(request, slug: str) -> HttpResponse:
"""The product landing page.
Args:
request: The HTTP request
slug: Product slug identifier
Returns:
Rendered product landing page
Raises:
Http404: If product not found
"""
if slug == "firefox-accounts":
return redirect(product_landing, slug="mozilla-account", permanent=True)

Expand All @@ -45,14 +56,16 @@ def product_landing(request, slug):
latest_version = versions[0].min_version
else:
latest_version = 0
topics = topics_for(request.user, product=product, parent=None)
topics_data = build_topics_data(request, product, topics)

return render(
request,
"products/product.html",
{
"product": product,
"products": Product.active.filter(visible=True),
"topics": topics_for(request.user, product=product, parent=None),
"topics": topics_data, # Use the new list with URLs
"search_params": {"product": slug},
"latest_version": latest_version,
"featured": get_featured_articles(product, locale=request.LANGUAGE_CODE),
Expand Down
5 changes: 4 additions & 1 deletion kitsune/questions/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
from kitsune.upload.models import ImageAttachment
from kitsune.users.models import Setting
from kitsune.wiki.facets import topics_for
from kitsune.wiki.utils import build_topics_data

log = logging.getLogger("k.questions")

Expand Down Expand Up @@ -568,8 +569,10 @@ def aaq(request, product_slug=None, step=1, is_loginless=False):
context["ga_products"] = f"/{product_slug}/"

if step == 2:
topics = topics_for(request.user, product, parent=None)

context["featured"] = get_featured_articles(product, locale=request.LANGUAGE_CODE)
context["topics"] = topics_for(request.user, product, parent=None)
context["topics"] = build_topics_data(request, product, topics)

elif step == 3:
context["cancel_url"] = get_next_url(request) or (
Expand Down
73 changes: 63 additions & 10 deletions kitsune/sumo/static/sumo/scss/components/_card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -181,21 +181,74 @@
}

&--topic {
@include c.elevation-01;
display: flex;
align-items: center;
flex-direction: column;
justify-content: space-between;
height: 100%;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
box-sizing: border-box;

.topic-header {
display: flex;
align-items: flex-start;
gap: 10px;
margin-bottom: 16px;
}

.card--icon {
flex-shrink: 0;
width: 18px;
height: 18px;
}

.card-title {
.card--title {
font-family: Inter;
font-size: 16px;
font-weight: 700;
margin: 0;
line-height: 1.2;
flex-grow: 1;
}

.card--icon {
width: p.$spacing-lg;
height: p.$spacing-lg;
object-fit: contain;
font-size: 9px;
line-height: 1;
flex: 0 0 auto;
.article-list {
flex-grow: 1;
margin: 0 0 16px;
padding: 0;
list-style: none;

li {
margin-bottom: 8px;
line-height: 1.5;

a {
color: black;
font-size: 14px;
text-decoration: underline;

&:hover {
text-decoration: underline;
}
}
}
}

.view-all-link {
border-top: 1px solid #ddd;
padding-top: 10px;
margin-top: 16px;
display: inline-block;
font-size: 14px;
color: #000000;
text-decoration: underline;
font-weight: normal;

&:hover {
text-decoration: underline;
}
}
}

Expand Down
59 changes: 59 additions & 0 deletions kitsune/sumo/static/sumo/scss/layout/_products.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,62 @@
margin: 0 p.$spacing-xs;
}
}


// SCSS for Topics Section Layout

.topics-section {
padding: 40px 20px;
h2 {
font-size: 24px;
margin-bottom: 0px;
color: #333;
}

@media #{p.$mq-sm} {
padding: 24px 16px;
}
}

.topics-grid {
@media #{p.$mq-lg} {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}

// Mobile styles
@media (max-width: #{p.$screen-lg}) {
display: flex;
overflow-x: auto;
gap: 16px;
padding: 16px 0;
scroll-snap-type: x mandatory;
-webkit-overflow-scrolling: touch;

// Hide scrollbar but keep functionality
scrollbar-width: none; // Firefox
&::-webkit-scrollbar {
display: none; // Chrome, Safari, Edge
}

// Make sure child items are properly sized
> .card--topic {
flex: 0 0 280px; // Fixed width for each item
height: 280px; // Fixed height
scroll-snap-align: start;

// Force all content inside the card to respect the height
display: flex;
flex-direction: column;

// Prevent content from overflowing
overflow: hidden;

// Ensure all direct children within the card also respect the height
> * {
flex-shrink: 0;
}
}
}
}
3 changes: 1 addition & 2 deletions kitsune/wiki/facets.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,7 @@ def _documents_for(user, locale, topics=None, products=None):
# so we can cache it rather aggressively
cache.set(votes_cache_key, votes_dict, timeout=settings.CACHE_LONG_TIMEOUT)

# Annotate each of the documents with its string of product titles. This must
# be a sub-query in order to free itself from the product filter(s) above.
# Annotate each of the documents with its string of product titles
qs = qs.annotate(
product_titles=Subquery(
Document.objects.filter(pk=OuterRef("pk"))
Expand Down
Loading

0 comments on commit f17ff85

Please sign in to comment.