Skip to content

Commit

Permalink
Use inline icons as components
Browse files Browse the repository at this point in the history
This is a backport of #2670
  • Loading branch information
jcoyne committed May 19, 2022
1 parent 5af44ee commit db17ced
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 22 deletions.
29 changes: 29 additions & 0 deletions app/components/blacklight/icons/legacy_icon_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

module Blacklight
module Icons
class LegacyIconComponent < ::ViewComponent::Base
extend Deprecation

def initialize(name:, classes: '', aria_hidden: false, label: true, role: 'img', additional_options: {})
@name = name
Deprecation.warn(self, "Calling the LegacyIconComponent with \"#{name}\" is deprecated. Instead create a component for this icon.")
@classes = classes
@aria_hidden = aria_hidden
@icon = Blacklight::Icon.new(name, classes: classes, label: label, role: role, additional_options: additional_options)
end

def call
tag.span(svg.html_safe, # rubocop:disable Rails/OutputSafety
class: "blacklight-icons blacklight-icon-#{@name} #{@classes}".strip,
'aria-hidden': (true if @aria_hidden))
end

def svg
Rails.cache.fetch([:blacklight_icon_svg, @name]) do
@icon.svg
end
end
end
end
end
20 changes: 20 additions & 0 deletions app/components/blacklight/icons/list_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

module Blacklight
module Icons
# This is the list icon for the search button.
# You can override the default svg by setting:
# Blacklight::Icons::ListComponent.svg = '<svg>your SVG here</svg>'
class ListComponent < ::ViewComponent::Base
def call
svg.html_safe # rubocop:disable Rails/OutputSafety
end

class_attribute :svg, default: <<~SVG
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">
<path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
</svg>
SVG
end
end
end
20 changes: 20 additions & 0 deletions app/components/blacklight/icons/search_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

module Blacklight
module Icons
# This is the magnifing glass icon for the search button.
# You can override the default svg by setting:
# Blacklight::Icons::SearchComponent.svg = '<svg>your SVG here</svg>'
class SearchComponent < ::ViewComponent::Base
def call
svg.html_safe # rubocop:disable Rails/OutputSafety
end

class_attribute :svg, default: <<~SVG
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">
<path fill="none" d="M0 0h24v24H0V0z"/><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
</svg>
SVG
end
end
end
9 changes: 4 additions & 5 deletions app/helpers/blacklight/icon_helper_behavior.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ module Blacklight::IconHelperBehavior
# the svg everytime.
# @param [String, Symbol] icon_name
# @return [String]
def blacklight_icon(icon_name, options = {})
Rails.cache.fetch([:blacklight_icons, icon_name, options]) do
icon = Blacklight::Icon.new(icon_name, **options)
tag.span(icon.svg.html_safe, **icon.options)
end
def blacklight_icon(icon_name, _options = {})
render "Blacklight::Icons::#{icon_name.to_s.camelize}Component".constantize.new
rescue NameError
render Blacklight::Icons::LegacyIconComponent.new(name: icon_name)
end
end
7 changes: 4 additions & 3 deletions spec/helpers/blacklight/icon_helper_behavior_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

RSpec.describe Blacklight::IconHelperBehavior do
describe '#blacklight_icon' do
it 'wraps the svg in a span with classes' do
expect(helper.blacklight_icon(:search))
.to have_css 'span.blacklight-icons svg'
subject(:icon) { helper.blacklight_icon(:search) }

it 'returns the svg' do
expect(icon).to have_css 'svg'
end
end
end
40 changes: 26 additions & 14 deletions spec/models/blacklight/icon_spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
# frozen_string_literal: true

RSpec.describe Blacklight::Icon do
subject { described_class.new(:search, classes: 'awesome', aria_hidden: true) }
subject(:instance) { described_class.new(:test, classes: 'awesome', aria_hidden: true) }

let(:svg) { String.new(Blacklight::Icons::SearchComponent.new.svg) }
let(:sprockets_asset) { instance_double(Sprockets::Asset, source: svg) }

before do
allow(Rails.application.assets).to receive(:find_asset).and_return(sprockets_asset)
# FileUtils.mkdir_p '.internal_test_app/app/assets/images/blacklight'
# File.write '.internal_test_app/app/assets/images/blacklight/test.svg', Blacklight::Icons::SearchComponent.new.svg
end

describe '#svg' do
it 'returns a string' do
Expand All @@ -20,31 +29,31 @@

it 'adds title' do
expect(Capybara.string(subject.svg))
.to have_css 'title', text: 'Search'
.to have_css 'title', text: 'Test'
end

context 'when label is false' do
subject { described_class.new(:search, classes: 'awesome', aria_hidden: true, label: false) }
subject { described_class.new(:test, classes: 'awesome', aria_hidden: true, label: false) }

it 'does not add title' do
expect(Capybara.string(subject.svg))
.not_to have_css 'title', text: 'Search'
.not_to have_css 'title', text: 'Test'
end
end

context ' with a label context' do
subject { described_class.new(:search, classes: 'awesome', aria_hidden: true, additional_options: { label_context: 'foo' }) }
context 'with a label context' do
subject { described_class.new(:test, classes: 'awesome', aria_hidden: true, additional_options: { label_context: 'foo' }) }

it 'adds title' do
expect(Capybara.string(subject.svg))
.to have_css 'title', text: 'Search'
.to have_css 'title', text: 'Test'
end
end
end

describe '#options' do
it 'applies options classes and default class' do
expect(subject.options[:class]).to eq 'blacklight-icons blacklight-icon-search awesome'
expect(subject.options[:class]).to eq 'blacklight-icons blacklight-icon-test awesome'
end

it 'applies options aria-hidden=true' do
Expand All @@ -66,23 +75,26 @@

describe '#path' do
it 'prepends blacklight and sufixes .svg' do
expect(subject.path).to eq 'blacklight/search.svg'
expect(subject.path).to eq 'blacklight/test.svg'
end
end

describe 'file_source' do
subject(:file_source) { instance.file_source }

context 'file is not available' do
subject { described_class.new(:yolo) }

it {
expect { subject.file_source }
.to raise_error(Blacklight::Exceptions::IconNotFound)
}
let(:sprockets_asset) { nil }

it 'raises an error when not found' do
expect { file_source }.to raise_error(Blacklight::Exceptions::IconNotFound)
end
end

context 'file is available' do
it 'returns the filesource' do
expect(subject.file_source).to include '<svg'
expect(file_source).to include '<svg'
end
end
end
Expand Down

0 comments on commit db17ced

Please sign in to comment.