Skip to content

Commit 432e4d4

Browse files
dflclaude
andcommitted
Normalize SVG fill/stroke to currentColor at authoring time
Instead of rewriting attribute values with regexes at load time, update the source SVG files to use fill="currentColor" / stroke="currentColor" directly. The load-time gsub transformation is removed; the loader now just reads each file verbatim and raises if viewBox is missing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent f589e67 commit 432e4d4

6 files changed

Lines changed: 26 additions & 29 deletions

File tree

Lines changed: 1 addition & 1 deletion
Loading

app/assets/images/icons/clock.svg

Lines changed: 1 addition & 1 deletion
Loading

app/assets/images/icons/id.svg

Lines changed: 1 addition & 1 deletion
Loading

app/assets/images/icons/loading.svg

Lines changed: 12 additions & 12 deletions
Loading
Lines changed: 3 additions & 3 deletions
Loading

app/components/base_component.rb

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,17 @@ class BaseComponent < ViewComponent::Base
1010
CfaUiComponents::Engine.root.join("app/assets/images", SPRITE_PATH)
1111
).scan(/<symbol id="([^"]+)"/).flatten.to_set.freeze
1212

13-
# File-based icons not present in the USWDS sprite. Pre-read at load time;
14-
# hardcoded fill/stroke colors are replaced with currentColor so the rendered
15-
# SVG inherits its color from the CSS `color` property, same as USWDS icons.
13+
# File-based icons not present in the USWDS sprite. Pre-read at load time
14+
# so inline_icon can render them without an asset pipeline round-trip.
15+
# SVG files must use fill="currentColor"/stroke="currentColor" so icons
16+
# inherit the CSS `color` property the same way USWDS sprite icons do.
1617
NON_USWDS_ICONS = Dir.glob(
1718
CfaUiComponents::Engine.root.join("app/assets/images/icons/*.svg")
1819
).each_with_object({}) do |file, icons|
1920
raw = File.read(file)
20-
viewbox = raw[/\bviewBox="([^"]+)"/i, 1]
21+
viewbox = raw[/\bviewBox="([^"]+)"/i, 1] or
22+
raise "#{file} is missing a viewBox attribute"
2123
inner = raw.sub(/\A.*?<svg[^>]*>/m, "").sub(/<\/svg>\s*\z/m, "").strip
22-
inner = inner
23-
.gsub(/\bfill="[^"]*"/) { |m| (m == 'fill="none"') ? m : 'fill="currentColor"' }
24-
.gsub(/\bstroke="[^"]*"/) { |m| (m == 'stroke="none"') ? m : 'stroke="currentColor"' }
2524
icons[File.basename(file, ".svg")] = {viewbox:, inner:}
2625
end.freeze
2726

@@ -58,10 +57,8 @@ def icon_aria(name, aria_hidden:, label:)
5857
{:role => "img", "aria-label" => label || "#{name.tr("_", " ")} icon"}
5958
end
6059

61-
# Inline SVG for file-based icons. Uses fill/stroke="currentColor" (substituted
62-
# at load time) so the icon inherits the CSS `color` property without any
63-
# CSS mask-image indirection, which browsers drop after Alpine-triggered style
64-
# recalculation.
60+
# Inline SVG for file-based icons. fill/stroke="currentColor" in the source
61+
# SVGs means the icon inherits CSS `color` without any mask-image indirection.
6562
def inline_svg_icon(icon, name, size:, css_class:, aria_hidden:, label:)
6663
content_tag :svg, icon[:inner].html_safe,
6764
viewBox: icon[:viewbox],

0 commit comments

Comments
 (0)