diff --git a/package.json b/package.json index 857d0b8b0..2287fe264 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vanilla-framework", - "version": "4.55.1", + "version": "4.56.0", "author": { "email": "webteam@canonical.com", "name": "Canonical Webteam" diff --git a/releases.yml b/releases.yml index 19e687fb0..9ff572c96 100644 --- a/releases.yml +++ b/releases.yml @@ -1,3 +1,9 @@ +- version: 4.56.0 + features: + - component: Product card + url: /docs/patterns/product-card + status: New + notes: Added a new Product card pattern - version: 4.55.1 features: - component: CheckboxInput diff --git a/scss/_patterns_product-card.scss b/scss/_patterns_product-card.scss new file mode 100644 index 000000000..930ed2272 --- /dev/null +++ b/scss/_patterns_product-card.scss @@ -0,0 +1,46 @@ +@import 'settings'; + +@mixin vf-p-product-card { + // Product card(s) in the blog article sidebar, above the newsletter card. + // The whole card is an anchor (no CTA link), so render it as a block and + // match the newsletter card's border hover transition. + .p-card--product { + @extend %vf-card; + @extend %vf-is-bordered; + + border-color: $colors--theme--border-low-contrast; + display: block; + + @include vf-transition(border-color, brisk); + + &:hover { + border-color: $colors--theme--border-high-contrast; + // Don't underline the whole card; the border highlight is the affordance. + text-decoration: none; + } + + // The whole card is a link; don't apply the visited colour to its text. + &:visited { + color: $colors--theme--text-default; + } + + // Arrow icon at the end of each card, in place of the removed CTA link. + // A recolourable mask, so the colour lives here rather than in inline SVG + // markup repeated in the template. + .product-card__arrow { + background-color: $color-brand; + display: inline-block; + height: $default-icon-size; + mask: url('data:image/svg+xml,') + no-repeat center / contain; + width: $default-icon-size; + + @include vf-transition(transform, snap); + } + + // Nudge the arrow to the right on hover. + &:hover .product-card__arrow { + transform: translateX($sp-small); + } + } +} diff --git a/scss/_vanilla.scss b/scss/_vanilla.scss index 4cfcb7d1c..aceb316ba 100644 --- a/scss/_vanilla.scss +++ b/scss/_vanilla.scss @@ -44,6 +44,7 @@ @import 'patterns_notifications'; @import 'patterns_pagination'; @import 'patterns_pricing-block'; +@import 'patterns_product-card'; @import 'patterns_newsletter-signup'; @import 'patterns_pull-quotes'; @import 'patterns_resources-block'; @@ -152,6 +153,7 @@ @include vf-p-pagination; @include vf-p-pricing-block; @include vf-p-pull-quotes; + @include vf-p-product-card; @include vf-p-resources-block; @include vf-p-rule; @include vf-p-search-and-filter; diff --git a/side-navigation.yaml b/side-navigation.yaml index 89b2a61f9..7f0427077 100644 --- a/side-navigation.yaml +++ b/side-navigation.yaml @@ -153,6 +153,8 @@ url: /docs/patterns/resources - title: Card url: /docs/patterns/content-card + - title: Product card + url: /docs/patterns/product-card - heading: Utilities ordering: alphabetical subheadings: diff --git a/templates/_macros/vf_product-card.jinja b/templates/_macros/vf_product-card.jinja new file mode 100644 index 000000000..1a2b45727 --- /dev/null +++ b/templates/_macros/vf_product-card.jinja @@ -0,0 +1,7 @@ +{%- macro vf_product_card(url, heading, content, class_name="") -%} + +

{{ heading }}

+

{{ content|safe }}

