Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vanilla-framework",
"version": "4.55.1",
"version": "4.56.0",
"author": {
"email": "webteam@canonical.com",
"name": "Canonical Webteam"
Expand Down
6 changes: 6 additions & 0 deletions releases.yml
Original file line number Diff line number Diff line change
@@ -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
Expand Down
46 changes: 46 additions & 0 deletions scss/_patterns_product-card.scss
Original file line number Diff line number Diff line change
@@ -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,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 17 14" fill="none"><path d="M0 6.92383H16M10 13.4238L16 6.92383L10 0.423828" stroke="%23fff" stroke-width="1.25"/></svg>')
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);
}
}
}
2 changes: 2 additions & 0 deletions scss/_vanilla.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions side-navigation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
7 changes: 7 additions & 0 deletions templates/_macros/vf_product-card.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{%- macro vf_product_card(url, heading, content, class_name="") -%}
<a class="{{ ('p-card--product ' ~ class_name)|trim }}" href="{{ url }}">
<p class="p-heading--5">{{ heading }}</p>
<p>{{ content|safe }}</p>
<i class="product-card__arrow" aria-hidden="true"></i>
</a>
{%- endmacro -%}
10 changes: 10 additions & 0 deletions templates/docs/examples/patterns/product-card/combined.html
Original file line number Diff line number Diff line change
@@ -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 %}
<section>
{% include 'docs/examples/patterns/product-card/default.html' %}
</section>
{% endwith %}
{% endblock %}
14 changes: 14 additions & 0 deletions templates/docs/examples/patterns/product-card/default.html
Original file line number Diff line number Diff line change
@@ -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 %}
<div class="grid-row--50-50">
<div class="grid-col">
{{ 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") }}
</div>
<div class="grid-col">
{{ 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") }}
</div>
</div>
{% endblock %}
139 changes: 139 additions & 0 deletions templates/docs/patterns/product-card/index.md
Original file line number Diff line number Diff line change
@@ -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 | <code>h5</code>-styled heading text |
| Content | <code>p</code> 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.

<div class="embedded-example"><a href="/docs/examples/patterns/product-card/default/" class="js-example" data-lang="jinja">
View example of the product card pattern
</a></div>

## 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

<div style="overflow: auto;">
<table>
<thead>
<tr>
<th style="width: 220px;">Name</th>
<th style="width: 160px;">Required?</th>
<th style="width: 160px;">Type</th>
<th style="width: 160px;">Default</th>
<th style="width: 250px;">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>url</code>
</td>
<td>
Yes
</td>
<td>
<code>string</code>
</td>
<td>
<code>''</code>
</td>
<td>
Destination the card links to
</td>
</tr>
<tr>
<td>
<code>heading</code>
</td>
<td>
Yes
</td>
<td>
<code>string</code>
</td>
<td>
<code>''</code>
</td>
<td>
Heading text displayed at the top of the card, using <code>h5</code> styling
</td>
</tr>
<tr>
<td>
<code>content</code>
</td>
<td>
Yes
</td>
<td>
<code>string</code>
</td>
<td>
<code>''</code>
</td>
<td>
Description text displayed below the heading; rendered as raw HTML
</td>
</tr>
<tr>
<td>
<code>class_name</code>
</td>
<td>
No
</td>
<td>
<code>string</code>
</td>
<td>
<code>''</code>
</td>
<td>
Additional CSS class(es) appended to the card element
</td>
</tr>
</tbody>
</table>
</div>

## 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.
2 changes: 1 addition & 1 deletion tests/parker.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function generateMetrics(file, metricsArray) {
{
name: 'Stylesheet size',
benchmark: 150000,
threshold: 558381,
threshold: 559567,
result: results['total-stylesheet-size'],
},
{
Expand Down
Loading