diff --git a/app/assets/images/globe-blue.svg b/app/assets/images/globe-blue.svg
deleted file mode 100644
index a1782e86118..00000000000
--- a/app/assets/images/globe-blue.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/globe-white.svg b/app/assets/images/globe-white.svg
deleted file mode 100644
index 88a59e3d128..00000000000
--- a/app/assets/images/globe-white.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/stylesheets/components/_language-picker.scss b/app/assets/stylesheets/components/_language-picker.scss
index 5910f030e92..481c220f5d2 100644
--- a/app/assets/stylesheets/components/_language-picker.scss
+++ b/app/assets/stylesheets/components/_language-picker.scss
@@ -43,10 +43,6 @@
}
}
- span {
- margin: 0 units(1);
- }
-
&::after {
content: '';
display: block;
@@ -84,6 +80,10 @@
}
}
+.language-picker__label-text {
+ margin: 0 units(1);
+}
+
.language-picker__list {
@include list-reset;
diff --git a/app/components/icon_component.html.erb b/app/components/icon_component.html.erb
index 59d6b4b5695..274a84e440e 100644
--- a/app/components/icon_component.html.erb
+++ b/app/components/icon_component.html.erb
@@ -1,10 +1,11 @@
<%= content_tag(
- :svg,
- aria: { hidden: true },
- focusable: 'false',
- role: 'img',
+ :span,
+ content_tag(
+ :style,
+ "#icon-#{unique_id} { mask-image: url(#{icon_path}); -webkit-mask-image: url(#{icon_path}); }",
+ nonce: content_security_policy_nonce,
+ ),
**tag_options,
+ id: "icon-#{unique_id}",
class: css_class,
- ) do %>
-
-<% end %>
+ ) -%>
diff --git a/app/components/icon_component.rb b/app/components/icon_component.rb
index 40250ff994a..4923b3ea551 100644
--- a/app/components/icon_component.rb
+++ b/app/components/icon_component.rb
@@ -255,13 +255,13 @@ def initialize(icon:, size: nil, **tag_options)
end
def css_class
- classes = ['usa-icon', *tag_options[:class]]
+ classes = ['icon', 'usa-icon', *tag_options[:class]]
classes << "usa-icon--size-#{size}" if size
classes
end
def icon_path
- asset_path([asset_path('sprite.svg'), '#', icon].join, host: asset_host)
+ @icon_path ||= asset_path("usa-icons/#{icon}.svg", host: asset_host)
end
private
diff --git a/app/components/icon_component.scss b/app/components/icon_component.scss
index 6b0bdc27e2a..2591b1d1b9c 100644
--- a/app/components/icon_component.scss
+++ b/app/components/icon_component.scss
@@ -3,6 +3,11 @@
@forward 'usa-icon';
+.icon {
+ mask-size: 100%;
+ background-color: currentColor;
+}
+
$icon-min-padding: 2px;
// Upstream: https://github.com/uswds/uswds/pull/4493
diff --git a/app/components/language_picker_component.html.erb b/app/components/language_picker_component.html.erb
index 7caa09ead3a..5217b896379 100644
--- a/app/components/language_picker_component.html.erb
+++ b/app/components/language_picker_component.html.erb
@@ -7,9 +7,8 @@
expanded: false,
},
) do %>
- <%= image_tag(asset_url('globe-blue.svg'), width: 12, height: 12, alt: '', class: 'tablet:display-none') %>
- <%= image_tag(asset_url('globe-white.svg'), width: 12, height: 12, alt: '', class: 'display-none tablet:display-inline') %>
-
+ <%= render IconComponent.new(icon: :language) %>
+
<%= t('i18n.language') %>
<% end %>
diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb
index 5f734f347bc..29d2b0e5002 100644
--- a/config/initializers/content_security_policy.rb
+++ b/config/initializers/content_security_policy.rb
@@ -47,5 +47,5 @@
# rubocop:enable Metrics/BlockLength
Rails.application.configure do
config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
- config.content_security_policy_nonce_directives = ['script-src']
+ config.content_security_policy_nonce_directives = ['script-src', 'style-src']
end
diff --git a/spec/components/button_component_spec.rb b/spec/components/button_component_spec.rb
index ce0ef65f49e..f448f220ce9 100644
--- a/spec/components/button_component_spec.rb
+++ b/spec/components/button_component_spec.rb
@@ -83,7 +83,7 @@
it 'renders an icon' do
rendered = render_inline ButtonComponent.new(icon: :print).with_content(content)
- expect(rendered).to have_css('use[href$="#print"]')
+ expect(rendered).to have_xpath('//style[contains(text(), "/print-")]')
expect(rendered.first_element_child.xpath('./text()').text).to eq(content)
end
@@ -93,7 +93,7 @@
it 'trims text of the content, maintaining html safety' do
rendered = render_inline ButtonComponent.new(icon: :print).with_content(content)
- expect(rendered.to_html).to include('Button')
+ expect(rendered.to_html).to include('Button')
end
end
@@ -103,7 +103,9 @@
it 'trims text of the content, maintaining html safety' do
rendered = render_inline ButtonComponent.new(icon: :print).with_content(content)
- expect(rendered.to_html).to include('<span class="example">Button</span>')
+ expect(rendered.to_html).to include(
+ '<span class="example">Button</span>',
+ )
end
end
diff --git a/spec/components/icon_component_spec.rb b/spec/components/icon_component_spec.rb
index ea92deadcaa..dc1fce80ed4 100644
--- a/spec/components/icon_component_spec.rb
+++ b/spec/components/icon_component_spec.rb
@@ -12,9 +12,15 @@
it 'renders icon svg' do
rendered = render_inline IconComponent.new(icon: :print)
- expect(rendered).to have_css(
- ".usa-icon use[href^='#{vc_test_request.base_url}'][href$='.svg#print']",
- )
+ icon = rendered.at_css('.icon.usa-icon')
+ id = icon.attr(:id)
+ inline_style = rendered.at_css('style').text.strip
+
+ expect(icon).to be_present
+ expect(inline_style).to match(%r{##{id}\s{.+?}}).
+ and(include('-webkit-mask-image:')).
+ and(include('mask-image:')).
+ and(match(%r{url\([^)]+/print-\w+\.svg\)}))
end
context 'with invalid icon' do
@@ -27,7 +33,7 @@
it 'adds size variant class' do
rendered = render_inline IconComponent.new(icon: :print, size: 2)
- expect(rendered).to have_css('.usa-icon.usa-icon--size-2')
+ expect(rendered).to have_css('.icon.usa-icon.usa-icon--size-2')
end
end
@@ -35,7 +41,7 @@
it 'renders with class' do
rendered = render_inline IconComponent.new(icon: :print, class: 'my-custom-class')
- expect(rendered).to have_css('.usa-icon.my-custom-class')
+ expect(rendered).to have_css('.icon.usa-icon.my-custom-class')
end
end
@@ -43,7 +49,7 @@
it 'renders with attributes' do
rendered = render_inline IconComponent.new(icon: :print, data: { foo: 'bar' })
- expect(rendered).to have_css('.usa-icon[data-foo="bar"]')
+ expect(rendered).to have_css('.icon.usa-icon[data-foo="bar"]')
end
end
@@ -55,9 +61,9 @@
it 'bypasses configured asset_host and uses domain_name instead' do
rendered = render_inline IconComponent.new(icon: :print)
- href = rendered.css('use').first['href']
+ inline_style = rendered.at_css('style').text.strip
- expect(href).to start_with(domain_name)
+ expect(inline_style).to match(%r{url\(#{Regexp.escape(domain_name)}})
end
end
end
diff --git a/spec/components/icon_list_component_spec.rb b/spec/components/icon_list_component_spec.rb
index 599ede1b38c..83acec19eb7 100644
--- a/spec/components/icon_list_component_spec.rb
+++ b/spec/components/icon_list_component_spec.rb
@@ -35,7 +35,7 @@
it 'renders items with default color' do
expect(rendered).to have_css('.usa-icon-list__icon:not([class*="text-"])', count: 2)
- expect(rendered).to have_css('.usa-icon use[href$=".svg#cancel"]', count: 2)
+ expect(rendered).to have_xpath('//style[contains(text(), "/cancel-")]')
end
context 'with icon or color attributes specified on parent component' do
@@ -48,7 +48,7 @@
it 'passes those attributes to slotted items' do
expect(rendered).to have_css('.usa-icon-list__icon.text-error', count: 2)
- expect(rendered).to have_css('.usa-icon use[href$=".svg#cancel"]', count: 2)
+ expect(rendered).to have_xpath('//style[contains(text(), "/cancel-")]', count: 2)
end
end
@@ -62,9 +62,9 @@
it 'renders items with their attributes' do
expect(rendered).to have_css('.usa-icon-list__icon.text-success', count: 1)
- expect(rendered).to have_css('.usa-icon use[href$=".svg#check_circle"]', count: 1)
+ expect(rendered).to have_xpath('//style[contains(text(), "/check_circle-")]', count: 1)
expect(rendered).to have_css('.usa-icon-list__icon.text-error', count: 1)
- expect(rendered).to have_css('.usa-icon use[href$=".svg#cancel"]', count: 1)
+ expect(rendered).to have_xpath('//style[contains(text(), "/cancel-")]', count: 1)
end
end
diff --git a/spec/features/phone/add_phone_spec.rb b/spec/features/phone/add_phone_spec.rb
index 9ee08661408..1b14f111958 100644
--- a/spec/features/phone/add_phone_spec.rb
+++ b/spec/features/phone/add_phone_spec.rb
@@ -6,7 +6,7 @@
phone = '+1 (225) 278-1234'
sign_in_and_2fa_user(user)
- expect(page).to have_link(t('account.index.phone_add'), normalize_ws: true, exact: true)
+ expect(page).to have_link(href: phone_setup_path, text: t('account.index.phone_add'))
within('.sidenav') do
click_on t('account.navigation.add_phone_number')
end
diff --git a/spec/requests/csp_spec.rb b/spec/requests/csp_spec.rb
index 73440a443ac..cbe92e3b7b2 100644
--- a/spec/requests/csp_spec.rb
+++ b/spec/requests/csp_spec.rb
@@ -31,7 +31,7 @@
expect(content_security_policy['script-src']).to match(
/'self' 'unsafe-eval' 'nonce-[\w\d=\/+]+'/,
)
- expect(content_security_policy['style-src']).to eq("'self'")
+ expect(content_security_policy['style-src']).to match(/'self' 'nonce-[\w\d=\/+]+'/)
end
it 'uses logout SP to override CSP form action that will allow a redirect to the CSP' do
@@ -75,7 +75,7 @@
expect(content_security_policy['script-src']).to match(
/'self' 'unsafe-eval' 'nonce-[\w\d=\/+]+'/,
)
- expect(content_security_policy['style-src']).to eq("'self'")
+ expect(content_security_policy['style-src']).to match(/'self' 'nonce-[\w\d=\/+]+'/)
end
it 'uses logout SP to override CSP form action that will allow a redirect to the CSP' do
@@ -111,7 +111,7 @@
expect(content_security_policy['script-src']).to match(
/'self' 'unsafe-eval' 'nonce-[\w\d=\/+]+'/,
)
- expect(content_security_policy['style-src']).to eq("'self'")
+ expect(content_security_policy['style-src']).to match(/'self' 'nonce-[\w\d=\/+]+'/)
end
end