WT-1193: Cards refactor#1371
Conversation
ref #WT-1203
…ing margin on cards.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## WT-1174-landing-page-follow-up #1371 +/- ##
===============================================================
Coverage 79.38% 79.39%
===============================================================
Files 152 152
Lines 10337 10341 +4
===============================================================
+ Hits 8206 8210 +4
Misses 2131 2131 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a new “Filled” card variant and refactors Flare 2026 card usage by consolidating multiple card types into a shared card-2026 template/component, updating CMS blocks, templates, pattern-library examples, CSS, and visual regression coverage accordingly.
Changes:
- Added Filled card pattern-library example + Playwright visual regression coverage.
- Refactored templates/CMS blocks to use
card-2026in place of older card include patterns. - Updated Flare 2026 card CSS + tests to match the new markup/classes.
Review note: I reviewed this using the repository’s Copilot custom instructions and AGENTS.md.
Reviewed changes
Copilot reviewed 27 out of 31 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/playwright/specs/visual-regression/illustration-card-variants.spec.js | Updates Pattern Library URL path for the illustration card variants visual test. |
| tests/playwright/specs/visual-regression/cards-list-filled.spec.js | Adds visual regression coverage for the new filled cards list (light/dark). |
| springfield/firefox/templates/firefox/landing/year-in-review-2025-flare26.html | Migrates highlight cards to card-2026. |
| springfield/firefox/templates/firefox/landing/get-new.html | Migrates “favorite browser” cards to card-2026. |
| springfield/firefox/templates/firefox/enterprise/index.html | Migrates enterprise icon/sticker cards to card-2026 and moves sticker content into content:media. |
| springfield/firefox/templates/firefox/developer/index-flare26.html | Migrates developer page card grids to card-2026. |
| springfield/firefox/templates/firefox/default/landing.html | Migrates default-landing icon cards to card-2026. |
| springfield/firefox/templates/firefox/browsers/mobile/index.html | Migrates mobile download cards to card-2026. |
| springfield/firefox/templates/firefox/browsers/desktop/base.html | Migrates desktop download platform cards to card-2026. |
| springfield/cms/tests/test_blocks.py | Updates CMS rendering tests to reflect new card markup/class structure. |
| springfield/cms/templates/pattern-library/components/flare-26/cards-list/illustration-card_variants.yaml | Updates illustration-card variant data to use media_type. |
| springfield/cms/templates/pattern-library/components/flare-26/cards-list/illustration-card_variants.html | Updates pattern-library illustration card variants to render via card-2026. |
| springfield/cms/templates/pattern-library/components/flare-26/cards-list/cards-list_outlined.html | Updates outlined cards list example to use card-2026 with variant="outlined" + media slot. |
| springfield/cms/templates/pattern-library/components/flare-26/cards-list/cards-list_filled.yaml | Adds pattern-library context data for filled cards list. |
| springfield/cms/templates/pattern-library/components/flare-26/cards-list/cards-list_filled.html | Adds pattern-library template for filled cards list using card-2026 with variant="filled". |
| springfield/cms/templates/components/card-2026.html | Refactors card-2026 into a shared card template with variant + media_type logic and updated classes. |
| springfield/cms/templates/cms/blog_index_page.html | Migrates blog index cards to card-2026. |
| springfield/cms/templates/cms/blocks/related-article-card.html | Migrates related article card block to card-2026. |
| springfield/cms/templates/cms/blocks/icon-card-2026.html | Migrates icon card block to card-2026 with media_type="icon". |
| springfield/cms/templates/cms/blocks/card-2026.html | Consolidates multiple CMS card styles into a unified card-2026 block template and computes variant/media_type. |
| springfield/cms/templates/cms/blocks/article-cards-list.html | Migrates article cards list block to card-2026 with explicit media_type. |
| springfield/cms/templates/cms/article_index_page.html | Migrates article index cards to card-2026, adding explicit outlined variant for outline-card mode. |
| springfield/cms/blocks.py | Introduces a variant setting on card settings and replaces the old outlined card block factory with a generalized CardBlock. |
| media/css/cms/variables/flare26-light-theme.css | Adds a new theme variable for filled card background color (light theme). |
| media/css/cms/variables/flare26-dark-theme.css | Adds a new theme variable for filled card background color (dark theme). |
| media/css/cms/pages/flare26-developer-edition.css | Removes developer page overrides tied to old sticker/illustration-card structure. |
| media/css/cms/components/flare26-card.css | Refactors card styling to be variant-driven (.fl-card-outlined / .fl-card-filled) and updates illustration-card layout hooks. |
Comments suppressed due to low confidence (6)
springfield/cms/templates/components/card-2026.html:31
- fix (blocking):
card-2026can currently emit invalid/unstyled class combinations for media cards. Whencontents.mediais present andvariantis empty, the template does not addfl-card-outlined/fl-card-filled, but.fl-cardno longer supplies padding/background/hover styles (those are now on the variant classes), so illustration/icon/sticker cards can render without core card styling. Also, whenmedia_typeis''/None, the template generatesfl-illustration--card/fl-illustration-None-card. Consider defaulting media cards to an explicit card variant (e.g. outlined) and treating falsymedia_typeas the default ("media") so the generated classes stay valid.
springfield/cms/templates/cms/blocks/card-2026.html:25 - fix (blocking):
media_typeis set toNonewhen there is no media/icon/sticker, which will typically render as the string "None" in the include attribute and can lead tofl-illustration-None-cardif media is later present. Use an empty string or omit the attribute when unset, and ensure the default illustration-card case passes/normalizes tomedia_type="media"(rather than"").
springfield/firefox/templates/firefox/developer/index-flare26.html:66 - fix (blocking): The media cards in this list omit
media_type, which can producefl-illustration--cardand/or omit the card theme variant class. Passmedia_type="media"(or normalize to it) so default illustration-card styling is applied consistently.
<include:cards-list cards_per_row="2">
<include:card-2026 expand_link>
<content:media>
<img src="{{ static('img/firefox/developer/hero-inactive-css.png') }}"
srcset="{{ static('img/firefox/developer/hero-inactive-css-high-res.png') }} 2x"
alt="{{ ftl('firefox-developer-inactive-css') }}"
loading="lazy" width="560" height="280" />
</content:media>
<content:heading>
springfield/cms/templates/cms/blocks/related-article-card.html:15
- fix (blocking): This block includes media but doesn’t pass
media_type, which can generate an invalidfl-illustration--cardclass and miss the card theme variant styling. Pass/normalizemedia_type="media"here (or update the component to default correctly when media is present).
<include:card-2026 expand_link="true">
<content:media>
{% set img = value.get_sticker() %}
{% if img %}
{{ image(img, "width-400") }}
{% else %}
<img src="/media/img/logos/firefox/firefox-logo.svg" alt="" />
{% endif %}
</content:media>
springfield/cms/templates/pattern-library/components/flare-26/cards-list/illustration-card_variants.yaml:8
- fix: For the "Default" illustration-card example,
media_typeis set to an empty string. With the currentcard-2026class logic, this will produce an invalidfl-illustration--cardclass. Usemedia_type: "media"(or omit and let the component normalize to the default) to keep the generated CSS class valid.
springfield/cms/tests/test_blocks.py:2724 - fix:
find_all(..., class_=[...])matches elements with any of the classes, not all of them. If the page layout changes, this could pick up non-icon illustration cards too. Prefer querying forfl-illustration-icon-cardspecifically (or require both classes via a CSS selector) to keep the test precise.
icon_section = sections[1]
icon_card_articles = icon_section.find_all("article", class_=["fl-illustration-card", "fl-illustration-icon-card"])
| <include:card-2026 variant="sticker"> | ||
| <content:media> |
| <include:card-2026> | ||
| <content:media> | ||
| <img src="/media/img/firefox/landing/get/kit-with-google.png" srcset="/media/img/firefox/landing/get/kit-with-google-high-res.png 2x" width="340" height="400" alt="" aria-hidden /> | ||
| </content:media> |
| <include:card-2026 variant="icon"> | ||
| <content:media> | ||
| <img src="{{ static('protocol/img/icons/brand/violet/no-eye.svg') }}" width="48" height="48" alt="" loading="lazy"> | ||
| </content:media> |
| <include:cards-list> | ||
| <include:illustration-card-2026 variant="sticker"> | ||
| <include:card-2026 variant="sticker"> | ||
| <content:media> | ||
| <img src="/media/{{ card1_image_url }}" aria-hidden="true" /> | ||
| </content:media> |
| <include:card-2026 variant="sticker" media_type="sticker" expand_link> | ||
| <content:media> |
| <include:cards-list container_width="fill"> | ||
| {% for block in page.featured_articles[4:] %} | ||
| <include:illustration-card-2026 expand_link="true"> | ||
| <include:card-2026 expand_link="true"> |
| def CardBlock(allow_uitour=False, *args, **kwargs): | ||
| """Factory function to create OutlinedCardBlock with appropriate button types. | ||
|
|
||
| Args: | ||
| allow_uitour: If True, allows both regular buttons and UI Tour buttons. | ||
| If False, only allows regular buttons. | ||
| """ | ||
|
|
||
| class _OutlinedCardBlock(blocks.StructBlock): | ||
| class _CardBlock(blocks.StructBlock): | ||
| settings = BaseCardSettings() |
|
|
||
| assert icon_card_section.find(class_="fl-card-grid") | ||
| icon_card_articles = icon_card_section.find_all("article", class_="fl-illustration-card fl-illustration-icon-card") | ||
| icon_card_articles = icon_card_section.find_all("article", class_=["fl-illustration-card", "fl-illustration-icon-card"]) |
One-line summary
This PR adds the Filled Card variant and refactors the cards to consolidate similar cards into a shared template.
This is based on the landing page follow-ups PR, so I'll wait for that one to be merged before this one.
Significant changes and points to review
Since I used the illustration card as base for the new generic card block/component, I also needed to search for all the places that were statically using the outline and illustration cards. I think I found them all, but I could've missed something.
Issue / Bugzilla link
https://mozilla-hub.atlassian.net/browse/WT-1193
Testing
Take a look at the new filled card in the pattern library, run the BE and visual regression tests, and check for possible places I could've forgotten to apply the new block/component.