Skip to content

Commit b82b3c6

Browse files
Merge pull request #5747 from canonical/update-hero
feat(WD-33316): Add blocks support to Hero section
2 parents ea8d6e0 + 0c165d0 commit b82b3c6

18 files changed

+718
-165
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vanilla-framework",
3-
"version": "4.43.0",
3+
"version": "4.44.0",
44
"author": {
55
"email": "webteam@canonical.com",
66
"name": "Canonical Webteam"

releases.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
- version: 4.44.0
2+
features:
3+
- component: Hero section
4+
url: /docs/patterns/hero
5+
status: Updated
6+
notes: Added <a href="/docs/patterns/hero#blocks">blocks</a> successor to slots.
7+
- component: Basic section
8+
url: /docs/patterns/basic-section
9+
status: Updated
10+
notes: Added more aspect_ratio options to the image block. Introduced two new parameters, <code>is_cover</code> and <code>override_last_item_padding</code>.
111
- version: 4.43.0
212
features:
313
- component: Icon

templates/_macros/vf_basic-section.jinja

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
{% from "_macros/shared/vf_linked-logo-block.jinja" import vf_linked_logo_block %}
77
{% from "_macros/shared/vf_logo-block.jinja" import vf_logo_block %}
88

9-
{% macro vf_basic_section_blocks(items=[]) %}
9+
{% macro vf_basic_section_blocks(items=[], override_last_item_padding=false) %}
1010
{%- for item in items -%}
1111
{%- set item_padding = (item.get("padding", "")) | trim -%}
1212
{%- if item_padding not in ["shallow"] -%}
@@ -19,7 +19,7 @@
1919
{%- endif -%}
2020

2121
{#- Last item should not have any additional padding - the pattern itself already has bottom padding -#}
22-
{%- if loop.last -%}
22+
{%- if loop.last and not override_last_item_padding -%}
2323
{%- set item_classes = "" -%}
2424
{%- endif -%}
2525
<div{%- if item_classes | length > 0 %} class="{{ item_classes }}"{%- endif -%}>
@@ -41,22 +41,27 @@
4141
{%- endmacro -%}
4242

4343
# image_config
44-
# - aspect_ratio: "16-9" | "3-2" | "" (default is "")
44+
# - aspect_ratio: "16-9" | "3-2" | "2-3", "cinematic" | "" (default is "")
4545
# - caption_html: The HTML content for the caption of the image (optional). Will be wrapped in <figcaption>, and the image and caption will be wrapped in a <figure>.
46+
# - is_highlighted: Whether to apply the "is-highlighted" class to the image container (default is true).
47+
# - is_cover: Whether to apply the "is-cover" class to the image container (default is false).
4648
# - attrs: A dictionary of attributes to apply to the image
4749
{% macro _basic_section_image(image_config={}) %}
4850
{%- set aspect_ratio = image_config.get("aspect_ratio", "") | trim -%}
49-
{%- if aspect_ratio not in ["16-9", "3-2"] -%}
51+
{%- if aspect_ratio not in ["16-9", "3-2", "2-3", "cinematic"] -%}
5052
{%- set aspect_ratio = "" -%}
5153
{%- endif -%}
5254

5355
{%- set caption_html = image_config.get("caption_html", "") | trim -%}
5456
{%- set has_caption = caption_html | length > 0 -%}
5557

58+
{%- set is_highlighted = image_config.get("is_highlighted", true) -%}
59+
{%- set is_cover = image_config.get("is_cover", false) -%}
60+
5661
{%- if has_caption -%}
5762
<figure>
5863
{%- endif -%}
59-
<div class="p-image-container{%- if aspect_ratio | length > 0 -%}--{{- aspect_ratio -}}{%- endif %} is-highlighted">
64+
<div class="p-image-container{%- if aspect_ratio | length > 0 -%}--{{- aspect_ratio -}}{%- endif %}{%- if is_highlighted %} is-highlighted{% endif -%}{%- if is_cover %} is-cover{% endif -%}">
6065
<img class="p-image-container__image {{ image_config.get("attrs", {}).get("class", "") -}}"
6166
{%- for attr, value in image_config.get("attrs", {}).items() -%}
6267
{% if attr != "class" %}
@@ -238,6 +243,7 @@
238243
padding="default",
239244
is_split_on_medium=false,
240245
top_rule_variant="default",
246+
override_last_item_padding=false,
241247
attrs={}
242248
) -%}
243249

