From 3654b46fbf65b752da7528e38c40a2bc84400e66 Mon Sep 17 00:00:00 2001 From: mhenrixon Date: Sat, 8 Nov 2025 08:17:00 +0100 Subject: [PATCH] Add FileInput component - Implements FileInput component with DaisyUI styling - Adds comprehensive test coverage - Includes responsive class comments for Tailwind --- lib/phlexy_ui/file_input.rb | 124 ++++++++++++++++++++++++++ spec/lib/phlexy_ui/file_input_spec.rb | 100 +++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 lib/phlexy_ui/file_input.rb create mode 100644 spec/lib/phlexy_ui/file_input_spec.rb diff --git a/lib/phlexy_ui/file_input.rb b/lib/phlexy_ui/file_input.rb new file mode 100644 index 0000000..b2d3fc7 --- /dev/null +++ b/lib/phlexy_ui/file_input.rb @@ -0,0 +1,124 @@ +# frozen_string_literal: true + +module PhlexyUI + # @component html class="file-input" + class FileInput < Base + def initialize(*, as: :input, **) + super(*, **) + @as = as + end + + def view_template(&) + generate_classes!( + # "file-input" + component_html_class: :"file-input", + modifiers_map: modifiers, + base_modifiers:, + options: + ).then do |classes| + public_send(as, type: :file, class: classes, **options, &) + end + end + + register_modifiers( + # "sm:file-input-ghost" + # "@sm:file-input-ghost" + # "md:file-input-ghost" + # "@md:file-input-ghost" + # "lg:file-input-ghost" + # "@lg:file-input-ghost" + ghost: "file-input-ghost", + # "sm:file-input-xs" + # "@sm:file-input-xs" + # "md:file-input-xs" + # "@md:file-input-xs" + # "lg:file-input-xs" + # "@lg:file-input-xs" + xs: "file-input-xs", + # "sm:file-input-sm" + # "@sm:file-input-sm" + # "md:file-input-sm" + # "@md:file-input-sm" + # "lg:file-input-sm" + # "@lg:file-input-sm" + sm: "file-input-sm", + # "sm:file-input-md" + # "@sm:file-input-md" + # "md:file-input-md" + # "@md:file-input-md" + # "lg:file-input-md" + # "@lg:file-input-md" + md: "file-input-md", + # "sm:file-input-lg" + # "@sm:file-input-lg" + # "md:file-input-lg" + # "@md:file-input-lg" + # "lg:file-input-lg" + # "@lg:file-input-lg" + lg: "file-input-lg", + # "sm:file-input-xl" + # "@sm:file-input-xl" + # "md:file-input-xl" + # "@md:file-input-xl" + # "lg:file-input-xl" + # "@lg:file-input-xl" + xl: "file-input-xl", + # "sm:file-input-neutral" + # "@sm:file-input-neutral" + # "md:file-input-neutral" + # "@md:file-input-neutral" + # "lg:file-input-neutral" + # "@lg:file-input-neutral" + neutral: "file-input-neutral", + # "sm:file-input-primary" + # "@sm:file-input-primary" + # "md:file-input-primary" + # "@md:file-input-primary" + # "lg:file-input-primary" + # "@lg:file-input-primary" + primary: "file-input-primary", + # "sm:file-input-secondary" + # "@sm:file-input-secondary" + # "md:file-input-secondary" + # "@md:file-input-secondary" + # "lg:file-input-secondary" + # "@lg:file-input-secondary" + secondary: "file-input-secondary", + # "sm:file-input-accent" + # "@sm:file-input-accent" + # "md:file-input-accent" + # "@md:file-input-accent" + # "lg:file-input-accent" + # "@lg:file-input-accent" + accent: "file-input-accent", + # "sm:file-input-info" + # "@sm:file-input-info" + # "md:file-input-info" + # "@md:file-input-info" + # "lg:file-input-info" + # "@lg:file-input-info" + info: "file-input-info", + # "sm:file-input-success" + # "@sm:file-input-success" + # "md:file-input-success" + # "@md:file-input-success" + # "lg:file-input-success" + # "@lg:file-input-success" + success: "file-input-success", + # "sm:file-input-warning" + # "@sm:file-input-warning" + # "md:file-input-warning" + # "@md:file-input-warning" + # "lg:file-input-warning" + # "@lg:file-input-warning" + warning: "file-input-warning", + # "sm:file-input-error" + # "@sm:file-input-error" + # "md:file-input-error" + # "@md:file-input-error" + # "lg:file-input-error" + # "@lg:file-input-error" + error: "file-input-error" + ) + end +end diff --git a/spec/lib/phlexy_ui/file_input_spec.rb b/spec/lib/phlexy_ui/file_input_spec.rb new file mode 100644 index 0000000..88ee92c --- /dev/null +++ b/spec/lib/phlexy_ui/file_input_spec.rb @@ -0,0 +1,100 @@ +require "spec_helper" + +describe PhlexyUI::FileInput 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 "conditions" do + { + ghost: "file-input-ghost", + xs: "file-input-xs", + sm: "file-input-sm", + md: "file-input-md", + lg: "file-input-lg", + xl: "file-input-xl", + neutral: "file-input-neutral", + primary: "file-input-primary", + secondary: "file-input-secondary", + accent: "file-input-accent", + info: "file-input-info", + success: "file-input-success", + warning: "file-input-warning", + error: "file-input-error" + }.each do |modifier, css| + context "when given :#{modifier} modifier" do + subject(:output) { render described_class.new(modifier) } + + 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" do + subject(:output) { render described_class.new(:primary, :lg) } + + 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"}) + 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(:primary, responsive: {viewport => :secondary}) + 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: :button) } + + it "renders as the given tag" do + expected_html = html <<~HTML + + HTML + + expect(output).to eq(expected_html) + end + end +end