diff --git a/app/components/blacklight_range_limit/range_form_component.html.erb b/app/components/blacklight_range_limit/range_form_component.html.erb
new file mode 100644
index 00000000..8154e849
--- /dev/null
+++ b/app/components/blacklight_range_limit/range_form_component.html.erb
@@ -0,0 +1,12 @@
+<%= form_tag search_action_path, method: :get, class: [@classes[:form], "range_#{@facet_field.key} d-flex justify-content-center"].join(' '), data: { controller: "range-limit" } do %>
+ <%= render hidden_search_state %>
+
+
+<% end %>
diff --git a/app/javascript/controllers/range_limit_controller.js b/app/javascript/controllers/range_limit_controller.js
new file mode 100644
index 00000000..812f708b
--- /dev/null
+++ b/app/javascript/controllers/range_limit_controller.js
@@ -0,0 +1,26 @@
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ connect() {
+ this.beginInput = this.element.querySelector('input[name="range[date_range][begin]"]');
+ this.endInput = this.element.querySelector('input[name="range[date_range][end]"]');
+ this.beginInput.addEventListener('input', event => this.updateInputRequiredState(event));
+ this.endInput.addEventListener('input', event => this.updateInputRequiredState(event));
+ }
+
+ updateInputRequiredState(event) {
+ const beginFilled = this.beginInput.value !== '';
+ const endFilled = this.endInput.value !== '';
+
+ if (beginFilled === endFilled) {
+ this.beginInput.removeAttribute('required');
+ this.endInput.removeAttribute('required');
+ } else if (beginFilled) {
+ this.beginInput.removeAttribute('required');
+ this.endInput.setAttribute('required', '');
+ } else {
+ this.endInput.removeAttribute('required');
+ this.beginInput.setAttribute('required', '');
+ }
+ }
+}
\ No newline at end of file
diff --git a/spec/features/range_limit_facet_spec.rb b/spec/features/range_limit_facet_spec.rb
new file mode 100644
index 00000000..d8b7e083
--- /dev/null
+++ b/spec/features/range_limit_facet_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Range Limit Facet', :js do
+ it 'only allows balanced ranges' do
+ visit search_catalog_path
+
+ click_on 'Show facets' if page.has_button?('Show facets')
+
+ expect(page).to have_button('Date range')
+ click_on 'Date range'
+
+ # Both empty
+ expect(page).to have_no_css('input#range_date_range_begin[required]')
+ expect(page).to have_no_css('input#range_date_range_end[required]')
+
+ # Only begin has a value
+ fill_in 'range_date_range_begin', with: '1986'
+ expect(page).to have_css('input#range_date_range_end[required]')
+
+ # Only end has a value
+ fill_in 'range_date_range_begin', with: ''
+ fill_in 'range_date_range_end', with: '1991'
+ expect(page).to have_css('input#range_date_range_begin[required]')
+
+ # Both have values
+ fill_in 'range_date_range_begin', with: '1986'
+ fill_in 'range_date_range_end', with: '1991'
+ expect(page).to have_no_css('input#range_date_range_begin[required]')
+ expect(page).to have_no_css('input#range_date_range_end[required]')
+ end
+end