@@ -280,7 +286,7 @@
280286
{%- if has_subtitle -%}
281287
<p class="p-heading--{{ subtitle_heading_level }}">{{- subtitle_text -}}</p>
282288
{%- endif -%}
283-
{{- vf_basic_section_blocks(items=items) -}}
289+
{{- vf_basic_section_blocks(items=items, override_last_item_padding=override_last_item_padding) -}}
284290
</div>
285291
</div>
286292
</section>

templates/_macros/vf_hero.jinja

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,42 @@
1+
{% from "_macros/shared/vf_cta-block.jinja" import vf_cta_block %}
2+
{% from "_macros/vf_basic-section.jinja" import vf_basic_section_blocks %}
3+
14
# Params
25
# title_text: Hero title text (required)
36
# subtitle_text: Hero subtitle text
47
# layout: layout of hero section. Options are '50/50', '50/50-full-width-image', '75/25', '25/75', 'fallback'
58
# is_split_on_medium: whether the layout is split on tablet in 50/50, 25/75, and 75/25 layouts.
69
# If false, the layout is stacked on tablet.
710
# If true, the layout is split on tablet.
8-
# Slots
9-
# description: paragraph-style content below the title and subtitle
10-
# cta: call-to-action block below the description
11-
# image: slot for image content
12-
# signpost_image: slot for signpost (left column) image content in 25/75 layout. Required for 25/75 layout.
1311
# display_blank_signpost_image_space: whether to indent the content for 25/75 layout on large screens.
12+
# blocks: list of content blocks for the hero section. Includes description, cta, image, and signpost_image blocks.
13+
# Slots
14+
# description (deprecated): paragraph-style content below the title and subtitle
15+
# cta (deprecated): call-to-action block below the description
16+
# image (deprecated): slot for image content
17+
# signpost_image (deprecated): slot for signpost (left column) image content in 25/75 layout. Required for 25/75 layout.
1418
{% macro vf_hero(
1519
title_text,
1620
subtitle_text='',
1721
layout="fallback",
1822
is_split_on_medium=false,
19-
display_blank_signpost_image_space=false
23+
display_blank_signpost_image_space=false,
24+
blocks=[]
2025
) -%}
26+
{%- set description_blocks = blocks | selectattr("type", "equalto", "description") | list -%}
27+
{%- set cta_block = blocks | selectattr("type", "equalto", "cta-block") | list | first | default(None) -%}
28+
{%- set image_block = blocks | selectattr("type", "equalto", "image") | list | first | default(None) -%}
29+
{%- set signpost_image_block = blocks | selectattr("type", "equalto", "signpost_image") | list | first | default(None) -%}
30+
2131
{% set has_subtitle = subtitle_text|trim|length > 0 %}
2232
{% set description_content = caller('description') %}
23-
{% set has_description = description_content|trim|length > 0 %}
33+
{% set has_description = description_blocks | length > 0 or description_content|trim|length > 0 %}
2434
{% set cta_content = caller('cta') %}
25-
{% set has_cta = cta_content|trim|length > 0 %}
35+
{% set has_cta = cta_block or cta_content|trim|length > 0 %}
2636
{% set image_content = caller('image') %}
27-
{% set has_image = image_content|trim|length > 0 %}
37+
{% set has_image = image_block or image_content|trim|length > 0 %}
2838
{% set signpost_image_content = caller('signpost_image') %}
29-
{% set has_signpost_image = signpost_image_content|trim|length > 0 or display_blank_signpost_image_space %}
39+
{% set has_signpost_image = signpost_image_block or signpost_image_content|trim|length > 0 or display_blank_signpost_image_space %}
3040

