-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Summary
USWDS alert markup is duplicated across 12 view files with inconsistent ARIA roles, heading levels, and margin classes. Extract a reusable AlertComponent using ViewComponent (already a project dependency at v4.5.0, used throughout the Strata SDK), then sweep all instances to use it.
Background
The _flash.html.erb partial has a TODO dating back to early development: "Dry this up using a partial or something like View Components." Since then, alert usage has grown across the app. Current issues:
- Inconsistency: Some info alerts incorrectly use
role="alert"(which is assertive and interrupts screen readers). Per USWDS guidelines, only error/emergency alerts should haverole="alert". - Duplication: Each instance re-implements the same
usa-alert/usa-alert__body/usa-alert__textstructure with minor variations. - Heading levels: Some alerts hardcode
<h3>, others use<h4>— the correct level depends on page context.
Reference: Similar Cleanup
PR #344 did the same kind of cleanup for USWDS icons: a uswds_icon helper was created, then all 6 files with inline SVG markup were swept to use it. Each replacement was mechanical (4 lines → 1 helper call) with identical HTML output and no behavior change.
This ticket follows the same approach, but uses a ViewComponent instead of a plain helper because alerts need to render nested content (error lists, buttons, accordions).
The work can be split across two PRs following the same pattern:
- Create
AlertComponentwith specs - Sweep all 12 views to use the component (pure refactor, no behavior change)
Affected Files (12 instances)
~8 are simple alerts (heading + text). 3 need block mode for complex content:
app/views/application/_flash.html.erb— success + error flash alerts (error lists, reload button)app/views/application/_case_documents.html.erbapp/views/application/_case_tasks.html.erbapp/views/dashboard/_request_for_information.html.erb— conditional link buttonsapp/views/dashboard/_activity_report_denied.html.erbapp/views/dashboard/_exemption_denied.html.erbapp/views/document_staging/create.html.erbapp/views/information_requests/_edit.html.erbapp/views/staff/certification_batch_uploads/index.html.erbapp/views/staff/certification_batch_uploads/new.html.erb— accordion inside alertapp/views/staff/certification_batch_uploads/_status_alert.html.erbapp/views/users/passwords/reset.html.erb
Proposed API
# app/components/alert_component.rb
class AlertComponent < ViewComponent::Base
TYPES = %w[info success warning error].freeze
renders_one :body # for complex content (block mode)
def initialize(type:, heading: nil, message: nil, heading_level: 2, classes: nil)
# type determines ARIA role: only "error" gets role="alert"
# heading_level allows callers to set contextually correct heading
# classes for extra CSS (margins, slim, no-icon)
end
endSimple mode:
<%= render AlertComponent.new(type: "success", heading: "Saved", message: "Your changes were saved.") %>Block mode (for complex content like lists, buttons, accordions):
<%= render AlertComponent.new(type: "error", heading: "Errors found") do |c| %>
<% c.with_body do %>
<ul class="usa-list">
<% errors.each do |error| %>
<li><%= error %></li>
<% end %>
</ul>
<% end %>
<% end %>Acceptance Criteria
-
AlertComponentexists withtype,heading,message,heading_level, andclassesparams - Supports simple mode (heading + message) and block mode (arbitrary content via
renders_one :body) -
role="alert"only applied fortype: "error"— all other types omit it - Component specs cover all types, both modes, heading level override, and ARIA role logic
- All 12 view files refactored to use the component
- No visual or behavioral changes (verify with existing tests + manual spot check)
- Existing test suite passes
Technical Notes
- ViewComponent is already in the Gemfile (v4.5.0) and used by Strata SDK (
AccordionComponent, etc.) - Follow existing Strata component conventions for file layout (
app/components/,app/components/*.html.erb) - The Strata SDK itself has the same gap (
_no_tasks_alert.html.erbuses raw markup) — this component could eventually be contributed upstream
Out of Scope
- Contributing this component to the Strata SDK. The SDK has the same gap (
_no_tasks_alert.html.erbuses raw alert markup), but the component API should stabilize in OSCER first. Revisit after this work ships.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status