Skip to content

Commit 3aebd66

Browse files
Merge pull request #1989 from nhsuk/component-actions
[v10] Add support for card and summary list actions as buttons
2 parents 1051d92 + e8f33e7 commit 3aebd66

30 files changed

Lines changed: 782 additions & 87 deletions

CHANGELOG.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,43 @@ The utility class `nhsuk-u-frontend-not-supported-hidden` is used to hide conten
6868

6969
This was added in [pull request #1707: Add checkbox "all" option](https://github.com/nhsuk/nhsuk-frontend/pull/1707).
7070

71+
#### Use buttons for card and summary list actions
72+
73+
You can now configure card and summary list actions as button elements, using new Nunjucks macro options:
74+
75+
- `item.element` to use `"button"` or `"a"` elements
76+
- `item.id` for the element `id` attribute
77+
- `item.type` for the button `type` attribute
78+
- `item.name` for the button `name` attribute
79+
- `item.value` for the button `value` attribute
80+
81+
Action items using `element: "button"` will be visually styled as links.
82+
83+
```patch
84+
+ <form method="post" novalidate>
85+
{{ card({
86+
heading: "Regional Manager",
87+
actions: {
88+
items: [
89+
{
90+
text: "Delete",
91+
- href: "/delete"
92+
+ element: "button",
93+
+ name: "action",
94+
+ value: "delete"
95+
},
96+
{
97+
text: "Withdraw",
98+
- href: "/withdraw",
99+
+ element: "button",
100+
+ name: "action",
101+
+ value: "withdraw"
102+
}
103+
]
104+
```
105+
106+
This was added in [pull request #1989: Add support for card and summary list actions as buttons](https://github.com/nhsuk/nhsuk-frontend/pull/1989).
107+
71108
#### Show or hide content in supported browsers
72109

73110
You can now show or hide content depending on whether NHS.UK frontend JavaScript is supported:

packages/nhsuk-frontend-review/src/examples/components/index.njk

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,64 @@
667667
]
668668
}) }}
669669

