Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

B5 Responsive Forms #35519

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
1 change: 0 additions & 1 deletion corehq/apps/app_execution/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 0 additions & 1 deletion corehq/apps/domain/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
30 changes: 6 additions & 24 deletions corehq/apps/hqwebapp/crispy.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import re
from contextlib import contextmanager
from django.forms.widgets import DateTimeInput
from django.template.loader import render_to_string
Expand All @@ -13,11 +12,9 @@
from crispy_forms.layout import LayoutObject
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_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_ACTION_CLASS = CSS_FIELD_CLASS + ' col-sm-offset-4 col-md-offset-4 col-lg-offset-2'
CSS_LABEL_CLASS = 'field-label'
CSS_FIELD_CLASS = 'field-control'
CSS_ACTION_CLASS = CSS_FIELD_CLASS


class HQFormHelper(FormHelper):
Expand All @@ -28,13 +25,7 @@ class HQFormHelper(FormHelper):
def __init__(self, *args, **kwargs):
super(HQFormHelper, self).__init__(*args, **kwargs)
from corehq.apps.hqwebapp.utils.bootstrap import get_bootstrap_version, BOOTSTRAP_5
bootstrap_version = get_bootstrap_version()
use_bootstrap5 = bootstrap_version == BOOTSTRAP_5
if use_bootstrap5:
self.label_class = CSS_LABEL_CLASS_BOOTSTRAP5
self.field_class = CSS_FIELD_CLASS_BOOTSTRAP5
self.use_bootstrap5 = use_bootstrap5
self.form_class = 'form'
self.use_bootstrap5 = get_bootstrap_version() == BOOTSTRAP_5

if 'autocomplete' not in self.attrs:
self.attrs.update({
Expand Down Expand Up @@ -76,15 +67,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


def _get_offsets(context):
label_class = context.get('label_class', '')
use_bootstrap5 = context.get('use_bootstrap5')
return (label_class.replace('col', 'offset') if use_bootstrap5
else re.sub(r'(xs|sm|md|lg)-', r'\g<1>-offset-', label_class))
return CSS_FIELD_CLASS


class FormActions(OriginalFormActions):
Expand All @@ -102,11 +85,10 @@ def render(self, form, context, template_pack=None, **kwargs):
template_pack=template_pack,
)
fields_html = mark_safe(fields_html) # nosec: just concatenated safe fields
offsets = _get_offsets(context)
context.update({
'formactions': self,
'fields_output': fields_html,
'offsets': offsets,
'offsets': '',
'field_class': context.get('field_class', '')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: can offsets be removed altogether form this dict?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mabye, I'll take another look. I'm not sure how many places use (require?) it. It's hard to search for because it's a common word. I also need to check if crispy-boostrap3to5 needs it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

})
return render_to_string(self.template, context.flatten())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.field-label {
&:extend(.col-xs-12, .col-sm-4, .col-md-4, .col-lg-2);
}

.field-label + .field-control {
&:extend(.col-xs-12, .col-sm-8, .col-md-8, .col-lg-6);
}

:not(.field-label) + .field-control,
.form-actions > .field-control:first-child,
.form-group > .field-control:first-child {
&:extend(
.col-sm-offset-4, .col-md-offset-4, .col-lg-offset-2,
.col-xs-12, .col-sm-8, .col-md-8, .col-lg-6
);
}
1 change: 1 addition & 0 deletions corehq/apps/hqwebapp/static/hqwebapp/less/bootstrap.less
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// Core variables and mixins
@import "_hq/includes/variables.less";
@import "_hq/includes/mixins.less";
@import "_hq/includes/extensions.less";

// Reset and dependencies
@import "../../../../../../node_modules/bootstrap/less/normalize.less";
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
Expand Down
10 changes: 2 additions & 8 deletions corehq/apps/hqwebapp/templatetags/hq_shared_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,19 +246,13 @@ def can_use_restore_as(request):

@register.simple_tag
def css_label_class():
from corehq.apps.hqwebapp.crispy import CSS_LABEL_CLASS, CSS_LABEL_CLASS_BOOTSTRAP5
from corehq.apps.hqwebapp.utils.bootstrap import get_bootstrap_version, BOOTSTRAP_5
if get_bootstrap_version() == BOOTSTRAP_5:
return CSS_LABEL_CLASS_BOOTSTRAP5
from corehq.apps.hqwebapp.crispy import CSS_LABEL_CLASS
return CSS_LABEL_CLASS


@register.simple_tag
def css_field_class():
from corehq.apps.hqwebapp.crispy import CSS_FIELD_CLASS, CSS_FIELD_CLASS_BOOTSTRAP5
from corehq.apps.hqwebapp.utils.bootstrap import get_bootstrap_version, BOOTSTRAP_5
if get_bootstrap_version() == BOOTSTRAP_5:
return CSS_FIELD_CLASS_BOOTSTRAP5
from corehq.apps.hqwebapp.crispy import CSS_FIELD_CLASS
return CSS_FIELD_CLASS


Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
---
+++
@@ -1,356 +1,7 @@
@@ -1,356 +1,20 @@
-// FORM ACTIONS from TWBS 2
-// ------------
-
-[ng\:cloak],[ng-cloak],.ng-cloak{
- display:none !important
-}
-
+.field-label {
+ @extend .col-form-label, .col-12, .col-sm-4, .col-md-3, .col-lg-2;
}

-.form-actions {
- padding: (@line-height-base * @font-size-base - 1px) 0px @line-height-base * @font-size-base;
- margin-top: @line-height-base * 1em;
+.row > div > .form-check:first-child,
+.row > div > .input-group > .form-check:first-child {
+ padding-top: add($input-padding-y, $input-border-width);
margin-bottom: 0;
- margin-bottom: 0;
- background-color: @navbar-default-bg;
- border-top: 1px solid @legend-border-color;
- .border-bottom-radius(@border-radius-base);
Expand All @@ -31,12 +30,17 @@
- margin-left: 0;
- }
- }
-}
-
+.field-label + .field-control {
+ @extend .col-12, .col-sm-8, .col-md-9, .col-lg-10;
}

