diff --git a/app/components/blacklight/document_component.html.erb b/app/components/blacklight/document_component.html.erb
index cd9bcd6d8..301c75435 100644
--- a/app/components/blacklight/document_component.html.erb
+++ b/app/components/blacklight/document_component.html.erb
@@ -8,14 +8,20 @@
itemtype: document.itemtype,
class: classes.flatten.join(' ') do %>
<%= header %>
+ <% header_components.each do |component| %>
+ <%= render component.new(presenter: @presenter, counter: @counter, document_counter: @document_counter) %>
+ <% end %>
+
<% if body.present? %>
<%= body %>
<% else %>
<%= title %>
- <%= embed %>
- <%= content %>
- <%= metadata %>
+
+ <% section_components.each do |section| %>
+ <%= section %>
+ <% end %>
+
<% metadata_sections.each do |section| %>
<%= section %>
<% end %>
@@ -27,5 +33,10 @@
<%= thumbnail %>
<% end %>
+
+ <% footer_components.each do |component| %>
+ <%= render component.new(presenter: @presenter, counter: @counter, document_counter: @document_counter) %>
+ <% end %>
+
<%= footer %>
<% end %>
diff --git a/app/components/blacklight/document_component.rb b/app/components/blacklight/document_component.rb
index e6199ceb3..4896a8c02 100644
--- a/app/components/blacklight/document_component.rb
+++ b/app/components/blacklight/document_component.rb
@@ -127,6 +127,27 @@ def before_render
end
end
+ def header_components
+ view_config.document_header_components
+ end
+
+ def section_components
+ return to_enum(:section_components) unless block_given?
+
+ view_config.document_section_components&.each do |component_or_key|
+ case component_or_key
+ when Symbol, String
+ yield public_send(component_or_key)
+ when Class
+ yield render component_or_key.new(presenter: @presenter, counter: @counter, document_counter: @document_counter)
+ end
+ end
+ end
+
+ def footer_components
+ view_config.document_footer_components
+ end
+
private
delegate :view_config, to: :@presenter
diff --git a/lib/blacklight/configuration.rb b/lib/blacklight/configuration.rb
index 6fb8a1f34..5c9ac5765 100644
--- a/lib/blacklight/configuration.rb
+++ b/lib/blacklight/configuration.rb
@@ -156,6 +156,9 @@ def initialized_default_configuration?
document_metadata_component: Blacklight::DocumentMetadataComponent,
document_thumbnail_component: Blacklight::Document::ThumbnailComponent,
document_title_component: Blacklight::DocumentTitleComponent,
+ document_header_components: [],
+ document_section_components: [:embed, :content, :metadata],
+ document_footer_components: [],
sidebar_component: Blacklight::Search::SidebarComponent,
dropdown_component: Blacklight::System::DropdownComponent,
# solr field to use to render a document title
diff --git a/lib/blacklight/configuration/view_config.rb b/lib/blacklight/configuration/view_config.rb
index 7560c7b7f..258b15d33 100644
--- a/lib/blacklight/configuration/view_config.rb
+++ b/lib/blacklight/configuration/view_config.rb
@@ -8,6 +8,12 @@ class ViewConfig < Blacklight::OpenStructWithHashAccess
# @return [Class] document presenter class used by helpers and views
# @!attribute document_component
# @return [Class] component class used to render a document; defaults to Blacklight::DocumentComponent
+ # @!attribute document_header_components
+ # @return [Array] component classes that render above the main document section
+ # @!attribute document_section_components
+ # @return [Array] component classes (or slot names) that render the main document section below the title
+ # @!attribute document_footer_components
+ # @return [Array] component classes that render below the main document section
# @!attribute document_title_component
# @return [Class] component class used to render a document title
# @!attribute document_metadata_component
diff --git a/spec/components/blacklight/document_component_spec.rb b/spec/components/blacklight/document_component_spec.rb
index accb9f85f..09182d92a 100644
--- a/spec/components/blacklight/document_component_spec.rb
+++ b/spec/components/blacklight/document_component_spec.rb
@@ -269,4 +269,32 @@ def call
expect(page).to have_content "Prefix!"
end
end
+
+ context 'with configured components' do
+ let(:static_component) do
+ lambda { |text|
+ inline = Class.new(ViewComponent::Base) do
+ class_attribute :text
+ def self.name = 'StaticComponent'
+ def initialize(**); end
+
+ def call
+ text
+ end
+ end
+
+ inline.tap { |klass| klass.text = text }
+ }
+ end
+
+ it 'renders header, section, and footer components' do
+ blacklight_config.index.document_header_components = [static_component.call('Header')]
+ blacklight_config.index.document_section_components = [static_component.call('Section')]
+ blacklight_config.index.document_footer_components = [static_component.call('Footer')]
+
+ render_inline component
+ puts page.native.inner_html
+ expect(page).to have_content('Header').and have_content('Section').and have_content('Footer')
+ end
+ end
end