670+
{% call summaryList({
671+
lastRowBorder: false
672+
}) %}
673+
{{ summaryListRow({
674+
key: {
675+
text: "Name"
676+
},
677+
value: {
678+
text: "Sarah Philips"
679+
},
680+
actions: {
681+
items: [
682+
{
683+
href: "#",
684+
text: "Change",
685+
visuallyHiddenText: "name"
686+
}
687+
]
688+
}
689+
}) }}
690+
691+
{{ summaryListRow({
692+
key: {
693+
text: "Date of birth"
694+
},
695+
value: {
696+
text: "5 January 1978"
697+
},
698+
actions: {
699+
items: [
700+
{
701+
href: "#",
702+
text: "Change",
703+
visuallyHiddenText: "date of birth"
704+
}
705+
]
706+
}
707+
}) }}
708+
709+
{{ summaryListRow({
710+
key: {
711+
text: "Contact information"
712+
},
713+
value: {
714+
html: "72 Guild Street<br>London<br>SE23 6FH"
715+
}
716+
}) }}
717+
718+
{{ summaryListRow({
719+
key: {
720+
text: "Contact details"
721+
},
722+
value: {
723+
html: "<p>07700 900457</p><p>sarah.philips@example.com</p>"
724+
}
725+
}) }}
726+
{% endcall %}
727+
670728
{{ summaryList({
671729
border: false,
672730
rows: [
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{% macro cardAction(params, parent) %}
2+
{%- include "./template.njk" -%}
3+
{% endmacro %}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{% from "nhsuk/macros/attributes.njk" import nhsukAttributes %}
2+
3+
{#- Set classes for this component #}
4+
{%- set classNames = "nhsuk-link" -%}
5+
6+
{%- if params.classes %}
7+
{% set classNames = classNames ~ " " ~ params.classes %}
8+
{% endif %}
9+
10+
{#- Determine type of element to use, if not explicitly set #}
11+
{%- if params.element %}
12+
{% set element = params.element | lower %}
13+
{% else %}
14+
{% if params.href %}
15+
{% set element = "a" %}
16+
{% else %}
17+
{% set element = "button" %}
18+
{% endif %}
19+
{% endif %}
20+
21+
{%- set attributesHtml %}
22+
{{- nhsukAttributes({
23+
class: classNames,
24+
id: {
25+
value: params.id,
26+
optional: true
27+
}
28+
}) -}}
29+
30+
{% if element == "button" %}
31+
{{- nhsukAttributes({
32+
name: {
33+
value: params.name,
34+
optional: true
35+
},
36+
type: params.type | default("submit"),
37+
value: {
38+
value: params.value,
39+
optional: true
40+
}
41+
}) -}}
42+
{% elif element == "a" %}
43+
{{- nhsukAttributes({
44+
href: params.href | default("#")
45+
}) -}}
46+
{% endif %}
47+
48+
{{- nhsukAttributes(params.attributes) -}}
49+
{% endset %}
50+
51+
<{{ element }} {{- attributesHtml | safe }}>
52+
{%- if params.html -%}
53+
{{- params.html | safe | trim | indent(2) -}}
54+
{%- elif params.text -%}
55+
{{- params.text | trim | indent(2) -}}
56+
{%- endif -%}
57+
{%- if params.visuallyHiddenText or parent.params.heading -%}
58+
<span class="nhsuk-u-visually-hidden">
59+
{%- if params.visuallyHiddenText %} {{ params.visuallyHiddenText }}{% endif -%}
60+
{%- if parent.params.heading %} ({{ parent.params.heading }}){% endif -%}
61+
</span>
62+
{%- endif -%}
63+
</{{ element }}>

packages/nhsuk-frontend/src/nhsuk/components/card/fixtures.mjs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,46 @@ const fixtures = {
112112
viewports: ['mobile', 'tablet']
113113
}
114114
},
115+
'basic with summary list and action': {
116+
context: {
117+
heading: 'Regional Manager',
118+
headingLevel: 3,
119+
actions: {
120+
items: [
121+
{
122+
text: 'Delete',
123+
href: '#/delete'
124+
}
125+
]
126+
}
127+
},
128+
callBlock: outdent`
129+
${components.render(
130+
'summary-list',
131+
summaryListExamples['example person: Karen Francis (no border)']
132+
)}
133+
`
134+
},
135+
'basic with summary list and action as a button': {
136+
context: {
137+
heading: 'Regional Manager',
138+
headingLevel: 3,
139+
actions: {
140+
items: [
141+
{
142+
element: 'button',
143+
text: 'Delete'
144+
}
145+
]
146+
}
147+
},
148+
callBlock: outdent`
149+
${components.render(
150+
'summary-list',
151+
summaryListExamples['example person: Karen Francis (no border)']
152+
)}
153+
`
154+
},
115155
'basic with summary list and actions': {
116156
context: {
117157
heading: 'Regional Manager',
@@ -136,6 +176,30 @@ const fixtures = {
136176
)}
137177
`
138178
},
179+
'basic with summary list and actions as buttons': {
180+
context: {
181+
heading: 'Regional Manager',
182+
headingLevel: 3,
183+
actions: {
184+
items: [
185+
{
186+
element: 'button',
187+
text: 'Delete'
188+
},
189+
{
190+
element: 'button',
191+
text: 'Withdraw'
192+
}
193+
]
194+
}
195+
},
196+
callBlock: outdent`
197+
${components.render(
198+
'summary-list',
199+
summaryListExamples['example person: Karen Francis (no border)']
200+
)}
201+
`
202+
},
139203
'basic with summary list and actions, without heading': {
140204
context: {
141205
actions: {

packages/nhsuk-frontend/src/nhsuk/components/card/macro-options.mjs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,18 @@ const options = {
187187
description: 'Array of actions as links for use in the card component.',
188188
released: '10.3.0',
189189
params: {
190-
href: {
190+
id: {
191191
type: 'string',
192-
required: true,
192+
required: false,
193+
description: 'The ID of the action item.',
194+
released: '10.6.0'
195+
},
196+
element: {
197+
type: 'string',
198+
required: false,
193199
description:
194-
"The value of the link's `href` attribute for an action item.",
195-
released: '10.3.0'
200+
'HTML element for the action item – `"button"` or `"a"`. In most cases you will not need to set this as it will be configured automatically if `href` is provided.',
201+
released: '10.6.0'
196202
},
197203
text: {
198204
type: 'string',
@@ -215,6 +221,34 @@ const options = {
215221
'Actions rely on context from the surrounding content so may require additional accessible text. Text supplied to this option is appended to the end. Use `html` for more complicated scenarios.',
216222
released: '10.3.0'
217223
},
224+
name: {
225+
type: 'string',
226+
required: false,
227+
description:
228+
'Name for the `button`. This has no effect on `a` elements.',
229+
released: '10.6.0'
230+
},
231+
type: {
232+
type: 'string',
233+
required: false,
234+
description:
235+
'Type of `button` – `"button"`, `"submit"` or `"reset"`. Defaults to `"submit"`. This has no effect on `a` elements.',
236+
released: '10.6.0'
237+
},
238+
value: {
239+
type: 'string',
240+
required: false,
241+
description:
242+
'The `value` attribute for the `button`. This has no effect on `a` elements.',
243+
released: '10.6.0'
244+
},
245+
href: {
246+
type: 'string',
247+
required: true,
248+
description:
249+
'The URL that the action item should link to. If this is set, `element` will be automatically set to `"a"` if it has not already been defined.',
250+
released: '10.3.0'
251+
},
218252
classes: {
219253
type: 'string',
220254
required: false,

packages/nhsuk-frontend/src/nhsuk/components/card/template.njk

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{% from "nhsuk/macros/attributes.njk" import nhsukAttributes %}
22
{% from "nhsuk/macros/icon.njk" import nhsukIcon %}
3+
{% from "nhsuk/components/card/action/macro.njk" import cardAction %}
34

45
{#- Set variant or (deprecated) type for this component #}
56
{%- set variant = params.variant or params.type -%}
@@ -81,7 +82,7 @@
8182
{% endif %}
8283

8384
{%- set headingLevel = params.headingLevel if params.headingLevel else 2 %}
84-
{%- set actionsItems = params.actions.items | select("mapping") if params.actions.items | length else [] %}
85+
{%- set actions = params.actions.items | select("mapping") if params.actions.items | length else [] %}
8586

8687
{%- set image = {
8788
src: params.imgURL,
@@ -135,19 +136,6 @@
135136
{% endif %}
136137
{% endmacro -%}
137138

138-
{%- macro _cardAction(action, cardHeading) %}
139-
<a class="nhsuk-link {%- if action.classes %} {{ action.classes }}{% endif %}" href="{{ action.href }}"
140-
{{- nhsukAttributes(action.attributes) }}>
141-
{{- action.html | safe | indent(4) if action.html else action.text -}}
142-
{%- if action.visuallyHiddenText or cardHeading -%}
143-
<span class="nhsuk-u-visually-hidden">
144-
{%- if action.visuallyHiddenText %} {{ action.visuallyHiddenText }}{% endif -%}
145-
{%- if cardHeading %} ({{ cardHeading }}){% endif -%}
146-
</span>
147-
{%- endif -%}
148-
</a>
149-
{% endmacro -%}
150-
151139
<div class="{{ classNames }}" {%- if params.id %} id="{{ params.id }}"{% endif %}
152140
{{- nhsukAttributes(params.attributes) }}>
153141
{% if image.html %}
@@ -159,30 +147,34 @@
159147
alt: image.alt
160148
}) }}>
161149
{% endif %}
162-
{% if isCareCard or actionsItems | length %}
150+
{% if isCareCard or actions | length %}
163151
<div class="nhsuk-card__heading-container">
164152
{% if isCareCard %}
165153
{{ _careHeading(params, classNamesHeading) | trim | indent(2) }}
166154
{% elif params.heading or params.headingHtml %}
167155
{{ _cardHeading(params, classNamesHeading) | trim | indent(2) }}
168156
{% endif %}
169-
{% if actionsItems | length == 1 %}
157+
{% if actions | length == 1 %}
170158
<div class="nhsuk-card__actions {%- if params.actions.classes %} {{ params.actions.classes }}{% endif %}">
171-
{{ _cardAction(actionsItems[0], params.heading) | trim | indent(4) }}
159+
{{ cardAction(actions[0], {
160+
params: params
161+
}) | trim | indent(6) }}
172162
</div>
173-
{% elif actionsItems | length %}
163+
{% elif actions | length %}
174164
<ul class="nhsuk-card__actions {%- if params.actions.classes %} {{ params.actions.classes }}{% endif %}">
175-
{% for action in actionsItems %}
165+
{% for action in actions %}
176166
<li class="nhsuk-card__action">
177-
{{ _cardAction(action, params.heading) | trim | indent(8) }}
167+
{{ cardAction(action, {
168+
params: params
169+
}) | trim | indent(8) }}
178170
</li>
179171
{% endfor %}
180172
</ul>
181173
{% endif %}
182174
</div>
183175
{% endif %}
184176
<div class="nhsuk-card__content">
185-
{% if not isCareCard and not actionsItems | length and (params.heading or params.headingHtml) %}
177+
{% if not isCareCard and not actions | length and (params.heading or params.headingHtml) %}
186178
{{ _cardHeading(params, classNamesHeading) | trim | indent(2) }}
187179
{% endif %}
188180
{% if caller or params.descriptionHtml %}

0 commit comments

Comments
 (0)