+ +
+{%- endmacro -%} diff --git a/templates/docs/examples/patterns/product-card/combined.html b/templates/docs/examples/patterns/product-card/combined.html new file mode 100644 index 000000000..0981dc91c --- /dev/null +++ b/templates/docs/examples/patterns/product-card/combined.html @@ -0,0 +1,10 @@ +{% extends "_layouts/examples.html" %} +{% block title %}Product card / Combined{% endblock %} +{% block standalone_css %}patterns_all{% endblock %} +{% block content %} + {% with is_combined = true %} +
+ {% include 'docs/examples/patterns/product-card/default.html' %} +
+ {% endwith %} +{% endblock %} diff --git a/templates/docs/examples/patterns/product-card/default.html b/templates/docs/examples/patterns/product-card/default.html new file mode 100644 index 000000000..7eb15bba4 --- /dev/null +++ b/templates/docs/examples/patterns/product-card/default.html @@ -0,0 +1,14 @@ +{% extends "_layouts/examples.html" %} +{% from "_macros/vf_product-card.jinja" import vf_product_card %} +{% block title %}Product card / Default{% endblock %} +{% block standalone_css %}patterns_all{% endblock %} +{% block content %} +
+
+ {{ vf_product_card('https://ubuntu.com/kernel/real-time/contact-us', 'Talk to us about real-time Ubuntu', 'Interested in running real-time Ubuntu in production? Tell us more about your needs', class_name="js-product-card") }} +
+
+ {{ vf_product_card('https://ubuntu.com/kernel/real-time/contact-us', 'Talk to us about real-time Ubuntu', 'Interested in running real-time Ubuntu in production? Tell us more about your needs', class_name="js-product-card") }} +
+
+{% endblock %} diff --git a/templates/docs/patterns/product-card/index.md b/templates/docs/patterns/product-card/index.md new file mode 100644 index 000000000..073bf4509 --- /dev/null +++ b/templates/docs/patterns/product-card/index.md @@ -0,0 +1,139 @@ +--- +wrapper_template: '_layouts/docs.html' +context: + title: Product card | Patterns +--- + +{% from "docs/macros/patterns/wip-notice.jinja" import pattern_wip_notice %} + +{{- pattern_wip_notice() }} + +The product card pattern is used to present a promotional or contextual link as +a self-contained, bordered card. The entire card is a single link, with a +heading, a short description, and a trailing arrow icon that indicates the card +is actionable. It is typically placed in a blog article sidebar, above the +newsletter card. + +The product card pattern is composed of the following elements: + +| Element | Description | +| ------- | --------------------------------------------------------- | +| Card | Anchor wrapping the whole card, linking to the target URL | +| Heading | h5-styled heading text | +| Content | p description text, rendered as raw HTML | +| Arrow | Decorative arrow icon indicating the card is actionable | + +## Default + +The default product card renders a bordered card that links to the provided +URL, with a heading, description, and trailing arrow. + +
+View example of the product card pattern +
+ +## Jinja Macro + +The `vf_product_card` Jinja macro can be used to generate a product card pattern. The API for the macro is shown below. + +### Parameters + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameRequired?TypeDefaultDescription
+ url + + Yes + + string + + '' + + Destination the card links to +
+ heading + + Yes + + string + + '' + + Heading text displayed at the top of the card, using h5 styling +
+ content + + Yes + + string + + '' + + Description text displayed below the heading; rendered as raw HTML +
+ class_name + + No + + string + + '' + + Additional CSS class(es) appended to the card element +
+
+ +## Import + +### Jinja Macro + +To import the Product Card Jinja macro, copy the following import statement into +your Jinja template: + +```jinja +{% raw -%} +{% from "_macros/vf_product-card.jinja" import vf_product_card %} +{%- endraw -%} +``` + +View the [building with Jinja macros guide](/docs/building-vanilla#jinja-macros) +for macro installation instructions. diff --git a/tests/parker.js b/tests/parker.js index f9204d55a..05860dbd5 100644 --- a/tests/parker.js +++ b/tests/parker.js @@ -12,7 +12,7 @@ function generateMetrics(file, metricsArray) { { name: 'Stylesheet size', benchmark: 150000, - threshold: 558381, + threshold: 559567, result: results['total-stylesheet-size'], }, {