vanilla-framework 4.17.1 → 4.18.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vanilla-framework",
3
- "version": "4.17.1",
3
+ "version": "4.18.1",
4
4
  "author": {
5
5
  "email": "webteam@canonical.com",
6
6
  "name": "Canonical Webteam"
@@ -98,6 +98,21 @@
98
98
  margin-right: -$sph--small;
99
99
  }
100
100
  }
101
+
102
+ &.is-small {
103
+ & [class*='p-icon'] {
104
+ margin-left: $sph--x-small;
105
+ margin-right: $sph--x-small;
106
+
107
+ &:first-child {
108
+ margin-left: -$sph--x-small;
109
+ }
110
+
111
+ &:last-child {
112
+ margin-right: -$sph--x-small;
113
+ }
114
+ }
115
+ }
101
116
  }
102
117
  }
103
118
 
@@ -15,8 +15,10 @@
15
15
  // stylelint-enable property-no-vendor-prefix
16
16
  background-color: $color-transparent;
17
17
  border-radius: $track-radius;
18
- margin: $sp-small 0;
18
+ height: $track-height;
19
+ margin: ($spv--small - $track-height * 0.5) 0;
19
20
  padding: 0;
21
+ vertical-align: bottom;
20
22
  width: 100%;
21
23
 
22
24
  // Chrome
@@ -25,6 +25,7 @@
25
25
  border: 0 solid transparent;
26
26
  border-bottom: $input-border-thickness solid $colors--theme--border-high-contrast;
27
27
  border-radius: 0;
28
+ border-top: $input-border-thickness solid transparent;
28
29
  color: $colors--theme--text-default;
29
30
  font-family: unquote($font-base-family);
30
31
  font-size: 1rem;
@@ -62,7 +63,8 @@
62
63
  color: $colors--theme--text-muted;
63
64
  }
64
65
 
65
- &.is-dense {
66
+ &.is-dense,
67
+ .p-form-validation__select-wrapper.is-dense & {
66
68
  margin: 0 0 $spv-nudge-compensation 0;
67
69
  padding-bottom: calc($spv-nudge - $spv--x-small - $input-border-thickness);
68
70
  padding-top: calc($spv-nudge - $spv--x-small - $input-border-thickness);
@@ -29,6 +29,7 @@
29
29
  }
30
30
  }
31
31
 
32
+ // Deprecated, use new 4/4/8 grid %vf-grid-row instead
32
33
  %vf-row {
33
34
  @extend %fixed-width-container;
34
35
 
@@ -70,6 +71,47 @@
70
71
  }
71
72
  }
72
73
 
74
+ %vf-grid-row {
75
+ @extend %fixed-width-container;
76
+
77
+ @supports (display: grid) {
78
+ display: grid;
79
+ grid-gap: 0 map-get($grid-gutter-widths, small);
80
+ grid-template-columns: repeat($grid-8-columns-small, minmax(0, 1fr));
81
+ grid-template-rows: auto;
82
+ margin-left: auto;
83
+ margin-right: auto;
84
+ max-width: $grid-max-width;
85
+
86
+ & > * {
87
+ grid-column-end: span $grid-8-columns-small;
88
+ }
89
+
90
+ [class*='#{$grid-8-column-prefix}'] {
91
+ grid-column-start: auto;
92
+ }
93
+
94
+ // set static gutter width per breakpoint
95
+ @media (min-width: $threshold-4-6-col) {
96
+ grid-gap: 0 map-get($grid-gutter-widths, default);
97
+ grid-template-columns: repeat($grid-8-columns-medium, minmax(0, 1fr));
98
+
99
+ & > * {
100
+ grid-column-end: span $grid-8-columns-medium;
101
+ }
102
+ }
103
+
104
+ @media (min-width: $threshold-6-12-col) {
105
+ grid-gap: 0 map-get($grid-gutter-widths, default);
106
+ grid-template-columns: repeat($grid-8-columns, minmax(0, 1fr));
107
+
108
+ & > * {
109
+ grid-column-end: span $grid-8-columns;
110
+ }
111
+ }
112
+ }
113
+ }
114
+
73
115
  %vf-grid-container-padding {
74
116
  // set static outside padding per breakpoint
75
117
  padding-left: map-get($grid-margin-widths, small);
@@ -17,6 +17,7 @@
17
17
  }
18
18
 
19
19
  .row &,
20
+ .grid-row &,
20
21
  .u-fixed-width & {
21
22
  width: 100%;
22
23
  }
@@ -863,7 +863,7 @@
863
863
 
864
864
  // arrow-bottom-left
865
865
  @function vf-icon-arrow-bottom-left-url($color) {
866
- @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' fill='#{vf-url-friendly-color($color)}' d='M5.6 11.4h5.3v1.5H3V5.1h1.5v5.3l7.9-7.9 1.1 1.1-7.9 7.9Z'/%3E%3C/svg%3E");
866
+ @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3E%3Cpath fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd' d='M5.594 11.431h5.284v1.5H3.033V5.086h1.5v5.285l7.905-7.904 1.06 1.06z' clip-rule='evenodd'/%3E%3C/svg%3E");
867
867
  }
868
868
 