-.form-horizontal .control-label {
- text-align: left; // override bootstrap
-}
-
+:not(.field-label) + .field-control,
+.row > .field-control:first-child {
+ @extend .offset-sm-4, .offset-md-3, .offset-lg-2;
}

-legend .subtext {
- font-size: .8em;
- color: lighten(@cc-text, 40%);
Expand Down Expand Up @@ -357,10 +361,14 @@
-
-.controls-text {
- padding-top: 7px;
+.row > div > .form-check:first-child,
+.row > div > .input-group > .form-check:first-child {
+ padding-top: add($input-padding-y, $input-border-width);
+ margin-bottom: 0;
}

.form-hide-actions .form-actions {
@@ -361,21 +12,34 @@
@@ -361,21 +25,34 @@
.validationMessage {
display: block;
padding-top: 8px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ section</a> of the style guide.

A few useful things to know about crispy forms in Bootstrap 5:

* Checkboxes, typically based on a `BooleanField`, need to be updated to use the `BootstrapCheckboxInput` as their
`widget`, as shown in <a href="https://www.commcarehq.org/styleguide/b5/organisms/forms/#crispy-forms-simple"
target="_blank">this style guide example</a>.
* As described in <a href="https://www.commcarehq.org/styleguide/b5/organisms/forms/#crispy-forms-simple"
target="_blank">this section of the style guide</a>, best practice is to use one of HQ's standard helper classes
for layout. Doing so means you can delete <code>form_class</code>, <code>label_class</code>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@
<fieldset>
<legend>Basic Information</legend>
<div class="row mb-3">
<!-- Generally, it is best practice to use the {% css_label_class %}
template tag below instead of the col-* classes -->
<label for="id_first_name"
class="col-form-label col-xs-12 col-sm-4 col-md-4 col-lg-3">
<label for="id_first_name" class="field-label">
First Name
</label>
<!-- Generally, it is best practice to use the {% css_field_class %}
template tag below instead of the col-* classes -->
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-9">
<div class="field-control">
<input type="text"
name="first_name"
class="form-control"
Expand All @@ -21,11 +16,10 @@
</div>
</div>
<div class="row mb-3">
<label for="id_favorite_color"
class="col-form-label col-xs-12 col-sm-4 col-md-4 col-lg-3">
<label for="id_favorite_color" class="field-label">
Favorite Color
</label>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-9">
<div class="field-control">
<select name="favorite_color"
class="form-select hqwebapp-select2"
id="id_favorite_color">
Expand All @@ -36,21 +30,18 @@
</div>
</div>
<div class="row mb-3">
<label for="id_hopes"
class="col-form-label col-xs-12 col-sm-4 col-md-4 col-lg-3">
<label for="id_hopes" class="field-label">
Hopes and Dreams
</label>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-9">
<div class="field-control">
<textarea name="hopes"
class="form-control vertical-resize"
id="id_hopes"></textarea>
</div>
</div>
</fieldset>
<div class="form-actions row">
<!-- Generally, it is best practice to use the {% css_action_class %}
template tag below instead of offset-* and col-* -->
<div class="offset-xs-12 offset-sm-4 offset-md-4 offset-lg-3 col-xs-12 col-sm-8 col-md-8 col-lg-9">
<div class="field-control">
<button class="btn btn btn-primary" type="submit">Save</button>
<a href="#" class="btn btn-outline-primary">Cancel</a>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<form>
<div class="mb-3 row">
<label for="height-input" class="col-sm-3 col-form-label">
<label for="height-input" class="field-label">
Height (cm)
</label>
<div class="col-sm-9">
<div class="field-control">
<input type="text" id="height-input" name="height" class="form-control" />
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-3 col-form-label">
<label class="field-label">
Smoking status
</label>
<div class="col-sm-9">
<div class="field-control">
<div class="form-check">
<input class="form-check-input"
type="checkbox"
Expand All @@ -26,10 +26,10 @@
</div>
</div>
<div class="mb-3 row">
<label for="heartRate-input" class="col-sm-3 col-form-label">
<label for="heartRate-input" class="field-label">
Heart Rate (bpm)
</label>
<div class="col-sm-9">
<div class="field-control">
<input type="text" id="heartRate-input" name="heartRate" class="form-control" />
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
Examples of Disabled Fields
</legend>
<div class="row mb-3">
<label for="id_first_name_dis"
class="col-form-label col-xs-12 col-sm-4 col-md-4 col-lg-3">
<label for="id_first_name_dis" class="field-label">
First Name
</label>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-9">
<div class="field-control">
<input type="text"
name="first_name_dis"
value="Jon"
Expand All @@ -19,11 +18,10 @@
</div>
</div>
<div class="row mb-3">
<label for="id_favorite_color_dis"
class="col-form-label col-xs-12 col-sm-4 col-md-4 col-lg-3">
<label for="id_favorite_color_dis" class="field-label">
Favorite Color
</label>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-9">
<div class="field-control">
<select name="favorite_color_dis"
class="form-select hqwebapp-select2"
id="id_favorite_color_dis"
Expand All @@ -36,11 +34,10 @@
</div>
</div>
<div class="row mb-3">
<label for="id_hopes_dis"
class="col-form-label col-xs-12 col-sm-4 col-md-4 col-lg-3">
<label for="id_hopes_dis" class="field-label">
Hopes and Dreams
</label>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-9">
<div class="field-control">
<textarea name="hopes_dis"
class="form-control vertical-resize"
id="id_hopes_dis"
Expand All @@ -54,11 +51,10 @@
Examples of Readonly Fields
</legend>
<div class="row mb-3">
<label for="id_first_name_ro"
class="col-form-label col-xs-12 col-sm-4 col-md-4 col-lg-3">
<label for="id_first_name_ro" class="field-label">
First Name
</label>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-9">
<div class="field-control">
<input type="text"
name="first_name_ro"
value="Jon"
Expand All @@ -70,11 +66,10 @@
</div>
</div>
<div class="row mb-3">
<label for="id_hopes_ro"
class="col-form-label col-xs-12 col-sm-4 col-md-4 col-lg-3">
<label for="id_hopes_ro" class="field-label">
Hopes and Dreams
</label>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-9">
<div class="field-control">
<textarea name="hopes_ro"
id="id_hopes_ro"
class="form-control-plaintext"
Expand Down
Loading
Loading