diff --git a/app/controllers/admin/forms_controller.rb b/app/controllers/admin/forms_controller.rb index bad184bab..7656b4725 100644 --- a/app/controllers/admin/forms_controller.rb +++ b/app/controllers/admin/forms_controller.rb @@ -518,6 +518,7 @@ def form_params :notification_frequency, :logo, :header_logo_display, + :logo_alt_text, :modal_button_text, :success_text_heading, :success_text, @@ -561,7 +562,7 @@ def form_params def form_logo_params params.require(:form).permit( - :logo, :header_logo_display + :logo, :header_logo_display, :logo_alt_text ) end diff --git a/app/models/form.rb b/app/models/form.rb index 7527c7cdd..c998f7bcb 100644 --- a/app/models/form.rb +++ b/app/models/form.rb @@ -42,6 +42,12 @@ class Form < ApplicationRecord enum :header_logo_display, { banner: 'banner', square: 'square' }, default: 'banner', prefix: true + def logo_alt_text_or_default + return logo_alt_text if logo_alt_text.present? + + "#{organization&.name} logo" + end + def self.my_forms(user, aasm_state) if user.organizational_form_approver? items = user.organization.forms @@ -340,6 +346,7 @@ def touchpoints_js_string 'form-header-logo-square' end end, + logo_alt_text: (logo_alt_text_or_default if logo.present?), questions: ordered_questions.map do |q| { answer_field: q.answer_field, diff --git a/app/serializers/form_serializer.rb b/app/serializers/form_serializer.rb index db3f46790..de5264053 100644 --- a/app/serializers/form_serializer.rb +++ b/app/serializers/form_serializer.rb @@ -23,6 +23,7 @@ class FormSerializer < ActiveModel::Serializer :whitelist_url_9, :whitelist_test_url, :header_logo_display, + :logo_alt_text, :success_text_heading, :success_text, :modal_button_text, diff --git a/app/serializers/full_form_serializer.rb b/app/serializers/full_form_serializer.rb index d90a1bd84..32e5c8cd6 100644 --- a/app/serializers/full_form_serializer.rb +++ b/app/serializers/full_form_serializer.rb @@ -45,6 +45,7 @@ def links :whitelist_url_9, :whitelist_test_url, :header_logo_display, + :logo_alt_text, :success_text_heading, :success_text, :modal_button_text, diff --git a/app/views/admin/forms/_logo_display.html.erb b/app/views/admin/forms/_logo_display.html.erb index 9e478032b..cc87788db 100644 --- a/app/views/admin/forms/_logo_display.html.erb +++ b/app/views/admin/forms/_logo_display.html.erb @@ -22,9 +22,9 @@
Current logo
<%- if form.header_logo_display_banner? %> - <%= image_tag(form.logo.tag.url, alt: "#{form.organization.name} logo", class: "form-header-logo") %> + <%= image_tag(form.logo.tag.url, alt: form.logo_alt_text_or_default, class: "form-header-logo") %> <%- elsif form.header_logo_display_square? %> - <%= image_tag(form.logo.logo_square.url, alt: "#{form.organization.name} logo", class: "form-header-logo-square") %> + <%= image_tag(form.logo.logo_square.url, alt: form.logo_alt_text_or_default, class: "form-header-logo-square") %> <%- end %>
<% end %> @@ -44,6 +44,17 @@ <%= f.label :header_logo_display, "Display as square (80px wide by 80px tall)", class: "usa-radio__label", value: "square" %> +
+ <%= f.label :logo_alt_text, "Logo alt text", class: "usa-label text-uppercase font-body-3xs" %> + + Describe the logo for people using screen readers. + Leave blank to use "<%= form.organization&.name %> logo". + + <%= f.text_field :logo_alt_text, + value: form.logo_alt_text, + class: "usa-input", + aria_describedby: "logo-alt-text-hint" %> +
<%= f.submit "Update Logo Display", class: "usa-button usa-button-outline" %> <%- if form.logo.present? %> diff --git a/app/views/components/forms/_logo_and_title.html.erb b/app/views/components/forms/_logo_and_title.html.erb index 7881a8037..baf6a58eb 100644 --- a/app/views/components/forms/_logo_and_title.html.erb +++ b/app/views/components/forms/_logo_and_title.html.erb @@ -6,11 +6,11 @@
<%- if form.header_logo_display_banner? %> <%= image_tag(form.logo.tag.url, - alt: "#{form.organization.name} banner", + alt: form.logo_alt_text_or_default, class: "form-header-logo") %> <% elsif form.header_logo_display_square? %> <%= image_tag(form.logo.logo_square.url, - alt: "#{form.organization.name} logo", + alt: form.logo_alt_text_or_default, class: "form-header-logo-square") %> <% end %>
diff --git a/db/migrate/20260618210000_add_logo_alt_text_to_forms.rb b/db/migrate/20260618210000_add_logo_alt_text_to_forms.rb new file mode 100644 index 000000000..91b45ed87 --- /dev/null +++ b/db/migrate/20260618210000_add_logo_alt_text_to_forms.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddLogoAltTextToForms < ActiveRecord::Migration[8.1] + def change + add_column :forms, :logo_alt_text, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index b004de4b9..70a786c32 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.1].define(version: 2026_06_01_125209) do +ActiveRecord::Schema[8.1].define(version: 2026_06_18_210000) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" @@ -267,6 +267,7 @@ t.string "legacy_touchpoint_uuid" t.boolean "load_css", default: true t.string "logo" + t.string "logo_alt_text" t.string "medium" t.string "modal_button_text" t.string "name" diff --git a/db/seeds.rb b/db/seeds.rb index 5ad0b0630..730e83b31 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -85,7 +85,7 @@ def production_suitable_seeds org_2 = Organization.create!({ name: 'Farmers.gov', - domain: 'example.gov', + domain: 'farmers.gov', url: 'https://farmers.gov', abbreviation: 'FARMERS' }) diff --git a/spec/controllers/admin/forms_controller_spec.rb b/spec/controllers/admin/forms_controller_spec.rb index 743f2f48f..bf5f890c8 100644 --- a/spec/controllers/admin/forms_controller_spec.rb +++ b/spec/controllers/admin/forms_controller_spec.rb @@ -309,6 +309,18 @@ expect(form.header_logo_display).to eq('banner') expect(response).to render_template(:update_display_logo) end + + it 'updates the logo alt text' do + patch :update_display_logo, params: { + id: form.to_param, + form: { logo: logo_file, header_logo_display: 'banner', logo_alt_text: 'Agency seal' }, + format: :js + }, session: valid_session + + form.reload + expect(form.logo_alt_text).to eq('Agency seal') + expect(response).to render_template(:update_display_logo) + end end context 'with invalid file type' do diff --git a/spec/models/form_spec.rb b/spec/models/form_spec.rb index eae1e7291..15287c74c 100644 --- a/spec/models/form_spec.rb +++ b/spec/models/form_spec.rb @@ -114,6 +114,22 @@ end end + describe '#logo_alt_text_or_default' do + context 'when logo_alt_text is set' do + it 'returns the configured alt text' do + form.update(logo_alt_text: 'Agency seal') + expect(form.logo_alt_text_or_default).to eq('Agency seal') + end + end + + context 'when logo_alt_text is blank' do + it 'falls back to the organization name' do + form.update(logo_alt_text: nil) + expect(form.logo_alt_text_or_default).to eq("#{organization.name} logo") + end + end + end + describe '#user_role?' do context 'without user_role' do it 'returns nil' do