869
869
  @mixin vf-icon-arrow-bottom-left($color: $colors--light-theme--icon) {
@@ -876,7 +876,7 @@
876
876
 
877
877
  // arrow-bottom-right
878
878
  @function vf-icon-arrow-bottom-right-url($color) {
879
- @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' fill='#{vf-url-friendly-color($color)}' d='M10.4 11.5H5.1V13h7.8V5.2h-1.5v5.3l-7.8-8-1.1 1.1z'/%3E%3C/svg%3E");
879
+ @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3E%3Cpath fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd' d='M10.406 11.503H5.122v1.5h7.845V5.158h-1.5v5.285L3.563 2.538 2.503 3.6z' clip-rule='evenodd'/%3E%3C/svg%3E");
880
880
  }
881
881
 
882
882
  @mixin vf-icon-arrow-bottom-right($color: $colors--light-theme--icon) {
@@ -889,7 +889,7 @@
889
889
 
890
890
  // arrow-down
891
891
  @function vf-icon-arrow-down-url($color) {
892
- @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3E%3Cpath fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd' d='M7.25 12.117 3.514 8.381l-1.06 1.06L7.47 14.46l.53.53.53-.53 5.018-5.017-1.061-1.06-3.737 3.736V.94h-1.5z' clip-rule='evenodd'/%3E%3C/svg%3E");
892
+ @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3E%3Cpath fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd' d='M7.25 12.117 3.514 8.381l-1.06 1.06L8 14.99l5.548-5.547-1.061-1.06-3.737 3.736V.94h-1.5z' clip-rule='evenodd'/%3E%3C/svg%3E");
893
893
  }
894
894
 
895
895
  @mixin vf-icon-arrow-down($color: $colors--light-theme--icon) {
@@ -902,7 +902,7 @@
902
902
 
903
903
  // arrow-left
904
904
  @function vf-icon-arrow-left-url($color) {
905
- @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3E%3Cpath fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd' d='m3.847 8.714 3.737 3.737-1.061 1.06-5.017-5.017-.53-.53.53-.53 5.017-5.017 1.06 1.06-3.736 3.737h11.178v1.5z' clip-rule='evenodd'/%3E%3C/svg%3E");
905
+ @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3E%3Cpath fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd' d='m3.847 8.714 3.736 3.737-1.06 1.06L.976 7.964l5.547-5.547 1.06 1.06-3.736 3.737h11.178v1.5z' clip-rule='evenodd'/%3E%3C/svg%3E");
906
906
  }
907
907
 
908
908
  @mixin vf-icon-arrow-left($color: $colors--light-theme--icon) {
@@ -915,7 +915,7 @@
915
915
 
916
916
  // arrow-right
917
917
  @function vf-icon-arrow-right-url($color) {
918
- @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3E%3Cpath fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd' d='m12.154 8.714-3.737 3.737 1.06 1.06 5.018-5.017.53-.53-.53-.53-5.017-5.017-1.06 1.06 3.736 3.737H.976v1.5z' clip-rule='evenodd'/%3E%3C/svg%3E");
918
+ @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3E%3Cpath fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd' d='m12.154 8.714-3.737 3.737 1.06 1.06 5.548-5.547-5.547-5.547-1.06 1.06 3.736 3.737H.976v1.5z' clip-rule='evenodd'/%3E%3C/svg%3E");
919
919
  }
920
920
 
921
921
  @mixin vf-icon-arrow-right($color: $colors--light-theme--icon) {
@@ -928,7 +928,7 @@
928
928
 
929
929
  // arrow-top-left
930
930
  @function vf-icon-arrow-top-left-url($color) {
931
- @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' fill='#{vf-url-friendly-color($color)}' d='M5.6 4.5h5.3V3H3v7.8h1.5V5.5l7.9 7.9 1.1-1.1-7.9-7.9Z'/%3E%3C/svg%3E");
931
+ @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3E%3Cpath fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd' d='M5.594 4.497h5.284v-1.5H3.033v7.845h1.5V5.557l7.905 7.904 1.06-1.06z' clip-rule='evenodd'/%3E%3C/svg%3E");
932
932
  }
933
933
 
934
934
  @mixin vf-icon-arrow-top-left($color: $colors--light-theme--icon) {
@@ -941,7 +941,7 @@
941
941
 
942
942
  // arrow-top-right
943
943
  @function vf-icon-arrow-top-right-url($color) {
944
- @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' fill='#{vf-url-friendly-color($color)}' d='M10.4 4.5H5.1V3h7.8v7.8h-1.5V5.5l-7.9 7.9-1.1-1.1 7.9-7.9Z'/%3Eą%3C/svg%3E");
944
+ @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3E%3Cpath fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd' d='M10.406 4.497H5.122v-1.5h7.845v7.845h-1.5V5.557l-7.904 7.904-1.06-1.06z' clip-rule='evenodd'/%3E%3C/svg%3E");
945
945
  }
946
946
 
947
947
  @mixin vf-icon-arrow-top-right($color: $colors--light-theme--icon) {
@@ -954,7 +954,7 @@
954
954
 
955
955
  // arrow-up
956
956
  @function vf-icon-arrow-up-url($color) {
957
- @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3E%3Cpath fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd' d='M7.25 3.811 3.514 7.547l-1.06-1.06L7.47 1.47 8 .94l.53.53 5.018 5.017-1.061 1.06L8.75 3.811v11.178h-1.5z' clip-rule='evenodd'/%3E%3C/svg%3E");
957
+ @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3E%3Cpath fill='#{vf-url-friendly-color($color)}' fill-rule='evenodd' d='M7.25 3.811 3.514 7.547l-1.06-1.06L8 .94l5.548 5.547-1.061 1.06L8.75 3.811v11.178h-1.5z' clip-rule='evenodd'/%3E%3C/svg%3E");
958
958
  }
959
959
 
960
960
  @mixin vf-icon-arrow-up($color: $colors--light-theme--icon) {
@@ -1006,7 +1006,7 @@
1006
1006
 
1007
1007
  // certification
1008
1008
  @function vf-icon-certification-url($color) {
1009
- @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' fill='#{vf-url-friendly-color($color)}' d='m10.7 1.1.3.5c.2.3.5.5.8.6h.5c.6.3 1.1.9 1 1.6v.6c0 .4 0 .7.3 1l.3.4c.4.5.4 1.2 0 1.7l-.3.4c-.2.3-.3.6-.3 1v.6c0 .7-.4 1.2-1 1.4h-.5c-.3.2-.6.4-.8.6v4l-3-1.6-3 1.6v-3.9c-.2-.3-.5-.5-.8-.6h-.5c-.6-.3-1.1-.9-1-1.6v-.6c0-.4 0-.7-.3-1l-.3-.4c-.4-.5-.4-1.2 0-1.7l.3-.4c.2-.3.3-.6.3-1v-.6c0-.7.4-1.2 1-1.4h.5c.3-.2.6-.5.8-.8l.3-.5C5.7.5 6.3.2 7 .5l.5.2c.3.1.7.1 1 0L9 .5c.6-.2 1.3 0 1.7.5ZM9.5 2l-.4.2c-.6.2-1.3.2-1.9 0H7L6.5 2l-.3.4q-.6.75-1.5 1.2h-.2l-.5.2v.5c0 .6-.1 1.3-.5 1.8v.2c-.1 0-.4.4-.4.4l.3.4q.6.75.6 1.8v.7h.5c.6.3 1.2.7 1.6 1.2v.2c.1 0 .4.4.4.4l.5-.2c.6-.2 1.3-.2 1.9 0h.2l.4.2.3-.4q.6-.75 1.5-1.2h.2l.5-.2v-.5c0-.6.1-1.3.5-1.8v-.2c.1 0 .4-.4.4-.4l-.3-.4q-.6-.75-.6-1.8v-.7h-.5c-.6-.3-1.2-.7-1.6-1.2v-.2c-.1 0-.4-.4-.4-.4'/%3E%3Cpath d='m7.8 7.6 1.8-2.7-2.2 3.4L6 7.2l.7.6.7.5z'/%3E%3Cpath fill='#{vf-url-friendly-color($color)}' d='m7.5 9.4-2-1.7 1-1.1.7.6L9 4.5l1.2.9z'/%3E%3C/svg%3E");
1009
+ @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xml:space='preserve' width='16' height='16' fill='none'%3E%3Cpath fill='#{vf-url-friendly-color($color)}' d='M6.488.475a1.4 1.4 0 0 0-1.193.627l-.307.462c-.199.3-.5.519-.847.616l-.536.15A1.404 1.404 0 0 0 2.58 3.742l.024.555c.015.36-.101.714-.325.996l-.343.436a1.4 1.4 0 0 0 0 1.744l.343.435c.224.282.34.637.325.996l-.024.555a1.404 1.404 0 0 0 1.025 1.412l.536.15c.346.097.648.316.847.616l.016.023v3.887l3-1.588 3 1.588v-3.899l.1-.134c.194-.237.458-.41.755-.493l.536-.15A1.404 1.404 0 0 0 13.42 9.46l-.024-.555c-.015-.36.101-.714.325-.996l.343-.435a1.4 1.4 0 0 0 0-1.744l-.343-.436a1.5 1.5 0 0 1-.325-.996l.024-.555a1.404 1.404 0 0 0-1.025-1.412l-.536-.15a1.5 1.5 0 0 1-.847-.616l-.307-.462a1.404 1.404 0 0 0-1.66-.54l-.522.194a1.5 1.5 0 0 1-1.046 0L6.955.563a1.4 1.4 0 0 0-.467-.088m.016 1.52.45.167.204.068a3 3 0 0 0 1.889-.068l.45-.168.265.4.127.176c.394.51.942.88 1.566 1.055l.463.129-.02.48-.002.215c.02.644.246 1.268.649 1.776l.297.375-.297.377-.127.173a3 3 0 0 0-.52 1.817l.02.478-.463.131-.205.065a3 3 0 0 0-1.488 1.166l-.266.398-.45-.166-.204-.068a3 3 0 0 0-1.889.068l-.45.166-.265-.398-.127-.176a3 3 0 0 0-1.566-1.055l-.465-.13.022-.48.002-.214a3 3 0 0 0-.649-1.775L3.156 6.6l.3-.375.128-.174a3 3 0 0 0 .518-1.817l-.022-.48.465-.129.205-.066a3 3 0 0 0 1.488-1.164ZM8.96 4.528 7.199 7.19l-.681-.59-.983 1.133.684.592 1.289 1.117.943-1.423 1.76-2.663Z'/%3E%3C/svg%3E");
1010
1010
  }
1011
1011
 
1012
1012
  @mixin vf-icon-certification($color: $colors--light-theme--icon) {
@@ -132,6 +132,17 @@
132
132
  }
133
133
 
134
134
  // Utilities
135
+ %u-off-screen {
136
+ &:not(:focus):not(:active) {
137
+ clip-path: inset(50%);
138
+ height: 1px;
139
+ overflow: hidden;
140
+ position: absolute;
141
+ white-space: nowrap;
142
+ width: 1px;
143
+ }
144
+ }
145
+
135
146
  %vf-hide-text {
136
147
  overflow: hidden;
137
148
  // vw value necessary because text indent in % does not work with padding;
@@ -69,6 +69,7 @@
69
69
  }
70
70
  }
71
71
 
72
+ // TODO implement new 4/4/8 grid (.grid-row)
72
73
  .row {
73
74
  max-width: 100%;
74
75
  padding-left: 0;
@@ -19,7 +19,7 @@
19
19
  }
20
20
 
21
21
  .l-full-width__sidebar {
22
- background: $color-light;
22
+ background: $colors--theme--background-alt;
23
23
 
24
24
  // height of top navigation, as padding applied to .p-navigation__link + line-heigh of the anchor text inside
25
25
  $navigation-top-height: $spv--large * 2 + map-get($line-heights, default-text);
@@ -65,6 +65,7 @@
65
65
  // grid should align to the left (no left margin)
66
66
  // TODO: ideally this should be applied to %fixed-width-container
67
67
  .row,
68
+ .grid-row,
68
69
  .u-fixed-width {
69
70
  margin-left: 0;
70
71
  }
@@ -84,6 +85,7 @@
84
85
 
85
86
  .l-main {
86
87
  .row,
88
+ .grid-row,
87
89
  .u-fixed-width {
88
90
  margin-left: auto;
89
91
  }
@@ -3,10 +3,10 @@
3
3
  @mixin vf-p-badge {
4
4
  %vf-badge {
5
5
  @extend %x-small-text;
6
- background-color: $colors--light-theme--text-default;
6
+ background-color: $colors--theme--text-default; // inverse the theme by using the text color
7
7
  border-radius: 1rem;
8
8
  box-sizing: content-box;
9
- color: $color-x-light;
9
+ color: $colors--theme--background-default; // inverse the theme by using the baackground color
10
10
  margin-bottom: 0;
11
11
  max-width: 4ch;
12
12
  overflow: hidden;
@@ -19,7 +19,8 @@
19
19
  }
20
20
 
21
21
  .p-badge--negative {
22
- background-color: $color-negative;
22
+ background-color: $colors--theme--button-negative-default;
23
+ color: $colors--theme--button-negative-text;
23
24
  }
24
25
 
25
26
  .p-chip,
@@ -25,6 +25,7 @@
25
25
  @mixin vf-p-equal-height-row {
26
26
  .p-equal-height-row,
27
27
  .p-equal-height-row--wrap {
28
+ // TODO use new 4/4/8 grid (`%vf-grid-row`)
28
29
  @extend %vf-row;
29
30
 
30
31
  position: relative;
@@ -139,6 +140,7 @@
139
140
  // ADVANCED GRID SUPPORT
140
141
 
141
142
  // Support for 25-75 split on large screen size
143
+ // TODO implement with new 4/4/8 grid (.grid-row)
142
144
  .row--25-75-on-large > .col,
143
145
  .row > .col-9 {
144
146
  & .p-equal-height-row,
@@ -7,6 +7,10 @@
7
7
  color: $colors--theme--text-muted;
8
8
  margin-top: -$sp-unit;
9
9
 
10
+ .is-dense + & {
11
+ margin-top: 0;
12
+ }
13
+
10
14
  &.is-tick-element {
11
15
  margin-left: $sph--large + $form-tick-box-size;
12
16
  }
@@ -15,6 +15,10 @@
15
15
  @extend %small-text;
16
16
  @extend %vf-validation-wrapper;
17
17
 
18
+ .is-dense + & {
19
+ margin-top: 0;
20
+ }
21
+
18
22
  margin-top: -$sp-unit;
19
23
  }
20
24
 
@@ -0,0 +1,167 @@
1
+ @import 'settings';
2
+
3
+ // CSS grid implementation of columns for all screens sizes
4
+ @mixin vf-grid-8-column($col) {
5
+ @supports (display: grid) {
6
+ grid-column-end: span #{$col};
7
+
8
+ //nesting
9
+ @if $col > 1 {
10
+ & .grid-row {
11
+ grid-template-columns: repeat($col, minmax(0, 1fr));
12
+ }
13
+ }
14
+ }
15
+ }
16
+
17
+ @mixin vf-grid-8-column-reordering($label, $col-count, $reset: false) {
18
+ @for $i from 1 through $col-count {
19
+ .grid-row [class*='#{$grid-8-column-prefix}'].#{$grid-8-column-prefix}start-#{$label}-#{$i} {
20
+ @if $reset {
21
+ grid-column-start: initial;
22
+ } @else {
23
+ grid-column-start: #{$i};
24
+ }
25
+ }
26
+
27
+ .#{$grid-8-column-prefix}order-#{$label}-#{$i} {
28
+ @if $reset {
29
+ order: initial;
30
+ } @else {
31
+ order: #{$i};
32
+ }
33
+ }
34
+ }
35
+ }
36
+
37
+ @mixin vf-p-grid-8 {
38
+ // FIXME: this should be removed from framework SCSS
39
+ // (see https://github.com/canonical/vanilla-framework/issues/3199)
40
+ .grid-demo .grid-col,
41
+ .grid-demo [class*='#{$grid-8-column-prefix}'] {
42
+ background: $colors--theme--background-negative-default;
43
+ margin-bottom: $spv--small;
44
+ }
45
+
46
+ .grid-row {
47
+ @extend %vf-grid-row;
48
+ }
49
+
50
+ // mobile grid
51
+
52
+ // by default medium and large screen col classes should span full width on mobile (to match block level element behaviour)
53
+ %grid-8-span-on-mobile {
54
+ grid-column: auto / span $grid-8-columns-small;
55
+ }
56
+
57
+ @for $i from 1 through $grid-8-columns-medium {
58
+ .#{$grid-8-medium-col-prefix}#{$i} {
59
+ @extend %grid-8-span-on-mobile;
60
+ @extend %display-block;
61
+ }
62
+ }
63
+
64
+ @for $i from 1 through $grid-8-columns {
65
+ .#{$grid-8-large-col-prefix}#{$i} {
66
+ @extend %grid-8-span-on-mobile;
67
+ @extend %display-block;
68
+ }
69
+ }
70
+
71
+ // col-small-X classes define grid for small screen
72
+ @for $i from $grid-8-columns-small through 1 {
73
+ .#{$grid-8-small-col-prefix}#{$i} {
74
+ @extend %display-block;
75
+ @include vf-grid-8-column($i);
76
+
77
+ width: 100%;
78
+ }
79
+ }
80
+
81
+ // tablet grid
82
+
83
+ // on medium/tablet screens, small and large grid class names span full width (to match block level element behaviour)
84
+ %grid-8-span-on-tablet {
85
+ @media (min-width: $threshold-4-6-col) {
86
+ grid-column: auto / span $grid-8-columns-medium;
87
+ }
88
+ }
89
+
90
+ @for $i from 1 through $grid-8-columns-small {
91
+ .#{$grid-8-small-col-prefix}#{$i} {
92
+ @extend %grid-8-span-on-tablet;
93
+ }
94
+ }
95
+
96
+ @for $i from 1 through $grid-8-columns {
97
+ .#{$grid-8-large-col-prefix}#{$i} {
98
+ @extend %grid-8-span-on-tablet;
99
+ }
100
+ }
101
+
102
+ // col-medium-X classes define grid for medium screens
103
+ @media (min-width: $threshold-4-6-col) {
104
+ @for $i from $grid-8-columns-medium through 1 {
105
+ .#{$grid-8-medium-col-prefix}#{$i} {
106
+ @include vf-grid-8-column($i);
107
+
108
+ width: 100%;
109
+ }
110
+ }
111
+ }
112
+
113
+ // desktop grid
114
+
115
+ // on desktop screens small and medium grid class names span full width (to match block level element behaviour)
116
+ %grid-8-span-on-desktop {
117
+ @media (min-width: $threshold-6-12-col) {
118
+ grid-column: auto / span $grid-8-columns;
119
+ }
120
+ }
121
+
122
+ @for $i from 1 through $grid-8-columns-small {
123
+ .#{$grid-8-small-col-prefix}#{$i} {
124
+ @extend %grid-8-span-on-desktop;
125
+ }
126
+ }
127
+
128
+ @for $i from 1 through $grid-8-columns-medium {
129
+ .#{$grid-8-medium-col-prefix}#{$i} {
130
+ @extend %grid-8-span-on-desktop;
131
+ }
132
+ }
133
+
134
+ // col-X class names define grid on large/desktop screens
135
+ @media (min-width: $threshold-6-12-col) {
136
+ @for $i from $grid-8-columns through 1 {
137
+ // set col-* to span respective number of columns on desktop
138
+ .#{$grid-8-large-col-prefix}#{$i} {
139
+ // on smaller screens let them display full width one under another
140
+ @include vf-grid-8-column($i);
141
+ }
142
+ }
143
+ }
144
+
145
+ // column reordering
146
+ $offsets: (
147
+ (small, 0, $threshold-4-6-col, $grid-8-columns-small),
148
+ (medium, $threshold-4-6-col, $threshold-6-12-col, $grid-8-columns-medium),
149
+ (large, $threshold-6-12-col, false, $grid-8-columns)
150
+ );
151
+
152
+ @each $label, $breakpoint-min, $breakpoint-reset, $col-count in $offsets {
153
+ @if $breakpoint-min == 0 {
154
+ @include vf-grid-8-column-reordering($label, $col-count);
155
+ } @else {
156
+ @media (min-width: #{$breakpoint-min}) {
157
+ @include vf-grid-8-column-reordering($label, $col-count);
158
+ }
159
+ }
160
+
161
+ @if $breakpoint-reset {
162
+ @media (min-width: #{$breakpoint-reset}) {
163
+ @include vf-grid-8-column-reordering($label, $col-count, $reset: true);
164
+ }
165
+ }
166
+ }
167
+ }
@@ -1,5 +1,6 @@
1
1
  @import 'settings';
2
2
 
3
+ // Deprecated, use new 4/4/8 grid instead.
3
4
  // CSS grid implementation of columns for all screens sizes
4
5
  @mixin vf-grid-column($col) {
5
6
  @supports (display: grid) {
@@ -192,6 +193,7 @@
192
193
  }
193
194
 
194
195
  // Common grid patterns
196
+ // TODO implement the common grid patterns for the new 4/4/8 grid (.grid-row--)
195
197
  $col-50-medium: calc($grid-columns-medium / 2);
196
198
 
197
199
  $col-25: calc($grid-columns / 4);
@@ -89,6 +89,10 @@
89
89
  vertical-align: 0;
90
90
  }
91
91
  }
