vanilla-framework 4.30.0 → 4.32.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/README.md CHANGED
@@ -78,8 +78,8 @@ If you're looking to contribute to the Vanilla project itself, [start here](/CON
78
78
 
79
79
  Keep up to date with all new developments and upcoming changes with Vanilla.
80
80
 
81
- - Follow us on Twitter [@vanillaframewrk](https://twitter.com/vanillaframewrk)
82
81
  - Read our latest blog posts at [Ubuntu Blog](https://blog.ubuntu.com/topics/design)
82
+ - Stay in touch with us on [Matrix](https://matrix.to/#/#vanilla:ubuntu.com)
83
83
 
84
84
  Code licensed [LGPLv3](https://opensource.org/license/lgpl-3-0/) by [Canonical Ltd](http://www.canonical.com/)
85
85
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vanilla-framework",
3
- "version": "4.30.0",
3
+ "version": "4.32.0",
4
4
  "author": {
5
5
  "email": "webteam@canonical.com",
6
6
  "name": "Canonical Webteam"
@@ -0,0 +1,8 @@
1
+ @import 'settings';
2
+
3
+ @mixin vf-p-divided-section {
4
+ .p-divided__heading::before,
5
+ .p-divided__block .p-stepped-list__title:before {
6
+ font-weight: $font-weight-bold;
7
+ }
8
+ }
@@ -0,0 +1,39 @@
1
+ /*
2
+ @classreference
3
+ newsletter-signup:
4
+ Newsletter signup:
5
+ .p-newsletter-signup:
6
+ Main element of the newsletter signup component.
7
+ .p-newsletter-signup--25-75:
8
+ Modifier class for a 25-75 split layout.
9
+ .p-newsletter-signup--50-50:
10
+ Modifier class for a 50-50 split layout.
11
+ .p-newsletter-signup--2-col:
12
+ Modifier class for a 2 column layout.
13
+ Takes at most 2 columns on large and medium dimensions.
14
+ Takes full width on small dimensions.
15
+ .p-newsletter-signup--4-col:
16
+ Modifier class for a 4 column layout.
17
+ Takes at most 4 columns on large and medium dimensions.
18
+ Takes full width on small dimensions.
19
+ */
20
+
21
+ @import 'settings';
22
+
23
+ @mixin vf-p-newsletter-signup {
24
+ .p-newsletter-signup--2-col {
25
+ padding-bottom: 0;
26
+
27
+ @media (width < $breakpoint-small) {
28
+ padding-bottom: $spv--strip-regular * 0.5;
29
+ }
30
+ }
31
+
32
+ .p-newsletter-signup--4-col {
33
+ padding-bottom: 0;
34
+
35
+ @media (width < $breakpoint-large) {
36
+ padding-bottom: $spv--strip-regular * 0.5;
37
+ }
38
+ }
39
+ }
@@ -12,6 +12,7 @@
12
12
  @import 'patterns_code-snippet';
13
13
  @import 'patterns_contextual-menu';
14
14
  @import 'patterns_cta';
15
+ @import 'patterns_divided-section';
15
16
  @import 'patterns_divider';
16
17
  @import 'patterns_equal-height-row';
17
18
  @import 'patterns_form-help-text';
@@ -39,6 +40,7 @@
39
40
  @import 'patterns_notifications';
40
41
  @import 'patterns_pagination';
41
42
  @import 'patterns_pricing-block';
43
+ @import 'patterns_newsletter-signup';
42
44
  @import 'patterns_pull-quotes';
43
45
  @import 'patterns_rule';
44
46
  @import 'patterns_search-and-filter';
@@ -108,6 +110,7 @@
108
110
  @include vf-p-code-snippet;
109
111
  @include vf-p-contextual-menu;
110
112
  @include vf-p-cta-block;
113
+ @include vf-p-divided-section;
111
114
  @include vf-p-divider;
112
115
  @include vf-p-equal-height-row;
113
116
  @include vf-p-form-help-text;
@@ -133,6 +136,7 @@
133
136
  @include vf-p-muted-heading;
134
137
  @include vf-p-navigation;
135
138
  @include vf-p-navigation-reduced;
139
+ @include vf-p-newsletter-signup;
136
140
  @include vf-p-notification;
137
141
  @include vf-p-pagination;
138
142
  @include vf-p-pricing-block;
@@ -64,6 +64,23 @@
64
64
  </div>
65
65
  {% endmacro %}
66
66
 
67
+ # notification_config
68
+ # - type: "information" | "caution" | "negative" | "positive" (default is "information")
69
+ # - title: The title of notification. Plain text.
70
+ # - content: The content of the notification. Plain text.
71
+ {% macro _basic_section_notification(notification_config={}) %}
72
+ {%- set type = (notification_config.get("type", "information")) | trim | lower -%}
73
+ {%- if type not in ["information", "caution", "negative", "positive"] -%}
74
+ {%- set type = "information" -%}
75
+ {%- endif -%}
76
+ <div class="p-notification--{{ type }}">
77
+ <div class="p-notification__content">
78
+ <h5 class="p-notification__title">{{ notification_config.get("title", "") }}</h5>
79
+ <p class="p-notification__message">{{ notification_config.get("content", "") }}</p>
80
+ </div>
81
+ </div>
82
+ {% endmacro %}
83
+
67
84
  # list_config
68
85
  # - list_item_type: "bullet" | "tick" | "cross" | "number" | "" (default is "")
69
86
  # - list_items: A list of items to be displayed in the section.
@@ -234,9 +251,9 @@
234
251
  {% endmacro %}
235
252
 
236
253
  # item_config
237
- # - type: "description" | "image" | "video" | "list" | "code-block" | "logo-block" | "liked-logo-block" | "cta-block"
254
+ # - type: "description" | "image" | "video" | "list" | "code-block" | "logo-block" | "liked-logo-block" | "cta-block" | "notification"
238
255
  # - item: The configuration for the item, which varies based on the type.
239
- {% macro _basic_section_item(item_config={}) %}
256
+ {% macro basic_section_item(item_config={}) %}
240
257
  {%- set type = (item_config.get("type", "")) | trim -%}
241
258
 
242
259
  {%- if type == "description" -%}
@@ -255,9 +272,52 @@
255
272
  {{- _basic_section_linked_logo_block(item_config.get("item", {})) -}}
256
273
  {%- elif type == "cta-block" -%}
257
274
  {{- _basic_section_cta_block(item_config.get("item", {})) -}}
275
+ {%- elif type == "notification" -%}
276
+ {{- _basic_section_notification(item_config.get("item", {})) -}}
258
277
  {%- endif -%}
259
278
  {% endmacro %}
260
279
 
280
+ {% macro basic_section_title(title={}) %}
281
+ <h2>
282
+ {%- if "link_attrs" in title and "href" in title.get("link_attrs", {}) -%}
283
+ <a
284
+ {% for attr, value in title.get("link_attrs", {}).items() -%}
285
+ {{ attr }}="{{ value }}"
286
+ {%- endfor -%}
287
+ >{{- title.get("text", "") -}}</a>
288
+ {%- else -%}
289
+ {{- title.get("text", "") -}}
290
+ {%- endif -%}
291
+ </h2>
292
+ {%- endmacro -%}
293
+
294
+ {%- macro basic_section_top_rule(top_rule_variant="default") -%}
295
+ {%- set top_rule_variant = top_rule_variant | trim | lower -%}
296
+ {%- if top_rule_variant not in ["default", "muted", "highlighted", "none"] -%}
297
+ {%- set top_rule_variant = "default" -%}
298
+ {%- endif -%}
299
+
300
+ {%- if top_rule_variant != "none" -%}
301
+ {%- set top_rule_classes = "p-rule" -%}
302
+ {%- if top_rule_variant != "default" -%}
303
+ {#-
304
+ p-rule--highlighted doesn't exist (use p-rule--highlight instead), but p-rule--muted does.
305
+ We keep the external API here consistent ("-ed" suffix) for simplicity but need to handle this internally.
306
+ -#}
307
+ {%- if top_rule_variant == "highlighted" -%}
308
+ {%- set top_rule_classes = "p-rule--highlight" -%}
309
+ {%- else -%}
310
+ {#- Other cases: just append the top_rule_variant to the p-rule class. -#}
311
+ {%- set top_rule_classes = top_rule_classes + "--" + top_rule_variant -%}
312
+ {%- endif -%}
313
+ {%- endif -%}
314
+ {%- endif -%}
315
+
316
+ {%- if top_rule_variant != "none" -%}
317
+ <hr class="{{- top_rule_classes -}}"/>
318
+ {%- endif -%}
319
+ {%- endmacro -%}
320
+
261
321
  # Params
262
322
  # title: A dictionary with "text" and optional "link_attrs" (a dictionary of link attributes for the title).
263
323
  # subtitle: A dictionary with "text" (required) and optional "heading_level" (default is 4).
@@ -281,27 +341,6 @@
281
341
  {%- set padding = "default" -%}
282
342
  {%- endif -%}
283
343
 
284
- {%- set top_rule_variant = top_rule_variant | trim -%}
285
- {%- if top_rule_variant not in ["default", "muted", "highlighted", "none"] -%}
286
- {%- set top_rule_variant = "default" -%}
287
- {%- endif -%}
288
-
289
- {%- if top_rule_variant != "none" -%}
290
- {%- set top_rule_classes = "p-rule" -%}
291
- {%- if top_rule_variant != "default" -%}
292
- {#-
293
- p-rule--highlighted doesn't exist (use p-rule--highlight instead), but p-rule--muted does.
294
- We keep the external API here consistent ("-ed" suffix) for simplicity but need to handle this internally.
295
- -#}
296
- {%- if top_rule_variant == "highlighted" -%}
297
- {%- set top_rule_classes = "p-rule--highlight" -%}
298
- {%- else -%}
299
- {#- Other cases: just append the top_rule_variant to the p-rule class. -#}
300
- {%- set top_rule_classes = top_rule_classes + "--" + top_rule_variant -%}
301
- {%- endif -%}
302
- {%- endif -%}
303
- {%- endif -%}
304
-
305
344
  {%- set padding_classes = "p-section--" + padding -%}
306
345
  {%- if padding == "default" -%}
307
346
  {%- set padding_classes = "p-section" -%}
@@ -319,24 +358,12 @@
319
358
 
320
359
  <section class="{{ padding_classes }}">
321
360
  <div class="grid-row--50-50{%- if not is_split_on_medium -%}-on-large{%- endif -%}">
322
- {%- if top_rule_variant != "none" %}
323
- <hr class="{{- top_rule_classes -}}"/>
324
- {%- endif -%}
361
+ {{ basic_section_top_rule(top_rule_variant) }}
325
362
  <div class="grid-col">
326
363
  {%- if has_label -%}
327
364
  <h3 class="p-muted-heading u-no-padding--top u-no-margin--bottom">{{- label_text -}}</h3>
328
365
  {%- endif -%}
329
- <h2>
330
- {%- if "link_attrs" in title and "href" in title.get("link_attrs", {}) -%}
331
- <a
332
- {% for attr, value in title.get("link_attrs", {}).items() -%}
333
- {{ attr }}="{{ value }}"
334
- {%- endfor -%}
335
- >{{- title.get("text", "") -}}</a>
336
- {%- else -%}
337
- {{- title.get("text", "") -}}
338
- {%- endif -%}
339
- </h2>
366
+ {{ basic_section_title(title) }}
340
367
  </div>
341
368
  <div class="grid-col">
342
369
  {%- if has_subtitle -%}
@@ -358,7 +385,7 @@
358
385
  {%- set item_classes = "" -%}
359
386
  {%- endif -%}
360
387
  <div{%- if item_classes | length > 0 %} class="{{ item_classes }}"{%- endif -%}>
361
- {{- _basic_section_item(item) -}}
388
+ {{- basic_section_item(item) -}}
362
389
  </div>
363
390
  {%- endfor -%}
364
391
  </div>
@@ -0,0 +1,77 @@
1
+ # Params
2
+ # - title: A dictionary with "text" and optional "link_attrs" (a dictionary of link attributes for the title).
3
+ # - padding: Type of padding to apply to the pattern - "deep", "shallow", "default" (default is "default").
4
+ # - is_split_on_medium: Boolean to indicate if the section should be split on medium screens (default is false).
5
+ # - top_rule_variant: Type of HR to render at the top of the pattern. "default" | "muted" (default is "default").
6
+ {% from "_macros/vf_basic-section.jinja" import basic_section_item, basic_section_title, basic_section_top_rule %}
7
+ {% macro _get_item_padding_classes(item_config={}, isLastLoopItr=False, isLastBlockItr=False) %}
8
+ {%- set item_padding = (item_config.get("padding", "")) | trim -%}
9
+ {%- if item_padding not in ["shallow"] -%}
10
+ {%- set item_padding = "" -%}
11
+ {%- endif -%}
12
+ {%- set item_classes = "" -%}
13
+ {%- if item_padding | length > 0 -%}
14
+ {%- set item_classes = "p-section--" + item_padding -%}
15
+ {%- endif -%}
16
+ {#- Last item of the last block should not have any bottom padding, as per desgin requirement -#}
17
+ {%- if isLastLoopItr and isLastBlockItr -%}
18
+ {%- set item_classes = "" -%}
19
+ {%- endif -%}
20
+ {{ item_classes | trim }}
21
+ {% endmacro %}
22
+ {% macro vf_divided_section(title, blocks=[], padding="default", is_split_on_medium=False, top_rule_variant="default", caller=None) %}
23
+ {%- set padding = padding | trim -%}
24
+ {%- if padding not in ["deep", "shallow", "default"] -%}
25
+ {%- set padding = "default" -%}
26
+ {%- endif -%}
27
+ {%- set padding_classes = "p-section--" + padding -%}
28
+ {%- if padding == "default" -%}
29
+ {%- set padding_classes = "p-section" -%}
30
+ {%- endif -%}
31
+ <section class="{{ padding_classes }}">
32
+ <div class="grid-row--50-50{%- if not is_split_on_medium -%}-on-large{%- endif -%}">
33
+ {%- set description_block = blocks | selectattr("type", "equalto", "description-block") | first -%}
34
+ {%- set divided_blocks = blocks | selectattr("type", "equalto", "divided-block") | list -%}
35
+ {{ basic_section_top_rule(top_rule_variant) }}
36
+ <div class="grid-col">{{- basic_section_title(title) -}}</div>
37
+ <div class="grid-col">
38
+ {%- if description_block -%}
39
+ {%- for item in description_block.get("items",[]) -%}
40
+ {% set item_classes = _get_item_padding_classes(item, loop.last) %}
41
+ <div {%- if item_classes | trim | length > 0 %}
42
+ class="{{ item_classes }}"
43
+ {%- endif -%}>{{- basic_section_item(item) -}}</div>
44
+ {%- endfor -%}
45
+ {%- if divided_blocks | length > 0 -%}<hr class="p-rule--muted" />{%- endif %}
46
+ {%- endif -%}
47
+ {%- for block in divided_blocks -%}
48
+ {%- set outer_last = loop.last -%}
49
+ {%- set ns = namespace(list_element="ul", list_class="p-list") -%}
50
+ {%- if block.get("bullet_type") == "number" -%}
51
+ {%- set ns.list_element = "ol" -%}
52
+ {%- set ns.list_class = "p-stepped-list" -%}
53
+ {%- endif -%}
54
+ <{{ ns.list_element }} class="p-divided__block {{ ns.list_class }} u-no-padding">
55
+ {%- for item in block.get("items",[]) -%}
56
+ {%- set list_bullet_type = "has-bullet" if block.bullet_type == "bullet" else "is-ticked" if block.bullet_type == "status" -%}
57
+ <li class="p-divided__heading u-no-padding--bottom {{ list_bullet_type }}{% if ns.list_class == 'p-stepped-list' %} p-stepped-list__item{% else %} p-list__item{% endif %}">
58
+ <div class="{% if not loop.last %}p-section--shallow{% endif %}{% if ns.list_class == 'p-stepped-list' %} p-stepped-list__title{% endif %}">
59
+ {%- if item.title_text -%}
60
+ <h3 class="p-heading--5 u-no-padding">{{ item.title_text }}</h3>
61
+ {%- endif -%}
62
+ {%- for content in item.contents -%}
63
+ {%- set item_classes = _get_item_padding_classes(content, loop.last, outer_last) -%}
64
+ <div {%- if item_classes | trim | length > 0 %}
65
+ class="{{ item_classes }}"
66
+ {%- endif -%}>{{- basic_section_item(content) -}}</div>
67
+ {%- endfor -%}
68
+ </div>
69
+ </li>
70
+ {% if not loop.last %}<hr class="p-rule--muted" />{% endif %}
71
+ {%- endfor -%}
72
+ </ {{ ns.list_element }}>
73
+ {%- endfor -%}
74
+ </div>
75
+ </div>
76
+ </section>
77
+ {% endmacro %}
@@ -0,0 +1,160 @@
1
+ {#
2
+ All Params:
3
+ @param title_text: H2 title text
4
+ @param input_label: Label for the input field
5
+ @param checkbox_id: Name for the checkbox field, used for agreeing to something before submitting the form. This may vary based on the backend used to collect form responses.
6
+ @param checkbox_label: Label for the checkbox
7
+ @param layout: Layout variant for the section. Options are "50-50", "25-75", "2-col", and "4-col". Default is "25-75".
8
+ @param form_id: Form ID
9
+ @param form_action: Action URL for the form submission, typically the form endpoint.
10
+ @param return_url: URL to return to after form submission
11
+ @param top_rule_variant (string) (optional): Variant of the top rule, default is "default". Options are "muted", "highlighted", "default", "none".
12
+
13
+ All Slots:
14
+ @slot description: Description text, one or more paragraphs
15
+ @slot addendum: Additional content to include in the form, such as a disclaimer or additional information
16
+ @slot hidden_fields: Additional hidden fields to include in the form
17
+ #}
18
+ {%- macro vf_newsletter_signup(form_id, return_url, title_text, form_action="https://ubuntu.com/marketo/submit", input_label="Work email", checkbox_id="canonicalUpdatesOptIn", checkbox_label="I agree to receive information about Canonical's products and services.", layout="25-75", top_rule_variant="default", caller=None) -%}
19
+ {% set layout = layout | trim %}
20
+ {% if layout not in ['50-50', '25-75', '2-col', '4-col'] %}
21
+ {% set layout = "25-75" %}
22
+ {% endif %}
23
+ {% set top_rule_variant = top_rule_variant | trim %}
24
+ {% if top_rule_variant not in ['muted', 'highlighted', 'default', 'none'] %}
25
+ {% set top_rule_variant = "default" %}
26
+ {% endif %}
27
+ {% set description = caller('description') %}
28
+ {% set addendum = caller('addendum') %}
29
+ {% set hidden_fields = caller('hidden_fields') %}
30
+ {% set is_section_level = layout in ['50-50', '25-75'] %}
31
+ {% set is_grid_level = layout in ['2-col', '4-col'] %}
32
+ {% set heading_level = 'h2' if is_section_level else 'h3' %}
33
+ {%- macro _top_rule() -%}
34
+ {% if top_rule_variant != 'none' %}
35
+ {% set rule_class = 'muted' if top_rule_variant == 'muted' else 'highlight' if top_rule_variant == 'highlighted' %}
36
+ <hr class="p-rule{% if top_rule_variant != 'default' %}--{{ rule_class }}{% endif %} is-fixed-width" />
37
+ {% endif %}
38
+ {%- endmacro -%}
39
+ {%- if is_section_level -%}
40
+ <section class="p-section">
41
+ {%- endif -%}
42
+ {{ _top_rule() | safe }}
43
+ <div class="grid-row--{% if is_section_level %}{{ layout }}-on-large{% else %}25-25-25-25{% endif %}">
44
+ {% if is_grid_level %}
45
+ {%- set upper_limit = 4 if layout == '2-col' else 3 -%}
46
+ {%- for number in range(1, upper_limit) -%}
47
+ {%- set col_content = caller('col_' + number|string) -%}
48
+ <div class="grid-col">{{ col_content | safe }}</div>
49
+ {%- endfor -%}
50
+ {% endif %}
51
+ <div class="grid-col{% if layout == '4-col' %}-4{% endif %} {% if is_grid_level %}p-newsletter-signup--{{ layout }}{% endif %}">
52
+ {%- if is_grid_level -%}
53
+ <hr class="p-rule--muted u-hide--large {% if layout == '2-col' %}u-hide--medium{% endif %}" />
54
+ {%- endif -%}
55
+ <{{ heading_level }}>{{ title_text }}</{{ heading_level }}>
56
+ {% if is_section_level %}</div>{% endif %}
57
+ {% if is_section_level %}<div class="grid-col">{% endif %}
58
+ {{ description | safe }}
59
+ <form action="{{ form_action }}" method="post" id="{{ form_id }}">
60
+ <label class="is-required" for="email">{{ input_label }}:</label>
61
+ <input required
62
+ id="email"
63
+ name="email"
64
+ maxlength="255"
65
+ type="email"
66
+ pattern="^[^ ]+@[^ ]+\.[a-z]{2,26}$"
67
+ required="required" />
68
+ <label class="p-checkbox is-required">
69
+ <input required
70
+ class="p-checkbox__input"
71
+ value="yes"
72
+ aria-labelledby="{{ checkbox_id }}"
73
+ name="{{ checkbox_id }}"
74
+ type="checkbox" />
75
+ <span class="p-checkbox__label" id="{{ checkbox_id }}">{{ checkbox_label }}</span>
76
+ </label>
77
+ {% if addendum %}
78
+ {{ addendum | safe }}
79
+ {% else %}
80
+ <p>
81
+ By submitting this form, I confirm that I have read and agree to <a href="https://ubuntu.com/legal/terms-and-policies/privacy-policy">Canonical's Privacy Policy</a>.
82
+ </p>
83
+ {% endif %}
84
+ <button type="submit" class="u-no-margin--bottom">Sign up</button>
85
+ {% if hidden_fields %}
86
+ {{ hidden_fields | safe }}
87
+ {% else %}
88
+ <input type="hidden"
89
+ aria-hidden="true"
90
+ aria-label="hidden field"
91
+ name="returnURL"
92
+ value="{{ return_url }}" />
93
+ <input type="hidden"
94
+ aria-hidden="true"
95
+ aria-label="hidden field"
96
+ name="formid"
97
+ value="{{ form_id }}" />
98
+ <input type="hidden"
99
+ aria-hidden="true"
100
+ aria-label="hidden field"
101
+ name="productContext"
102
+ id="product-context"
103
+ value="" />
104
+ <input type="hidden"
105
+ aria-hidden="true"
106
+ aria-label="hidden field"
107
+ name="utm_campaign"
108
+ id="utm_campaign"
109
+ value="" />
110
+ <input type="hidden"
111
+ aria-hidden="true"
112
+ aria-label="hidden field"
113
+ name="utm_medium"
114
+ id="utm_medium"
115
+ value="" />
116
+ <input type="hidden"
117
+ aria-hidden="true"
118
+ aria-label="hidden field"
119
+ name="utm_source"
120
+ id="utm_source"
121
+ value="" />
122
+ <input type="hidden"
123
+ aria-hidden="true"
124
+ aria-label="hidden field"
125
+ name="utm_content"
126
+ id="utm_content"
127
+ value="" />
128
+ <input type="hidden"
129
+ aria-hidden="true"
130
+ aria-label="hidden field"
131
+ name="utm_term"
132
+ id="utm_term"
133
+ value="" />
134
+ <input type="hidden"
135
+ aria-hidden="true"
136
+ aria-label="hidden field"
137
+ name="GCLID__c"
138
+ id="GCLID__c"
139
+ value="" />
140
+ <input type="hidden"
141
+ aria-hidden="true"
142
+ aria-label="hidden field"
143
+ name="Facebook_Click_ID__c"
144
+ id="Facebook_Click_ID__c"
145
+ value="" />
146
+ <input type="hidden"
147
+ aria-hidden="true"
148
+ aria-label="hidden field"
149
+ id="preferredLanguage"
150
+ name="preferredLanguage"
151
+ maxlength="255"
152
+ value="" />
153
+ {% endif %}
154
+ </form>
155
+ </div>
156
+ </div>
157
+ {%- if is_section_level -%}
158
+ </section>
159
+ {%- endif -%}
160
+ {%- endmacro -%}
@@ -3,9 +3,14 @@
3
3
  @param title_text: H2 title text
4
4
  @param list_items (Array<string>)
5
5
  An array of HTML strings to be rendered
6
+ @param item_heading_level: Level of the heading to use, defaults to 2. Can be 2, or 4.
6
7
  #}
7
- {%- macro vf_text_spotlight(title_text, list_items=[], caller=None) -%}
8
+ {%- macro vf_text_spotlight(title_text, item_heading_level=2, list_items=[], caller=None) -%}
8
9
  {% set has_list = list_items | length >= 2 and list_items | length <= 7 %}
10
+ {% set item_heading_level = item_heading_level | trim %}
11
+ {%- if item_heading_level not in [2, 4] -%}
12
+ {%- set item_heading_level = 2 -%}
13
+ {%- endif -%}
9
14
  <section class="p-section">
10
15
  <hr class="p-rule is-fixed-width" />
11
16
  <div class="grid-row--25-75-on-large">
@@ -15,7 +20,7 @@
15
20
  <div class="grid-col">
16
21
  {%- if has_list -%}
17
22
  {%- for list_item in list_items -%}
18
- <p class="p-heading--2">{{- list_item -}}</p>
23
+ <p class="p-heading--{{ item_heading_level }}">{{- list_item -}}</p>
19
24
  {%- if not loop.last %}<hr class="p-rule--muted" />{%- endif %}
20
25
  {%- endfor -%}
21
26
  {%- else -%}