diff --git a/CHANGELOG.md b/CHANGELOG.md index ec90eaba3..2b48b2e55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * Remove redundant `aria-required` attribute for required fields. [@aduth](https://github.com/aduth) * Add `weekday` input. [@nashby](https://github.com/nashby) +* Add support for `css-zero` framework [@CuddlyBunion341](https://github.com/CuddlyBunion341) ## 5.3.1 diff --git a/README.md b/README.md index 97dc60d07..c4f72d351 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ INFO: This README refers to **Simple Form** 5.0. For older releases, check the r - [Installation](#installation) - [Bootstrap](#bootstrap-5) + - [Css-zero](#css-zero) - [Zurb Foundation 5](#zurb-foundation-5) - [Country Select](#country-select) - [Usage](#usage) @@ -84,6 +85,17 @@ For more information see the generator output, our [example application code](https://github.com/heartcombo/simple_form-bootstrap) and [the live example app](https://simple-form-bootstrap.herokuapp.com/). +### CSS-Zero + +To generate wrappers that are compatible with [CSS-Zero](https://github.com/lazaronixon/css-zero), pass +the `css_zero` option to the generator, like this: + +```console +rails generate simple_form:install --css-zero +``` + +Please see the [Installation instructions](https://github.com/lazaronixon/css-zero?tab=readme-ov-file#installation) for more information. + ### Zurb Foundation 5 To generate wrappers that are compatible with [Zurb Foundation 5](http://foundation.zurb.com/), pass diff --git a/lib/generators/simple_form/install_generator.rb b/lib/generators/simple_form/install_generator.rb index bf7ca0653..6c9548825 100644 --- a/lib/generators/simple_form/install_generator.rb +++ b/lib/generators/simple_form/install_generator.rb @@ -7,12 +7,13 @@ class InstallGenerator < Rails::Generators::Base class_option :template_engine, desc: 'Template engine to be invoked (erb, haml or slim).' class_option :bootstrap, type: :boolean, desc: 'Add the Bootstrap 5 wrappers to the SimpleForm initializer.' class_option :foundation, type: :boolean, desc: 'Add the Zurb Foundation 5 wrappers to the SimpleForm initializer.' + class_option :css_zero, type: :boolean, desc: 'Add the CSS Zero wrappers to the SimpleForm initializer.' def info_bootstrap - return if options.bootstrap? || options.foundation? - puts "SimpleForm supports Bootstrap 5 and Zurb Foundation 5. If you want "\ + return if options.bootstrap? || options.foundation? || options.css_zero? + puts "SimpleForm supports Bootstrap 5, Zurb Foundation 5 and CSS Zero. If you want "\ "a configuration that is compatible with one of these frameworks, then please " \ - "re-run this generator with --bootstrap or --foundation as an option." + "re-run this generator with --bootstrap, --foundation or --css-zero as an option." end def copy_config @@ -20,6 +21,8 @@ def copy_config if options[:bootstrap] template "config/initializers/simple_form_bootstrap.rb" + elsif options[:css_zero] + template "config/initializers/simple_form_css_zero.rb" elsif options[:foundation] template "config/initializers/simple_form_foundation.rb" end diff --git a/lib/generators/simple_form/templates/config/initializers/simple_form_css_zero.rb b/lib/generators/simple_form/templates/config/initializers/simple_form_css_zero.rb new file mode 100644 index 000000000..f8c1add0f --- /dev/null +++ b/lib/generators/simple_form/templates/config/initializers/simple_form_css_zero.rb @@ -0,0 +1,235 @@ +# frozen_string_literal: true + +# These defaults are defined for CSS Zero +# Please submit feedback, changes and tests through proper channels. + +# Uncomment this and change the path if necessary to include your own +# components. +# See https://github.com/heartcombo/simple_form#custom-components +# to know more about custom components. +# Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f } + +# Use this setup block to configure all options available in SimpleForm. +SimpleForm.setup do |config| # rubocop:disable Metrics/BlockLength + config.button_class = "btn" + config.boolean_label_class = "checkbox" + config.label_text = ->(label, required, _explicit_label) { "#{label} #{required}" } + config.boolean_style = :inline + config.item_wrapper_tag = :div + config.include_default_input_wrapper_class = false + config.error_notification_class = "invalid-feedback" + config.error_method = :to_sentence + config.input_field_error_class = "field_with_errors" + config.input_field_valid_class = "field_without_errors" + + config.wrappers :default do |b| + b.use :html5 + end + + config.wrappers :vertical_form, class: "mbe-3" do |b| + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :pattern + b.optional :min_max + b.optional :readonly + b.use :label, class: "mbe-1" + b.use :input, class: "input", error_class: "field_with_errors", valid_class: "field_without_errors" + b.use :error, wrap_with: { class: "invalid-feedback block" } + b.use :hint, wrap_with: { class: "text-subtle" } + end + + config.wrappers :vertical_boolean, tag: "fieldset", class: "mbe-3" do |b| + b.optional :readonly + b.wrapper :form_check_wrapper, class: "flex items-center" do |bb| + bb.use :input, class: "checkbox", error_class: "field_with_errors", valid_class: "field_without_errors" + bb.use :label, class: "mis-2" + bb.use :error, wrap_with: { class: "invalid-feedback block" } + bb.use :hint, wrap_with: { class: "text-subtle" } + end + end + + config.wrappers :vertical_collection, item_wrapper_class: "flex items-center", item_label_class: "mis-2", + tag: "fieldset", class: "mbe-3" do |b| + b.optional :readonly + b.wrapper :legend_tag, tag: "legend", class: "mbe-1" do |ba| + ba.use :label_text + end + b.use :input, class: "radio", error_class: "field_with_errors", valid_class: "field_without_errors" + b.use :error, wrap_with: { class: "invalid-feedback block" } + b.use :hint, wrap_with: { class: "text-subtle" } + end + + config.wrappers :vertical_collection_inline, item_wrapper_class: "flex items-center mie-2", + item_label_class: "mis-2", tag: "fieldset", class: "mbe-3" do |b| + b.optional :readonly + b.wrapper :legend_tag, tag: "legend", class: "mbe-1" do |ba| + ba.use :label_text + end + b.use :input, class: "radio", error_class: "field_with_errors", valid_class: "field_without_errors" + b.use :error, wrap_with: { class: "invalid-feedback block" } + b.use :hint, wrap_with: { class: "text-subtle" } + end + + config.wrappers :vertical_file, class: "mbe-3" do |b| + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :readonly + b.use :label, class: "mbe-1" + b.use :input, class: "input", error_class: "field_with_errors", valid_class: "field_without_errors" + b.use :error, wrap_with: { class: "invalid-feedback block" } + b.use :hint, wrap_with: { class: "text-subtle" } + end + + config.wrappers :vertical_select, class: "mbe-3" do |b| + b.optional :readonly + b.use :label, class: "mbe-1" + b.use :input, class: "input", error_class: "field_with_errors", valid_class: "field_without_errors" + b.use :error, wrap_with: { class: "invalid-feedback block" } + b.use :hint, wrap_with: { class: "text-subtle" } + end + + config.wrappers :vertical_multi_select, class: "mbe-3" do |b| + b.optional :readonly + b.use :label, class: "mbe-1" + b.wrapper class: "flex flex-col gap" do |ba| + ba.use :input, class: "input mbe-2", error_class: "field_with_errors", valid_class: "field_without_errors" + end + b.use :error, wrap_with: { class: "invalid-feedback block" } + b.use :hint, wrap_with: { class: "text-subtle" } + end + + config.wrappers :date_time_inputs, class: "mbe-3" do |b| + b.use :placeholder + b.optional :readonly + b.use :label, class: "mbe-1" + b.wrapper class: "flex flex-row gap" do |ba| + ba.use :input, class: "input", error_class: "field_with_errors", valid_class: "field_without_errors" + end + b.use :error, wrap_with: { class: "invalid-feedback block" } + b.use :hint, wrap_with: { class: "text-subtle" } + end + + config.wrappers :horizontal_form, class: "flex flex-col mb-3" do |b| + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :pattern + b.optional :min_max + b.optional :readonly + b.use :label, class: "mbe-2" + b.wrapper :grid_wrapper, class: "flex flex-col" do |ba| + ba.use :input, class: "input", error_class: "field_with_errors", valid_class: "field_without_errors" + ba.use :error, wrap_with: { class: "invalid-feedback block" } + ba.use :hint, wrap_with: { class: "text-subtle" } + end + end + + config.wrappers :horizontal_boolean, class: "mbe-3" do |b| + b.optional :readonly + b.wrapper :grid_wrapper, class: "flex items-center" do |wr| + wr.wrapper :form_check_wrapper, class: "flex items-center" do |bb| + bb.use :input, class: "checkbox", error_class: "field_with_errors", valid_class: "field_without_errors" + bb.use :label, class: "mis-2" + bb.use :error, wrap_with: { class: "invalid-feedback block" } + bb.use :hint, wrap_with: { class: "text-subtle" } + end + end + end + + config.wrappers :horizontal_collection, item_wrapper_class: "flex items-center", item_label_class: "mis-2", + class: "mbe-3" do |b| + b.optional :readonly + b.use :label, class: "mbe-2" + b.wrapper :grid_wrapper, class: "flex flex-col" do |ba| + ba.use :input, class: "radio", error_class: "field_with_errors", valid_class: "field_without_errors" + ba.use :error, wrap_with: { class: "invalid-feedback block" } + ba.use :hint, wrap_with: { class: "text-subtle" } + end + end + + config.wrappers :horizontal_collection_inline, item_wrapper_class: "flex items-center mie-3", + item_label_class: "mis-2", class: "mbe-3" do |b| + b.optional :readonly + b.use :label, class: "mbe-2" + b.wrapper :grid_wrapper, class: "flex" do |ba| + ba.use :input, class: "radio", error_class: "field_with_errors", valid_class: "field_without_errors" + ba.use :error, wrap_with: { class: "invalid-feedback block" } + ba.use :hint, wrap_with: { class: "text-subtle" } + end + end + + config.wrappers :horizontal_file, class: "mbe-3" do |b| + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :readonly + b.use :label, class: "mbe-2" + b.wrapper :grid_wrapper, class: "flex flex-col" do |ba| + ba.use :input, class: "input", error_class: "field_with_errors", valid_class: "field_without_errors" + ba.use :error, wrap_with: { class: "invalid-feedback block" } + ba.use :hint, wrap_with: { class: "text-subtle" } + end + end + + config.wrappers :horizontal_select, class: "mbe-3" do |b| + b.optional :readonly + b.use :label, class: "mbe-2" + b.wrapper :grid_wrapper, class: "flex flex-col" do |ba| + ba.use :input, class: "input", error_class: "field_with_errors", valid_class: "field_without_errors" + ba.use :error, wrap_with: { class: "invalid-feedback block" } + ba.use :hint, wrap_with: { class: "text-subtle" } + end + end + + config.wrappers :horizontal_multi_select, class: "mbe-3" do |b| + b.optional :readonly + b.use :label, class: "mbe-2" + b.wrapper :grid_wrapper, class: "flex flex-col" do |ba| + ba.wrapper class: "flex flex-col gap" do |bb| + bb.use :input, class: "input mbe-2", error_class: "field_with_errors", valid_class: "field_without_errors" + end + ba.use :error, wrap_with: { class: "invalid-feedback block" } + ba.use :hint, wrap_with: { class: "text-subtle" } + end + end + + config.wrappers :inline_form, class: "i-full" do |b| + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :pattern + b.optional :min_max + b.optional :readonly + b.use :label, class: "sr-only" + + b.use :input, class: "input", error_class: "field_with_errors", valid_class: "field_without_errors" + b.use :error, wrap_with: { class: "invalid-feedback block" } + b.optional :hint, wrap_with: { class: "text-subtle" } + end + + config.wrappers :inline_boolean, class: "i-full" do |b| + b.optional :readonly + b.wrapper :form_check_wrapper, class: "flex items-center" do |bb| + bb.use :input, class: "checkbox", error_class: "field_with_errors", valid_class: "field_without_errors" + bb.use :label, class: "mis-2" + bb.use :error, wrap_with: { class: "invalid-feedback block" } + bb.optional :hint, wrap_with: { class: "text-subtle" } + end + end + + config.default_wrapper = :vertical_form + + config.wrapper_mappings = { + boolean: :vertical_boolean, + check_boxes: :vertical_collection, + date: :date_time_inputs, + datetime: :date_time_inputs, + file: :vertical_file, + radio_buttons: :vertical_collection, + range: :vertical_multi_select, + time: :date_time_inputs, + select: :vertical_select + } +end diff --git a/test/generators/simple_form_generator_test.rb b/test/generators/simple_form_generator_test.rb index abb526316..5d0946276 100644 --- a/test/generators/simple_form_generator_test.rb +++ b/test/generators/simple_form_generator_test.rb @@ -34,6 +34,14 @@ class SimpleFormGeneratorTest < Rails::Generators::TestCase /config\.default_wrapper = :vertical_form/, /config\.item_wrapper_tag = :div/ end + test 'generates the simple_form initializer with the css-zero wrappers' do + run_generator %w[--css-zero] + assert_file 'config/initializers/simple_form.rb', + /config\.default_wrapper = :default/, /config\.boolean_style = :nested/ + assert_file 'config/initializers/simple_form_css_zero.rb', /config\.wrappers :vertical_form/, + /config\.default_wrapper = :vertical_form/, /config\.item_wrapper_tag = :div/ + end + %w[erb haml slim].each do |engine| test "generates the scaffold template when using #{engine}" do run_generator ['-e', engine]