@qld-gov-au/qgds-bootstrap5 2.0.10 → 2.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/.storybook/main.mjs +2 -2
  2. package/.storybook/preview.js +5 -2
  3. package/dist/assets/components/bs5/banner/banner.hbs +3 -6
  4. package/dist/assets/components/bs5/card/card.hbs +2 -2
  5. package/dist/assets/components/bs5/dateinput/dateinput.hbs +27 -27
  6. package/dist/assets/components/bs5/formcheck/formcheck.hbs +10 -2
  7. package/dist/assets/components/bs5/head/head.hbs +1 -1
  8. package/dist/assets/components/bs5/searchInput/searchInput.hbs +31 -29
  9. package/dist/assets/components/bs5/select/select.hbs +19 -19
  10. package/dist/assets/components/bs5/tag/tag.hbs +1 -1
  11. package/dist/assets/components/bs5/textarea/textarea.hbs +17 -17
  12. package/dist/assets/components/bs5/textbox/textbox.hbs +17 -18
  13. package/dist/assets/css/qld.bootstrap.css +2 -2
  14. package/dist/assets/css/qld.bootstrap.css.map +3 -3
  15. package/dist/assets/css/qld.bootstrap.legacy.css +2 -2
  16. package/dist/assets/css/qld.bootstrap.legacy.css.map +3 -3
  17. package/dist/assets/js/handlebars.helpers.bundle.js +2 -2
  18. package/dist/assets/js/handlebars.helpers.bundle.js.map +2 -2
  19. package/dist/assets/js/handlebars.init.min.js +141 -135
  20. package/dist/assets/js/handlebars.init.min.js.map +2 -2
  21. package/dist/assets/js/handlebars.partials.js +141 -135
  22. package/dist/assets/js/handlebars.partials.js.map +2 -2
  23. package/dist/assets/js/qld.bootstrap.min.js +9 -10
  24. package/dist/assets/js/qld.bootstrap.min.js.map +4 -4
  25. package/dist/assets/node/handlebars.init.min.js +59 -11
  26. package/dist/assets/node/handlebars.init.min.js.map +2 -2
  27. package/dist/components/bs5/banner/banner.hbs +3 -6
  28. package/dist/components/bs5/card/card.hbs +2 -2
  29. package/dist/components/bs5/dateinput/dateinput.hbs +27 -27
  30. package/dist/components/bs5/formcheck/formcheck.hbs +10 -2
  31. package/dist/components/bs5/head/head.hbs +1 -1
  32. package/dist/components/bs5/searchInput/searchInput.hbs +31 -29
  33. package/dist/components/bs5/select/select.hbs +19 -19
  34. package/dist/components/bs5/tag/tag.hbs +1 -1
  35. package/dist/components/bs5/textarea/textarea.hbs +17 -17
  36. package/dist/components/bs5/textbox/textbox.hbs +17 -18
  37. package/dist/package.json +1 -1
  38. package/dist/sample-data/card/card.data.json +4 -1
  39. package/dist/sample-data/dateinput/dateinput.data.json +14 -12
  40. package/dist/sample-data/formcheck/stories/checkbox/checkbox.data.json +4 -5
  41. package/dist/sample-data/formcheck/stories/radio/radio.data.json +4 -4
  42. package/dist/sample-data/searchInput/searchInput.data.json +19 -10
  43. package/dist/sample-data/select/select.data.json +12 -10
  44. package/dist/sample-data/tag/tag.data.json +149 -143
  45. package/dist/sample-data/textarea/textarea.data.json +14 -11
  46. package/dist/sample-data/textbox/textbox.data.json +13 -10
  47. package/package.json +1 -1
  48. package/src/components/bs5/banner/banner.hbs +3 -6
  49. package/src/components/bs5/banner/banner.scss +10 -7
  50. package/src/components/bs5/banner/banner.stories.js +2 -5
  51. package/src/components/bs5/button/button.scss +4 -11
  52. package/src/components/bs5/button/button.stories.js +17 -15
  53. package/src/components/bs5/card/Card.js +31 -2
  54. package/src/components/bs5/card/Card.mdx +4 -0
  55. package/src/components/bs5/card/card--icon-list-footer.stories.js +2 -24
  56. package/src/components/bs5/card/card--multi-action.stories.js +9 -28
  57. package/src/components/bs5/card/card--no-action.stories.js +5 -27
  58. package/src/components/bs5/card/card--single-action.stories.js +4 -33
  59. package/src/components/bs5/card/card.data.json +4 -1
  60. package/src/components/bs5/card/card.hbs +2 -2
  61. package/src/components/bs5/dateinput/Dateinput.js +26 -11
  62. package/src/components/bs5/dateinput/dateinput.data.json +14 -12
  63. package/src/components/bs5/dateinput/dateinput.hbs +27 -27
  64. package/src/components/bs5/footer/footer_formio.scss +5 -5
  65. package/src/components/bs5/formcheck/Formcheck.js +57 -6
  66. package/src/components/bs5/formcheck/_form-variables.scss +131 -0
  67. package/src/components/bs5/formcheck/formcheck.hbs +10 -2
  68. package/src/components/bs5/formcheck/formcheck.scss +229 -66
  69. package/src/components/bs5/formcheck/stories/bootstrap-validation/bootstrap-validation.stories.js +304 -0
  70. package/src/components/bs5/formcheck/stories/checkbox/checkbox.data.json +4 -5
  71. package/src/components/bs5/formcheck/stories/checkbox/checkbox.stories.js +19 -111
  72. package/src/components/bs5/formcheck/stories/radio/radio.data.json +4 -4
  73. package/src/components/bs5/formcheck/stories/radio/radio.stories.js +30 -122
  74. package/src/components/bs5/inpageAlert/inpageAlert.scss +1 -1
  75. package/src/components/bs5/modal/modal.scss +106 -99
  76. package/src/components/bs5/navbar/navbar.functions.js +122 -19
  77. package/src/components/bs5/pageLayout/{ThemeShowcase.stories.js → PaletteShowcase.stories.js} +36 -35
  78. package/src/components/bs5/searchInput/__snapshots__/searchInput.test.js.snap +24 -28
  79. package/src/components/bs5/searchInput/search.functions.js +93 -76
  80. package/src/components/bs5/searchInput/searchInput.data.json +19 -10
  81. package/src/components/bs5/searchInput/searchInput.hbs +31 -29
  82. package/src/components/bs5/searchInput/searchInput.scss +140 -196
  83. package/src/components/bs5/searchInput/searchInput.stories.js +35 -13
  84. package/src/components/bs5/searchInput/searchInput.test.js +5 -1
  85. package/src/components/bs5/select/Select.js +13 -5
  86. package/src/components/bs5/select/Select.stories.js +27 -83
  87. package/src/components/bs5/select/select.data.json +12 -10
  88. package/src/components/bs5/select/select.hbs +19 -19
  89. package/src/components/bs5/tag/tag--status.stories.js +1 -0
  90. package/src/components/bs5/tag/tag.data.json +149 -143
  91. package/src/components/bs5/tag/tag.hbs +1 -1
  92. package/src/components/bs5/tag/tag.scss +2 -5
  93. package/src/components/bs5/tag/tag.stories.js +1 -0
  94. package/src/components/bs5/textarea/Textarea.js +13 -5
  95. package/src/components/bs5/textarea/Textarea.stories.js +29 -55
  96. package/src/components/bs5/textarea/textarea.data.json +14 -11
  97. package/src/components/bs5/textarea/textarea.hbs +17 -17
  98. package/src/components/bs5/textbox/Textbox.js +16 -5
  99. package/src/components/bs5/textbox/Textbox.stories.js +26 -51
  100. package/src/components/bs5/textbox/textInput.scss +12 -232
  101. package/src/components/bs5/textbox/textbox.data.json +13 -10
  102. package/src/components/bs5/textbox/textbox.hbs +17 -18
  103. package/src/components/bs5/typography/typography.stories.js +1 -1
  104. package/src/css/functions/_index.scss +2 -0
  105. package/src/css/functions/remify.scss +32 -0
  106. package/src/css/functions/snap-line-height.scss +7 -0
  107. package/src/css/main.scss +1 -1
  108. package/src/css/mixins/focusable.scss +4 -1
  109. package/src/css/mixins/make-icon.scss +1 -1
  110. package/src/css/{qld-theme.scss → qld-palettes.scss} +30 -23
  111. package/src/js/handlebars.helpers.js +9 -1
  112. package/src/js/utils.js +142 -0
  113. package/src/components/bs5/formcheck/_formcheck.stories.bak.js +0 -432
