simple_form_tailwind_css 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b73ad445d1750d1d2ee3e739191e13faf3810ffb21cd4b70b950ea1231c496fe
4
+ data.tar.gz: 837eecadfea116d27a355f6ee87d6466cae2d58b6a9737cb15a32b88af3a6bc0
5
+ SHA512:
6
+ metadata.gz: ff4c73b207528ed9297774f13867d89ef662e1ab4ac20ca32caa32a598b0f0220442371e31c78b0cf4ecbe7b83d3817bfe50232ee960aca4b9fc714f155215ba
7
+ data.tar.gz: 4b9f200c89ea591ea4abd778a2de6b83b077c87bebb6554347532f319c0416c919a87ee9422e17f4a5484b4f1fe6f083a5ae5d0cd0cfd6ddf25408287a869b9b
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/tmp
9
+ /tmp/
10
+ Gemfile.lock
11
+
12
+ # rspec failure tracking
13
+ .rspec_status
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in simple_form_tailwind.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 10.0"
9
+
10
+ group :test do
11
+ gem "rspec", "~> 3.0"
12
+ gem "generator_spec"
13
+ gem "timecop"
14
+ gem "pry"
15
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Abe Voelker
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,130 @@
1
+ # SimpleForm::Tailwind
2
+
3
+ Tailwind components for [Simple Form][]
4
+
5
+ ## Installation
6
+
7
+ First, install and setup [Tailwind](https://github.com/rails/tailwindcss-rails) ([helpful additional steps here](https://github.com/rails/tailwindcss-rails/issues/25)), [Simple Form][], and the [heroicon gem](https://github.com/bharget/heroicon).
8
+
9
+ Then add this gem to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem "simple_form_tailwind", github: "abevoelker/simple_form_tailwind"
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ ```
18
+ $ bundle install
19
+ ```
20
+
21
+ Finally, overwrite your Simple Form initializer with ours:
22
+
23
+ ```
24
+ $ rails g simple_form:tailwind:install
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ Here's an example form demonstrating usage:
30
+
31
+ ```erb
32
+ <%= simple_form_for(@foo, builder: SimpleForm::Tailwind::FormBuilder) do |f| %>
33
+ <%= f.error_notification %>
34
+ <%= f.input :name, autocomplete: "name", placeholder: "Alex Smith", label: "Display name" %>
35
+ <%= f.input :email, autocomplete: "email", placeholder: "asmith@example.com", label: "Email address" %>
36
+ <div>
37
+ <%= f.button :button, "Get started", class: "w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" %>
38
+ </div>
39
+ <% end %>
40
+ ```
41
+
42
+ One important difference when using Tailwind form builder versus Simple Form's default form builder is that `:error_class` and `:valid_class` classes **completely overwrite** `:class` rather than add to it. This is more amenable to the Tailwind way of doing things, as the "error" state may have completely different classes than the form component in its "default" state.
43
+
44
+ ## Components
45
+
46
+ ### Default
47
+
48
+ ```
49
+ <%= f.input :display_name, placeholder: "Alex Smith", hint: "Max 255 characters" %>
50
+ ```
51
+
52
+ ![Default component preview](/docs/images/components/default.png?raw=true)
53
+
54
+ With an error, it looks like this:
55
+
56
+ ![Default component with error preview](/docs/images/components/default_with_error.png?raw=true)
57
+
58
+ ### Corner hint
59
+
60
+ ```
61
+ <%= f.input :display_name, wrapper: "corner_hint", placeholder: "Alex Smith", hint: "Max 255 characters" %>
62
+ ```
63
+
64
+ ![Corner hint component preview](/docs/images/components/corner_hint.png?raw=true)
65
+
66
+ ### Prepend
67
+
68
+ ```
69
+ <%= f.input :twitter_username, as: "prepend_string", prepend: "twitter.com/", placeholder: "jack" %>
70
+ ```
71
+
72
+ ![Prepend component preview](/docs/images/components/prepend.png?raw=true)
73
+
74
+ ### Append
75
+
76
+ ```
77
+ <%= f.input :substack_username, as: "append_string", append: ".substack.com", placeholder: "graymirror" %>
78
+ ```
79
+
80
+ ![Append component preview](/docs/images/components/append.png?raw=true)
81
+
82
+ ### Error notification
83
+
84
+ Simple Form's error notification is supported, defaulting to a red color with x-circle Heroicon:
85
+
86
+ ```erb
87
+ <%= f.error_notification %>
88
+ ```
89
+
90
+ ![Red error notification](/docs/images/error_notification_red.png?raw=true)
91
+
92
+ You can customize the color and icon used:
93
+
94
+ ```erb
95
+ <%= f.error_notification color: "blue", icon: "information-circle" %>
96
+ ```
97
+
98
+ ![Blue error notification](/docs/images/error_notification_blue.png?raw=true)
99
+
100
+ The message and other parameters can be customized using the [expected Simple Form configuration options](https://www.rubydoc.info/github/plataformatec/simple_form/SimpleForm%2FFormBuilder:error_notification).
101
+
102
+ ## Tailwind workarounds
103
+
104
+ When using spacing classes such as `space-y-<number>`, Tailwind 2 has [an unfortunate shortcoming](https://github.com/tailwindlabs/tailwindcss/issues/3413) where certain hidden elements disrupt element spacing. Rails's authenticity token unfortunately is one such hidden element that triggers this behavior.
105
+
106
+ To work around the issue, instead of using spacing classes directly on the `<form>` like this:
107
+
108
+ ```erb
109
+ <%= simple_form_for(@foo, builder: SimpleForm::Tailwind::FormBuilder, html: { class: "space-y-6" }) do |f| %>
110
+ <%= f.error_notification %>
111
+ <%= f.input :name %>
112
+ <% end %>
113
+ ```
114
+
115
+ Instead add a wrapper `<div>` around the form elements:
116
+
117
+ ```erb
118
+ <%= simple_form_for(@foo, builder: SimpleForm::Tailwind::FormBuilder) do |f| %>
119
+ <div class="space-y-6">
120
+ <%= f.error_notification %>
121
+ <%= f.input :name %>
122
+ </div>
123
+ <% end %>
124
+ ```
125
+
126
+ ## License
127
+
128
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
129
+
130
+ [Simple Form]: https://github.com/heartcombo/simple_form
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
Binary file
Binary file
Binary file
@@ -0,0 +1,17 @@
1
+ require "rails/generators"
2
+
3
+ module SimpleForm::Tailwind
4
+ module Generators # :nodoc:
5
+ class InstallGenerator < ::Rails::Generators::Base # :nodoc:
6
+ desc "Creates SimpleForm initializer using default Tailwind components"
7
+
8
+ def self.default_generator_root
9
+ File.dirname(__FILE__)
10
+ end
11
+
12
+ def copy_initializer
13
+ copy_file "simple_form.rb", "config/initializers/simple_form.rb"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,210 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Uncomment this and change the path if necessary to include your own
4
+ # components.
5
+ # See https://github.com/heartcombo/simple_form#custom-components to know
6
+ # more about custom components.
7
+ # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
8
+ #
9
+ # Use this setup block to configure all options available in SimpleForm.
10
+ SimpleForm.setup do |config|
11
+ # Wrappers are used by the form builder to generate a
12
+ # complete input. You can remove any component from the
13
+ # wrapper, change the order or even add your own to the
14
+ # stack. The options given below are used to wrap the
15
+ # whole input.
16
+
17
+ config.wrappers :default, tag: 'div', class: '', error_class: '', valid_class: '' do |b|
18
+ b.use :html5
19
+ b.use :placeholder
20
+ b.optional :maxlength
21
+ b.optional :minlength
22
+ b.optional :pattern
23
+ b.optional :min_max
24
+ b.optional :readonly
25
+
26
+ b.use :label, class: "block text-sm font-medium text-gray-700"
27
+ b.use :input,
28
+ class: 'appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm',
29
+ error_class: 'block w-full pr-10 border-red-300 text-red-900 placeholder-red-300 focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm rounded-md'
30
+ b.use :full_error, wrap_with: { tag: 'p', class: 'mt-2 text-sm text-red-600' }
31
+ b.use :hint, wrap_with: { tag: :p, class: "mt-2 text-sm text-gray-500" }
32
+ end
33
+
34
+ config.wrappers :prepend_string, tag: 'div', class: '', error_class: '', valid_class: '' do |b|
35
+ b.use :html5
36
+ b.use :placeholder
37
+ b.optional :maxlength
38
+ b.optional :minlength
39
+ b.optional :pattern
40
+ b.optional :min_max
41
+ b.optional :readonly
42
+
43
+ b.use :label, class: "block text-sm font-medium text-gray-700"
44
+
45
+ b.wrapper tag: 'div', class: 'mt-1 flex rounded-md shadow-sm' do |d|
46
+ d.use :prepend
47
+ d.use :input,
48
+ class: "flex-1 min-w-0 block w-full px-3 py-2 rounded-none rounded-r-md focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border-gray-300",
49
+ error_class: "flex-1 min-w-0 block w-full px-3 py-2 rounded-none rounded-r-md focus:ring-red-500 focus:border-red-500 sm:text-sm border-red-300 text-red-900 placeholder-red-300"
50
+ end
51
+ b.use :full_error, wrap_with: { tag: "p", class: "mt-2 text-sm text-red-600" }
52
+ b.use :hint, wrap_with: { tag: :p, class: "mt-2 text-sm text-gray-500" }
53
+ end
54
+
55
+ config.wrappers :append_string, tag: 'div', class: '', error_class: '', valid_class: '' do |b|
56
+ b.use :html5
57
+ b.use :placeholder
58
+ b.optional :maxlength
59
+ b.optional :minlength
60
+ b.optional :pattern
61
+ b.optional :min_max
62
+ b.optional :readonly
63
+
64
+ b.use :label, class: "block text-sm font-medium text-gray-700"
65
+
66
+ b.wrapper tag: 'div', class: 'mt-1 flex rounded-md shadow-sm' do |d|
67
+ d.use :input,
68
+ class: "flex-1 min-w-0 block w-full px-3 py-2 rounded-none rounded-l-md focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border-gray-300",
69
+ error_class: "flex-1 min-w-0 block w-full px-3 py-2 rounded-none rounded-l-md focus:ring-red-500 focus:border-red-500 sm:text-sm border-red-300 text-red-900 placeholder-red-300"
70
+ d.use :append
71
+ end
72
+ b.use :full_error, wrap_with: { tag: "p", class: "mt-2 text-sm text-red-600" }
73
+ b.use :hint, wrap_with: { tag: :p, class: "mt-2 text-sm text-gray-500" }
74
+ end
75
+
76
+ config.wrappers :corner_hint, tag: :div do |b|
77
+ b.use :html5
78
+ b.use :placeholder
79
+ b.optional :maxlength
80
+ b.optional :minlength
81
+ b.optional :pattern
82
+ b.optional :min_max
83
+ b.optional :readonly
84
+
85
+ b.wrapper tag: :div, class: "flex justify-between", error_class: nil, valid_class: nil do |c|
86
+ c.use :label, class: "block text-sm font-medium text-gray-700"
87
+ c.use :hint, wrap_with: { tag: :span, class: "text-sm text-gray-500" }
88
+ end
89
+
90
+ b.use :input,
91
+ class: "appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm",
92
+ error_class: "block w-full pr-10 border-red-300 text-red-900 placeholder-red-300 focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm rounded-md"
93
+ b.use :full_error, wrap_with: { tag: "p", class: "mt-2 text-sm text-red-600" }
94
+ end
95
+
96
+ # The default wrapper to be used by the FormBuilder.
97
+ config.default_wrapper = :default
98
+
99
+ # Define the way to render check boxes / radio buttons with labels.
100
+ # Defaults to :nested for bootstrap config.
101
+ # inline: input + label
102
+ # nested: label > input
103
+ config.boolean_style = :nested
104
+
105
+ # Default class for buttons
106
+ config.button_class = nil
107
+
108
+ # Method used to tidy up errors. Specify any Rails Array method.
109
+ # :first lists the first message for each field.
110
+ # Use :to_sentence to list all errors for each field.
111
+ # config.error_method = :first
112
+
113
+ # Default tag used for error notification helper.
114
+ config.error_notification_tag = :div
115
+
116
+ # CSS class to add for error notification helper.
117
+ config.error_notification_class = ''
118
+
119
+ # Series of attempts to detect a default label method for collection.
120
+ # config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
121
+
122
+ # Series of attempts to detect a default value method for collection.
123
+ # config.collection_value_methods = [ :id, :to_s ]
124
+
125
+ # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
126
+ # config.collection_wrapper_tag = nil
127
+
128
+ # You can define the class to use on all collection wrappers. Defaulting to none.
129
+ # config.collection_wrapper_class = nil
130
+
131
+ # You can wrap each item in a collection of radio/check boxes with a tag,
132
+ # defaulting to :span.
133
+ # config.item_wrapper_tag = :span
134
+
135
+ # You can define a class to use in all item wrappers. Defaulting to none.
136
+ # config.item_wrapper_class = nil
137
+
138
+ # How the label text should be generated altogether with the required text.
139
+ config.label_text = lambda { |label, required, explicit_label| "#{label}" }
140
+
141
+ # You can define the class to use on all labels. Default is nil.
142
+ # config.label_class = nil
143
+
144
+ # You can define the default class to be used on forms. Can be overriden
145
+ # with `html: { :class }`. Defaulting to none.
146
+ config.default_form_class = nil
147
+ config.form_class = nil
148
+
149
+ # You can define which elements should obtain additional classes
150
+ config.generate_additional_classes_for = []
151
+
152
+ # Whether attributes are required by default (or not). Default is true.
153
+ # config.required_by_default = true
154
+
155
+ # Tell browsers whether to use the native HTML5 validations (novalidate form option).
156
+ # These validations are enabled in SimpleForm's internal config but disabled by default
157
+ # in this configuration, which is recommended due to some quirks from different browsers.
158
+ # To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations,
159
+ # change this configuration to true.
160
+ config.browser_validations = false
161
+
162
+ # Custom mappings for input types. This should be a hash containing a regexp
163
+ # to match as key, and the input type that will be used when the field name
164
+ # matches the regexp as value.
165
+ # config.input_mappings = { /count/ => :integer }
166
+
167
+ # Custom wrappers for input types. This should be a hash containing an input
168
+ # type as key and the wrapper that will be used for all inputs with specified type.
169
+ config.wrapper_mappings = {
170
+ string: :default,
171
+ prepend_string: :prepend_string,
172
+ append_string: :append_string,
173
+ }
174
+
175
+ # Namespaces where SimpleForm should look for custom input classes that
176
+ # override default inputs.
177
+ # config.custom_inputs_namespaces << "CustomInputs"
178
+
179
+ # Default priority for time_zone inputs.
180
+ # config.time_zone_priority = nil
181
+
182
+ # Default priority for country inputs.
183
+ # config.country_priority = nil
184
+
185
+ # When false, do not use translations for labels.
186
+ # config.translate_labels = true
187
+
188
+ # Automatically discover new inputs in Rails' autoload path.
189
+ # config.inputs_discovery = true
190
+
191
+ # Cache SimpleForm inputs discovery
192
+ # config.cache_discovery = !Rails.env.development?
193
+
194
+ # Default class for inputs
195
+ # config.input_class = nil
196
+
197
+ # Define the default class of the input wrapper of the boolean input.
198
+ config.boolean_label_class = 'checkbox'
199
+
200
+ # Defines if the default input wrapper class should be included in radio
201
+ # collection wrappers.
202
+ # config.include_default_input_wrapper_class = true
203
+
204
+ # Defines which i18n scope will be used in Simple Form.
205
+ # config.i18n_scope = 'simple_form'
206
+
207
+ # Defines validation classes to the input_field. By default it's nil.
208
+ # config.input_field_valid_class = 'is-valid'
209
+ # config.input_field_error_class = 'is-invalid'
210
+ end
@@ -0,0 +1,38 @@
1
+ module SimpleForm
2
+ module Tailwind
3
+ class ErrorNotification < SimpleForm::ErrorNotification
4
+ def render
5
+ if has_errors?
6
+ color = @options.fetch(:color, "red")
7
+ icon = @options.fetch(:icon, "x-circle")
8
+
9
+ template.content_tag(
10
+ :div,
11
+ (
12
+ template.content_tag(
13
+ :div,
14
+ (
15
+ template.content_tag(
16
+ :div,
17
+ template.heroicon(icon, options: { class: "h-5 w-5 text-#{color}-400" }),
18
+ class: "flex-shrink-0"
19
+ ) + template.content_tag(
20
+ :div,
21
+ template.content_tag(
22
+ :p,
23
+ error_message,
24
+ class: "text-sm text-#{color}-700"
25
+ ),
26
+ class: "ml-3"
27
+ )
28
+ ),
29
+ class: "flex"
30
+ )
31
+ ),
32
+ class: "bg-#{color}-50 border-l-4 border-#{color}-400 p-4"
33
+ )
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+ require "simple_form/form_builder"
3
+ require "simple_form/tailwind/inputs/append_string_input"
4
+ require "simple_form/tailwind/inputs/password_input"
5
+ require "simple_form/tailwind/inputs/prepend_string_input"
6
+ require "simple_form/tailwind/inputs/string_input"
7
+
8
+ module SimpleForm
9
+ module Tailwind
10
+ class FormBuilder < SimpleForm::FormBuilder
11
+ map_type :string, :email, :search, :tel, :url, :uuid, :citext, to: SimpleForm::Tailwind::Inputs::StringInput
12
+ map_type :password, to: SimpleForm::Tailwind::Inputs::PasswordInput
13
+ map_type :prepend_string, to: SimpleForm::Tailwind::Inputs::PrependStringInput
14
+ map_type :append_string, to: SimpleForm::Tailwind::Inputs::AppendStringInput
15
+
16
+ def error_notification(options = {})
17
+ SimpleForm::Tailwind::ErrorNotification.new(self, options).render
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ require "simple_form/inputs/string_input"
3
+ require "simple_form/tailwind/overwrite_class_with_error_or_valid_class"
4
+
5
+ module SimpleForm
6
+ module Tailwind
7
+ module Inputs
8
+ class AppendStringInput < SimpleForm::Inputs::StringInput
9
+ include SimpleForm::Tailwind::OverwriteClassWithErrorOrValidClass
10
+
11
+ def input(*args, &blk)
12
+ input_html_options[:type] ||= "text"
13
+
14
+ super
15
+ end
16
+
17
+ def append(wrapper_options = nil)
18
+ template.content_tag(:span, options[:append], class: "inline-flex items-center px-3 rounded-r-md border border-l-0 border-gray-300 bg-gray-50 text-gray-500 sm:text-sm")
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ module SimpleForm
3
+ module Tailwind
4
+ module Inputs
5
+ class PasswordInput < SimpleForm::Inputs::PasswordInput
6
+ include SimpleForm::Tailwind::OverwriteClassWithErrorOrValidClass
7
+
8
+ def input(*args, &blk)
9
+ if has_errors?
10
+ template.content_tag(:div, (
11
+ super + (
12
+ template.content_tag(
13
+ :div,
14
+ template.heroicon("exclamation-circle", options: { class: "h-5 w-5 text-red-500" }),
15
+ class: "absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none"
16
+ )
17
+ )
18
+ ), class: "mt-1 relative rounded-md shadow-sm")
19
+ else
20
+ template.content_tag(:div, super, class: "mt-1")
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ require "simple_form/inputs/string_input"
3
+ require "simple_form/tailwind/overwrite_class_with_error_or_valid_class"
4
+
5
+ module SimpleForm
6
+ module Tailwind
7
+ module Inputs
8
+ class PrependStringInput < SimpleForm::Inputs::StringInput
9
+ include SimpleForm::Tailwind::OverwriteClassWithErrorOrValidClass
10
+
11
+ def input(*args, &blk)
12
+ input_html_options[:type] ||= "text"
13
+
14
+ super
15
+ end
16
+
17
+ def prepend(wrapper_options = nil)
18
+ template.content_tag(:span, options[:prepend], class: "inline-flex items-center px-3 rounded-l-md border border-r-0 border-gray-300 bg-gray-50 text-gray-500 sm:text-sm")
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ require "simple_form/inputs/string_input"
3
+ require "simple_form/tailwind/overwrite_class_with_error_or_valid_class"
4
+
5
+ module SimpleForm
6
+ module Tailwind
7
+ module Inputs
8
+ class StringInput < SimpleForm::Inputs::StringInput
9
+ include SimpleForm::Tailwind::OverwriteClassWithErrorOrValidClass
10
+
11
+ def input(*args, &blk)
12
+ if has_errors?
13
+ template.content_tag(:div, (
14
+ super + (
15
+ template.content_tag(
16
+ :div,
17
+ template.heroicon("exclamation-circle", options: { class: "h-5 w-5 text-red-500" }),
18
+ class: "absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none"
19
+ )
20
+ )
21
+ ), class: "mt-1 relative rounded-md shadow-sm")
22
+ else
23
+ template.content_tag(:div, super, class: "mt-1")
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ module SimpleForm
2
+ module Tailwind
3
+ # This module can be mixed in to inputs to change the default
4
+ # :error_class and :valid_class option behavior to *overwrite* the existing
5
+ # :class value when there's an error or the model is valid, instead of
6
+ # *adding* these classes to the :class value.
7
+ module OverwriteClassWithErrorOrValidClass
8
+ def set_input_classes(wrapper_options)
9
+ wrapper_options = wrapper_options.dup
10
+ error_class = wrapper_options.delete(:error_class)
11
+ valid_class = wrapper_options.delete(:valid_class)
12
+
13
+ if error_class.present? && has_errors?
14
+ wrapper_options[:class] = error_class
15
+ end
16
+
17
+ if valid_class.present? && valid?
18
+ wrapper_options[:class] = valid_class
19
+ end
20
+
21
+ wrapper_options
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ module SimpleForm
2
+ module Tailwind
3
+ VERSION = "0.0.2"
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ require "heroicon"
2
+ require "simple_form/tailwind/form_builder"
3
+ require "simple_form/tailwind/error_notification"
@@ -0,0 +1,42 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "simple_form/tailwind/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "simple_form_tailwind_css"
8
+ spec.version = SimpleForm::Tailwind::VERSION
9
+ spec.authors = ["Abe Voelker"]
10
+ spec.email = ["_@abevoelker.com"]
11
+
12
+ spec.summary = %q{Tailwind components for Simple Form}
13
+ #spec.description = %q{TODO: Write a longer description or delete this line.}
14
+ spec.homepage = "https://github.com/abevoelker/simple_form_tailwind_css"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ #spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
21
+
22
+ spec.metadata["homepage_uri"] = spec.homepage
23
+ spec.metadata["source_code_uri"] = spec.homepage
24
+ #spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
25
+ else
26
+ raise "RubyGems 2.0 or newer is required to protect against " \
27
+ "public gem pushes."
28
+ end
29
+
30
+ # Specify which files should be added to the gem when it is released.
31
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
32
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
33
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
34
+ end
35
+ spec.bindir = "exe"
36
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
37
+ spec.require_paths = ["lib"]
38
+ spec.required_ruby_version = ">= 2.1.0"
39
+
40
+ spec.add_dependency "simple_form"
41
+ spec.add_dependency "heroicon"
42
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_form_tailwind_css
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Abe Voelker
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-05-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: simple_form
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: heroicon
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
42
+ email:
43
+ - _@abevoelker.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - docs/images/components/append.png
54
+ - docs/images/components/corner_hint.png
55
+ - docs/images/components/default.png
56
+ - docs/images/components/default_with_error.png
57
+ - docs/images/components/prepend.png
58
+ - docs/images/error_notification_blue.png
59
+ - docs/images/error_notification_red.png
60
+ - lib/generators/simple_form/tailwind/install_generator.rb
61
+ - lib/generators/simple_form/tailwind/templates/simple_form.rb
62
+ - lib/simple_form/tailwind/error_notification.rb
63
+ - lib/simple_form/tailwind/form_builder.rb
64
+ - lib/simple_form/tailwind/inputs/append_string_input.rb
65
+ - lib/simple_form/tailwind/inputs/password_input.rb
66
+ - lib/simple_form/tailwind/inputs/prepend_string_input.rb
67
+ - lib/simple_form/tailwind/inputs/string_input.rb
68
+ - lib/simple_form/tailwind/overwrite_class_with_error_or_valid_class.rb
69
+ - lib/simple_form/tailwind/version.rb
70
+ - lib/simple_form_tailwind_css.rb
71
+ - simple_form_tailwind_css.gemspec
72
+ homepage: https://github.com/abevoelker/simple_form_tailwind_css
73
+ licenses:
74
+ - MIT
75
+ metadata:
76
+ homepage_uri: https://github.com/abevoelker/simple_form_tailwind_css
77
+ source_code_uri: https://github.com/abevoelker/simple_form_tailwind_css
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: 2.1.0
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubygems_version: 3.1.2
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Tailwind components for Simple Form
97
+ test_files: []