From e446f8e730bdab2329ee538cc0fc1b3c6bea822f Mon Sep 17 00:00:00 2001 From: John Rassa Date: Fri, 23 Aug 2024 09:04:15 -0400 Subject: [PATCH] feat: Enable boostrap form validation styling for angular control states Added SCSS to apply bootstrap form validation styling for form controls. --- src/app/common/flyout/flyout.component.scss | 1 - .../system-alert/system-alert.component.scss | 1 - .../manage-message.component.html | 1 + .../feedback-flyout.component.scss | 1 - .../recent-messages.component.scss | 1 - src/styles/_bootstrap.scss | 54 ++++++++++++++++--- src/styles/_ng-select.scss | 40 +++++++++++++- src/styles/bootstrap/_buttons.scss | 1 + src/styles/bootstrap/_forms.scss | 13 +++++ src/styles/bootstrap/_mixins_override.scss | 21 ++++++++ src/styles/bootstrap/_nav.scss | 1 - src/styles/bootstrap/_shared.scss | 16 ++++-- ...riables.scss => _variables_overrides.scss} | 0 13 files changed, 134 insertions(+), 17 deletions(-) create mode 100644 src/styles/bootstrap/_mixins_override.scss delete mode 100644 src/styles/bootstrap/_nav.scss rename src/styles/bootstrap/{_variables.scss => _variables_overrides.scss} (100%) diff --git a/src/app/common/flyout/flyout.component.scss b/src/app/common/flyout/flyout.component.scss index be7f65da..5053cd76 100644 --- a/src/app/common/flyout/flyout.component.scss +++ b/src/app/common/flyout/flyout.component.scss @@ -1,5 +1,4 @@ @import '../../../styles/shared'; -@import '../../../styles/bootstrap/shared'; $flyout-border-top: 8px !default; $flyout-box-shadow: 0 0.25rem 0.5rem rgba(var(--bs-body-bg-rgb), 0.2) !default; diff --git a/src/app/common/system-alert/system-alert.component.scss b/src/app/common/system-alert/system-alert.component.scss index cf0b656d..742f79e1 100644 --- a/src/app/common/system-alert/system-alert.component.scss +++ b/src/app/common/system-alert/system-alert.component.scss @@ -1,6 +1,5 @@ @use 'sass:map'; @import '../../../styles/shared'; -@import '../../../styles/bootstrap/shared'; $system-alert-icons: () !default; $system-alert-icons: map.merge( diff --git a/src/app/core/admin/messages/manage-message/manage-message.component.html b/src/app/core/admin/messages/manage-message/manage-message.component.html index db11a7b8..ab5bfbce 100644 --- a/src/app/core/admin/messages/manage-message/manage-message.component.html +++ b/src/app/core/admin/messages/manage-message/manage-message.component.html @@ -21,6 +21,7 @@

{{ mode() | titlecase }} Message

name="type" bindLabel="display" bindValue="value" + required style="width: 350px" [(ngModel)]="message().type" [items]="typeOptions" diff --git a/src/app/core/feedback/feedback-flyout/feedback-flyout.component.scss b/src/app/core/feedback/feedback-flyout/feedback-flyout.component.scss index 0305bdd4..384f7d68 100644 --- a/src/app/core/feedback/feedback-flyout/feedback-flyout.component.scss +++ b/src/app/core/feedback/feedback-flyout/feedback-flyout.component.scss @@ -1,5 +1,4 @@ @import '../../../../styles/shared'; -@import '../../../../styles/bootstrap/shared'; .feedback-form { width: 550px; diff --git a/src/app/core/messages/recent-messages/recent-messages.component.scss b/src/app/core/messages/recent-messages/recent-messages.component.scss index 42f67ad3..8a61dad9 100644 --- a/src/app/core/messages/recent-messages/recent-messages.component.scss +++ b/src/app/core/messages/recent-messages/recent-messages.component.scss @@ -1,5 +1,4 @@ @use 'sass:map'; -@import '../../../../styles/bootstrap/shared'; @import '../../../../styles/shared'; @import '../shared'; diff --git a/src/styles/_bootstrap.scss b/src/styles/_bootstrap.scss index c5287737..6b57f7b0 100644 --- a/src/styles/_bootstrap.scss +++ b/src/styles/_bootstrap.scss @@ -1,18 +1,60 @@ -@import 'bootstrap/shared'; - -@import '../../node_modules/bootstrap/scss/bootstrap'; - /** * _bootstrap.scss - * This file is globally included in the Angular application. * All bootstrap theme styles should be included in this file. */ +//@import '../../node_modules/bootstrap/scss/bootstrap'; + +@import "bootstrap/shared"; + +// Layout & components +/** + * Individual components can be removed below to help reduce + * bundle size if not being used. + */ +@import "../../node_modules/bootstrap/scss/root"; +@import "../../node_modules/bootstrap/scss/reboot"; +@import "../../node_modules/bootstrap/scss/type"; +@import "../../node_modules/bootstrap/scss/images"; +@import "../../node_modules/bootstrap/scss/containers"; +@import "../../node_modules/bootstrap/scss/grid"; +@import "../../node_modules/bootstrap/scss/tables"; +@import "../../node_modules/bootstrap/scss/forms"; +@import "../../node_modules/bootstrap/scss/buttons"; +@import "../../node_modules/bootstrap/scss/transitions"; +@import "../../node_modules/bootstrap/scss/dropdown"; +@import "../../node_modules/bootstrap/scss/button-group"; +@import "../../node_modules/bootstrap/scss/nav"; +@import "../../node_modules/bootstrap/scss/navbar"; +@import "../../node_modules/bootstrap/scss/card"; +@import "../../node_modules/bootstrap/scss/accordion"; +@import "../../node_modules/bootstrap/scss/breadcrumb"; +@import "../../node_modules/bootstrap/scss/pagination"; +@import "../../node_modules/bootstrap/scss/badge"; +@import "../../node_modules/bootstrap/scss/alert"; +@import "../../node_modules/bootstrap/scss/progress"; +@import "../../node_modules/bootstrap/scss/list-group"; +@import "../../node_modules/bootstrap/scss/close"; +@import "../../node_modules/bootstrap/scss/toasts"; +@import "../../node_modules/bootstrap/scss/modal"; +@import "../../node_modules/bootstrap/scss/tooltip"; +@import "../../node_modules/bootstrap/scss/popover"; +@import "../../node_modules/bootstrap/scss/carousel"; +@import "../../node_modules/bootstrap/scss/spinners"; +@import "../../node_modules/bootstrap/scss/offcanvas"; +@import "../../node_modules/bootstrap/scss/placeholders"; + +// Helpers +@import "../../node_modules/bootstrap/scss/helpers"; + +// Utilities +@import "../../node_modules/bootstrap/scss/utilities/api"; + +// Additional styles @import 'bootstrap/buttons'; @import 'bootstrap/cards'; @import 'bootstrap/dropdowns'; @import 'bootstrap/forms'; @import 'bootstrap/grid'; -@import 'bootstrap/nav'; @import 'bootstrap/tables'; diff --git a/src/styles/_ng-select.scss b/src/styles/_ng-select.scss index 021c7f58..01e2f9f5 100644 --- a/src/styles/_ng-select.scss +++ b/src/styles/_ng-select.scss @@ -1,6 +1,5 @@ @use 'sass:color'; @import 'shared'; -@import 'bootstrap/shared'; @import '../../node_modules/@ng-select/ng-select/scss/mixins'; /* stylelint-disable-line no-invalid-position-at-import-rule */ @@ -35,6 +34,41 @@ $ng-select-dropdown-option-bg: $ng-select-dropdown-bg !default; $ng-select-dropdown-option-text: var(--bs-body-color) !default; $ng-select-dropdown-option-disabled: color.adjust($ng-select-primary-text-old, $lightness: 60%) !default; +@mixin ng-select-form-validation-state( + $state, + $color, + $icon, + $tooltip-color: color-contrast($color), + $tooltip-bg-color: rgba($color, $form-feedback-tooltip-opacity), + $focus-box-shadow: 0 0 $input-btn-focus-blur $input-focus-width rgba($color, $input-btn-focus-color-opacity), + $border-color: $color +) { + @include form-validation-state-selector($state) { + .ng-select-container { + border-color: $border-color; + + @if $enable-validation-icons { + padding-right: $input-height-inner; + background-image: escape-svg($icon); + background-repeat: no-repeat; + background-position: right $input-height-inner-quarter center; + background-size: $input-height-inner-half $input-height-inner-half; + } + } + &.ng-select-focused { + &:not(.ng-select-opened) > .ng-select-container { + border-color: $border-color; + @if $enable-shadows { + @include box-shadow($input-box-shadow, $focus-box-shadow); + } @else { + // Avoid using mixin so we can pass custom focus shadow properly + box-shadow: $focus-box-shadow; + } + } + } + } +} + .ng-select { &.ng-select-opened { > .ng-select-container { @@ -253,6 +287,10 @@ $ng-select-dropdown-option-disabled: color.adjust($ng-select-primary-text-old, $ border-width: 5px 5px 2.5px; } } + + @each $state, $data in $form-validation-states { + @include ng-select-form-validation-state($state, $data...); + } } .ng-dropdown-panel { diff --git a/src/styles/bootstrap/_buttons.scss b/src/styles/bootstrap/_buttons.scss index 9ba77ebb..4eac5a00 100644 --- a/src/styles/bootstrap/_buttons.scss +++ b/src/styles/bootstrap/_buttons.scss @@ -1,4 +1,5 @@ @use 'sass:math'; +@import 'shared'; // Submit Button $btn-submit-style: spinner !default; diff --git a/src/styles/bootstrap/_forms.scss b/src/styles/bootstrap/_forms.scss index 813c5a4d..5bddb70c 100644 --- a/src/styles/bootstrap/_forms.scss +++ b/src/styles/bootstrap/_forms.scss @@ -77,3 +77,16 @@ $form-inline-edit-label-col-width: 30% !default; } } } + +@mixin form-validation-state-selector($state) { + @if ($state == "valid" or $state == "invalid") { + .was-validated #{if(&, "&", "")}:#{$state}, + #{if(&, "&", "")}.is-#{$state} { + @content; + } + } @else { + #{if(&, "&", "")}.is-#{$state} { + @content; + } + } +} diff --git a/src/styles/bootstrap/_mixins_override.scss b/src/styles/bootstrap/_mixins_override.scss new file mode 100644 index 00000000..050bd622 --- /dev/null +++ b/src/styles/bootstrap/_mixins_override.scss @@ -0,0 +1,21 @@ +// Mixins defined here will override mixins of the same name provided by bootstrap + +@mixin form-validation-state-selector($state) { + @if ($state == "valid" or $state == "invalid") { + .was-validated #{if(&, "&", "")}:#{$state}, + #{if(&, "&", "")}.is-#{$state} { + @content; + } + } @else { + #{if(&, "&", "")}.is-#{$state} { + @content; + } + } + // Add bootstrap validation styling based on ng-invalid + @if ($state == "invalid") { + #{if(&, "&", "")}.ng-#{$state}.ng-dirty, + #{if(&, "&", "")}.ng-#{$state}.ng-touched { + @content; + } + } +} diff --git a/src/styles/bootstrap/_nav.scss b/src/styles/bootstrap/_nav.scss deleted file mode 100644 index 8b137891..00000000 --- a/src/styles/bootstrap/_nav.scss +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/styles/bootstrap/_shared.scss b/src/styles/bootstrap/_shared.scss index fd250571..7053ec81 100644 --- a/src/styles/bootstrap/_shared.scss +++ b/src/styles/bootstrap/_shared.scss @@ -1,7 +1,13 @@ -// Imports non-rendering bootstrap SASS (i.e. variables, functions, mixins) for easy import into other files. +// Variable overrides must be imported before the variables are defined +@import 'variables_overrides'; -@import 'variables'; +// Configuration +@import "../../../node_modules/bootstrap/scss/functions"; +@import "../../../node_modules/bootstrap/scss/variables"; +@import "../../../node_modules/bootstrap/scss/variables-dark"; +@import "../../../node_modules/bootstrap/scss/maps"; +@import "../../../node_modules/bootstrap/scss/mixins"; +@import "../../../node_modules/bootstrap/scss/utilities"; -@import '../../../node_modules/bootstrap/scss/functions'; -@import '../../../node_modules/bootstrap/scss/variables'; -@import '../../../node_modules/bootstrap/scss/mixins'; +// Mixin overrides must be imported before the mixins are used. +@import "mixins_override"; diff --git a/src/styles/bootstrap/_variables.scss b/src/styles/bootstrap/_variables_overrides.scss similarity index 100% rename from src/styles/bootstrap/_variables.scss rename to src/styles/bootstrap/_variables_overrides.scss