@@ -0,0 +1,131 @@
1
+ // Expand this file with all themable shared form variables
2
+ // @extend %form-variables in all input and form components.
3
+ %form-control-variables {
4
+ &,
5
+ .default &,
6
+ .light &,
7
+ .alt & {
8
+ // colors
9
+ --#{$prefix}bg: #{$core-default-color-neutral-white};
10
+ --#{$prefix}bg-hover: #{$core-default-color-neutral-lightest};
11
+ --#{$prefix}bg-focus: #{$core-default-color-neutral-white};
12
+ --#{$prefix}border-color: #{$color-default-color-light-border-alt};
13
+ --#{$prefix}border-color-hover: #{$qld-light-action-primary-hover};
14
+ --#{$prefix}border-color-focus: #{$core-default-color-neutral-lighter};
15
+ --#{$prefix}color: #{$color-default-color-light-text-default};
16
+ --#{$prefix}color-hover: var(--#{$prefix}color);
17
+ --#{$prefix}color-focus: var(--#{$prefix}color);
18
+ --#{$prefix}placeholder-color: #{$color-default-color-light-text-lighter};
19
+ --#{$prefix}placeholder-color-hover: var(--#{$prefix}placeholder-color);
20
+ --#{$prefix}placeholder-color-focus: var(--#{$prefix}placeholder-color);
21
+
22
+ // other properties
23
+ --#{$prefix}border-top-width: 0.125rem;
24
+ --#{$prefix}border-right-width: 0.125rem;
25
+ --#{$prefix}border-bottom-width: 0.125rem;
26
+ --#{$prefix}border-left-width: 0.125rem;
27
+ --#{$prefix}border-width: var(--#{$prefix}border-top-width)
28
+ var(--#{$prefix}border-right-width) var(--#{$prefix}border-bottom-width)
29
+ var(--#{$prefix}border-left-width);
30
+ --#{$prefix}border-radius: 0.25rem;
31
+
32
+ // .form-style-filled legacy class
33
+ &.is-filled,
34
+ &.form-style-filled {
35
+ --#{$prefix}bg: #{$core-default-color-neutral-lightest};
36
+ --#{$prefix}border-radius: 0.25rem 0.25rem 0 0;
37
+ --#{$prefix}border-top-width: 0px; // px unit required for use in calc()
38
+ --#{$prefix}border-right-width: 0px; // px unit required for use in calc()
39
+ --#{$prefix}border-left-width: 0px; // px unit required for use in calc()
40
+
41
+ &:focus {
42
+ --#{$prefix}border-top-width: 0.125rem;
43
+ --#{$prefix}border-right-width: 0.125rem;
44
+ --#{$prefix}border-left-width: 0.125rem;
45
+ --#{$prefix}border-radius: 0.25rem;
46
+ }
47
+ }
48
+
49
+ // .qld-input-success legacy class
50
+ &.is-valid,
51
+ &.qld-input-success,
52
+ .was-validated &:valid {
53
+ --#{$prefix}bg: #{$core-default-color-status-success-lightest};
54
+ --#{$prefix}bg-hover: #{$core-default-color-status-success-lighter};
55
+ --#{$prefix}border-color: #{$core-default-color-status-success-default};
56
+ --#{$prefix}border-color-hover: var(--#{$prefix}border-color);
57
+ }
58
+
59
+ // .qld-input-error legacy class
60
+ &.is-invalid,
61
+ &.qld-input-error,
62
+ .was-validated &:invalid {
63
+ --#{$prefix}bg: #{$qld-color-error-light};
64
+ --#{$prefix}bg-hover: #{$core-default-color-status-error-lighter};
65
+ --#{$prefix}border-color: #{$qld-notify-warning};
66
+ --#{$prefix}border-color-hover: var(--#{$prefix}border-color);
67
+ }
68
+ }
69
+
70
+ .dark &,
71
+ .dark-alt & {
72
+ --#{$prefix}bg: #{$qld-color-dark-background};
73
+ --#{$prefix}bg-hover: #{$qld-color-dark-background--shade};
74
+ --#{$prefix}border-color: #{$color-default-color-dark-border-alt};
75
+ --#{$prefix}border-color-hover: #{$color-default-color-dark-action-primary-hover};
76
+ --#{$prefix}border-color-focus: #{$core-default-color-neutral-lighter};
77
+ --#{$prefix}color: #{$color-default-color-dark-text-default};
78
+ --#{$prefix}color-focus: #{$color-default-color-light-text-lighter};
79
+ --#{$prefix}placeholder-color: #{$color-default-color-dark-text-lighter};
80
+ --#{$prefix}placeholder-color-focus: #{$color-default-color-light-text-lighter};
81
+
82
+ &.is-filled,
83
+ &.form-style-filled {
84
+ --#{$prefix}bg: #{$qld-color-dark-background--shade};
85
+ }
86
+
87
+ &.is-valid,
88
+ &.qld-input-success,
89
+ .was-validated &:valid {
90
+ --#{$prefix}bg: #{$core-default-color-status-success-lightest};
91
+ --#{$prefix}bg-hover: #{$core-default-color-status-success-lighter};
92
+ --#{$prefix}border-color: #{$core-default-color-status-success-default};
93
+ --#{$prefix}border-color-hover: #{$core-default-color-status-success-default};
94
+ --#{$prefix}color: #{$color-default-color-light-text-default};
95
+ --#{$prefix}placeholder-color: #{$color-default-color-light-text-lighter};
96
+ }
97
+
98
+ &.is-invalid,
99
+ &.qld-input-error,
100
+ .was-validated &:invalid {
101
+ --#{$prefix}bg: #{$qld-color-error-light};
102
+ --#{$prefix}bg-hover: #{$core-default-color-status-error-lighter};
103
+ --#{$prefix}border-color: #{$qld-notify-warning};
104
+ --#{$prefix}border-color-hover: #{$qld-notify-warning};
105
+ --#{$prefix}color: #{$color-default-color-light-text-default};
106
+ --#{$prefix}placeholder-color: #{$color-default-color-light-text-lighter};
107
+ }
108
+ }
109
+ }
110
+
111
+ %form-valid-feedback-variables {
112
+ &,
113
+ :is(.default, .light, .alt) & {
114
+ --color-text: #{$color-default-color-light-text-default};
115
+ }
116
+
117
+ :is(.dark, .dark-alt) & {
118
+ --color-text: #{$color-default-color-dark-text-default};
119
+ }
120
+ }
121
+
122
+ %form-invalid-feedback-variables {
123
+ &,
124
+ :is(.default, .light, .alt) & {
125
+ --color-text: #{$core-default-color-status-error-default};
126
+ }
127
+
128
+ :is(.dark, .dark-alt) & {
129
+ --color-text: #{$core-default-color-status-error-lighter};
130
+ }
131
+ }
@@ -11,10 +11,18 @@
11
11
  {{#if hintLabel}}
12
12
  <span class="qld-hint-text">{{hintLabel}}</span>
13
13
  {{/if}}
14
+
15
+ {{#if successMessageText}}
16
+ <div class="valid-feedback">{{successMessageText}}</div>
17
+ {{/if}}
18
+
19
+ {{#if errorMessageText}}
20
+ <div class="invalid-feedback">{{errorMessageText}}</div>
21
+ {{/if}}
14
22
 
15
23
  {{#each listitems}}
16
- <div class="form-check">
17
- <input class="form-check-input" type="{{type}}" name="{{name}}" id="{{id}}" value="{{value}}" {{#if isDisabled}}disabled{{/if}} {{#if isChecked}}checked{{/if}}>
24
+ <div class="form-check {{#if ../isValid}}is-valid{{else}}{{#ifCond ../isValid "===" false}}is-invalid{{/ifCond}}{{/if}}">
25
+ <input class="form-check-input" type="{{#if ../type}}{{../type}}{{else}}{{#if type}}{{type}}{{else}}checkbox{{/if}}{{/if}}" name="{{name}}" id="{{id}}" value="{{value}}" {{#if isDisabled}}disabled{{/if}} {{#if isChecked}}checked{{/if}} {{#if isRequired}}required{{/if}} >
18
26
  <label class="form-check-label" for="{{id}}">
19
27
  {{label}}
20
28
  </label>
@@ -1,3 +1,6 @@
1
+ @use "../../../css/mixins" as m;
2
+ @use "../../../css/functions" as f;
3
+ @import "form-variables";
1
4
  // NTGOV Form Controls, radios, checkboxes and input groups
2
5
  // https://getbootstrap.com/docs/5.2/forms/form-control/#variables
3
6
 
@@ -16,11 +19,8 @@ $input-padding-y-lg: $input-padding-y;
16
19
  $input-padding-x-lg: $input-padding-x;
17
20
  $input-font-size-lg: 1rem;
18
21
 
19
- $input-border-width: 3px;
22
+ $input-border-width: 2px;
20
23
  $input-border-radius: $border-radius;
21
- $input-transition:
22
- border-color 0.15s ease-in-out,
23
- box-shadow 0.15s ease-in-out;
24
24
 
25
25
  // Checks and radios (LARGE)
26
26
  $form-check-input-width: 2rem;
@@ -29,8 +29,9 @@ $form-check-input-width: 2rem;
29
29
  $form-check-input-width-small: 1.375rem;
30
30
 
31
31
  $form-check-min-height: $font-size-base * $line-height-base;
32
- $form-check-padding-start: $form-check-input-width + 0.5rem;
33
- $form-check-margin-bottom: 1rem;
32
+ $form-check-padding-start: $form-check-input-width + f.remify(8px);
33
+ $form-check-margin-top: f.remify(8px);
34
+ $form-check-margin-bottom: f.remify(16px);
34
35
  $form-check-label-color: $body-color;
35
36
  $form-check-label-cursor: null;
36
37
  $form-check-transition: null;
@@ -52,8 +53,7 @@ $form-check-valid-color: var(--#{$prefix}notify-success);
52
53
  $form-check-invalid-color: var(--#{$prefix}notify-warning);
53
54
 
54
55
  // OUTLINES
55
- $form-check-input-outline: 3px solid var(--#{$prefix}light-blue);
56
- $form-check-input-outline-dark: 3px solid var(--#{$prefix}dark-focus);
56
+ $form-check-input-outline: 3px solid var(--#{$prefix}focus-color);
57
57
 
58
58
  // SMALL BORDER WIDTH
59
59
  $form-check-input-border-width-small: 2px;
@@ -80,9 +80,7 @@ $form-check-bg-image-dark: url("data:image/svg+xml,%3Csvg width='18' height='14'
80
80
  // ESCAPE SVGs FOR ICONS
81
81
  $form-radio-button: #{escape-svg($form-radio-bg-image)};
82
82
  $form-radio-button-small: #{escape-svg($form-radio-bg-image-small)};
83
- $form-radio-button-dark: #{escape-svg($form-radio-bg-image-dark)};
84
83
  $form-checkbox-button: #{escape-svg($form-check-bg-image)};
85
- $form-checkbox-button-dark: #{escape-svg($form-check-bg-image-dark)};
86
84
 
87
85
  $form-check-input-indeterminate-color: $component-active-color;
88
86
  $form-check-input-indeterminate-bg-color: $component-active-bg;
@@ -108,30 +106,133 @@ $form-check-inline-margin-end: 1rem;
108
106
  margin-bottom: 0.5rem;
109
107
  }
110
108
 
111
- .form-control,
112
- .form-select {
113
- // CSS Custom properties scoped to .form-control components
114
- // Settable via frontend or JS if required. Related to theme.
109
+ %form-control {
110
+ $_padding: calc(#{$input-padding-y} - var(--#{$prefix}border-top-width, 0px))
111
+ calc(#{$input-padding-x} - var(--#{$prefix}border-right-width, 0px))
112
+ calc(#{$input-padding-y} - var(--#{$prefix}border-bottom-width, 0px))
113
+ calc(#{$input-padding-x} - var(--#{$prefix}border-right-width, 0px));
114
+ @extend %form-control-variables;
115
+
116
+ color: var(--#{$prefix}color);
117
+ background-color: var(--#{$prefix}bg);
118
+ border: {
119
+ style: solid;
120
+ width: var(--#{$prefix}border-width);
121
+ color: var(--#{$prefix}border-color);
122
+ }
123
+ padding: $_padding;
124
+ border-radius: var(--#{$prefix}border-radius);
125
+ font-size: $input-font-size;
126
+ min-height: f.remify(52px);
115
127
 
116
- --#{$prefix}input-bg: transparent;
117
- --#{$prefix}input-border-color: #{$form-check-input-checked-border-color};
118
- --#{$prefix}input-color: var(--#{$prefix}dark-grey-muted);
119
- --#{$prefix}input-border-color-hover: var(--#{$prefix}button-dark-blue);
128
+ transition: none; // no transitions until a holistic decision at design system level
120
129
 
121
- padding: $input-padding-y $input-padding-x;
122
- border: solid $input-border-width var(--#{$prefix}input-border-color);
123
- border-radius: $input-border-radius;
124
- font-size: $input-font-size;
130
+ &::placeholder {
131
+ color: var(--#{$prefix}placeholder-color);
132
+ }
125
133
 
126
- &:active,
127
- &:focus {
128
- border-color: var(--#{$prefix}input-border-color-hover);
129
- outline: $form-check-input-outline;
130
- outline-offset: 2px;
131
- box-shadow: none;
134
+ &:hover {
135
+ background-color: var(--#{$prefix}bg-hover);
136
+ border-color: var(--#{$prefix}border-color-hover);
137
+
138
+ &::placeholder {
139
+ color: var(--#{$prefix}placeholder-color-hover);
140
+ }
141
+ }
142
+
143
+ @include m.focusable() {
144
+ color: var(--#{$prefix}color-focus);
145
+ background-color: var(--#{$prefix}bg-focus);
146
+ border-color: var(--#{$prefix}border-color-focus);
147
+ box-shadow: none !important;
148
+
149
+ &::placeholder {
150
+ color: var(--#{$prefix}placeholder-color-focus);
151
+ }
152
+ }
153
+
154
+ &:disabled,
155
+ &.disabled,
156
+ &.is-disabled {
157
+ &,
158
+ &:hover {
159
+ cursor: not-allowed;
160
+ opacity: 0.5;
161
+ background-color: var(--#{$prefix}bg);
162
+ border-color: var(--#{$prefix}border-color);
163
+ }
164
+ }
165
+ // Bootstrap base styling overrides
166
+ &.is-valid,
167
+ &.is-invalid,
168
+ .was-validated &:valid,
169
+ .was-validated &:invalid {
170
+ border-color: var(
171
+ --#{$prefix}border-color
172
+ ); // already scoped to .valid/.invalid.
173
+ // USe the same padding value as default state, and remove the background image icon.
174
+ padding: $_padding;
175
+ background-image: none;
176
+
177
+ &:focus {
178
+ border-color: var(
179
+ --#{$prefix}border-color-focus
180
+ ); // This value already scoped to valid/invalid.
181
+ }
132
182
  }
133
183
  }
134
184
 
185
+ .form-control {
186
+ @extend %form-control;
187
+ }
188
+
189
+ // .qld-select legacy class
190
+ .form-select,
191
+ .qld-select {
192
+ @extend %form-control;
193
+
194
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='%23008635' d='M4.251 181.1C7.392 177.7 11.69 175.1 16 175.1c3.891 0 7.781 1.406 10.86 4.25l197.1 181.1l197.1-181.1c6.5-6 16.64-5.625 22.61 .9062c6 6.5 5.594 16.59-.8906 22.59l-208 192c-6.156 5.688-15.56 5.688-21.72 0l-208-192C-1.343 197.7-1.749 187.6 4.251 181.1z'/%3E%3C/svg%3E");
195
+ background-repeat: no-repeat;
196
+ appearance: none;
197
+ background-position: right 1rem center;
198
+ background-size: f.remify(20px);
199
+ background-origin: border-box;
200
+ width: 100%;
201
+
202
+ &.disabled,
203
+ &:disabled,
204
+ &.is-disabled {
205
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='%23636363' d='M4.251 181.1C7.392 177.7 11.69 175.1 16 175.1c3.891 0 7.781 1.406 10.86 4.25l197.1 181.1l197.1-181.1c6.5-6 16.64-5.625 22.61 .9062c6 6.5 5.594 16.59-.8906 22.59l-208 192c-6.156 5.688-15.56 5.688-21.72 0l-208-192C-1.343 197.7-1.749 187.6 4.251 181.1z'/%3E%3C/svg%3E");
206
+ }
207
+
208
+ &.qld-input-error,
209
+ &.is-invalid {
210
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='%23E22339' d='M4.251 181.1C7.392 177.7 11.69 175.1 16 175.1c3.891 0 7.781 1.406 10.86 4.25l197.1 181.1l197.1-181.1c6.5-6 16.64-5.625 22.61 .9062c6 6.5 5.594 16.59-.8906 22.59l-208 192c-6.156 5.688-15.56 5.688-21.72 0l-208-192C-1.343 197.7-1.749 187.6 4.251 181.1z'/%3E%3C/svg%3E");
211
+
212
+ &:not([multiple]):not([size]),
213
+ &:not([multiple])[size="1"] {
214
+ background-size: 1rem auto;
215
+ }
216
+ }
217
+
218
+ &.qld-input-success,
219
+ &.is-valid {
220
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='%23339d37' d='M4.251 181.1C7.392 177.7 11.69 175.1 16 175.1c3.891 0 7.781 1.406 10.86 4.25l197.1 181.1l197.1-181.1c6.5-6 16.64-5.625 22.61 .9062c6 6.5 5.594 16.59-.8906 22.59l-208 192c-6.156 5.688-15.56 5.688-21.72 0l-208-192C-1.343 197.7-1.749 187.6 4.251 181.1z'/%3E%3C/svg%3E");
221
+
222
+ &:not([multiple]):not([size]),
223
+ &:not([multiple])[size="1"] {
224
+ background-size: 1rem auto;
225
+ }
226
+ }
227
+ }
228
+
229
+ .form-check {
230
+ display: flex;
231
+ align-items: center;
232
+ margin-block: f.remify(8px 16px);
233
+ padding-left: 0; // override bootstrap default - icon is now attached to <label>.
234
+ }
235
+
135
236
  .form-check-input {
136
237
  // hides the original input element, and + label recreates it visually
137
238
  background-size: calc(2rem - 8px);
@@ -152,7 +253,6 @@ $form-check-inline-margin-end: 1rem;
152
253
  vertical-align: bottom;
153
254
  line-height: 2rem;
154
255
  padding-left: 2.5rem;
155
- margin-left: -1.5em;
156
256
 
157
257
  // before is the outer box with border,
158
258
  // after is the check or radio icon
@@ -236,26 +336,6 @@ $form-check-inline-margin-end: 1rem;
236
336
  }
237
337
  }
238
338
 
239
- // DEFAULT VALID & INVALID
240
- .valid &,
241
- .invalid & {
242
- &:focus + label::before {
243
- outline: $form-check-input-outline;
244
- outline-offset: 2px;
245
- box-shadow: none;
246
- }
247
- }
248
- .valid & {
249
- + label::before {
250
- outline: $form-check-valid-color solid 2px;
251
- }
252
- }
253
- .invalid & {
254
- + label::before {
255
- outline: $form-check-invalid-color solid 2px;
256
- }
257
- }
258
-
259
339
  .small & {
260
340
  &:checked + label::before {
261
341
  background-size: 22px 22px;
@@ -287,32 +367,115 @@ $form-check-inline-margin-end: 1rem;
287
367
 
288
368
  .dark &,
289
369
  .dark-alt & {
290
- &:hover + label {
291
- --_background-color: $form-check-hover;
292
- }
293
- &:hover + label::after {
294
- background-color: $form-check-hover;
295
- }
296
370
  + label::before,
297
371
  + label::after {
298
372
  border-color: $form-check-input-border-dark;
299
373
  }
300
- &:checked {
301
- & + label::after {
302
- background-color: $form-check-input-checked-color-dark;
374
+ &:hover + label {
375
+ --_background-color: $form-check-hover;
376
+
377
+ &::after {
378
+ background-color: $form-check-hover;
303
379
  }
304
380
  }
305
- :focus {
306
- outline: $form-check-input-outline-dark;
381
+ &:checked + label::after {
382
+ background-color: $form-check-input-checked-color-dark;
383
+ }
384
+
385
+ &:focus + label::before {
386
+ outline: $form-check-input-outline;
307
387
  }
308
388
  }
309
389
  }
310
390
 
311
- .form-check {
312
- display: flex;
313
- align-items: center;
314
- margin-bottom: $form-check-margin-bottom;
315
- &-label {
316
- margin-left: 0.5rem;
391
+ %_form-check-input-valid,
392
+ %_form-check-input-invalid {
393
+ + .form-check-label {
394
+ color: var(--body-color);
395
+ }
396
+ &:focus + .form-check-label::before {
397
+ outline: $form-check-input-outline;
398
+ outline-offset: 2px;
399
+ box-shadow: none;
400
+ }
401
+ }
402
+
403
+ %_form-check-input-valid {
404
+ + .form-check-label::before {
405
+ outline: $form-check-valid-color solid 2px;
317
406
  }
318
407
  }
408
+
409
+ %_form-check-input-invalid {
410
+ + .form-check-label::before {
411
+ outline: $form-check-invalid-color solid 2px;
412
+ }
413
+ }
414
+
415
+ .valid .form-check-input,
416
+ .is-valid .form-check-input,
417
+ .was-validated .form-check-input:valid {
418
+ @extend %_form-check-input-valid;
419
+ }
420
+
421
+ .invalid .form-check-input,
422
+ .is-invalid .form-check-input,
423
+ .was-validated .form-check-input:invalid {
424
+ @extend %_form-check-input-invalid;
425
+ }
426
+
427
+ %_valid-feedback,
428
+ %_invalid-feedback {
429
+ font-size: f.remify(14px);
430
+ line-height: f.snap-line-height(1.5);
431
+ display: none;
432
+ gap: f.remify(4px);
433
+ flex-wrap: nowrap;
434
+ margin-block: f.remify(8px);
435
+ }
436
+
437
+ %_valid-feedback {
438
+ @extend %form-valid-feedback-variables;
439
+ color: var(--color-text);
440
+
441
+ @include m.make-icon(
442
+ $name: "status-success",
443
+ $size: "sm",
444
+ $pseudo: "before"
445
+ ) {
446
+ flex-shrink: 0;
447
+ }
448
+ }
449
+
450
+ %_invalid-feedback {
451
+ @extend %form-invalid-feedback-variables;
452
+ color: var(--color-text);
453
+ @include m.make-icon($name: "status-error", $size: "sm", $pseudo: "before") {
454
+ flex-shrink: 0;
455
+ }
456
+ }
457
+
458
+ // .qld-input-success legacy class which is applied to both inputs, and feedback text >:(
459
+ .valid-feedback,
460
+ .qld-input-success:not(select, textarea, input[type="text"], .date-container) {
461
+ @extend %_valid-feedback;
462
+ }
463
+
464
+ .invalid-feedback,
465
+ .qld-input-error:not(select, textarea, input[type="text"], .date-container) {
466
+ @extend %_invalid-feedback;
467
+ }
468
+
469
+ // Bootstrap default styles already support placing feedback after the input element.
470
+ // However for QGDS Feedback is placed before the validated input element, so CSS sibling doesn't work here.
471
+ // We can has() to check for the existence of next siblings instead.
472
+ .valid-feedback:has(~ .is-valid, ~ * .is-valid ),
473
+ .invalid-feedback:has(~ .is-invalid, ~ * .is-invalid),
474
+ .was-validated .valid-feedback:has(~ :where(input, select, textarea):valid, ~ * :where(input, select, textarea):valid), // need to scope to input:valid within has(), :valid seems to match non inputs. the form-check input is wrapped in a div, so * > :input-valid
475
+ .was-validated .invalid-feedback:has(~ :invalid, ~ * :invalid),
476
+ .valid .valid-feedback,
477
+ .invalid .invalid-feedback,
478
+ .qld-input-success:not(select, textarea, input[type="text"]),
479
+ .qld-input-error:not(select, textarea, input[type="text"]) {
480
+ display: flex;
481
+ }