vanilla-framework 4.38.0 → 4.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -5
- package/scss/_patterns_data-spotlight.scss +2 -3
- package/scss/_patterns_equal-height-row.scss +18 -11
- package/templates/_macros/shared/vf_article_block.jinja +1 -0
- package/templates/_macros/shared/vf_blog-block.jinja +60 -0
- package/templates/_macros/shared/vf_cta-block.jinja +93 -0
- package/templates/_macros/shared/vf_description-block.jinja +33 -0
- package/templates/_macros/shared/vf_divided-section-block.jinja +67 -0
- package/templates/_macros/shared/vf_equal-heights-block.jinja +68 -0
- package/templates/_macros/shared/vf_linked-logo-block.jinja +34 -0
- package/templates/_macros/shared/vf_logo-block.jinja +29 -0
- package/templates/_macros/shared/vf_section_top_rule.jinja +27 -4
- package/templates/_macros/shared/vf_tabs.jinja +78 -0
- package/templates/_macros/vf_basic-section.jinja +48 -137
- package/templates/_macros/vf_blog.jinja +4 -48
- package/templates/_macros/vf_cta-section.jinja +9 -2
- package/templates/_macros/vf_divided-section.jinja +4 -56
- package/templates/_macros/vf_equal-heights.jinja +21 -49
- package/templates/_macros/vf_linked-logo-section.jinja +5 -32
- package/templates/_macros/vf_logo-section.jinja +37 -13
- package/templates/_macros/vf_quote-wrapper.jinja +278 -139
- package/templates/_macros/vf_tab-section.jinja +238 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
{% from "_macros/shared/vf_section_top_rule.jinja" import vf_section_top_rule %}
|
|
2
|
+
{% from "_macros/shared/vf_cta-block.jinja" import vf_cta_block %}
|
|
3
|
+
{% from "_macros/shared/vf_description-block.jinja" import vf_description_block %}
|
|
4
|
+
{% from "_macros/shared/vf_tabs.jinja" import vf_tabs %}
|
|
5
|
+
{% from "_macros/vf_quote-wrapper.jinja" import vf_quote_block %}
|
|
6
|
+
{% from "_macros/shared/vf_linked-logo-block.jinja" import vf_linked_logo_block %}
|
|
7
|
+
{% from "_macros/shared/vf_logo-block.jinja" import vf_logo_block %}
|
|
8
|
+
{% from "_macros/shared/vf_divided-section-block.jinja" import vf_divided_section_block %}
|
|
9
|
+
{% from "_macros/shared/vf_blog-block.jinja" import vf_blog_block %}
|
|
10
|
+
{% from "_macros/vf_basic-section.jinja" import vf_basic_section_blocks %}
|
|
11
|
+
|
|
12
|
+
{#-
|
|
13
|
+
- tab (Object) - Configuration object with the following properties:
|
|
14
|
+
- type (String) - The type of content block. Must be one of:
|
|
15
|
+
- "quote" - Quote block (full-width only). See _tab_section_quote
|
|
16
|
+
- "linked-logo" - Linked logo block. See vf_linked_logo_block
|
|
17
|
+
- "logo-block" - Logo block. See vf_logo_block
|
|
18
|
+
- "divided-section" - Divided section block. See vf_divided_section_block
|
|
19
|
+
- "blog" - Blog articles block. See vf_blog_block
|
|
20
|
+
- "basic-section" - Basic section with content blocks. See vf_basic_section_blocks
|
|
21
|
+
- item (Object) - Configuration specific to the block type.
|
|
22
|
+
The structure depends on the type selected (see referenced macros).
|
|
23
|
+
- tab_html (String) - HTML content for the tab label
|
|
24
|
+
-#}
|
|
25
|
+
{%- macro _tab_section_tab(tab={}) -%}
|
|
26
|
+
{%- set type = tab.get("type", "") | trim -%}
|
|
27
|
+
{%- set item = tab.get("item", {}) -%}
|
|
28
|
+
{% if type == "quote" %}
|
|
29
|
+
{{ vf_quote_block(signpost=item.get('signpost', {}), contents=item.get('contents', {})) }}
|
|
30
|
+
{% elif type == "linked-logo" %}
|
|
31
|
+
{{ vf_linked_logo_block({'links': item.get('links', [])}) }}
|
|
32
|
+
{% elif type == "logo-block" %}
|
|
33
|
+
{{ vf_logo_block({'logos': item.get('logos', []), 'is_fixed_width': item.get('is_fixed_width', true)}) }}
|
|
34
|
+
{% elif type == "divided-section" %}
|
|
35
|
+
{{ vf_divided_section_block(blocks=item.get('blocks', [])) }}
|
|
36
|
+
{% elif type == "blog" %}
|
|
37
|
+
<div class="p-blog grid-row">
|
|
38
|
+
{{ vf_blog_block(articles=item.get('articles', []), template_config=item.get('template_config', {})) }}
|
|
39
|
+
</div>
|
|
40
|
+
{% elif type == "basic-section" %}
|
|
41
|
+
{{ vf_basic_section_blocks(items=item.get('items', [])) }}
|
|
42
|
+
{% endif %}
|
|
43
|
+
{%- endmacro -%}
|
|
44
|
+
|
|
45
|
+
{#-
|
|
46
|
+
A higher-order component that renders a section with a title, optional description,
|
|
47
|
+
optional call-to-action, and a tabbed interface containing various content blocks.
|
|
48
|
+
|
|
49
|
+
This pattern combines a top heading area with tabs that can contain different types of
|
|
50
|
+
content blocks (quotes, logos, blog articles, etc.). The allowed block types vary by layout.
|
|
51
|
+
|
|
52
|
+
Parameters:
|
|
53
|
+
- title (Object) - Configuration for the title. Properties:
|
|
54
|
+
- text (String, Required) - The main title text (rendered as h2 by default)
|
|
55
|
+
- link_attrs (Object, Optional) - Attributes for the title link (e.g., href, class)
|
|
56
|
+
- heading_level (Number, Optional) - Heading level for the title (2, 3, or 4). Default: 2
|
|
57
|
+
|
|
58
|
+
- description (Object, Optional) - Configuration for the secondary description column.
|
|
59
|
+
Passed directly to vf_description_block. Properties:
|
|
60
|
+
- content (String) - The description text or HTML content
|
|
61
|
+
- type (String, Optional) - "text" or "html". Default: "text"
|
|
62
|
+
|
|
63
|
+
- cta (Object, Optional) - Call-to-action configuration passed to vf_cta_block. Properties:
|
|
64
|
+
- primary (Object) - Primary button configuration
|
|
65
|
+
- secondaries (Array) - Array of secondary button configurations
|
|
66
|
+
- link (Object) - Text link configuration
|
|
67
|
+
|
|
68
|
+
- layout (String, Optional) - Layout variant. One of:
|
|
69
|
+
- "full-width" - Tabs span full width. Allows: quote, linked-logo, logo-block, blog
|
|
70
|
+
- "50-50" - Tabs in right 50% column. Allows: linked-logo, logo-block, divided-section, blog, basic-section
|
|
71
|
+
- "25-75" - Tabs in right 75% column. Allows: linked-logo, logo-block, blog
|
|
72
|
+
Default: "50-50"
|
|
73
|
+
|
|
74
|
+
- padding (String, Optional) - Padding variant. One of:
|
|
75
|
+
- "deep" - Uses p-section--deep
|
|
76
|
+
- "shallow" - Uses p-section--shallow
|
|
77
|
+
- "default" - Uses p-section
|
|
78
|
+
Default: "default"
|
|
79
|
+
|
|
80
|
+
- top_rule_variant (String, Optional) - Horizontal rule variant above title. One of:
|
|
81
|
+
- "default" - Standard horizontal rule
|
|
82
|
+
- "muted" - Muted horizontal rule
|
|
83
|
+
- "none" - No rule
|
|
84
|
+
Default: "default"
|
|
85
|
+
|
|
86
|
+
- tabs (Array, Required) - Array of tab configurations. Each tab object should have:
|
|
87
|
+
- type (String, Required) - Block type: "quote", "linked-logo", "logo-block", "divided-section", "blog", or "basic-section"
|
|
88
|
+
- item (Object, Required) - Configuration specific to the block type
|
|
89
|
+
- tab_html (String, Required) - HTML for the tab control
|
|
90
|
+
|
|
91
|
+
- attrs (Object, Optional) - Dictionary of attributes to apply to the section element.
|
|
92
|
+
|
|
93
|
+
Note: Some block types are only allowed in certain layouts (see allowed_blocks_per_layout).
|
|
94
|
+
Unsupported blocks for a layout will silently be skipped.
|
|
95
|
+
-#}
|
|
96
|
+
{%- macro vf_tab_section(
|
|
97
|
+
title={},
|
|
98
|
+
description={},
|
|
99
|
+
cta={},
|
|
100
|
+
layout="50-50",
|
|
101
|
+
padding="default",
|
|
102
|
+
top_rule_variant="default",
|
|
103
|
+
tabs=[],
|
|
104
|
+
attrs={}
|
|
105
|
+
) -%}
|
|
106
|
+
{#- Marshall values from parameters into variables, apply safe defaults, and trim contents -#}
|
|
107
|
+
{%- set title_text = title.get("text", "") | trim -%}
|
|
108
|
+
{%- set title_link_attrs = title.get("link_attrs", {}) -%}
|
|
109
|
+
{%- set title_heading_level = title.get("heading_level", 2) -%}
|
|
110
|
+
{%- set padding = padding | trim -%}
|
|
111
|
+
|
|
112
|
+
{#- Store the existence of optional content -#}
|
|
113
|
+
{%- set title_is_link = title_link_attrs.items() | length > 0 -%}
|
|
114
|
+
{%- set has_description = description.get("content", "") | trim | length > 0 -%}
|
|
115
|
+
{%- set has_cta = cta.get("primary") or cta.get("secondaries") or cta.get("link") -%}
|
|
116
|
+
|
|
117
|
+
{#- Input validation -#}
|
|
118
|
+
{%- if title_heading_level not in [2, 3, 4] -%}
|
|
119
|
+
{%- set title_heading_level = 2 -%}
|
|
120
|
+
{%- endif -%}
|
|
121
|
+
|
|
122
|
+
{%- if padding not in ["deep", "shallow", "default"] -%}
|
|
123
|
+
{%- set padding = "default" -%}
|
|
124
|
+
{%- endif -%}
|
|
125
|
+
|
|
126
|
+
{%- set padding_classes = "p-section--" + padding -%}
|
|
127
|
+
{%- if padding == "default" -%}
|
|
128
|
+
{%- set padding_classes = "p-section" -%}
|
|
129
|
+
{%- endif -%}
|
|
130
|
+
|
|
131
|
+
{%- if layout not in ["50-50", "25-75", "full-width"] -%}
|
|
132
|
+
{%- set layout = "full-width" -%}
|
|
133
|
+
{%- endif -%}
|
|
134
|
+
|
|
135
|
+
{%- if layout == "full-width" -%}
|
|
136
|
+
{%- set tabs_column_count = 8 -%}
|
|
137
|
+
{%- elif layout == "50-50" -%}
|
|
138
|
+
{%- set tabs_column_count = 4 -%}
|
|
139
|
+
{%- elif layout == "25-75" -%}
|
|
140
|
+
{%- set tabs_column_count = 6 -%}
|
|
141
|
+
{%- endif -%}
|
|
142
|
+
|
|
143
|
+
{%- set tabs_column_start = 8 - tabs_column_count + 1 -%}
|
|
144
|
+
{%- set title_row_has_two_columns = has_description or has_cta or (layout == "50-50") -%}
|
|
145
|
+
{%- set tabs_in_title_row = not has_description and not has_cta and layout == "50-50" -%}
|
|
146
|
+
|
|
147
|
+
{#- Configuration: which block types are allowed per layout.
|
|
148
|
+
If a layout key is present, only those block types will be rendered
|
|
149
|
+
for that layout. If a layout is not present in the mapping, all
|
|
150
|
+
block types are permitted. This provides an easy place to control
|
|
151
|
+
designer constraints (e.g. quote only allowed in full-width).
|
|
152
|
+
-#}
|
|
153
|
+
{%- set allowed_blocks_per_layout = {
|
|
154
|
+
'50-50': [ 'linked-logo', 'logo-block', 'divided-section', 'blog', 'basic-section' ],
|
|
155
|
+
'25-75': [ 'linked-logo', 'logo-block', 'blog' ],
|
|
156
|
+
'full-width': [ 'quote', 'linked-logo', 'logo-block', 'blog' ]
|
|
157
|
+
} -%}
|
|
158
|
+
|
|
159
|
+
{#- Build a list of rendered tabs for the `vf_tabs` helper -#}
|
|
160
|
+
{%- set ns = namespace(rendered_tabs=[]) -%}
|
|
161
|
+
{%- for tab in tabs -%}
|
|
162
|
+
{%- set type = tab.get('type', '') | trim -%}
|
|
163
|
+
|
|
164
|
+
{#- Enforce allowed blocks per layout if configured - replace `continue` (unsupported) with a render flag -#}
|
|
165
|
+
{%- set render_tab = true -%}
|
|
166
|
+
{%- if layout in allowed_blocks_per_layout -%}
|
|
167
|
+
{%- set allowed = allowed_blocks_per_layout[layout] -%}
|
|
168
|
+
{%- if not (type in allowed) -%}
|
|
169
|
+
{%- set render_tab = false -%}
|
|
170
|
+
{%- endif -%}
|
|
171
|
+
{%- endif -%}
|
|
172
|
+
|
|
173
|
+
{%- if render_tab -%}
|
|
174
|
+
{#-
|
|
175
|
+
Prepend the section title text to the name.
|
|
176
|
+
This helps ensure uniqueness of tab section tab names across an entire page,
|
|
177
|
+
in case multiple tab sections are used in a single page.
|
|
178
|
+
The user still needs to ensure that the page's section titles are unique.
|
|
179
|
+
-#}
|
|
180
|
+
{%- set name = title_text | trim | lower | replace(' ', '_') -%}
|
|
181
|
+
{%- set content_html = _tab_section_tab(tab=tab) -%}
|
|
182
|
+
{%- set ns.rendered_tabs = ns.rendered_tabs + [ { 'name': name, 'tab_html': tab.get('tab_html', ''), 'content_html': content_html } ] -%}
|
|
183
|
+
{%- endif -%}
|
|
184
|
+
{%- endfor -%}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
<section
|
|
188
|
+
class="{{ padding_classes }} {{ attrs.get("class", "") }}"
|
|
189
|
+
{%- for attr, value in attrs.items() -%}
|
|
190
|
+
{% if attr != "class" %}
|
|
191
|
+
{{ attr }}="{{ value }}"
|
|
192
|
+
{%- endif -%}
|
|
193
|
+
{%- endfor -%}
|
|
194
|
+
>
|
|
195
|
+
{% if not tabs_in_title_row %}
|
|
196
|
+
<div class="p-section--shallow">
|
|
197
|
+
{% endif %}
|
|
198
|
+
<div class="grid-row{% if title_row_has_two_columns %}--50-50-on-large{% endif %}">
|
|
199
|
+
{{ vf_section_top_rule(top_rule_variant) }}
|
|
200
|
+
<div class="grid-col">
|
|
201
|
+
{%- if title_is_link -%}
|
|
202
|
+
<a {% for attr, value in title_link_attrs.items() %} {{ attr }}="{{ value }}" {% endfor %}>
|
|
203
|
+
{%- endif -%}
|
|
204
|
+
<h{{ title_heading_level }}>
|
|
205
|
+
{{ title_text }}
|
|
206
|
+
</h{{ title_heading_level }}>
|
|
207
|
+
{%- if title_is_link -%}
|
|
208
|
+
</a>
|
|
209
|
+
{%- endif -%}
|
|
210
|
+
</div>
|
|
211
|
+
{%- if title_row_has_two_columns -%}
|
|
212
|
+
<div class="grid-col">
|
|
213
|
+
{{ vf_description_block(
|
|
214
|
+
type=description.get("type"),
|
|
215
|
+
content=description.get("content")
|
|
216
|
+
)}}
|
|
217
|
+
{{ vf_cta_block(
|
|
218
|
+
primary=cta.get("primary"),
|
|
219
|
+
secondaries=cta.get("secondaries"),
|
|
220
|
+
link=cta.get("link")
|
|
221
|
+
) }}
|
|
222
|
+
{#- On 50-50, if there is no description or CTA, the tabs live in the same row as the title. -#}
|
|
223
|
+
{% if tabs_in_title_row %}
|
|
224
|
+
{{ vf_tabs(list={ 'tabs': ns.rendered_tabs }) }}
|
|
225
|
+
{% endif %}
|
|
226
|
+
</div>
|
|
227
|
+
{%- endif -%}
|
|
228
|
+
</div>
|
|
229
|
+
{% if not tabs_in_title_row %}
|
|
230
|
+
</div>
|
|
231
|
+
<div class="grid-row">
|
|
232
|
+
<div class="grid-col-{{ tabs_column_count }} grid-col-start-large-{{ tabs_column_start }}">
|
|
233
|
+
{{ vf_tabs(list={ 'tabs': ns.rendered_tabs }) }}
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
{% endif %}
|
|
237
|
+
</section>
|
|
238
|
+
{%- endmacro -%}
|