From 6751c836e3c8dffe135a309b8d54929e975a312e Mon Sep 17 00:00:00 2001 From: Daniel Miller Date: Tue, 10 Dec 2024 14:55:03 -0500 Subject: [PATCH 01/12] Document responsive form layout on Bootstrap 5 --- .../templates/styleguide/bootstrap5/organisms/forms.html | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/corehq/apps/styleguide/templates/styleguide/bootstrap5/organisms/forms.html b/corehq/apps/styleguide/templates/styleguide/bootstrap5/organisms/forms.html index 604b659a84b0..43d6336dc849 100644 --- a/corehq/apps/styleguide/templates/styleguide/bootstrap5/organisms/forms.html +++ b/corehq/apps/styleguide/templates/styleguide/bootstrap5/organisms/forms.html @@ -60,9 +60,16 @@

Overview

Different parts of HQ use these two approaches, and you should always consider existing context when deciding whether to use Crispy Forms or HTML.

+

+ Form layouts are responsive. On wide screens, labels are arranged in a column to the left and input fields are + arranged in a wider column to the right. In Bootstrap 5 this is referred to as + horizontal form layout. On + narrow screens such as mobile devices, the layout automatically collapses to a single column with each label + above its corresponding input control. +

The benefit of Crispy Forms, and why you should opt for using it over bespoke HTML whenever possible, - is that the HTML for each form component is controlled by templates. From HTML is often affected + is that the HTML for each form component is controlled by templates. Form HTML is often affected during a front-end migration (like Bootstrap). If a bespoke HTML form was used, that HTML needs to be re-examined everywhere. However, for forms using Crispy Forms, the relevant HTML only has to be changed once in the templates, From 3552c8f9e1031261b0ef720a681adf2e08b7d625 Mon Sep 17 00:00:00 2001 From: Daniel Miller Date: Tue, 10 Dec 2024 14:59:34 -0500 Subject: [PATCH 02/12] B5 crispy horizontal forms --- corehq/apps/hqwebapp/crispy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/corehq/apps/hqwebapp/crispy.py b/corehq/apps/hqwebapp/crispy.py index fceb944f7fa9..0957bb339719 100644 --- a/corehq/apps/hqwebapp/crispy.py +++ b/corehq/apps/hqwebapp/crispy.py @@ -34,7 +34,6 @@ def __init__(self, *args, **kwargs): self.label_class = CSS_LABEL_CLASS_BOOTSTRAP5 self.field_class = CSS_FIELD_CLASS_BOOTSTRAP5 self.use_bootstrap5 = use_bootstrap5 - self.form_class = 'form' if 'autocomplete' not in self.attrs: self.attrs.update({ From 1cabe25b161ccd247ffe44bd85d708fc3010db61 Mon Sep 17 00:00:00 2001 From: Daniel Miller Date: Tue, 10 Dec 2024 15:26:43 -0500 Subject: [PATCH 03/12] Remove redundant B5 form class assignemnts --- corehq/apps/app_execution/forms.py | 1 - corehq/apps/domain/forms.py | 1 - corehq/motech/forms.py | 1 - corehq/motech/repeaters/forms.py | 1 - 4 files changed, 4 deletions(-) diff --git a/corehq/apps/app_execution/forms.py b/corehq/apps/app_execution/forms.py index 317500f3c30e..7e6e40f0d1db 100644 --- a/corehq/apps/app_execution/forms.py +++ b/corehq/apps/app_execution/forms.py @@ -57,7 +57,6 @@ def __init__(self, request, *args, **kwargs): if self.instance.id: self.fields["username"].initial = self.instance.django_user.username self.helper = hqcrispy.HQFormHelper() - self.helper.form_class = "form-horizontal" fields = [ "name", diff --git a/corehq/apps/domain/forms.py b/corehq/apps/domain/forms.py index c24ecc4f92d9..51a61cafbc61 100644 --- a/corehq/apps/domain/forms.py +++ b/corehq/apps/domain/forms.py @@ -1273,7 +1273,6 @@ def __init__(self, domain, can_edit_eula, *args, user, **kwargs): ) self.helper = hqcrispy.HQFormHelper() - self.helper.form_class = "form-horizontal" self.helper.layout = crispy.Layout( crispy.Fieldset( _("Basic Information"), diff --git a/corehq/motech/forms.py b/corehq/motech/forms.py index 30e92b2773aa..fda4f35775c3 100644 --- a/corehq/motech/forms.py +++ b/corehq/motech/forms.py @@ -144,7 +144,6 @@ def helper(self): from corehq.motech.views import ConnectionSettingsListView helper = hqcrispy.HQFormHelper() - helper.form_class = "form-horizontal" helper.layout = crispy.Layout( crispy.Field('name'), crispy.Field('notify_addresses_str'), diff --git a/corehq/motech/repeaters/forms.py b/corehq/motech/repeaters/forms.py index 88c3b45e7135..0907c3822153 100644 --- a/corehq/motech/repeaters/forms.py +++ b/corehq/motech/repeaters/forms.py @@ -72,7 +72,6 @@ def set_extra_django_form_fields(self): def _initialize_crispy_layout(self): self.helper = hqcrispy.HQFormHelper(self) - self.helper.form_class = 'form-horizontal' self.helper.layout = crispy.Layout( crispy.Fieldset( From 1ac2e1fa390ef1dfbc46b885f0a63c6d6c6877a6 Mon Sep 17 00:00:00 2001 From: Daniel Miller Date: Tue, 10 Dec 2024 15:06:40 -0500 Subject: [PATCH 04/12] Adjust column widths for crispy horizontal forms Make it easier to associate label with field on wide screens. Restore large-screen (lg) column widths used with Bootstrap 3. Tweak medium-screen (md) column widths to improve consistency. --- corehq/apps/hqwebapp/crispy.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/corehq/apps/hqwebapp/crispy.py b/corehq/apps/hqwebapp/crispy.py index 0957bb339719..e3a064e2ae89 100644 --- a/corehq/apps/hqwebapp/crispy.py +++ b/corehq/apps/hqwebapp/crispy.py @@ -14,9 +14,9 @@ from crispy_forms.utils import flatatt, get_template_pack, render_field CSS_LABEL_CLASS = 'col-xs-12 col-sm-4 col-md-4 col-lg-2' -CSS_LABEL_CLASS_BOOTSTRAP5 = 'col-xs-12 col-sm-4 col-md-4 col-lg-3' +CSS_LABEL_CLASS_BOOTSTRAP5 = 'col-xs-12 col-sm-4 col-md-3 col-lg-2' CSS_FIELD_CLASS = 'col-xs-12 col-sm-8 col-md-8 col-lg-6' -CSS_FIELD_CLASS_BOOTSTRAP5 = 'col-xs-12 col-sm-8 col-md-8 col-lg-9' +CSS_FIELD_CLASS_BOOTSTRAP5 = 'col-xs-12 col-sm-8 col-md-9 col-lg-10' CSS_ACTION_CLASS = CSS_FIELD_CLASS + ' col-sm-offset-4 col-md-offset-4 col-lg-offset-2' From ba970600b7326e79308da3d868510619cc5324ea Mon Sep 17 00:00:00 2001 From: Daniel Miller Date: Thu, 12 Dec 2024 11:10:07 -0500 Subject: [PATCH 05/12] Form style extensions to simplify field classes Should reduce the overhead of future site-wide style changes such as when upgrading Bootstrap. --- corehq/apps/hqwebapp/crispy.py | 6 +++--- .../static/hqwebapp/scss/commcarehq/_forms.scss | 13 +++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/corehq/apps/hqwebapp/crispy.py b/corehq/apps/hqwebapp/crispy.py index e3a064e2ae89..602ec696c3f6 100644 --- a/corehq/apps/hqwebapp/crispy.py +++ b/corehq/apps/hqwebapp/crispy.py @@ -14,9 +14,9 @@ from crispy_forms.utils import flatatt, get_template_pack, render_field CSS_LABEL_CLASS = 'col-xs-12 col-sm-4 col-md-4 col-lg-2' -CSS_LABEL_CLASS_BOOTSTRAP5 = 'col-xs-12 col-sm-4 col-md-3 col-lg-2' +CSS_LABEL_CLASS_BOOTSTRAP5 = 'field-label' CSS_FIELD_CLASS = 'col-xs-12 col-sm-8 col-md-8 col-lg-6' -CSS_FIELD_CLASS_BOOTSTRAP5 = 'col-xs-12 col-sm-8 col-md-9 col-lg-10' +CSS_FIELD_CLASS_BOOTSTRAP5 = 'field-control' CSS_ACTION_CLASS = CSS_FIELD_CLASS + ' col-sm-offset-4 col-md-offset-4 col-lg-offset-2' @@ -76,7 +76,7 @@ class ErrorsOnlyField(Field): def get_form_action_class(): """This is only valid for bootstrap 5""" - return CSS_LABEL_CLASS_BOOTSTRAP5.replace('col', 'offset') + ' ' + CSS_FIELD_CLASS_BOOTSTRAP5 + return CSS_FIELD_CLASS_BOOTSTRAP5 def _get_offsets(context): diff --git a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_forms.scss b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_forms.scss index 481acf947bd2..2f7aef91a69d 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_forms.scss +++ b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_forms.scss @@ -1,3 +1,16 @@ +.field-label { + @extend .col-form-label, .col-12, .col-sm-4, .col-md-3, .col-lg-2; +} + +.field-label + .field-control { + @extend .col-12, .col-sm-8, .col-md-9, .col-lg-10; +} + +:not(.field-label) + .field-control, +.row > .field-control:first-child { + @extend .offset-sm-4, .offset-md-3, .offset-lg-2; +} + .row > div > .form-check:first-child, .row > div > .input-group > .form-check:first-child { padding-top: add($input-padding-y, $input-border-width); From af45509d3eff9846ef2c11df5ad4f87beec12872 Mon Sep 17 00:00:00 2001 From: Daniel Miller Date: Thu, 12 Dec 2024 11:15:47 -0500 Subject: [PATCH 06/12] Simplify field classes in styleguide examples --- .../bootstrap5/examples/basic_form.html | 23 ++++++----------- .../examples/checkbox_horizontal_form.html | 12 ++++----- .../bootstrap5/examples/disabled_fields.html | 25 ++++++++----------- .../bootstrap5/examples/form_invalid.html | 15 +++++------ .../bootstrap5/examples/form_valid.html | 15 +++++------ .../examples/placeholder_help_text.html | 5 ++-- 6 files changed, 37 insertions(+), 58 deletions(-) diff --git a/corehq/apps/styleguide/templates/styleguide/bootstrap5/examples/basic_form.html b/corehq/apps/styleguide/templates/styleguide/bootstrap5/examples/basic_form.html index b8141230cc9d..3adca1f544b0 100644 --- a/corehq/apps/styleguide/templates/styleguide/bootstrap5/examples/basic_form.html +++ b/corehq/apps/styleguide/templates/styleguide/bootstrap5/examples/basic_form.html @@ -4,15 +4,10 @@

Basic Information
- -
- -
+
Cancel
diff --git a/corehq/apps/styleguide/templates/styleguide/bootstrap5/examples/checkbox_horizontal_form.html b/corehq/apps/styleguide/templates/styleguide/bootstrap5/examples/checkbox_horizontal_form.html index 7b7d95eb7344..a8c27c522f49 100644 --- a/corehq/apps/styleguide/templates/styleguide/bootstrap5/examples/checkbox_horizontal_form.html +++ b/corehq/apps/styleguide/templates/styleguide/bootstrap5/examples/checkbox_horizontal_form.html @@ -1,17 +1,17 @@
-