= ({ field: Field }) => (
+ <>
+ } />
+ } />
+ } />
+ } />
+ >
+)
+
+export const FormFieldVariants: React.FunctionComponent = () => (
+
+ (
+
+ )}
+ />
+ (
+
+ )}
+ />
+ (
+
+ )}
+ />
+ (
+
+ )}
+ />
+ (
+
+ )}
+ />
+
+)
diff --git a/client/branded/src/global-styles/GlobalStylesStory/GlobalStyles.story.tsx b/client/branded/src/global-styles/GlobalStylesStory/GlobalStyles.story.tsx
index a35ab8dca45..57f35123dd2 100644
--- a/client/branded/src/global-styles/GlobalStylesStory/GlobalStyles.story.tsx
+++ b/client/branded/src/global-styles/GlobalStylesStory/GlobalStyles.story.tsx
@@ -23,6 +23,7 @@ import { Form } from '../../components/Form'
import { ButtonVariants } from './ButtonVariants'
import { SEMANTIC_COLORS } from './constants'
+import { FormFieldVariants } from './FormFieldVariants'
import { TextStory } from './TextStory'
import { preventDefault } from './utils'
@@ -788,7 +789,7 @@ add(
-
-
+
@@ -850,25 +851,20 @@ add(
Sizing
- Form controls can be made smaller or larger for rare use cases, like a select inside a dropdown menu.
+ Form fields can be made smaller
+ Field reference
+
>
),
{
diff --git a/client/branded/src/global-styles/colors-redesign.scss b/client/branded/src/global-styles/colors-redesign.scss
index 51786360647..f3b7ec4235d 100644
--- a/client/branded/src/global-styles/colors-redesign.scss
+++ b/client/branded/src/global-styles/colors-redesign.scss
@@ -62,7 +62,7 @@ $theme-colors-redesign: (
--tooltip-bg: #{$redesign-gray-08};
// Assumption: Uses light-mode body-color, which matches current behavior
--box-shadow: 0 0.25rem 0.5rem #{rgba($redesign-gray-08, 0.07)};
- --btn-focus-box-shadow: 0 0 0 2px var(--primary-2);
+ --focus-box-shadow: 0 0 0 2px var(--primary-2);
--btn-link-disabled-color: var(--primary-2);
}
diff --git a/client/branded/src/global-styles/colors.scss b/client/branded/src/global-styles/colors.scss
index 79a3b8b578e..e7b9c595ca4 100644
--- a/client/branded/src/global-styles/colors.scss
+++ b/client/branded/src/global-styles/colors.scss
@@ -87,7 +87,7 @@ $text-muted: var(--text-muted);
--logo-purple: #{$logo-purple};
--tooltip-bg: #{$gray-19};
--box-shadow: 0 0.25rem 0.5rem #{rgba($gray-19, 0.07)};
- --btn-focus-box-shadow: 0 0 0 2px #{rgba($primary, 0.8)};
+ --focus-box-shadow: 0 0 0 2px #{rgba($primary, 0.8)};
// Matches Bootstrap colors, using variable to easily change for redesign
--btn-link-disabled-color: #6c757d;
}
diff --git a/client/branded/src/global-styles/forms.scss b/client/branded/src/global-styles/forms.scss
index c7097470849..530c585d761 100644
--- a/client/branded/src/global-styles/forms.scss
+++ b/client/branded/src/global-styles/forms.scss
@@ -11,6 +11,11 @@
--input-group-addon-color: var(--body-color);
--input-group-addon-bg: var(--color-bg-4);
--input-group-addon-border-color: var(--color-bg-4);
+ --input-focus-border-color: var(--primary);
+ --input-focus-box-shadow: 0 0 0 2px #{rgba($primary, 0.25)};
+
+ // Checkbox margins
+ --form-check-input-margin-y: 0.2rem;
}
.theme-light {
@@ -22,11 +27,14 @@
--input-group-addon-color: var(--body-color);
--input-group-addon-bg: var(--color-bg-4);
--input-group-addon-border-color: var(--color-bg-4);
+ --input-focus-border-color: var(--primary);
+ --input-focus-box-shadow: 0 0 0 2px #{rgba($primary, 0.25)};
+
+ // Checkbox margins
+ --form-check-input-margin-y: 0.2rem;
}
-.theme-light.theme-redesign,
-// Descendant selector is required for Storybook `addRedesignVariants` helper.
-.theme-light .theme-redesign {
+.theme-light.theme-redesign {
--input-bg: #{$white};
--input-disabled-bg: #{$redesign-gray-04};
--input-border-color: #{$redesign-gray-04};
@@ -35,10 +43,14 @@
--input-group-addon-color: #{$redesign-gray-08};
--input-group-addon-bg: #{$redesign-gray-03};
--input-group-addon-border-color: #{$redesign-gray-03};
+ --input-focus-border-color: var(--border-active-color);
+ --input-focus-box-shadow: var(--focus-box-shadow);
+
+ // Checkbox margins
+ --form-check-input-margin-y: 0.3rem;
}
-.theme-dark.theme-redesign,
-.theme-dark .theme-redesign {
+.theme-dark.theme-redesign {
--input-bg: #{$redesign-gray-10};
--input-disabled-bg: #{$redesign-gray-08};
--input-border-color: #{$redesign-gray-08};
@@ -47,6 +59,11 @@
--input-group-addon-color: #{$redesign-gray-01};
--input-group-addon-bg: #{$redesign-gray-08};
--input-group-addon-border-color: #{$redesign-gray-08};
+ --input-focus-border-color: var(--border-active-color);
+ --input-focus-box-shadow: var(--focus-box-shadow);
+
+ // Checkbox margins
+ --form-check-input-margin-y: 0.3rem;
}
// Prevent Firefox's default red outline for inputs
@@ -56,3 +73,98 @@
:not(output):-moz-ui-invalid:-moz-focusring:not(:focus) {
box-shadow: none;
}
+
+// Add an additional feedback class to add context to form controls without requiring a valid state
+.field-message {
+ @extend .valid-feedback;
+ display: block;
+ color: var(--text-muted);
+}
+
+.was-validated :valid.form-control,
+.was-validated :invalid.form-control,
+.is-valid.form-control,
+.is-invalid.form-control,
+.custom-select {
+ // Adjust icon padding
+ background-position: right 0.75rem center;
+
+ &-sm {
+ background-position: right 0.5rem center;
+ }
+}
+
+// Overrides
+.theme-redesign {
+ // Input feedback messages
+ .valid-feedback {
+ color: var(--text-muted);
+ }
+ .invalid-feedback {
+ color: var(--danger);
+ }
+ .form-check-input {
+ ~ .field-message,
+ ~ .valid-feedback,
+ ~ .invalid-feedback {
+ // Adjust spacing for radio/checkboxes
+ margin-top: 0;
+ }
+ }
+
+ // Valid form inputs and selects
+ .was-validated .form-control:valid,
+ .was-validated .custom-select:valid,
+ .form-control.is-valid,
+ .custom-select.is-valid {
+ border-color: var(--success);
+
+ &:focus {
+ @at-root #{selector-append('.theme-light', &)} {
+ box-shadow: 0 0 0 2px var(--success-2);
+ }
+ @at-root #{selector-append('.theme-dark', &)} {
+ box-shadow: 0 0 0 2px var(--success-3);
+ }
+ }
+ }
+
+ // Invalid form inputs and selects
+ .was-validated .form-control:invalid,
+ .was-validated .custom-select:invalid,
+ .form-control.is-invalid,
+ .custom-select.is-invalid {
+ border-color: var(--danger);
+
+ &:focus {
+ @at-root #{selector-append('.theme-light', &)} {
+ box-shadow: 0 0 0 2px var(--danger-2);
+ }
+ @at-root #{selector-append('.theme-dark', &)} {
+ box-shadow: 0 0 0 2px var(--danger-3);
+ }
+ }
+ }
+
+ // Valid Radio/checkbox labels
+ .was-validated .form-check-input:valid,
+ .form-check-input.is-valid {
+ ~ .form-check-label {
+ color: var(--success);
+ }
+ }
+
+ // Invalid Radio/checkbox labels
+ .was-validated .form-check-input:invalid,
+ .form-check-input.is-invalid {
+ ~ .form-check-label {
+ color: var(--danger);
+ }
+ }
+
+ // Remove feedback icon for and