diff --git a/package-lock.json b/package-lock.json index 83875c35f..ebcc9f440 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.5.2", "license": "MIT", "devDependencies": { - "@tacc/core-styles": "git+https://git@github.com/TACC/Core-Styles.git", + "@tacc/core-styles": "git+https://git@github.com/TACC/Core-Styles.git#v0.3.0", "minimist": "^1.2.6", "node-cmd": "^5.0.0" }, @@ -64,7 +64,7 @@ }, "node_modules/@tacc/core-styles": { "version": "1.0.0", - "resolved": "git+https://git@github.com/TACC/Core-Styles.git#e7c038a21d2134ddafd0cb552602791a0fadd749", + "resolved": "git+https://git@github.com/TACC/Core-Styles.git#b3bc63617cbbf930dfcf08f5e2a3d162929a788f", "dev": true, "license": "MIT", "dependencies": { @@ -3938,9 +3938,9 @@ } }, "@tacc/core-styles": { - "version": "git+https://git@github.com/TACC/Core-Styles.git#e7c038a21d2134ddafd0cb552602791a0fadd749", + "version": "git+https://git@github.com/TACC/Core-Styles.git#b3bc63617cbbf930dfcf08f5e2a3d162929a788f", "dev": true, - "from": "@tacc/core-styles@git+https://git@github.com/TACC/Core-Styles.git", + "from": "@tacc/core-styles@git+https://git@github.com/TACC/Core-Styles.git#v0.3.0", "requires": { "commander": "^9.0.0", "cssnano": "^4.1.10", diff --git a/package.json b/package.json index e193b7110..c1068d6c5 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "npm": "8.5.5" }, "devDependencies": { - "@tacc/core-styles": "git+https://git@github.com/TACC/Core-Styles.git", + "@tacc/core-styles": "git+https://git@github.com/TACC/Core-Styles.git#v0.3.0", "minimist": "^1.2.6", "node-cmd": "^5.0.0" }, diff --git a/poetry.lock b/poetry.lock index 234f6bb1a..3a6528b17 100644 --- a/poetry.lock +++ b/poetry.lock @@ -307,6 +307,17 @@ python-versions = "*" [package.dependencies] Django = ">=2.1" +[[package]] +name = "django-recaptcha" +version = "3.0.0" +description = "Django recaptcha form field/widget app." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +django = "*" + [[package]] name = "django-sekizai" version = "2.0.0" @@ -526,8 +537,8 @@ django-filer = ">=1.7" djangocms-attributes-field = ">=1" [[package]] -name = "djangocms-forms" -version = "0.2.5" +name = "djangocms-forms-maintained" +version = "202011091152" description = "The easiest and most flexible Django CMS Form builder w/ ReCaptcha v2 support!" category = "main" optional = false @@ -537,6 +548,7 @@ python-versions = "*" django-appconf = "*" django-cms = ">=3.0" django-ipware = "*" +django-recaptcha = "*" hashids = "*" jsonfield = "*" requests = "*" @@ -826,7 +838,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" parso = ">=0.7.0,<0.8.0" [package.extras] -qa = ["flake8 (==3.7.9)"] +qa = ["flake8 (3.7.9)"] testing = ["Django (<3.1)", "colorama", "docopt", "pytest (>=3.9.0,<5.0.0)"] [[package]] @@ -1105,7 +1117,7 @@ idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} urllib3 = ">=1.21.1,<1.27" [package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] [[package]] @@ -1212,7 +1224,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" [package.extras] brotli = ["brotlipy (>=0.6.0)"] secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] [[package]] name = "urlobject" @@ -1277,7 +1289,7 @@ testing = ["jaraco.itertools", "func-timeout"] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "ede4ded5906287ebc533a39066285a4aa70377909a594c51f34fe0c8f72da0a6" +content-hash = "8515ec924f9be13f59a965c2328565289c11c642a3ed1c79a3a3ad16396f91b7" [metadata.files] aldryn-apphooks-config = [ @@ -1378,6 +1390,10 @@ django-polymorphic = [ {file = "django-polymorphic-3.0.0.tar.gz", hash = "sha256:9d886f19f031d26bb1391c055ed9be06fb226a04a4cec1842b372c58873b3caa"}, {file = "django_polymorphic-3.0.0-py2.py3-none-any.whl", hash = "sha256:73b75eb44ea302bd32820f8661e469509d245ce7f7ff09cd2ad149e5c42034ff"}, ] +django-recaptcha = [ + {file = "django-recaptcha-3.0.0.tar.gz", hash = "sha256:253197051288923cae675d7eff91b619e3775311292a5dbaf27a8a55ffebc670"}, + {file = "django_recaptcha-3.0.0-py3-none-any.whl", hash = "sha256:1aed69fd6ac8fd9e99e52665392ae6748f8b6339ace656fad779fe0c6c915a52"}, +] django-sekizai = [ {file = "django-sekizai-2.0.0.tar.gz", hash = "sha256:e829f09b0d6bf01ee5cde05de1fb3faf2fbc5df66dc4dc280fbaac224ca4336f"}, {file = "django_sekizai-2.0.0-py3-none-any.whl", hash = "sha256:5c5e16845d37ce822fc655ce79ec02715191b3d03330b550997bcb842cf24fdf"}, @@ -1446,8 +1462,9 @@ djangocms-file = [ {file = "djangocms-file-3.0.0.tar.gz", hash = "sha256:61f8df1ee136c0202fa65b9fe87024f3ceece66262ddd0cccfffbe979170ffdd"}, {file = "djangocms_file-3.0.0-py3-none-any.whl", hash = "sha256:6918717355488c764941d56813362e7ab497f3a4cd73e71e2d4c0f09bff79687"}, ] -djangocms-forms = [ - {file = "djangocms-forms-0.2.5.tar.gz", hash = "sha256:83719b7bec66f935fc30698d81541d52cf35a45bef27089cd8899fa9d4d19d36"}, +djangocms-forms-maintained = [ + {file = "djangocms-forms-maintained-202011091152.tar.gz", hash = "sha256:d3d45179e4d536ca2e6cd1a62f5c39e130417b2e4163d1f1510e8d78ac2839d7"}, + {file = "djangocms_forms_maintained-202011091152-py2.py3-none-any.whl", hash = "sha256:973d1df55bb8742718b20ec576dc7d153b9264b1abd824d4e1561caf4a615b0a"}, ] djangocms-googlemap = [ {file = "djangocms-googlemap-2.0.0.tar.gz", hash = "sha256:1e63f2e3adb6278b401881476aa3795560bd4a441e3509310044316bf9c9b867"}, diff --git a/pyproject.toml b/pyproject.toml index ef73f889f..22fc0d6d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,7 @@ djangocms-blog = "1.1.1" djangocms-bootstrap4 = "2.0.0" djangocms-column = "1.11.0" djangocms-file = "3.0.0" -djangocms-forms = "0.2.5" +djangocms-forms-maintained = { git = "https://github.com/avryhof/djangocms-forms", rev = "30f464303d317cf7a3170ad64e11ab4471b4287b" } djangocms-googlemap = "2.0.0" djangocms-icon = "2.0.0" djangocms-link = "3.0.0" diff --git a/taccsite_cms/_settings/form_plugin.py b/taccsite_cms/_settings/form_plugin.py new file mode 100644 index 000000000..7e42af918 --- /dev/null +++ b/taccsite_cms/_settings/form_plugin.py @@ -0,0 +1,115 @@ +"""Configure djangocms_forms and related apps""" + +from django.utils.translation import gettext_lazy as _ + +######################## +# KNOWN ISSUES +######################## + +# Unable to export to Excel nor YAML +# (No success hiding those formats from editor) +# https://github.com/avryhof/djangocms-forms/issues/8 + +######################## +# DJANGOCMS_FORMS +# https://github.com/avryhof/djangocms-forms/ +######################## + +# DJANGOCMS_FORMS_PLUGIN_MODULE = ('Generic') +# DJANGOCMS_FORMS_PLUGIN_NAME = ('Form') + +# DJANGOCMS_FORMS_TEMPLATES = ( +# ('djangocms_forms/form_template/default.html', ('Default')), +# ) +DJANGOCMS_FORMS_USE_HTML5_REQUIRED = True + +# DJANGOCMS_FORMS_REDIRECT_DELAY = 1000 + +# The default value is only for test and dev +# DJANGO_FORMS_RECAPTCHA_PUBLIC_KEY = '' # set in Deployments repo, not here +# DJANGO_FORMS_RECAPTCHA_SECRET_KEY = '' # set on sever directly, not here + +DJANGOCMS_FORMS_SPAM_PROTECTIONS = ( + (0, _('None')), + # (1, _('Honeypot')), # if necessary, learn how to use + (2, _('ReCAPTCHA')), +) +DEFAULT_SPAM_PROTECTION = 0 + +# Improve form legibility and conceal unavailable features +# https://github.com/avryhof/djangocms-forms/blob/97d7c21/djangocms_forms/cms_plugins.py#L69-L121 +DJANGOCMS_FORMS_FIELDSETS = ( + (None, {'fields': ('name', 'form_template',),}), + ( + _('Text'), + { + 'description': _( + 'The Title and Description ' + 'will display above the input fields and Submit button.' + ), + 'fields': ('title', 'description','submit_btn_txt',), + }, + ), + ( + None, + { + 'description': _( + 'You can change the message that appears after someone submits your form. By default, this says "Thank you!"' + ), + 'fields': ('post_submit_msg',), + }, + ), + ( + _('Redirect settings'), + { + 'description': _( + 'Whether and how to redirect the form after submission.' + ), + 'fields': ('success_redirect', ('page_redirect', 'external_redirect'), 'redirect_delay',), + } + ), + ( + _('Submission settings'), + { + 'description': 'Whether to save form data.', + 'fields': ( + 'save_data', + 'spam_protection', + ), + }, + ), + ( + _('Submission e-mail (unavailable feature)'), + { + 'classes': ('collapse',), + 'description': 'Choose storage options to capture form data. You can enter an e-mail address to which to e-mail form submissions.', + 'fields': ( + # Submitting form with 'email_to' defined causes server error + # FAQ: We may need to setup some django e-mail server for these + 'email_to', + 'email_from', + 'email_subject', + 'email_uploaded_files', + ), + }, + ), +) + +######################## +# DJANGO +# https://docs.djangoproject.com/en/2.2/ref/settings/#form-renderer +######################## + +# Allow form template override +# https://github.com/torchbox/django-recaptcha/issues/211#issuecomment-675608391 +FORM_RENDERER = 'django.forms.renderers.TemplatesSetting' + +######################## +# DJANGO CMS +######################## + +_INSTALLED_APPS = [ + 'djangocms_forms', # form plugin for editors + 'django.forms', # support form template override + 'captcha', # support recaptcha for djangocms_forms +] diff --git a/taccsite_cms/settings.py b/taccsite_cms/settings.py index 5ea7908ee..65b1bd8c1 100644 --- a/taccsite_cms/settings.py +++ b/taccsite_cms/settings.py @@ -14,6 +14,11 @@ import ldap from django_auth_ldap.config import LDAPSearch, GroupOfNamesType +from taccsite_cms._settings.form_plugin import * +from taccsite_cms._settings.form_plugin import ( + _INSTALLED_APPS as form_plugin_INSTALLED_APPS +) + SECRET_KEY = 'CHANGE_ME' def gettext(s): return s @@ -91,16 +96,6 @@ def gettext(s): return s GOOGLE_ANALYTICS_PROPERTY_ID = "UA-123ABC@%$&-#" GOOGLE_ANALYTICS_PRELOAD = True -######################## -# CMS FORMS -######################## - -# Create CMS Forms -# SEE: https://pypi.org/project/djangocms-forms/ -# SEE: https://www.google.com/recaptcha/admin/create -DJANGOCMS_FORMS_RECAPTCHA_PUBLIC_KEY = "" -DJANGOCMS_FORMS_RECAPTCHA_SECRET_KEY = "" - ######################## # ELASTICSEARCH ######################## @@ -318,6 +313,9 @@ def gettext(s): return s 'haystack', 'aldryn_apphooks_config', 'test_without_migrations', + +] + form_plugin_INSTALLED_APPS + [ + 'taccsite_cms', 'taccsite_cms.contrib.bootstrap4_djangocms_link', 'taccsite_cms.contrib.bootstrap4_djangocms_picture', @@ -415,18 +413,6 @@ def get_subdirs_as_module_names(path): DJANGOCMS_AUDIO_ALLOWED_EXTENSIONS = ['mp3', 'ogg', 'wav'] -# Djangocms Forms Settings. -# SEE: https://github.com/mishbahr/djangocms-forms#configuration -DJANGOCMS_FORMS_PLUGIN_MODULE = ('Generic') -DJANGOCMS_FORMS_PLUGIN_NAME = ('Form') - -DJANGOCMS_FORMS_TEMPLATES = ( - ('djangocms_forms/form_template/default.html', ('Default')), -) -DJANGOCMS_FORMS_USE_HTML5_REQUIRED = False - -DJANGOCMS_FORMS_REDIRECT_DELAY = 1 - # Elasticsearch Indexing HAYSTACK_ROUTERS = ['aldryn_search.router.LanguageRouter', ] HAYSTACK_SIGNAL_PROCESSOR = 'taccsite_cms.signal_processor.RealtimeSignalProcessor' diff --git a/taccsite_cms/static/css/djangocms_forms/djangocms_forms.css b/taccsite_cms/static/css/djangocms_forms/djangocms_forms.css new file mode 100644 index 000000000..5c31cda20 --- /dev/null +++ b/taccsite_cms/static/css/djangocms_forms/djangocms_forms.css @@ -0,0 +1,3 @@ +/* SEE: ../../site_cms/css/src/app.djangocms_forms.css */ +/* FAQ: We use future syntax that often must be processed to work in the now; + and the process does not support outputting files to this directory */ diff --git a/taccsite_cms/static/site_cms/css/src/_imports/components/c-button--from-future-core-styles.css b/taccsite_cms/static/site_cms/css/src/_imports/components/c-button--from-future-core-styles.css new file mode 100644 index 000000000..240503789 --- /dev/null +++ b/taccsite_cms/static/site_cms/css/src/_imports/components/c-button--from-future-core-styles.css @@ -0,0 +1,277 @@ +/* https://github.com/TACC/Core-Styles/blob/d162cfb/source/_imports/components/c-button.css */ + +/* +Button + +A button that may have icon(s) before and/or after its text. + +.c-button--primary - A primary (expected) user action +.c-button--secondary - For an optional user action +.c-button--tertiary - A button that represents inactive buttons among many +.c-button--is-active - A button that represents the one active button among many +.c-button--as-link - A button that visually resembles a link +.c-button--is-busy - A clicked button that started an incomplete process + +Markup: c-button--from-future-core-styles.html + +Styleguide Components.Button +*/ +@import url("_imports/tools/x-truncate.css"); + + + + + +/* Base */ + +[class*='c-button'] { + --min-width: 75px; + --mid-width: 110px; + --max-width: 130px; +} +.c-button { + display: inline-block; + + border-width: var(--global-border-width--normal); + border-style: solid; + + font-weight: 500; + font-size: 0.75rem; /* 12px (10px design * 1.2 design-to-app ratio) */ + + @extend %x-truncate--one-line; +} + +.c-button:not(:disabled) { + cursor: pointer; /* WARNING: Opinionated */ +} +.c-button:disabled:not(.c-button--is-busy) { + color: var(--global-color-primary--dark); + background-color: var(--global-color-primary--xx-light); + border-color: var(--global-color-primary--dark); + + pointer-events: none; +} + + + + + +/* Modifiers */ + +/* Modifiers: Types */ + +.c-button--primary, +.c-button--secondary, +.c-button--tertiary, +.c-button--is-active { + padding: 6px 18px; + min-width: var(--min-width); + max-width: var(--max-width); +} + +/* Modifiers: Types: Primary */ + +.c-button--primary:hover { + color: var(--global-color-primary--xx-light); + background-color: var(--global-color-accent--dark); + border-color: var(--global-color-accent--dark); +} + +.c-button--primary:active:not(.c-button--is-busy) { + color: var(--global-color-primary--xx-light); + background-color: var(--global-color-accent--x-dark); + border-color: var(--global-color-accent--dark); + + border-width: var(--global-border-width--normal); + outline: var(--global-border-width--normal) solid + var(--global-color-accent--dark); +} + +.c-button--primary:focus:not(:active) { + color: var(--global-color-primary--xx-light); + background-color: var(--global-color-accent--normal); + border-color: var(--global-color-primary--xx-light); + + outline: var(--global-border-width--normal) solid + var(--global-color-accent--light); +} + +.c-button--primary.c-button--is-busy, +.c-button--primary:not( + .c-button:hover, + .c-button:focus, + .c-button:active, + .c-button:disabled +) { + color: var(--global-color-primary--xx-light); + background-color: var(--global-color-accent--normal); + border-color: var(--global-color-accent--normal); +} + +/* Modifiers: Types: Secondary */ + +.c-button--secondary:hover { + color: var(--global-color-primary--xx-dark); + background-color: var(--global-color-accent--weak); + border-color: var(--global-color-accent--normal); +} + +.c-button--secondary:active:not(.c-button--is-busy) { + color: var(--global-color-primary--xx-dark); + background-color: var(--global-color-accent--x-light); + border-color: var(--global-color-accent--dark); + + border-width: var(--global-border-width--normal); + outline: var(--global-border-width--normal) solid + var(--global-color-accent--dark); +} + +.c-button--secondary:focus:not(:active) { + color: var(--global-color-primary--xx-dark); + background-color: var(--global-color-accent--weak); + border-color: var(--global-color-primary--xx-dark); + + outline: var(--global-border-width--thick) solid + var(--global-color-accent--light); +} + +.c-button--secondary.c-button--is-busy, +.c-button--secondary:not(.c-button:hover, .c-button:focus, .c-button:active, .c-button:disabled) { + color: var(--global-color-primary--xx-dark); + background-color: var(--global-color-primary--x-light); + border-color: var(--global-color-primary--xx-dark); +} + +.c-button/* for specificity to override */.c-button--secondary:disabled { + background-color: var(--global-color-primary--x-light); +} + +/* Modifiers: Types: Tertiary */ + +.c-button--tertiary:hover { + color: var(--global-color-primary--xx-dark); + background-color: var(--global-color-primary--light); + border-color: var(--global-color-accent--dark); +} + +.c-button--tertiary:active:not(.c-button--is-busy) { + color: var(--global-color-primary--xx-dark); + background-color: var(--global-color-accent--x-light); + border-color: var(--global-color-accent--dark); + + border-width: var(--global-border-width--normal); + outline: var(--global-border-width--normal) solid + var(--global-color-accent--dark); +} + +.c-button--tertiary:focus:not(:active) { + color: var(--global-color-primary--xx-dark); + background-color: var(--global-color-primary--light); + border-color: var(--global-color-primary--xx-dark); + + outline: var(--global-border-width--thick) solid + var(--global-color-accent--light); +} + +.c-button--tertiary.c-button--is-busy, +.c-button--tertiary:not( + .c-button:hover, + .c-button:focus, + .c-button:active, + .c-button:disabled +) { + color: var(--global-color-primary--xx-dark); + background-color: var(--global-color-primary--xx-light); + border-color: var(--global-color-primary--xx-dark); +} + +/* Modifiers: Types: Is Active */ + +.c-button--is-active:hover { + color: var(--global-color-primary--xx-dark); + background-color: var(--global-color-accent--alt); + border-color: var(--global-color-accent--dark); +} + +.c-button--is-active:active { + color: var(--global-color-primary--xx-dark); + background-color: var(--global-color-accent--x-light); + border-color: var(--global-color-accent--dark); + + border-width: var(--global-border-width--normal); + outline: var(--global-border-width--normal) solid + var(--global-color-accent--dark); +} + +.c-button--is-active:focus:not(:active) { + color: var(--global-color-primary--xx-dark); + background-color: var(--global-color-accent--alt); + border-color: var(--global-color-primary--xx-dark); + + outline: var(--global-border-width--thick) solid + var(--global-color-accent--light); +} + +.c-button--is-active.c-button--is-busy, +.c-button--is-active:not( + .c-button:hover, + .c-button:focus, + .c-button:active, + .c-button:disabled +) { + color: var(--global-color-primary--xx-dark); + background-color: var(--global-color-accent--x-light); + border-color: var(--global-color-primary--xx-dark); +} + +/* Modifiers: Types: As Link */ + +.c-button--as-link { + color: var(--global-color-accent--normal); + + background: unset; + border: unset; + padding-inline: unset; +} +.c-button--as-link:not(:disabled):hover { + text-decoration: underline; +} + +/* Modifiers: Types: Is Busy */ + +.c-button--is-busy { + opacity: 0.5; +} +.c-button--is-busy .c-button__text { + opacity: 0.3; +} + +/* Modifiers: Sizes */ + +.c-button--width-short { + width: var(--min-width); +} +.c-button--width-medium { + width: var(--mid-width); +} +.c-button--width-long { + width: var(--max-width); +} +.c-button--size-small { + min-width: 0; + padding: 4px 9px; + line-height: 1; +} + + + + + +/* Elements */ + +.c-button__icon--before { + margin-right: 0.5em; +} +.c-button__icon--after { + margin-left: 0.5em; +} diff --git a/taccsite_cms/static/site_cms/css/src/_imports/components/c-button.css b/taccsite_cms/static/site_cms/css/src/_imports/components/c-button.css new file mode 100644 index 000000000..79fc3f5d3 --- /dev/null +++ b/taccsite_cms/static/site_cms/css/src/_imports/components/c-button.css @@ -0,0 +1,7 @@ +@import url("./c-button--from-future-core-styles.css"); + +.c-button { + --max-width: unset; + + font-size: 1.6rem; +} diff --git a/taccsite_cms/static/site_cms/css/src/_imports/components/django.cms.forms.css b/taccsite_cms/static/site_cms/css/src/_imports/components/django.cms.forms.css new file mode 100644 index 000000000..ddfebaba4 --- /dev/null +++ b/taccsite_cms/static/site_cms/css/src/_imports/components/django.cms.forms.css @@ -0,0 +1,96 @@ +/* +Django CMS Form Components + +These styles are only for forms created by the Django CMS Form plugin. + +Reference: + +- [Django CMS Form Default Template](https://github.com/avryhof/djangocms-forms/blob/master/djangocms_forms/templates/djangocms_forms/form_template/default.html) +- [TACC's Django CMS Form Default Template](https://github.com/TACC/Core-CMS/blob/master/taccsite_cms/templates/djangocms_forms/form_template/default.html) + +Styleguide Components.DjangoCMS.Blog.App +*/ + + + +/* Content */ + +.description { + margin-block: 25px; +} + +.help-text { + font-size: var(--global-font-size--small); + font-style: italic; + margin-top: 0.5rem; /* mimic Bootstrap _reboot.css label { margin-bottom } */ +} +p.help-text:last-child { + margin-bottom: 0; +} + + + +/* Field */ + +.field-wrapper { + margin-bottom: 2rem; /* mimic
`margin-bottom` */ +} + +.field-wrapper:not(.checkboxinput) { + display: flex; + flex-direction: column; + align-items: start; /* i.e. prevent stretch */ +} +.field-wrapper:not(.checkboxinput) > .field-errors { + order: 1; /* i.e. move to end */ +} + +.field-wrapper.checkboxinput { + display: inline-grid; + + column-gap: 0.25em; + align-items: baseline; + grid-template-columns: min-content auto; /* shrink input, let label extend */ + grid-template-areas: + 'error _____' + 'input label' + 'notes notes'; +} +.field-wrapper.checkboxinput .field-errors { grid-area: error; } +.field-wrapper.checkboxinput input { grid-area: input; } +.field-wrapper.checkboxinput label { grid-area: label; } +.field-wrapper.checkboxinput .help-text { grid-area: notes; } +.field-wrapper.checkboxinput label { + margin-bottom: 0; /* overwrite forms.css label */ +} + + + +/* Errors */ + +.field-errors { + font-size: var(--global-font-size--small); +} +.field-errors ul { + margin-top: 1rem; /* mimic ul margin-bottom */ + margin-bottom: 0; /* overwrite ul margin-bottom */ +} + + + +/* Lists */ + +ul.radioselect, +ul.checkboxselectmultiple { + list-style: none; + + padding-left: 0; +} + + + +/* Layout */ + +.button-wrapper { + margin-top: 35px; +} diff --git a/taccsite_cms/static/site_cms/css/src/_imports/elements/form.css b/taccsite_cms/static/site_cms/css/src/_imports/elements/form.css new file mode 100644 index 000000000..7dbfa17b1 --- /dev/null +++ b/taccsite_cms/static/site_cms/css/src/_imports/elements/form.css @@ -0,0 +1,45 @@ +/* +Forms + +Elements that create forms which the user can fill out and submit to the Web site or application. + +``` +