diff --git a/lib/phlexy_ui/indicator.rb b/lib/phlexy_ui/indicator.rb new file mode 100644 index 0000000..53c8b08 --- /dev/null +++ b/lib/phlexy_ui/indicator.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module PhlexyUI + class Indicator < Base + def initialize(*, as: :div, **) + super(*, **) + @as = as + end + + def view_template(&) + generate_classes!( + # "indicator" + component_html_class: :indicator, + options: + ).then do |classes| + public_send(as, class: classes, **options, &) + end + end + + def item(*base_modifiers, **, &) + render IndicatorItem.new(*base_modifiers, **, &) + end + end +end diff --git a/lib/phlexy_ui/indicator_item.rb b/lib/phlexy_ui/indicator_item.rb new file mode 100644 index 0000000..c162965 --- /dev/null +++ b/lib/phlexy_ui/indicator_item.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +module PhlexyUI + class IndicatorItem < Base + def initialize(*, as: :span, **) + super(*, **) + @as = as + end + + def view_template(&) + generate_classes!( + # "indicator-item" + component_html_class: :"indicator-item", + modifiers_map: modifiers, + base_modifiers:, + options: + ).then do |classes| + public_send(as, class: classes, **options, &) + end + end + + private + + register_modifiers( + # "sm:indicator-start" + # "@sm:indicator-start" + # "md:indicator-start" + # "@md:indicator-start" + # "lg:indicator-start" + # "@lg:indicator-start" + start: "indicator-start", + # "sm:indicator-center" + # "@sm:indicator-center" + # "md:indicator-center" + # "@md:indicator-center" + # "lg:indicator-center" + # "@lg:indicator-center" + center: "indicator-center", + # "sm:indicator-end" + # "@sm:indicator-end" + # "md:indicator-end" + # "@md:indicator-end" + # "lg:indicator-end" + # "@lg:indicator-end" + end: "indicator-end", + # "sm:indicator-top" + # "@sm:indicator-top" + # "md:indicator-top" + # "@md:indicator-top" + # "lg:indicator-top" + # "@lg:indicator-top" + top: "indicator-top", + # "sm:indicator-middle" + # "@sm:indicator-middle" + # "md:indicator-middle" + # "@md:indicator-middle" + # "lg:indicator-middle" + # "@lg:indicator-middle" + middle: "indicator-middle", + # "sm:indicator-bottom" + # "@sm:indicator-bottom" + # "md:indicator-bottom" + # "@md:indicator-bottom" + # "lg:indicator-bottom" + # "@lg:indicator-bottom" + bottom: "indicator-bottom" + ) + end +end diff --git a/spec/lib/phlexy_ui/indicator_spec.rb b/spec/lib/phlexy_ui/indicator_spec.rb new file mode 100644 index 0000000..d49caac --- /dev/null +++ b/spec/lib/phlexy_ui/indicator_spec.rb @@ -0,0 +1,199 @@ +require "spec_helper" + +describe PhlexyUI::Indicator do + subject(:output) { render described_class.new } + + it "is expected to match the formatted HTML" do + expected_html = html <<~HTML +
+ HTML + + is_expected.to eq(expected_html) + end + + describe "with item" do + subject(:output) do + render described_class.new do |i| + i.item { "Badge 1" } + i.item { "Badge 2" } + end + end + + it "renders item" do + expected_html = html <<~HTML +
+ Badge 1 + Badge 2 +
+ HTML + + expect(output).to eq(expected_html) + end + end + + describe "conditions" do + { + start: "indicator-start", + center: "indicator-center", + end: "indicator-end", + top: "indicator-top", + middle: "indicator-middle", + bottom: "indicator-bottom" + }.each do |modifier, css| + context "when given :#{modifier} modifier on an item" do + subject(:output) do + render described_class.new do |indicator| + indicator.item modifier + end + end + + it "renders it apart from the main class" do + expected_html = html <<~HTML +
+ +
+ HTML + + expect(output).to eq(expected_html) + end + end + end + + context "when given multiple conditions on an item" do + subject(:output) do + render described_class.new do |indicator| + indicator.item :top, :end + end + end + + it "renders them separately" do + expected_html = html <<~HTML +
+ +
+ HTML + + expect(output).to eq(expected_html) + end + end + end + + describe "data" do + subject(:output) do + render described_class.new(data: {foo: "bar"}) do |indicator| + indicator.item data: {baz: "qux"} + end + end + + it "renders it correctly" do + expected_html = html <<~HTML +
+ +
+ HTML + + expect(output).to eq(expected_html) + end + end + + describe "responsiveness" do + %i[sm md lg xl @sm @md @lg @xl].each do |viewport| + context "when given an :#{viewport} responsive option" do + subject(:output) do + render described_class.new do |indicator| + indicator.item responsive: {viewport => :bottom} + indicator.item responsive: {viewport => true} + end + end + + it "renders it separately with a responsive prefix" do + expected_html = html <<~HTML +
+ + +
+ HTML + + expect(output).to eq(expected_html) + end + end + end + end + + describe "passing :as option" do + subject(:output) { render described_class.new(as: :div) } + + it "renders as the given tag" do + expected_html = html <<~HTML +
+ HTML + + expect(output).to eq(expected_html) + end + end + + describe "rendering via Kit" do + subject(:output) do + Indicator do |indicator| + indicator.item :top + end + end + + it "renders it correctly" do + expected_html = html <<~HTML +
+ +
+ HTML + + expect(output).to eq(expected_html) + end + end + + describe "rendering a full indicator" do + let(:component) do + Class.new(Phlex::HTML) do + def view_template(&) + # Ignores :top modifier on the main component + render PhlexyUI::Indicator.new(:top, data: {foo: "bar"}) do |i| + i.item(:top, :start, class: "badge", data: {baz: "qux"}) { "↖︎" } + i.item(:top, :center, class: "badge") { "↑" } + i.item(:top, :end, class: "badge") { "↗︎" } + i.item(:middle, :start, class: "badge") { "←" } + i.item(:middle, :center, class: "badge") { "●" } + i.item(:middle, :end, class: "badge") { "→" } + i.item(:bottom, :start, class: "badge") { "↙︎" } + i.item(:bottom, :center, class: "badge") { "↓" } + i.item(:bottom, :end, class: "badge") { "↘︎" } + div(class: "bg-base-300 grid h-32 w-60 place-items-center") do + "Box" + end + end + end + end + end + + subject(:output) do + render component.new + end + + it "renders it correctly" do + expected_html = html <<~HTML +
+ ↖︎ + + ↗︎ + + + + ↙︎ + + ↘︎ +
Box
+
+ HTML + + expect(output).to eq(expected_html) + end + end +end