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 +7 -0
- data/.gitignore +13 -0
- data/Gemfile +15 -0
- data/LICENSE.txt +21 -0
- data/README.md +130 -0
- data/Rakefile +6 -0
- data/docs/images/components/append.png +0 -0
- data/docs/images/components/corner_hint.png +0 -0
- data/docs/images/components/default.png +0 -0
- data/docs/images/components/default_with_error.png +0 -0
- data/docs/images/components/prepend.png +0 -0
- data/docs/images/error_notification_blue.png +0 -0
- data/docs/images/error_notification_red.png +0 -0
- data/lib/generators/simple_form/tailwind/install_generator.rb +17 -0
- data/lib/generators/simple_form/tailwind/templates/simple_form.rb +210 -0
- data/lib/simple_form/tailwind/error_notification.rb +38 -0
- data/lib/simple_form/tailwind/form_builder.rb +21 -0
- data/lib/simple_form/tailwind/inputs/append_string_input.rb +23 -0
- data/lib/simple_form/tailwind/inputs/password_input.rb +26 -0
- data/lib/simple_form/tailwind/inputs/prepend_string_input.rb +23 -0
- data/lib/simple_form/tailwind/inputs/string_input.rb +29 -0
- data/lib/simple_form/tailwind/overwrite_class_with_error_or_valid_class.rb +25 -0
- data/lib/simple_form/tailwind/version.rb +5 -0
- data/lib/simple_form_tailwind_css.rb +3 -0
- data/simple_form_tailwind_css.gemspec +42 -0
- metadata +97 -0
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
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
Binary file
|
Binary file
|
Binary file
|
Binary file
|
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,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: []
|