Skip to content

Commit

Permalink
Append card title to summary list actions (#481)
Browse files Browse the repository at this point in the history
This change appends the card title to action links when rendered within
a summary card. It follows [the upstream
change](alphagov/govuk-frontend#3961) introduced
in govuk-frontend version 5.

In the simplest case it works like the reference implementation:

```erb
<%= govuk_summary_list(card: { title: "Shiny new widget" }) do |sl| %>
  <%= sl.with_row do |r| %>
    <%= r.with_key(text: "Price") %>
    <%= r.with_value(text: "£19.99") %>
    <%= r.with_action(href: "/widgets/1/edit", text: "Modify", visually_hidden_text: "this widget's price") %>
  <% end %>
<% end %>
```

Here, the rendered HTML will now include the card title in the visually
hidden text on the action:

```html
<dl class="govuk-summary-list">
  <div class="govuk-summary-list__row">
    <dt class="govuk-summary-list__key">Price</dt>
    <dd class="govuk-summary-list__value">£19.99</dd>
    <dd class="govuk-summary-list__actions">
      <a class="govuk-link" href="/a">Modify<span class="govuk-visually-hidden"> this widget's price (Shiny new widget)</span></a>
    </dd>
  </div>
</dl>
```

Additionally the suffix text can be set manually. This allows it to be
set without passing in `card: { ... }` when initialising the summary
list. It might be useful when rendering the summary list within an outer
card. It is set using the `action_suffix` keyword.

```erb
<%= govuk_summary_card(title: "Shiny new widget") do %>
  <%= govuk_summary_list(action_suffix: "Shiny new widget") do |sl| %>
    <%= sl.with_row do |r| %>
      <%= r.with_key(text: "Price") %>
      <%= r.with_value(text: "£19.99") %>
      <%= r.with_action(href: "/widgets/1/edit", text: "Modify", visually_hidden_text: "this widget's price") %>
    <% end %>
  <% end %>
<% end %>
```

This will output the same HTML as the above example.

When both the `card` and `action_suffix` arguments are provided the
`action_suffix` takes precedence, which offers a little more flexibility
as there might be some cases other text would make more sense than the
card's title.

Fixes #479, #480
  • Loading branch information
peteryates authored Dec 21, 2023
2 parents 8e16d84 + 20f7d7f commit f049d82
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 19 deletions.
20 changes: 13 additions & 7 deletions app/components/govuk_component/summary_list_component.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
module GovukComponent
class SummaryListComponent < GovukComponent::Base
attr_reader :borders, :actions, :card
attr_reader :borders, :actions, :card, :visually_hidden_action_suffix

renders_many :rows, ->(classes: [], html_attributes: {}, &block) do
GovukComponent::SummaryListComponent::RowComponent.new(
show_actions_column: @show_actions_column,
visually_hidden_action_suffix: visually_hidden_action_suffix || card&.title,
classes: classes,
html_attributes: html_attributes,
&block
)
end

def initialize(rows: nil, actions: true, borders: config.default_summary_list_borders, card: nil, classes: [], html_attributes: {})
@borders = borders
@show_actions_column = actions
@card = card
def initialize(rows: nil, actions: true, borders: config.default_summary_list_borders, card: {}, visually_hidden_action_suffix: nil, classes: [], html_attributes: {})
@borders = borders
@show_actions_column = actions
@card = GovukComponent::SummaryListComponent::CardComponent.new(**card) if card.present?
@visually_hidden_action_suffix = visually_hidden_action_suffix

super(classes: classes, html_attributes: html_attributes)

Expand All @@ -26,16 +28,20 @@ def initialize(rows: nil, actions: true, borders: config.default_summary_list_bo
def call
summary_list = tag.dl(**html_attributes) { safe_join(rows) }

(card.nil?) ? summary_list : card_with(summary_list)
(card?) ? card_with(summary_list) : summary_list
end

private

def card?
@card.present?
end

# we're not using `renders_one` here because we always want the card to render
# outside of the summary list. when manually building use
# govuk_summary_list_card { govuk_summary_list }
def card_with(summary_list)
render(GovukComponent::SummaryListComponent::CardComponent.new(**card)) { summary_list }
render(@card) { summary_list }
end

def borders_class
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
class GovukComponent::SummaryListComponent::ActionComponent < GovukComponent::Base
attr_reader :href, :text, :visually_hidden_text, :attributes, :classes
attr_reader :href, :text, :visually_hidden_text, :visually_hidden_action_suffix, :attributes, :classes

def initialize(href: nil, text: 'Change', visually_hidden_text: false, classes: [], html_attributes: {})
def initialize(href: nil, text: 'Change', visually_hidden_text: false, visually_hidden_action_suffix: nil, classes: [], html_attributes: {})
@visually_hidden_text = visually_hidden_text

if config.require_summary_list_action_visually_hidden_text && visually_hidden_text == false
fail(ArgumentError, "missing keyword: visually_hidden_text")
end

super(classes: classes, html_attributes: html_attributes)

@href = href
@text = text
@visually_hidden_action_suffix = visually_hidden_action_suffix
end

def render?
Expand All @@ -36,7 +36,13 @@ def action_text
content || text || fail(ArgumentError, "no text or content")
end

def visually_hidden_content
return "#{visually_hidden_text} (#{visually_hidden_action_suffix})" if visually_hidden_action_suffix

visually_hidden_text
end

def visually_hidden_span
tag.span(%( #{visually_hidden_text}), class: "#{brand}-visually-hidden") if visually_hidden_text.present?
tag.span(%( #{visually_hidden_content}), class: "#{brand}-visually-hidden") if visually_hidden_text.present?
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<% if actions.any? %>
<ul class="<%= brand %>-summary-card__actions">
<% actions.each do |action| %>
<%= tag.li(action, class: "#{brand}-summary-card__action") %>
<%= tag.li(action_text(action), class: "#{brand}-summary-card__action") %>
<% end %>
</ul>
<% end %>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ def initialize(title:, actions: [], classes: [], html_attributes: {})
def default_attributes
{ class: "#{brand}-summary-card" }
end

def action_text(action)
safe_join([action, tag.span(" (" + title + ")", class: "#{brand}-visually-hidden")])
end
end
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
class GovukComponent::SummaryListComponent::RowComponent < GovukComponent::Base
attr_reader :href, :visually_hidden_text, :show_actions_column
attr_reader :href, :visually_hidden_text, :show_actions_column, :visually_hidden_action_suffix

renders_one :key, GovukComponent::SummaryListComponent::KeyComponent
renders_one :value, GovukComponent::SummaryListComponent::ValueComponent
renders_many :actions, GovukComponent::SummaryListComponent::ActionComponent
renders_many :actions, ->(href: nil, text: 'Change', visually_hidden_text: false, classes: [], html_attributes: {}, &block) do
GovukComponent::SummaryListComponent::ActionComponent.new(
href: href,
text: text,
visually_hidden_text: visually_hidden_text,
visually_hidden_action_suffix: visually_hidden_action_suffix,
classes: classes,
html_attributes: html_attributes,
&block
)
end

def initialize(show_actions_column: nil, classes: [], html_attributes: {})
def initialize(show_actions_column: nil, visually_hidden_action_suffix: nil, classes: [], html_attributes: {})
@show_actions_column = show_actions_column
@visually_hidden_action_suffix = visually_hidden_action_suffix

super(classes: classes, html_attributes: html_attributes)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@

specify "the actions are rendered" do
expect(rendered_content).to have_tag("ul", with: { class: "govuk-summary-card__actions" }) do
actions.each { |action| with_tag("li", text: action, with: { class: "govuk-summary-card__action" }) }
actions.each { |action| with_tag("li", text: "#{action} (#{title})", with: { class: "govuk-summary-card__action" }) }
end
end
end
Expand Down
48 changes: 45 additions & 3 deletions spec/components/govuk_component/summary_list_component_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,54 @@
context "when there is a card" do
subject! do
render_inline(described_class.new(card: { title: "Hi" }, **kwargs)) do |component|
component.with_row { |row| helper.safe_join([row.with_key(text: "Key"), row.with_value(text: "Value"), row.with_action(href: "/a", visually_hidden_text: "for key")]) }
component.with_row { |row| helper.safe_join([row.with_key(text: "Key"), row.with_value(text: "Value"), row.with_action(href: "/a", visually_hidden_text: "this row")]) }
end
end

specify "when the card parameters are passed into the summary list via card:" do
expect(rendered_content).to have_tag("div", with: { class: "govuk-summary-card" }) do
with_tag("dl", with: { class: "govuk-summary-list" })
end
end

specify "the summary card's title is included in the visually hidden action suffix" do
expect(rendered_content).to have_tag("dd", with: { class: "govuk-summary-list__actions" }) do
with_text("Change this row (Hi)")
with_tag("span", with: { class: "govuk-visually-hidden" }, text: %r{this row \(Hi\)})
end
end

specify "the summary list is wrapped in a card" do
expect(rendered_content).to have_tag("div", with: { class: "govuk-summary-card" })
context "when the visually_hidden_action_suffix is present" do
subject! do
render_inline(described_class.new(card: { title: "Hi" }, visually_hidden_action_suffix: "Hello", **kwargs)) do |component|
component.with_row { |row| helper.safe_join([row.with_key(text: "Key"), row.with_value(text: "Value"), row.with_action(href: "/a", visually_hidden_text: "this row")]) }
end
end

specify "the visually_hidden_action_suffix overrides the card's title in action links" do
expect(rendered_content).to have_tag("dd", with: { class: "govuk-summary-list__actions" }) do
with_tag("span", with: { class: "govuk-visually-hidden" }, text: %r{this row \(Hello\)})
end
end
end
end

context "when the summary list is manually placed within a card and the title is set with visually_hidden_action_suffix:" do
subject! do
render_inline(described_class.new(visually_hidden_action_suffix: "Hi", **kwargs)) do |component|
component.with_row { |row| helper.safe_join([row.with_key(text: "Key"), row.with_value(text: "Value"), row.with_action(href: "/a", visually_hidden_text: "this row")]) }
end
end

specify "the summary list isn't wrapped in a card" do
expect(rendered_content).not_to have_tag("div", with: { class: "govuk-summary-card" })
end

specify "the summary card's title is included in the visually hidden action suffix" do
expect(rendered_content).to have_tag("dd", with: { class: "govuk-summary-list__actions" }) do
with_text("Change this row (Hi)")
with_tag("span", with: { class: "govuk-visually-hidden" }, text: %r{this row \(Hi\)})
end
end
end

Expand Down

0 comments on commit f049d82

Please sign in to comment.