From e0ec49bc914d9c77df1d2f09bb17046a08e6bf50 Mon Sep 17 00:00:00 2001 From: Muhammad Ali Date: Thu, 29 Jan 2026 12:04:47 +0500 Subject: [PATCH 1/7] feat: add blocks support to Hero section --- releases.yml | 6 + templates/_macros/vf_basic-section.jinja | 5 +- templates/_macros/vf_hero.jinja | 68 ++++++--- .../docs/examples/patterns/hero/combined.html | 4 + .../examples/patterns/hero/cta-block.html | 42 ++++++ .../patterns/hero/description-block.html | 26 ++++ .../examples/patterns/hero/image-block.html | 35 +++++ .../patterns/hero/signpost-image-block.html | 35 +++++ .../docs/patterns/basic-section/index.md | 3 + templates/docs/patterns/hero/index.md | 140 +++++++++++++++++- 10 files changed, 341 insertions(+), 23 deletions(-) create mode 100644 templates/docs/examples/patterns/hero/cta-block.html create mode 100644 templates/docs/examples/patterns/hero/description-block.html create mode 100644 templates/docs/examples/patterns/hero/image-block.html create mode 100644 templates/docs/examples/patterns/hero/signpost-image-block.html diff --git a/releases.yml b/releases.yml index 84c8bce28..cbc1626e3 100644 --- a/releases.yml +++ b/releases.yml @@ -1,3 +1,9 @@ +- version: 4.42.0 + features: + - component: Hero section + url: /docs/patterns/hero + status: Updated + notes: Added blocks alternative to slots. - version: 4.42.0 features: - component: Resources diff --git a/templates/_macros/vf_basic-section.jinja b/templates/_macros/vf_basic-section.jinja index 772266035..9cab1ad19 100644 --- a/templates/_macros/vf_basic-section.jinja +++ b/templates/_macros/vf_basic-section.jinja @@ -43,6 +43,7 @@ # image_config # - aspect_ratio: "16-9" | "3-2" | "" (default is "") # - caption_html: The HTML content for the caption of the image (optional). Will be wrapped in
, and the image and caption will be wrapped in a
. +# - is_highlighted: Whether to apply the "is-highlighted" class to the image container (default is true). # - attrs: A dictionary of attributes to apply to the image {% macro _basic_section_image(image_config={}) %} {%- set aspect_ratio = image_config.get("aspect_ratio", "") | trim -%} @@ -53,10 +54,12 @@ {%- set caption_html = image_config.get("caption_html", "") | trim -%} {%- set has_caption = caption_html | length > 0 -%} + {%- set is_highlighted = image_config.get("is_highlighted", true) -%} + {%- if has_caption -%}
{%- endif -%} -
+
0 %} {% set description_content = caller('description') %} - {% set has_description = description_content|trim|length > 0 %} + {% set has_description = description_blocks | length > 0 or description_content|trim|length > 0 %} {% set cta_content = caller('cta') %} - {% set has_cta = cta_content|trim|length > 0 %} + {% set has_cta = cta_block or cta_content|trim|length > 0 %} {% set image_content = caller('image') %} - {% set has_image = image_content|trim|length > 0 %} + {% set has_image = image_block or image_content|trim|length > 0 %} {% set signpost_image_content = caller('signpost_image') %} - {% set has_signpost_image = signpost_image_content|trim|length > 0 or display_blank_signpost_image_space %} + {% set has_signpost_image = signpost_image_block or signpost_image_content|trim|length > 0 or display_blank_signpost_image_space %} {#- User can pass layout as "X-Y" or "X/Y" -#} {% set layout = layout | trim | replace('/', '-') %} @@ -98,7 +107,9 @@ {%- endmacro %} {%- macro _hero_cta_block() -%} - {% if has_cta -%} + {%- if cta_block -%} + {{- basic_section_item(cta_block) -}} + {% elif has_cta -%}
{{ cta_content }}
@@ -106,19 +117,34 @@ {%- endmacro %} {%- macro _hero_description_block() -%} - {% if has_description %} + {%- if description_blocks | length > 0 -%} + {% for description_block in description_blocks %} + {{ basic_section_item(description_block) }} + {% endfor %} + {% elif has_description %}
{{ description_content }}
{% endif %} {%- endmacro %} + {%- macro _hero_image_block() -%} + {%- if image_block -%} + {{- basic_section_item(image_block) -}} + {% elif has_image -%} + {{ image_content }} + {% endif %} + {%- endmacro %} + {%- macro _hero_signpost_image_block() -%} - {% if layout == '25-75' and has_signpost_image -%} -
+
+ {%- if signpost_image_block -%} + {%- set x=signpost_image_block.__setitem__("type", "image") -%} + {{- basic_section_item(signpost_image_block) -}} + {% else -%} {{ signpost_image_content }} -
- {% endif %} + {% endif %} +
{%- endmacro %}
@@ -140,7 +166,7 @@
{% if has_image -%}
- {{ image_content }} + {{ _hero_image_block() }}
{% endif -%} {% elif (has_full_width_image and not has_signpost_image) or is_50_50_no_image %} @@ -156,8 +182,8 @@ {{- _hero_description_block() -}} {{- _hero_cta_block() -}}
- {{ image_content -}} - {% elif has_signpost_image %} + {{ _hero_image_block() }} + {% elif has_signpost_image and layout == '25-75' %} {#- 25/75 Signpost layout -#}
{{ _hero_signpost_image_block() -}} @@ -172,7 +198,7 @@
{% if has_image %} {#- Signpost with image is always full-width, so set it after the columns -#} - {{- image_content }} + {{- _hero_image_block() }} {% endif -%} {% else %}
@@ -185,7 +211,7 @@
{% if has_image -%}
- {{ image_content }} + {{ _hero_image_block() }}
{% endif -%} {% endif -%} diff --git a/templates/docs/examples/patterns/hero/combined.html b/templates/docs/examples/patterns/hero/combined.html index 110a80b2f..8b87695bb 100644 --- a/templates/docs/examples/patterns/hero/combined.html +++ b/templates/docs/examples/patterns/hero/combined.html @@ -24,5 +24,9 @@
{% include 'docs/examples/patterns/hero/hero-75-25.html' %}
{% include 'docs/examples/patterns/hero/hero-fallback.html' %}
{% include 'docs/examples/patterns/hero/hero-50-50-no-image.html' %}
+
{% include 'docs/examples/patterns/hero/cta-block.html' %}
+
{% include 'docs/examples/patterns/hero/description-block.html' %}
+
{% include 'docs/examples/patterns/hero/image-block.html' %}
+
{% include 'docs/examples/patterns/hero/signpost-image-block.html' %}
{% endwith %} {% endblock %} diff --git a/templates/docs/examples/patterns/hero/cta-block.html b/templates/docs/examples/patterns/hero/cta-block.html new file mode 100644 index 000000000..78f611feb --- /dev/null +++ b/templates/docs/examples/patterns/hero/cta-block.html @@ -0,0 +1,42 @@ +{% extends "_layouts/examples.html" %} +{% from "_macros/vf_hero.jinja" import vf_hero %} + +{% block title %}Hero | CTA block{% endblock %} +{% block standalone_css %}patterns_all{% endblock %} + +{% set is_paper = true %} +{% block content %} + +{% call(slot) vf_hero( + title_text='H1 - ideally one line, up to two', + subtitle_text='H2 placeholder - aim for one line, 2 is acceptable, more - use a paragraph', + layout='50/50', + blocks=[ + { + "type": "cta-block", + "item": { + "primary": { + "content_html": "Contact us", + "attrs": { + "href": "#" + } + }, + "link": { + "content_html": "Learn more ›", + "attrs": { + "href": "#" + } + } + } + } + ] +) -%} + {%- if slot == 'description' -%} +

+ Generally, the height of the right hand side of a 50/50 split should contain more content than the left + hand side. +

+ {%- endif -%} +{% endcall -%} + +{% endblock %} diff --git a/templates/docs/examples/patterns/hero/description-block.html b/templates/docs/examples/patterns/hero/description-block.html new file mode 100644 index 000000000..7c350ac0e --- /dev/null +++ b/templates/docs/examples/patterns/hero/description-block.html @@ -0,0 +1,26 @@ +{% extends "_layouts/examples.html" %} +{% from "_macros/vf_hero.jinja" import vf_hero %} + +{% block title %}Hero | Description block{% endblock %} +{% block standalone_css %}patterns_all{% endblock %} + +{% set is_paper = true %} +{% block content %} + +{% call(slot) vf_hero( + title_text='H1 - ideally one line, up to two', + subtitle_text='H2 placeholder - aim for one line, 2 is acceptable, more - use a paragraph', + layout='50/50', + blocks=[ + { + "type": "description", + "item": { + "type": "text", + "content": "Generally, the height of the right hand side of a 50/50 split should contain more content than the left hand side." + } + } + ] +) -%} +{% endcall -%} + +{% endblock %} diff --git a/templates/docs/examples/patterns/hero/image-block.html b/templates/docs/examples/patterns/hero/image-block.html new file mode 100644 index 000000000..06791ca73 --- /dev/null +++ b/templates/docs/examples/patterns/hero/image-block.html @@ -0,0 +1,35 @@ +{% extends "_layouts/examples.html" %} +{% from "_macros/vf_hero.jinja" import vf_hero %} + +{% block title %}Hero | Image block{% endblock %} +{% block standalone_css %}patterns_all{% endblock %} + +{% set is_paper = true %} +{% block content %} + +{% call(slot) vf_hero( + title_text='H1 - ideally one line, up to two', + layout='50/50', + blocks=[ + { + "type": "description", + "item": { + "type": "text", + "content": "Generally, the height of the right hand side of a 50/50 split should contain more content than the left hand side." + } + }, + { + "type": "image", + "item": { + "aspect_ratio": "16-9", + "attrs": { + "src": "https://assets.ubuntu.com/v1/9b4c074f-Kernelt%20industries-80-short.png", + "alt": "16:9 aspect ratio image" + } + } + }, + ] +) -%} +{% endcall -%} + +{% endblock %} diff --git a/templates/docs/examples/patterns/hero/signpost-image-block.html b/templates/docs/examples/patterns/hero/signpost-image-block.html new file mode 100644 index 000000000..f5f187333 --- /dev/null +++ b/templates/docs/examples/patterns/hero/signpost-image-block.html @@ -0,0 +1,35 @@ +{% extends "_layouts/examples.html" %} +{% from "_macros/vf_hero.jinja" import vf_hero %} + +{% block title %}Hero | Image block{% endblock %} +{% block standalone_css %}patterns_all{% endblock %} + +{% set is_paper = true %} +{% block content %} + +{% call(slot) vf_hero( + title_text='H1 - ideally one line, up to two', + layout='25/75', + blocks=[ + { + "type": "description", + "item": { + "type": "text", + "content": "Generally, the height of the right hand side of a 50/50 split should contain more content than the left hand side." + } + }, + { + "type": "signpost_image", + "item": { + "is_highlighted": false, + "attrs": { + "src": "https://assets.ubuntu.com/v1/fe20126d-RISC-V-logo.svg", + "alt": "16:9 aspect ratio image" + } + } + } + ] +) -%} +{% endcall -%} + +{% endblock %} diff --git a/templates/docs/patterns/basic-section/index.md b/templates/docs/patterns/basic-section/index.md index afa0f0e1b..b795b5f48 100644 --- a/templates/docs/patterns/basic-section/index.md +++ b/templates/docs/patterns/basic-section/index.md @@ -150,6 +150,7 @@ ratios and a [caption](/docs/patterns/images#image-with-caption). "item": { "aspect_ratio": "16-9" | "3-2" | "", "caption_html": "Optional caption with HTML", + "is_highlighted": "Optional boolean to enable/disable background highlighting. Default is true", "attrs": { "src": "image-url", "alt": "alt-text" @@ -160,6 +161,8 @@ ratios and a [caption](/docs/patterns/images#image-with-caption). - **`aspect_ratio`**: Optional aspect ratio constraint. Valid values: `"16-9"`, `"3-2"`, or empty string for default. - **`caption_html`**: Optional HTML caption. If provided, the image and caption are wrapped in a `
` element. +- **`is_highlighted`**: Optional boolean which defaults to true. Wraps image in a highlighted image + container. - **`attrs`**: Dictionary of image attributes (src, alt, class, etc.). The `p-image-container__image` class is automatically applied. See [attribute forwarding docs](/docs/building-vanilla#attribute-forwarding) for more info. #### Videos diff --git a/templates/docs/patterns/hero/index.md b/templates/docs/patterns/hero/index.md index cfb9e31a0..d5640f61e 100644 --- a/templates/docs/patterns/hero/index.md +++ b/templates/docs/patterns/hero/index.md @@ -113,6 +113,142 @@ This places the title and subtitle in their own row above the rest of the hero c View example of the hero pattern in fallback configuration +## Blocks + +### Description + +Description blocks can be used to display elaborative text content. + +By default, the description contents are rendered within a `

` tag, but you can also use `type:"html"` to render raw HTML +content. + +

+ +```json +{ + "type": "description", + "item": { + "type": "text" | "html", + "content": "Your content here" + } +} +``` + +- **`type`**: Either `"text"` (default) or `"html"`. Text content is wrapped in `

` tags, HTML content is rendered as-is. +- **`content`**: The text or HTML content to display. + +### CTA + +The CTA block allows you to include call-to-action elements within the section. + +It supports three types of CTA items: + +- **Primary**: 1 main call-to-action button +- **Secondary**: Supporting action buttons +- **Link**: Text link + +

+ +```json +{ + "type": "cta-block", + "item": { + "primary": { + "content_html": "Primary button text", + "attrs": { + "href": "link-url", + "class": "optional-css-class" + } + }, + "secondaries": [ + { + "content_html": "Secondary button text", + "attrs": { + "href": "link-url" + } + } + ], + "link": { + "content_html": "Link text", + "attrs": { + "href": "link-url" + } + } + } +} +``` + +- **`primary`**: Optional primary button configuration. +- **`secondaries`**: Optional array of secondary button configurations. +- **`link`**: Optional text link configuration. + +Each of the CTA configurations accepts the following properties: + +- **`content_html`**: The inner HTML of the CTA item. +- **`attrs`**: Dictionary of button/link attributes. These are applied to the CTA element. If `href` is present, the CTA item will be an ``, otherwise it will be a `