3141
{#- User can pass layout as "X-Y" or "X/Y" -#}
3242
{% set layout = layout | trim | replace('/', '-') %}
@@ -98,27 +108,45 @@
98108
{%- endmacro %}
99109

100110
{%- macro _hero_cta_block() -%}
101-
{% if has_cta -%}
111+
{%- if cta_block -%}
112+
{{- vf_basic_section_blocks(items=[cta_block], override_last_item_padding=true) -}}
113+
{% elif has_cta -%}
102114
<div class="p-cta-block">
103115
{{ cta_content }}
104116
</div>
105117
{% endif %}
106118
{%- endmacro %}
107119

108120
{%- macro _hero_description_block() -%}
109-
{% if has_description %}
121+
{%- if description_blocks | length > 0 -%}
122+
{% for description_block in description_blocks %}
123+
{{ vf_basic_section_blocks(items=[description_block], override_last_item_padding=true) }}
124+
{% endfor %}
125+
{% elif has_description %}
110126
<div class="p-section--shallow">
111127
{{ description_content }}
112128
</div>
113129
{% endif %}
114130
{%- endmacro %}
115131

132+
{%- macro _hero_image_block() -%}
133+
{%- if image_block -%}
134+
{{- vf_basic_section_blocks(items=[image_block], override_last_item_padding=true) -}}
135+
{% elif has_image -%}
136+
{{ image_content }}
137+
{% endif %}
138+
{%- endmacro %}
139+
116140
{%- macro _hero_signpost_image_block() -%}
117-
{% if layout == '25-75' and has_signpost_image -%}
118-
<div class="p-section--shallow">
141+
<div class="p-section--shallow">
142+
{%- if signpost_image_block -%}
143+
{% set _ = signpost_image_block.update(type="image") %}
144+
{% set _ = signpost_image_block.item.attrs.update({"class": "u-no-margin"}) %}
145+
{{- vf_basic_section_blocks(items=[signpost_image_block], override_last_item_padding=true) -}}
146+
{% else -%}
119147
{{ signpost_image_content }}
120-
</div>
121-
{% endif %}
148+
{% endif %}
149+
</div>
122150
{%- endmacro %}
123151

124152
<section class="p-section--hero">
@@ -140,7 +168,7 @@
140168
</div>
141169
{% if has_image -%}
142170
<div class="{{ col_classes[1] }}">
143-
{{ image_content }}
171+
{{ _hero_image_block() }}
144172
</div>
145173
{% endif -%}
146174
{% elif (has_full_width_image and not has_signpost_image) or is_50_50_no_image %}
@@ -156,8 +184,8 @@
156184
{{- _hero_description_block() -}}
157185
{{- _hero_cta_block() -}}
158186
</div>
159-
{{ image_content -}}
160-
{% elif has_signpost_image %}
187+
{{ _hero_image_block() }}
188+
{% elif has_signpost_image and layout == '25-75' %}
161189
{#- 25/75 Signpost layout -#}
162190
<div class="{{ col_classes[0] }}">
163191
{{ _hero_signpost_image_block() -}}
@@ -172,7 +200,7 @@
172200
</div>
173201
{% if has_image %}
174202
{#- Signpost with image is always full-width, so set it after the columns -#}
175-
{{- image_content }}
203+
{{- _hero_image_block() }}
176204
{% endif -%}
177205
{% else %}
178206
<div class="{{ col_classes[0] }}">
@@ -185,7 +213,7 @@
185213
</div>
186214
{% if has_image -%}
187215
<div class="{{ col_classes[1] }}">
188-
{{ image_content }}
216+
{{ _hero_image_block() }}
189217
</div>
190218
{% endif -%}
191219
{% endif -%}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{% extends "_layouts/examples.html" %}
2+
{% from "_macros/vf_hero.jinja" import vf_hero %}
3+
4+
{% block title %}Hero | CTA block{% endblock %}
5+
{% block standalone_css %}patterns_all{% endblock %}
6+
7+
{% set is_paper = true %}
8+
{% block content %}
9+
10+
{% call(slot) vf_hero(
11+
title_text='H1 - ideally one line, up to two',
12+
subtitle_text='H2 placeholder - aim for one line, 2 is acceptable, more - use a paragraph',
13+
layout='50/50',
14+
blocks=[
15+
{
16+
"type": "cta-block",
17+
"item": {
18+
"primary": {
19+
"content_html": "Contact us",
20+
"attrs": {
21+
"href": "#"
22+
}
23+
},
24+
"link": {
25+
"content_html": "Learn more &rsaquo;",
26+
"attrs": {
27+
"href": "#"
28+
}
29+
}
30+
}
31+
}
32+
]
33+
) -%}
34+
{%- if slot == 'description' -%}
35+
<p>
36+
Generally, the height of the right hand side of a 50/50 split should contain more content than the left
37+
hand side.
38+
</p>
39+
{%- endif -%}
40+
{% endcall -%}
41+
42+
{% endblock %}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{% extends "_layouts/examples.html" %}
2+
{% from "_macros/vf_hero.jinja" import vf_hero %}
3+
4+
{% block title %}Hero | Description block{% endblock %}
5+
{% block standalone_css %}patterns_all{% endblock %}
6+
7+
{% set is_paper = true %}
8+
{% block content %}
9+
10+
{% call(slot) vf_hero(
11+
title_text='H1 - ideally one line, up to two',
12+
subtitle_text='H2 placeholder - aim for one line, 2 is acceptable, more - use a paragraph',
13+
layout='50/50',
14+
blocks=[
15+
{
16+
"type": "description",
17+
"item": {
18+
"type": "text",
19+
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate."
20+
}
21+
}
22+
]
23+
) -%}
24+
{% endcall -%}
25+
26+
{% endblock %}

templates/docs/examples/patterns/hero/hero-50-50-full-width-image.html

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,49 @@
1010
{% call(slot) vf_hero(
1111
title_text='H1 - ideally one line, up to two',
1212
subtitle_text='H2 placeholder - aim for one line, 2 is acceptable.',
13-
layout='50/50-full-width-image'
13+
layout='50/50-full-width-image',
14+
blocks=[
15+
{
16+
"type": "description",
17+
"padding": "shallow",
18+
"item": {
19+
"type": "text",
20+
"content": "Generally, the height of the right hand side of a 50/50 split should contain more content than the left
21+
hand side."
22+
}
23+
},
24+
{
25+
"type": "cta-block",
26+
"padding": "shallow",
27+
"item": {
28+
"primary": {
29+
"content_html": "Learn more",
30+
"attrs": {
31+
"href": "#"
32+
}
33+
},
34+
"link": {
35+
"content_html": "Contact us ›",
36+
"attrs": {
37+
"href": "#"
38+
}
39+
}
40+
}
41+
},
42+
{
43+
"type": "image",
44+
"item": {
45+
"aspect_ratio": "cinematic",
46+
"is_highlighted": false,
47+
"is_cover": true,
48+
"attrs": {
49+
"src": "https://assets.ubuntu.com/v1/a299c914-GettyImages-DataCenter.jpeg",
50+
"alt": "alt-text"
51+
}
52+
}
53+
},
54+
]
1455
) -%}
15-
{%- if slot == 'description' -%}
16-
<p>
17-
Generally, the height of the right hand side of a 50/50 split should contain more content than the left
18-
hand side.
19-
</p>
20-
{%- endif -%}
21-
{%- if slot == 'cta' -%}
22-
<a href="#" class="p-button--positive">Learn more</a>
23-
<a href="#">Contact us ›</a>
24-
{%- endif -%}
25-
{%- if slot == 'image' -%}
26-
<div class="p-image-container--cinematic is-cover">
27-
<img class="p-image-container__image" src="https://assets.ubuntu.com/v1/a299c914-GettyImages-DataCenter.jpeg" alt="">
28-
</div>
29-
{% endif -%}
3056
{% endcall -%}
3157

3258
{% endblock %}

0 commit comments

Comments
 (0)