DFE-Digital/govuk-components

View on GitHub
app/components/govuk_component/summary_list_component.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
module GovukComponent
  class SummaryListComponent < GovukComponent::Base
    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:,
        html_attributes:,
        &block
      )
    end

    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:, html_attributes:)

      return unless rows.presence

      build(rows)
    end

    def call
      summary_list = tag.dl(**html_attributes) { safe_join(rows) }

      (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(@card) { summary_list }
    end

    def borders_class
      "#{brand}-summary-list--no-border" unless borders
    end

    def default_attributes
      { class: ["#{brand}-summary-list", borders_class].compact }
    end

    def build(rows)
      @show_actions_column &&= rows.any? { |r| r.key?(:actions) }

      rows.each do |data|
        k, v, a = data.values_at(:key, :value, :actions)

        with_row(**data.slice(:classes, :html_attributes)) do |r|
          r.with_key(**k)
          r.with_value(**v)
          Array.wrap(a).each { |ad| r.with_action(**ad) }
        end
      end
    end
  end
end