92
+
93
+ p > [class*='p-icon'] {
94
+ vertical-align: middle;
95
+ }
92
96
  // stylelint-enable selector-max-type
93
97
  }
94
98
 
@@ -84,6 +84,11 @@ $aspect-ratios: (
84
84
  justify-content: center;
85
85
  text-align: center;
86
86
 
87
+ // If there is a child element that is not the image, don't let it affect the layout
88
+ & > *:not(.p-image-container__image) {
89
+ display: contents;
90
+ }
91
+
87
92
  &.is-highlighted {
88
93
  background: $colors--theme--background-alt;
89
94
  }
@@ -110,7 +115,7 @@ $aspect-ratios: (
110
115
  // Deprecated; will be removed in v5
111
116
  .p-image--bordered {
112
117
  border: {
113
- color: $color-mid-light;
118
+ color: $colors--theme--border-low-contrast;
114
119
  style: solid;
115
120
  width: 1px;
116
121
  }
@@ -118,6 +123,6 @@ $aspect-ratios: (
118
123
 
119
124
  // Deprecated; will be removed in v5
120
125
  .p-image--shadowed {
121
- box-shadow: 0 1px 5px 1px color.scale($color-mid-light, $alpha: -80%);
126
+ box-shadow: $box-shadow;
122
127
  }
123
128
  }
@@ -428,6 +428,7 @@ $list-step-bullet-margin: $sph--x-large;
428
428
 
429
429
  .p-stepped-list__item {
430
430
  @extend %numbered-step-item;
431
+ // TODO use new grid (`%vf-grid-row`)
431
432
  @extend %vf-row;
432
433
  @include vf-b-row-reset;
433
434
 
@@ -213,6 +213,7 @@ $navigation-height: calc(map-get($line-heights, default-text) + 2 * $spv--large)
213
213
  .p-navigation__row--25-75 {
214
214
  // ideally we'd like to extend row only on large screens,
215
215
  // but that's not possible to use @extend inside media query
216
+ // TODO implement with new 4/4/8 grid (`%vf-grid-row`)
216
217
  @extend %vf-row;
217
218
 
218
219
  // when mobile navigation is displayed, remove default row padding
@@ -788,6 +789,7 @@ $navigation-height: calc(map-get($line-heights, default-text) + 2 * $spv--large)
788
789
 
789
790
  // rows think they are nested (because they are inside of navigation row)
790
791
  // we need to reset them back to original state
792
+ // TODO add support for new 4/4/8 grid (.grid-row)
791
793
  .row,
792
794
  [class*='row--'] {
793
795
  @extend %fixed-width-container--common-properties;
@@ -18,15 +18,15 @@
18
18
 
19
19
  // When the search and filter is not expanded, but is overflowing with chips, we need to
20
20
  // specify a height that matches that of a standard input element. This height is a combination
21
- // of an input's line-height, its vertical padding, and a nudge.
22
- $input-height: calc(map-get($line-heights, default-text) + $input-vertical-padding + $spv-nudge - $input-border-thickness);
21
+ // of an input's line-height, its vertical padding, and the (top transparent) border.
22
+ $input-height: calc(map-get($line-heights, default-text) + $input-vertical-padding + $input-vertical-padding + $input-border-thickness);
23
23
 
24
24
  .p-search-and-filter {
25
25
  border-bottom: $input-border-thickness solid $colors--theme--border-high-contrast;
26
26
  position: relative;
27
27
 
28
28
  .p-search-and-filter__search-container {
29
- align-items: center;
29
+ align-items: flex-start;
30
30
  background-color: $colors--theme--background-inputs;
31
31
  display: flex;
32
32
  flex-wrap: wrap;
@@ -47,7 +47,7 @@
47
47
  }
48
48
 
49
49
  .p-chip {
50
- margin-bottom: $spv--x-small;
50
+ margin-bottom: 0;
51
51
  margin-top: $spv--x-small;
52
52
  }
53
53
 
@@ -116,14 +116,31 @@
116
116
  }
117
117
 
118
118
  .p-search-and-filter__box {
119
+ align-items: center;
119
120
  display: inline-flex;
120
121
  flex: 1;
122
+ height: 100%;
121
123
  margin: 0;
122
124
  position: relative;
123
125
  }
124
126
 
127
+ // tab-selectable search button
128
+ .p-search-and-filter__search-button {
129
+ // Hide the search button unless it is focused
130
+ @extend %u-off-screen;
131
+ // Prevents the bottom margin of the search button from growing the height of the search container
132
+ @extend %u-no-margin--bottom;
133
+ // Make the button dense to ensure it fits vertically in the search box
134
+ @extend %vf-button-dense-vertical-padding;
135
+
136
+ // Make sure the hidden search button appears on top of the input field
137
+ &:focus {
138
+ z-index: 1;
139
+ }
140
+ }
141
+
125
142
  .p-search-and-filter__input {
126
- border: 0;
143
+ border-bottom: 0; // only remove bottom border (replaced by component border), as the top transparent border is still needed for correct alignment
127
144
  box-shadow: none;
128
145
  flex-grow: 1;
129
146
  margin-bottom: 0;
@@ -34,12 +34,7 @@
34
34
  @extend %transparent-button;
35
35
  }
36
36
 
37
- // Theme set on body element
38
37
  .p-search-box__input {
39
- background-color: $colors--theme--background-inputs;
40
- border-color: $colors--theme--border-high-contrast;
41
-
42
- color: $colors--theme--text-default;
43
38
  flex: 1 1 100%;
44
39
  margin-bottom: 0;
45
40
  padding-right: calc(2 * (2 * $spv-nudge + map-get($line-heights, default-text)));
@@ -39,7 +39,8 @@
39
39
  display: none;
40
40
  }
41
41
 
42
- .row {
42
+ .row,
43
+ .grid-row {
43
44
  max-width: 100%;
44
45
  padding: 0;
45
46
  width: 100%;
@@ -29,3 +29,13 @@ $l-fluid-breakout-max-width: $grid-max-width !default;
29
29
  $l-fluid-breakout-aside-width: 14rem !default;
30
30
  $l-fluid-breakout-main-child-width: 13rem !default;
31
31
  $l-fluid-breakout-3-col-threshold: calc($grid-max-width + $l-fluid-breakout-aside-width);
32
+
33
+ // New 4/4/8 grid
34
+
35
+ $grid-8-columns-small: 4 !default;
36
+ $grid-8-columns-medium: 4 !default;
37
+ $grid-8-columns: 8 !default;
38
+ $grid-8-column-prefix: 'grid-#{$grid-column-prefix}' !default;
39
+ $grid-8-small-col-prefix: 'grid-#{$grid-small-col-prefix}' !default;
40
+ $grid-8-medium-col-prefix: 'grid-#{$grid-medium-col-prefix}' !default;
41
+ $grid-8-large-col-prefix: 'grid-#{$grid-large-col-prefix}' !default;
@@ -3,7 +3,6 @@
3
3
  @import 'settings_colors';
4
4
 
5
5
  // Global placeholder settings
6
- $input-border-thickness: 1.5px;
7
6
  $bar-thickness: 0.1875rem !default; // 3px at 16px fontsize, expressed in rems so it scales with text if the root font-size changes at a breakpoint
8
7
  $border-radius: 0; // deprecated, will be removed in future version of Vanilla
9
8
  $border: $input-border-thickness solid $colors--theme--border-default !default;
@@ -117,8 +117,11 @@ $sp-after: (
117
117
  // commonly occuring calculations available as variables
118
118
  $spv-nudge: map-get($nudges, p) !default; // top: nudge; bottom: unit - nudge; result: height = exact multiple of base unit
119
119
  $spv-nudge-compensation: $sp-unit - $spv-nudge !default;
120
+
121
+ // form input spacing variables
120
122
  $input-margin-bottom: $sp-unit * 4 - $spv-nudge * 2;
121
- $input-vertical-padding: calc($spv-nudge - 1px);
123
+ $input-border-thickness: 1.5px;
124
+ $input-vertical-padding: calc($spv-nudge - $input-border-thickness);
122
125
 
123
126
  // tick element variables
124
127
  $form-tick-box-size: 1rem;
@@ -7,7 +7,8 @@
7
7
  @media (min-width: $threshold-6-12-col) {
8
8
  display: flex;
9
9
 
10
- &.row {
10
+ &.row,
11
+ &.grid-row {
11
12
  display: grid;
12
13
  }
13
14
  }
@@ -2,12 +2,7 @@
2
2
 
3
3
  // Positions element out of flow & off screen for screen readers
4
4
  @mixin vf-u-off-screen {
5
- .u-off-screen:not(:focus):not(:active) {
6
- clip-path: inset(50%);
7
- height: 1px;
8
- overflow: hidden;
9
- position: absolute;
10
- white-space: nowrap;
11
- width: 1px;
5
+ .u-off-screen {
6
+ @extend %u-off-screen;
12
7
  }
13
8
  }
@@ -20,6 +20,7 @@
20
20
  @import 'patterns_form-validation';
21
21
  @import 'patterns_forms';
22
22
  @import 'patterns_grid';
23
+ @import 'patterns_grid-8';
23
24
  @import 'patterns_heading-icon';
24
25
  @import 'patterns_headings';
25
26
  @import 'patterns_icons';
@@ -113,6 +114,7 @@
113
114
  @include vf-p-form-validation;
114
115
  @include vf-p-forms;
115
116
  @include vf-p-grid;
117
+ @include vf-p-grid-8;
116
118
  @include vf-p-heading-icon;
117
119
  @include vf-p-headings;
118
120
  @include vf-p-section;
@@ -0,0 +1,186 @@
1
+ {#
2
+ Params
3
+ - title_text (string) (optional): The text to be displayed as the heading
4
+ - quote_size (string) (required): The size of the quote. Possible values are 'small', 'medium', 'large'. Default is 'medium'.
5
+ - quote_text (string) (required): The text of the quote. The macro will surround it with quotes, so there is no need to quote it yourself.
6
+ - citation_source_name_text (string) (optional): The name of the source being quoted
7
+ - citation_source_title_text (string) (optional): The title of the source being quoted
8
+ - citation_source_organisation_text (string) (optional): The organisation associated with the source being quoted.
9
+ - is_shallow (boolean) (optional): Whether the quote wrapper pattern should be displayed in a shallow section. Defaults to false.
10
+ Slots
11
+ - signpost_image (optional): The signpost_image of the source being quoted
12
+ - heading_link (optional): Link to be displayed beside the heading text
13
+ - cta (optional): Contents of the call to action block to be displayed below the quote
14
+ - image (optional): An image to be displayed below the quote
15
+ #}
16
+ {%- macro vf_quote_wrapper(
17
+ title_text="",
18
+ quote_size="medium",
19
+ quote_text="",
20
+ citation_source_name_text="",
21
+ citation_source_title_text="",
22
+ citation_source_organisation_text="",
23
+ is_shallow=False
24
+ ) -%}
25
+ {% set heading_link_content = caller('heading_link') %}
26
+ {% set has_heading_link = heading_link_content|trim|length > 0 %}
27
+ {% set has_title = title_text|length > 0 %}
28
+ {% set has_heading_row = has_title or has_heading_link %}
29
+ {% set signpost_image_content = caller('signpost_image') %}
30
+ {% set has_signpost_image = signpost_image_content|trim|length > 0 %}
31
+ {% set has_citation_source_name = citation_source_name_text|trim|length > 0 %}
32
+ {% set has_citation_source_title = citation_source_title_text|trim|length > 0 %}
33
+ {% set has_citation_source_organisation = citation_source_organisation_text|trim|length > 0 %}
34
+ {% set has_citation = has_citation_source_name or has_citation_source_title or has_citation_source_organisation %}
35
+ {% set cta_content = caller('cta') %}
36
+ {% set has_cta = cta_content|trim|length > 0 %}
37
+ {% set image_content = caller('image') %}
38
+ {% set has_image = image_content|trim|length > 0 %}
39
+ {% set quote_size = quote_size|trim|lower %}
40
+
41
+ {# Translate quote size param to quote heading level #}
42
+ {% if quote_size == 'large' %}
43
+ {% set quote_heading_level = 2 %}
44
+ {% elif quote_size == 'small' %}
45
+ {% set quote_heading_level = 6 %}
46
+ {% else %}
47
+ {% set quote_heading_level = 4 %}
48
+ {% endif %}
49
+
50
+ {%- macro _quote_body() -%}
51
+ <div class="p-section--shallow">
52
+ <p class="p-heading--{{ quote_heading_level }}">
53
+ <i>
54
+ &#8220;{{ quote_text }}&#8221;
55
+ </i>
56
+ </p>
57
+ </div>
58
+ {%- endmacro %}
59
+
60
+ {%- macro _citation_block() -%}
61
+ {%- if has_citation -%}
62
+ {#- Optional citation block -#}
63
+ <p>
64
+ {% if has_citation_source_name -%}
65
+ {#- Optional citation source name -#}
66
+ <strong>{{ citation_source_name_text }}</strong>
67
+ {% if has_citation_source_title or has_citation_source_organisation -%}
68
+ {#- If the citation name is followed by title and/or organisation, add a line break -#}
69
+ <br>
70
+ {% endif -%}
71
+ {% endif -%}
72
+ {% if has_citation_source_title or has_citation_source_organisation -%}
73
+ {#- Optional citation source title and/or organisation -#}
74
+ <span class="u-text--muted">
75
+ {% if has_citation_source_title -%}
76
+ {#- Optional citation source title -#}
77
+ {{ citation_source_title_text }}
78
+ {%- if has_citation_source_organisation %}
79
+ {#- Add a line break between the title and org if both are present -#}
80
+ <br>
81
+ {%- endif %}
82
+ {% endif %}
83
+ {%- if has_citation_source_organisation -%}
84
+ {#- Optional citation source organisation -#}
85
+ {{ citation_source_organisation_text }}
86
+ {%- endif %}
87
+ </span>
88
+ {%- endif %}
89
+ </p>
90
+ {% endif %}
91
+ {%- endmacro -%}
92
+
93
+ {%- macro _heading_block() %}
94
+ {% if has_heading_row -%}
95
+ {#- Optional heading -#}
96
+ <div class="p-section--shallow">
97
+ <hr class="p-rule--highlight is-fixed-width">
98
+ <div class="row">
99
+ {%- if has_title %}
100
+ {#- Optional heading text -#}
101
+ <div class="col-3 col-medium-2">
102
+ <p class="p-muted-heading">{{ title_text }}</p>
103
+ </div>
104
+ {%- endif -%}
105
+
106
+ {%- if has_heading_link %}
107
+ {#- Optional heading link -#}
108
+ <div class="col-3 col-medium-4 col-start-large-10 col-start-medium-3">
109
+ <p class="p-text--default">
110
+ {{ heading_link_content }}
111
+ </p>
112
+ </div>
113
+ {% endif -%}
114
+ </div>
115
+ </div>
116
+ {% endif -%}
117
+ {%- endmacro %}
118
+
119
+ <div class="p-section{% if is_shallow %}--shallow{% endif %}">
120
+ {{- _heading_block() -}}
121
+ <div class="row">
122
+ {% if has_signpost_image -%}
123
+ {% if not has_heading_row %}
124
+ {#-
125
+ If a signpost is present, but no heading row, the signpost is the first piece of content in the pattern on small.
126
+ So, we place a standard rule above the signpost to separate it from the preceding section.
127
+ -#}
128
+ <hr class="p-rule u-hide--medium u-hide--large">
129
+ {% endif %}
130
+ {#- Optional signpost image -#}
131
+ <div class="col-3 col-medium-2">
132
+ <div class="p-section--shallow">
133
+ {{ signpost_image_content }}
134
+ </div>
135
+ </div>
136
+ {% endif -%}
137
+
138
+ <div class="col-9 col-start-large-4 col-medium-4 col-start-medium-3">
139
+ {% if has_heading_row %}
140
+ {#- If a heading is present, a muted rule separates the heading from the quote, and can be used on all breakpoints. -#}
141
+ <hr class="p-rule--muted">
142
+ {% elif has_signpost_image %}
143
+ {#-
144
+ If a heading is not present, we use a standard rule to separate the pattern from preceding content on large and medium.
145
+ On small, the signpost is stacked above the quote, so we use a muted rule to separate the signpost from the quote.
146
+ -#}
147
+ <hr class="p-rule u-hide--small">
148
+ <hr class="p-rule--muted u-hide--large u-hide--medium">
149
+ {% else %}
150
+ {#- If neither heading nor signpost image is present, use a standard rule on all screen sizes to separate from preceding section -#}
151
+ <hr class="p-rule">
152
+ {% endif %}
153
+ {% if has_citation -%}
154
+ {#- When a citation is present, wrap the quote and citation in a nested grid to space them properly -#}
155
+ <div class="row">
156
+ <div class="col-6">
157
+ {{ _quote_body() }}
158
+ </div>
159
+ <div class="col-3">
160
+ <hr class="p-rule--muted u-hide--large">
161
+ {{ _citation_block() }}
162
+ </div>
163
+ </div>
164
+ {% else -%}
165
+ {#- When no citation is present, display quote body without a nested grid -#}
166
+ {{ _quote_body() }}
167
+ {% endif -%}
168
+
169
+ {%- if has_cta or has_image -%}
170
+ {#- Optional CTA and/or image block -#}
171
+ {%- if has_cta %}
172
+ {#- Optional CTA block -#}
173
+ <div class="p-cta-block">
174
+ {{ cta_content }}
175
+ </div>
176
+ {% endif -%}
177
+
178
+ {% if has_image -%}
179
+ {#- Optional image block -#}
180
+ {{ image_content }}
181
+ {% endif -%}
182
+ {% endif -%}
183
+ </div>
184
+ </div>
185
+ </div>
186
+ {% endmacro -%}
@@ -0,0 +1,127 @@
1
+ # Params
2
+ # title_text (string) (required): Title of the rich vertical list
3
+ # list_item_tick_style (string) (optional): Type of list item tick styling. Options are "bullet", "tick", "number".
4
+ # is_flipped (boolean) (optional): Whether the list items are flipped so image is on the left and the text is on the right. Defaults to false.
5
+ # Slots
6
+ # description: Paragraph-style description content
7
+ # logo_section Logo section block
8
+ # list_item_[1-7]: List item content, assumed to be li.p-list__item
9
+ # image (required)
10
+ {% macro vf_rich_vertical_list(
11
+ title_text,
12
+ list_item_tick_style="",
13
+ is_flipped=false
14
+ ) -%}
15
+ {% set description_content = caller('description') %}
16
+ {% set has_description = description_content|trim|length > 0 %}
17
+ {% set logo_section_content = caller('logo_section') %}
18
+ {% set has_logo_section = logo_section_content|trim|length > 0 %}
19
+ {% set cta_content = caller('cta') %}
20
+ {% set has_cta = cta_content|trim|length > 0 %}
21
+ {% set has_list = caller('list_item_1')|trim|length > 0 %}
22
+ {% set image_content = caller('image') %}
23
+ {% set max_list_items = 7 %}
24
+
25
+ {% set list_item_tick_style=list_item_tick_style|trim|lower %}
26
+ {% if list_item_tick_style|length > 0 and list_item_tick_style not in ['bullet', 'tick', 'number'] %}
27
+ {% set list_item_tick_style = '' %}
28
+ {% endif %}
29
+
30
+ {% if list_item_tick_style == "bullet" %}
31
+ {% set list_item_tick_class = "has-bullet" %}
32
+ {% elif list_item_tick_style == "tick" %}
33
+ {% set list_item_tick_class = "is-ticked" %}
34
+ {% endif %}
35
+
36
+ {% set list_element_type = "ul" %}
37
+ {% if list_item_tick_style == "number" %}
38
+ {% set list_element_type = "ol" %}
39
+ {% endif %}
40
+
41
+ {#-
42
+ Construct list of list items using caller in the top-level macro
43
+ The _text_column_contents macro will not have access to the caller block, so we need to extract the list items here.
44
+ -#}
45
+ {% set list_items = [] %}
46
+ {% if has_list %}
47
+ {% for list_item_index in range(1, max_list_items + 1) %}
48
+ {% set list_item_content = caller('list_item_' + list_item_index|string) %}
49
+ {% set has_list_item_content = list_item_content|trim|length > 0 %}
50
+ {% if has_list_item_content %}
51
+ {{ list_items.append(list_item_content) or ""}}
52
+ {% endif %}
53
+ {% endfor %}
54
+ {% endif %}
55
+
56
+ {%- macro _text_column_contents(list_items) %}
57
+ {#- Mandatory title -#}
58
+ <div class="p-section--shallow">
59
+ <h2>{{ title_text }}</h2>
60
+ </div>
61
+
62
+ {%- if has_logo_section %}
63
+ {#- Optional logo section -#}
64
+ <div class="p-section--shallow">
65
+ <div class="u-fixed-width">
66
+ {{- logo_section_content -}}
67
+ </div>
68
+ </div>
69
+ {%- endif -%}
70
+
71
+ {%- if has_description %}
72
+ {#- Optional description -#}
73
+ <div class="p-section--shallow">
74
+ {{- description_content -}}
75
+ </div>
76
+ {%- endif -%}
77
+
78
+ {%- if list_items|length > 0 %}
79
+ {#- Optional list -#}
80
+ <{{ list_element_type }} class="p-list--divided">
81
+ {% for list_item in list_items %}
82
+ <li class="p-list__item {{ list_item_tick_class }}">
83
+ {{- list_item -}}
84
+ </li>
85
+ {% endfor %}
86
+ </{{ list_element_type }}>
87
+ {%- endif -%}
88
+
89
+ {%- if has_cta %}
90
+ {#- Optional CTA block -#}
91
+ <div class="p-cta-block">
92
+ {{- cta_content -}}
93
+ </div>
94
+ {%- endif -%}
95
+
96
+ {%- endmacro -%}
97
+
98
+ {%- macro _image_column_contents() %}
99
+ {#- Mandatory image -#}
100
+ <div class="p-section--shallow">
101
+ {{- image_content -}}
102
+ </div>
103
+ {%- endmacro -%}
104
+
105
+ <div class="p-section">
106
+ <div class="row--50-50-on-large">
107
+ <hr>
108
+ {% if not is_flipped -%}
109
+ <div class="col">
110
+ {{- _text_column_contents(list_items) -}}
111
+ </div>
112
+ <div class="col">
113
+ {{- _image_column_contents() -}}
114
+ </div>
115
+ {%- else -%}
116
+ {#- For flipped layout, place the image contents in the first column and the text in the second column -#}
117
+ <div class="col">
118
+ {{- _image_column_contents() -}}
119
+ </div>
120
+ <div class="col">
121
+ {{- _text_column_contents(list_items) -}}
122
+ </div>
123
+ {%- endif -%}
124
+ </div>
125
+ </div>
126
+
127
+ {%- endmacro %}