@cfpb/cfpb-design-system 4.2.4 → 4.3.0

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 (124) hide show
  1. package/CHANGELOG.md +166 -1
  2. package/dist/components/cfpb-expandables/index.js +1 -1
  3. package/dist/components/cfpb-expandables/index.js.map +3 -3
  4. package/dist/components/cfpb-forms/index.js +1 -1
  5. package/dist/components/cfpb-forms/index.js.map +2 -2
  6. package/dist/elements/cfpb-button/index.js +4 -4
  7. package/dist/elements/cfpb-button/index.js.map +3 -3
  8. package/dist/elements/cfpb-checkbox-icon/index.js +29 -0
  9. package/dist/elements/{cfpb-checkbox → cfpb-checkbox-icon}/index.js.map +4 -4
  10. package/dist/elements/cfpb-expandable/index.css +2 -0
  11. package/dist/elements/cfpb-expandable/index.css.map +7 -0
  12. package/dist/elements/cfpb-expandable/index.js +33 -0
  13. package/dist/elements/cfpb-expandable/index.js.map +7 -0
  14. package/dist/elements/cfpb-file-upload/index.js +4 -4
  15. package/dist/elements/cfpb-file-upload/index.js.map +3 -3
  16. package/dist/elements/cfpb-form-alert/index.js +32 -0
  17. package/dist/elements/cfpb-form-alert/index.js.map +7 -0
  18. package/dist/elements/cfpb-form-choice/index.js +12 -3
  19. package/dist/elements/cfpb-form-choice/index.js.map +4 -4
  20. package/dist/elements/cfpb-form-search/index.js +41 -0
  21. package/dist/elements/cfpb-form-search/index.js.map +7 -0
  22. package/dist/elements/cfpb-form-search-input/index.js +41 -0
  23. package/dist/elements/cfpb-form-search-input/index.js.map +7 -0
  24. package/dist/elements/cfpb-icon-text/index.js +3 -3
  25. package/dist/elements/cfpb-icon-text/index.js.map +3 -3
  26. package/dist/elements/cfpb-label/index.js +3 -3
  27. package/dist/elements/cfpb-label/index.js.map +2 -2
  28. package/dist/elements/cfpb-list/index.js +39 -0
  29. package/dist/elements/cfpb-list/index.js.map +7 -0
  30. package/dist/elements/cfpb-list-item/index.js +39 -0
  31. package/dist/elements/cfpb-list-item/index.js.map +7 -0
  32. package/dist/elements/cfpb-multiselect/index.js +13 -4
  33. package/dist/elements/cfpb-multiselect/index.js.map +4 -4
  34. package/dist/elements/cfpb-pagination/index.js +3 -3
  35. package/dist/elements/cfpb-pagination/index.js.map +2 -2
  36. package/dist/elements/cfpb-select/index.css +2 -0
  37. package/dist/elements/cfpb-select/index.css.map +7 -0
  38. package/dist/elements/cfpb-select/index.js +42 -0
  39. package/dist/elements/cfpb-select/index.js.map +7 -0
  40. package/dist/elements/cfpb-select-list/index.js +39 -0
  41. package/dist/elements/cfpb-select-list/index.js.map +7 -0
  42. package/dist/elements/cfpb-tag-filter/index.js +3 -3
  43. package/dist/elements/cfpb-tag-filter/index.js.map +3 -3
  44. package/dist/elements/cfpb-tag-group/index.js +3 -3
  45. package/dist/elements/cfpb-tag-group/index.js.map +4 -4
  46. package/dist/elements/cfpb-tag-topic/index.js +4 -4
  47. package/dist/elements/cfpb-tag-topic/index.js.map +1 -1
  48. package/dist/elements/index.css +2 -0
  49. package/dist/elements/index.css.map +7 -0
  50. package/dist/elements/index.js +7 -6
  51. package/dist/elements/index.js.map +4 -4
  52. package/dist/index.js +7 -6
  53. package/dist/index.js.map +4 -4
  54. package/dist/utilities/index.js +1 -1
  55. package/dist/utilities/index.js.map +3 -3
  56. package/package.json +1 -1
  57. package/src/components/cfpb-expandables/expandable.js +3 -0
  58. package/src/components/cfpb-forms/multiselect.js +1 -1
  59. package/src/elements/abstracts/custom-props.css +123 -0
  60. package/src/elements/abstracts/grid-mixins.scss +83 -0
  61. package/src/elements/abstracts/heading-mixins.scss +346 -0
  62. package/src/elements/abstracts/index.scss +7 -0
  63. package/src/elements/abstracts/media-queries.scss +35 -0
  64. package/src/elements/abstracts/sizing-vars.scss +65 -0
  65. package/src/elements/abstracts/vars-breakpoints.scss +16 -0
  66. package/src/elements/abstracts/vars.css +79 -0
  67. package/src/elements/base/base.scss +375 -0
  68. package/src/elements/base/font.scss +27 -0
  69. package/src/elements/base/index.scss +3 -0
  70. package/src/elements/base/normalize.scss +290 -0
  71. package/src/elements/cfpb-button/cfpb-button-group.scss +10 -0
  72. package/src/elements/cfpb-button/cfpb-button-link.scss +96 -0
  73. package/src/elements/cfpb-button/cfpb-button.component.scss +11 -4
  74. package/src/elements/cfpb-button/cfpb-button.scss +222 -0
  75. package/src/elements/cfpb-button/index.js +28 -29
  76. package/src/elements/cfpb-button/vars.css +30 -0
  77. package/src/elements/cfpb-checkbox-icon/cfpb-checkbox-icon.component.scss +88 -0
  78. package/src/elements/cfpb-checkbox-icon/index.js +104 -0
  79. package/src/elements/cfpb-expandable/cfpb-expandable.component.scss +218 -0
  80. package/src/elements/cfpb-expandable/index.js +127 -0
  81. package/src/elements/cfpb-file-upload/cfpb-file-upload.component.scss +2 -2
  82. package/src/elements/cfpb-file-upload/index.js +16 -18
  83. package/src/elements/cfpb-form-alert/cfpb-form-alert.component.scss +36 -0
  84. package/src/elements/cfpb-form-alert/index.js +55 -0
  85. package/src/elements/cfpb-form-choice/cfpb-form-choice.component.scss +42 -81
  86. package/src/elements/cfpb-form-choice/index.js +58 -18
  87. package/src/elements/cfpb-form-search/cfpb-form-search.component.scss +54 -0
  88. package/src/elements/cfpb-form-search/index.js +194 -0
  89. package/src/elements/cfpb-form-search-input/cfpb-form-search-input.component.scss +217 -0
  90. package/src/elements/cfpb-form-search-input/index.js +136 -0
  91. package/src/elements/cfpb-icon-text/cfpb-icon-text.component.scss +32 -39
  92. package/src/elements/cfpb-icon-text/index.js +32 -104
  93. package/src/elements/cfpb-label/cfpb-label.component.scss +2 -2
  94. package/src/elements/cfpb-label/index.js +6 -9
  95. package/src/elements/cfpb-list/cfpb-list.component.scss +23 -0
  96. package/src/elements/cfpb-list/index.js +357 -0
  97. package/src/elements/cfpb-list/index.spec.js +169 -0
  98. package/src/elements/cfpb-list-item/cfpb-list-item.component.scss +69 -0
  99. package/src/elements/cfpb-list-item/index.js +215 -0
  100. package/src/elements/cfpb-pagination/cfpb-pagination.component.scss +2 -7
  101. package/src/elements/cfpb-pagination/index.js +6 -8
  102. package/src/elements/cfpb-select/cfpb-select.component.scss +241 -0
  103. package/src/elements/cfpb-select/index.js +381 -0
  104. package/src/elements/cfpb-tag-filter/cfpb-tag-filter.component.scss +6 -3
  105. package/src/elements/cfpb-tag-filter/index.js +15 -7
  106. package/src/elements/cfpb-tag-group/cfpb-tag-group.component.scss +2 -2
  107. package/src/elements/cfpb-tag-group/index.js +53 -6
  108. package/src/elements/cfpb-tag-topic/index.js +5 -7
  109. package/src/elements/cfpb-utilities/parse-child-data.js +50 -0
  110. package/src/elements/cfpb-utilities/parse-child-data.spec.js +56 -0
  111. package/src/elements/cfpb-utilities/search-service.js +46 -0
  112. package/src/elements/cfpb-utilities/search-service.spec.js +138 -0
  113. package/src/elements/cfpb-utilities/transition/transition.scss +98 -0
  114. package/src/elements/index.js +7 -1
  115. package/src/index.scss +11 -0
  116. package/src/tokens/abstracts/custom-props.json +1642 -0
  117. package/src/tokens/abstracts/vars.json +1319 -0
  118. package/src/tokens/cfpb-button/vars.json +436 -0
  119. package/src/utilities/transition/max-height-transition.js +74 -0
  120. package/dist/elements/cfpb-checkbox/index.js +0 -29
  121. package/src/elements/cfpb-multiselect/cfpb-multiselect.component.scss +0 -225
  122. package/src/elements/cfpb-multiselect/index.js +0 -444
  123. package/src/elements/cfpb-multiselect/multiselect-model.js +0 -288
  124. package/src/elements/cfpb-multiselect/multiselect-model.spec.js +0 -236
@@ -0,0 +1,96 @@
1
+ @use 'sass:math';
2
+ @use './vars' as *;
3
+ @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
4
+
5
+ //
6
+ // Button link
7
+ //
8
+
9
+ /*
10
+ Link text and underline.
11
+ $v: Link link and visited color.
12
+ $h: Link hover color.
13
+ $f: Link focus color.
14
+ $a: Link active color.
15
+ */
16
+ @mixin u-btn-link-states($selector, $v, $h, $f, $a) {
17
+ #{$selector} {
18
+ &,
19
+ &:link,
20
+ &:visited {
21
+ text-decoration-color: $v;
22
+ background-color: transparent;
23
+ color: $v;
24
+ }
25
+
26
+ &:hover,
27
+ &.hover {
28
+ text-decoration-color: $h;
29
+ text-decoration-style: solid;
30
+ background-color: transparent;
31
+ color: $h;
32
+ }
33
+
34
+ &:focus,
35
+ &.focus {
36
+ background-color: transparent;
37
+ outline: 1px dotted $f;
38
+ color: $f;
39
+ }
40
+
41
+ &:active,
42
+ &.active {
43
+ text-decoration-color: $a;
44
+ text-decoration-style: solid;
45
+ background-color: transparent;
46
+ color: $a;
47
+ }
48
+ }
49
+ }
50
+
51
+ .a-btn--link {
52
+ // Padding added so the focus rectangle falls below the underline.
53
+ padding: 1.5px 0;
54
+ border-radius: 0;
55
+ text-decoration-line: underline;
56
+ text-decoration-thickness: 1px;
57
+ text-decoration-style: dotted;
58
+ text-underline-offset: 4.5px;
59
+
60
+ &:has(svg) {
61
+ // Button links should be closer to their icon.
62
+ gap: math.div(5px, $base-font-size-px) + rem;
63
+
64
+ // Button links shouldn't have a divider.
65
+ &::before {
66
+ display: none;
67
+ }
68
+ }
69
+ }
70
+
71
+ @include u-btn-link-states(
72
+ '.a-btn--link',
73
+ var(--link-text),
74
+ var(--link-text-hover),
75
+ var(--link-text),
76
+ var(--link-text-active)
77
+ );
78
+
79
+ //
80
+ // Secondary button link
81
+ //
82
+
83
+ // The .a-btn--link.a-btn--secondary combo shouldn't be used,
84
+ // so we provide no styles.
85
+
86
+ //
87
+ // Destructive action button link
88
+ //
89
+
90
+ @include u-btn-link-states(
91
+ '.a-btn--link.a-btn--warning',
92
+ var(--btn-warning-bg),
93
+ var(--btn-warning-bg-hover),
94
+ var(--btn-warning-bg),
95
+ var(--btn-warning-bg-active)
96
+ );
@@ -1,7 +1,7 @@
1
- @use '@cfpb/cfpb-design-system/src/base' as *;
2
- @use '@cfpb/cfpb-design-system/src/abstracts' as *;
3
- @use '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button' as *;
4
- @use '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button-link' as *;
1
+ @use '@cfpb/cfpb-design-system/src/elements/base' as *;
2
+ @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
3
+ @use '@cfpb/cfpb-design-system/src/elements/cfpb-button/cfpb-button' as *;
4
+ @use '@cfpb/cfpb-design-system/src/elements/cfpb-button/cfpb-button-link' as *;
5
5
 
6
6
  :host {
7
7
  // This prevents the child button from having an empty gap after the button.
@@ -13,10 +13,16 @@
13
13
  // Mobile only.
14
14
  @include respond-to-max($bp-xs-max) {
15
15
  width: 100%;
16
+
17
+ button,
18
+ [role='button'] {
19
+ width: 100%;
20
+ }
16
21
  }
17
22
  }
18
23
 
19
24
  :host([flush-left]) {
25
+ button,
20
26
  [role='button'] {
21
27
  border-top-left-radius: 0;
22
28
  border-bottom-left-radius: 0;
@@ -24,6 +30,7 @@
24
30
  }
25
31
 
26
32
  :host([flush-right]) {
33
+ button,
27
34
  [role='button'] {
28
35
  border-top-right-radius: 0;
29
36
  border-bottom-right-radius: 0;
@@ -0,0 +1,222 @@
1
+ @use 'sass:math';
2
+ @use './vars' as *;
3
+ @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
4
+
5
+ //
6
+ // Default button
7
+ //
8
+
9
+ button.a-btn::-moz-focus-inner,
10
+ input.a-btn::-moz-focus-inner {
11
+ // Fixes inconsistent button.btn height in Firefox.
12
+ // Helps with inconsistent input.btn height in Firefox but not completely.
13
+ border: 0;
14
+ }
15
+
16
+ @mixin u-btn-divider() {
17
+ content: '';
18
+ border-left: 1px solid var(--btn-divider);
19
+ order: 2;
20
+ place-self: normal;
21
+ }
22
+
23
+ .a-btn {
24
+ line-height: math.div(19px, $base-font-size-px);
25
+ appearance: none;
26
+ display: flex;
27
+ gap: math.div(10px, $base-font-size-px) + rem;
28
+
29
+ box-sizing: border-box;
30
+ padding: math.div($btn-v-padding, $btn-font-size) + em
31
+ math.div($btn-h-padding, $btn-font-size) + em;
32
+ border: 0;
33
+ margin: 0;
34
+ border-radius: math.div($btn-border-radius-size, $btn-font-size) + em;
35
+ cursor: pointer;
36
+ font-size: math.div($btn-font-size, $base-font-size-px) + em;
37
+ font-weight: 500;
38
+ text-align: center;
39
+ text-decoration: none;
40
+ transition: background-color 0.1s;
41
+ width: fit-content;
42
+ height: fit-content;
43
+ justify-content: center;
44
+ align-items: center;
45
+
46
+ &,
47
+ &:link,
48
+ &:visited {
49
+ background-color: var(--btn-bg);
50
+ color: var(--btn-text);
51
+ }
52
+
53
+ &:hover,
54
+ &.hover,
55
+ &:focus,
56
+ &.focus {
57
+ background-color: var(--btn-bg-hover);
58
+ color: var(--btn-text);
59
+ }
60
+
61
+ &:focus,
62
+ &.focus {
63
+ outline: 1px dotted var(--btn-bg);
64
+
65
+ // The outline-offset property is not supported everywhere (e.g. IE)
66
+ // but it adds a nice touch in browsers where it is.
67
+ outline-offset: 1px;
68
+ }
69
+
70
+ &:active,
71
+ &.active {
72
+ background-color: var(--btn-bg-active);
73
+ }
74
+
75
+ //
76
+ // Secondary button
77
+ //
78
+
79
+ &--secondary {
80
+ &,
81
+ &:link,
82
+ &:visited {
83
+ background-color: var(--btn-secondary-bg);
84
+ color: var(--btn-secondary-text);
85
+ box-shadow: 0 0 0 1px var(--btn-secondary-border) inset;
86
+ }
87
+
88
+ &:hover,
89
+ &.hover,
90
+ &:focus,
91
+ &.focus {
92
+ background-color: var(--btn-secondary-bg-hover);
93
+ color: var(--btn-secondary-text-hover);
94
+ box-shadow: 0 0 0 1px var(--btn-secondary-border-hover) inset;
95
+ }
96
+
97
+ &:focus,
98
+ &.focus {
99
+ outline-color: var(--btn-secondary-border);
100
+ }
101
+
102
+ &:active,
103
+ &.active {
104
+ background-color: var(--btn-secondary-bg-active);
105
+ color: var(--btn-secondary-text-active);
106
+ box-shadow: 0 0 0 1px var(--btn-secondary-border-active) inset;
107
+ }
108
+ }
109
+
110
+ //
111
+ // Destructive action button
112
+ //
113
+
114
+ &--warning {
115
+ &,
116
+ &:link,
117
+ &:visited {
118
+ background-color: var(--btn-warning-bg);
119
+ color: var(--btn-warning-text);
120
+ }
121
+
122
+ &:hover,
123
+ &.hover,
124
+ &:focus,
125
+ &.focus {
126
+ background-color: var(--btn-warning-bg-hover);
127
+ }
128
+
129
+ &:focus,
130
+ &.focus {
131
+ outline-color: var(--btn-warning-bg);
132
+ }
133
+
134
+ &:active,
135
+ &.active {
136
+ background-color: var(--btn-warning-bg-active);
137
+ }
138
+ }
139
+
140
+ //
141
+ // Disabled button
142
+ //
143
+
144
+ &--disabled,
145
+ &[disabled],
146
+ &[aria-disabled='true'] {
147
+ &,
148
+ &:link,
149
+ &:visited,
150
+ &:hover,
151
+ &.hover,
152
+ &:focus,
153
+ &.focus,
154
+ &:active,
155
+ &.active {
156
+ background-color: var(--btn-disabled-bg);
157
+ color: var(--btn-disabled-text);
158
+ cursor: default; // Fallback for IE/Opera
159
+ cursor: not-allowed;
160
+ }
161
+
162
+ &:focus,
163
+ &.focus {
164
+ outline-color: var(--btn-disabled-outline);
165
+ }
166
+ }
167
+
168
+ //
169
+ // Full width button on x-small screens
170
+ //
171
+ &--full-on-xs {
172
+ // Mobile only.
173
+ @include respond-to-max($bp-xs-max) {
174
+ width: 100%;
175
+ }
176
+ }
177
+
178
+ // Set either the text or icon as the last item in the button.
179
+ &:has(svg + span) {
180
+ span {
181
+ order: 3;
182
+ }
183
+ }
184
+
185
+ &:has(span + svg) {
186
+ svg {
187
+ order: 3;
188
+
189
+ // Prevent icon from shrinking when button wraps.
190
+ flex: none;
191
+ }
192
+ }
193
+
194
+ // Handle button with icon divider logic.
195
+ &:not(.a-btn--hide-icon):has(svg + span)::before,
196
+ &:not(.a-btn--hide-icon):has(span + svg)::before {
197
+ @include u-btn-divider;
198
+ }
199
+
200
+ // Handle different coloring in divider.
201
+ &--secondary:has(svg)::before {
202
+ border-color: var(--btn-secondary-divider) !important;
203
+ }
204
+
205
+ &--warning:has(svg)::before {
206
+ border-color: var(--btn-warning-divider) !important;
207
+ }
208
+
209
+ &--disabled:has(svg)::before,
210
+ &[disabled]:has(svg)::before,
211
+ &[aria-disabled='true']:has(svg)::before {
212
+ border-color: var(--btn-disabled-divider) !important;
213
+ }
214
+
215
+ // Hide the icon if the a-btn--hide-icon modifier is set.
216
+ // Useful for showing and hiding a loading icon, for example.
217
+ &--hide-icon {
218
+ svg {
219
+ display: none;
220
+ }
221
+ }
222
+ }
@@ -24,41 +24,40 @@ export class CfpbButton extends LitElement {
24
24
  * @property {string} type - The button type: button, submit, or reset.
25
25
  * @property {string} href - The URL to link to (makes the button a link).
26
26
  * @property {boolean} disabled - Whether the button is disabled or not.
27
- * @property {string} variant - The button variant: secondary and warning.
27
+ * @property {string} variant
28
+ * The button variant: primary, secondary, or warning.
28
29
  * @property {boolean} fullOnMobile - Whether to be width 100% on mobile.
29
30
  * @property {boolean} flushLeft - Whether button is not rounded on left.
30
31
  * @property {boolean} flushRight - Whether button is not rounded on right.
31
32
  * @property {boolean} styleAsLink - Style the button as a link.
32
33
  * @returns {object} The map of properties.
33
34
  */
34
- static get properties() {
35
- return {
36
- type: { type: String },
37
- href: { type: String },
38
- disabled: { type: Boolean, reflect: true },
39
- variant: { type: String },
40
- fullOnMobile: {
41
- type: Boolean,
42
- attribute: 'full-on-mobile',
43
- reflect: true,
44
- },
45
- flushLeft: {
46
- type: Boolean,
47
- attribute: 'flush-left',
48
- reflect: true,
49
- },
50
- flushRight: {
51
- type: Boolean,
52
- attribute: 'flush-right',
53
- reflect: true,
54
- },
55
- styleAsLink: {
56
- type: Boolean,
57
- attribute: 'style-as-link',
58
- reflect: true,
59
- },
60
- };
61
- }
35
+ static properties = {
36
+ type: { type: String },
37
+ href: { type: String },
38
+ disabled: { type: Boolean, reflect: true },
39
+ variant: { type: String },
40
+ fullOnMobile: {
41
+ type: Boolean,
42
+ attribute: 'full-on-mobile',
43
+ reflect: true,
44
+ },
45
+ flushLeft: {
46
+ type: Boolean,
47
+ attribute: 'flush-left',
48
+ reflect: true,
49
+ },
50
+ flushRight: {
51
+ type: Boolean,
52
+ attribute: 'flush-right',
53
+ reflect: true,
54
+ },
55
+ styleAsLink: {
56
+ type: Boolean,
57
+ attribute: 'style-as-link',
58
+ reflect: true,
59
+ },
60
+ };
62
61
 
63
62
  // DOM references.
64
63
  #iconTextDom = createRef();
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Do not edit directly, this file was auto-generated.
3
+ */
4
+
5
+ :host {
6
+ --btn-bg: var(--pacific);
7
+ --btn-bg-active: var(--navy);
8
+ --btn-bg-hover: var(--pacific-dark);
9
+ --btn-disabled-bg: var(--gray-20);
10
+ --btn-disabled-divider: var(--gray-60);
11
+ --btn-disabled-outline: var(--gray-20);
12
+ --btn-disabled-text: var(--gray-dark);
13
+ --btn-divider: var(--pacific-60);
14
+ --btn-secondary-bg: var(--white);
15
+ --btn-secondary-bg-active: var(--pacific-20);
16
+ --btn-secondary-bg-hover: var(--pacific-10);
17
+ --btn-secondary-border: var(--pacific);
18
+ --btn-secondary-border-active: var(--navy);
19
+ --btn-secondary-border-hover: var(--pacific-dark);
20
+ --btn-secondary-divider: var(--pacific-60);
21
+ --btn-secondary-text: var(--pacific);
22
+ --btn-secondary-text-active: var(--navy);
23
+ --btn-secondary-text-hover: var(--pacific-dark);
24
+ --btn-text: var(--white);
25
+ --btn-warning-bg: var(--red-mid-dark);
26
+ --btn-warning-bg-active: var(--gray-dark);
27
+ --btn-warning-bg-hover: var(--red-dark);
28
+ --btn-warning-divider: var(--red-60);
29
+ --btn-warning-text: var(--white);
30
+ }
@@ -0,0 +1,88 @@
1
+ @use 'sass:math';
2
+ @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
3
+ @use '@cfpb/cfpb-design-system/src/utilities' as *;
4
+
5
+ :host {
6
+ // Theme variables.
7
+ --choice-border: var(--choice-border-default);
8
+ --choice-border-hover: var(--choice-border-hover-default);
9
+ --choice-bg: var(--choice-bg-default);
10
+ --choice-bg-selected: var(--choice-bg-selected-default);
11
+
12
+ // Private variables.
13
+ --choice-border-width-addendum: 0;
14
+
15
+ .cfpb-checkbox-icon::before {
16
+ display: inline-block;
17
+ grid-row-start: 1;
18
+ grid-row-end: 3;
19
+ border: 1px solid var(--choice-border);
20
+ outline: var(--choice-border-width-addendum) solid var(--choice-border);
21
+ height: math.div(18px, $base-font-size-px) + em;
22
+ width: math.div(18px, $base-font-size-px) + em;
23
+ margin-right: 10px;
24
+ background-color: var(--choice-bg);
25
+ content: '';
26
+ vertical-align: top;
27
+
28
+ // Offset so that the checkbox/radio fits within focused area.
29
+ position: relative;
30
+ top: 1px;
31
+ left: 1px;
32
+ }
33
+
34
+ .checked::before {
35
+ --cfpb-background-icon-svg: 'approved';
36
+ background-size: auto $cf-icon-height;
37
+ background-repeat: no-repeat;
38
+ background-position: center 0;
39
+ }
40
+
41
+ .disabled::before {
42
+ cursor: not-allowed;
43
+
44
+ --choice-border: var(--choice-border-disabled);
45
+ --choice-bg: var(--choice-bg-disabled);
46
+ --choice-bg-selected: var(--choice-bg-selected-disabled);
47
+ }
48
+
49
+ .checked.disabled::before {
50
+ // RGB values are CFPB gray (#5a5d61).
51
+ // For some reason SVG isn't accepting hex values for the fill.
52
+ --cfpb-background-icon-svg: 'approved rgb(90,93,97)';
53
+ }
54
+
55
+ .cfpb-checkbox-icon:not(.disabled, .borderless).focus::before,
56
+ .cfpb-checkbox-icon:not(.disabled, .borderless):focus::before,
57
+ .cfpb-checkbox-icon:not(.disabled, .borderless).hover::before,
58
+ .cfpb-checkbox-icon:not(.disabled, .borderless):hover::before {
59
+ cursor: pointer;
60
+ border-color: var(--choice-border-hover);
61
+ box-shadow: 0 0 0 1px var(--choice-border-hover);
62
+ outline-color: var(--choice-border-hover);
63
+ }
64
+
65
+ .validation-error,
66
+ .validation-warning,
67
+ .validation-success {
68
+ --choice-border-width-addendum: 1px;
69
+ }
70
+
71
+ .validation-error {
72
+ --choice-border: var(--choice-border-error);
73
+ }
74
+
75
+ .validation-warning {
76
+ --choice-border: var(--choice-border-warning);
77
+ }
78
+
79
+ .validation-success {
80
+ --choice-border: var(--choice-border-success);
81
+ }
82
+
83
+ .borderless::before {
84
+ border-color: transparent;
85
+ outline-color: transparent;
86
+ background-color: transparent;
87
+ }
88
+ }
@@ -0,0 +1,104 @@
1
+ import { html, LitElement, css, unsafeCSS } from 'lit';
2
+ import styles from './cfpb-checkbox-icon.component.scss';
3
+
4
+ // The validation states are error, warning, or success.
5
+ const VALID_VALIDATION = ['error', 'warning', 'success'];
6
+
7
+ /**
8
+ * @element cfpb-checkbox-icon
9
+ */
10
+ export class CfpbCheckboxIcon extends LitElement {
11
+ static styles = css`
12
+ ${unsafeCSS(styles)}
13
+ `;
14
+
15
+ #hover;
16
+ #focus;
17
+
18
+ /**
19
+ * @property {boolean} borderless - Whether the checkbox has a border or not.
20
+ * @property {boolean} checked - Whether the checkbox is checked or not.
21
+ * @property {boolean} disabled - Whether the checkbox is disabled or not.
22
+ * @property {string} validation - Validation style: error, warning, success.
23
+ * @returns {object} The map of properties.
24
+ */
25
+ static properties = {
26
+ borderless: { type: Boolean, reflect: true },
27
+ checked: { type: Boolean, reflect: true },
28
+ disabled: { type: Boolean, reflect: true },
29
+ validation: { type: String, reflect: true },
30
+ };
31
+
32
+ constructor() {
33
+ super();
34
+ this.borderless = false;
35
+ this.checked = false;
36
+ this.disabled = false;
37
+ this.validation = '';
38
+ this.#hover = false;
39
+ this.#focus = false;
40
+ }
41
+
42
+ /**
43
+ * Ensure the validation value is valid, and fall back to a default if not.
44
+ * @returns {string|undefined} A valid validation value string, or undefined.
45
+ */
46
+ get #validValidation() {
47
+ return VALID_VALIDATION.includes(this.validation)
48
+ ? this.validation
49
+ : undefined;
50
+ }
51
+
52
+ mouseover() {
53
+ if (!this.disabled) {
54
+ this.#hover = true;
55
+ this.requestUpdate();
56
+ }
57
+ }
58
+
59
+ mouseleave() {
60
+ this.#hover = false;
61
+ this.requestUpdate();
62
+ }
63
+
64
+ focus() {
65
+ if (!this.disabled) {
66
+ this.#focus = true;
67
+ this.requestUpdate();
68
+ }
69
+ }
70
+
71
+ blur() {
72
+ this.#focus = false;
73
+ this.requestUpdate();
74
+ }
75
+
76
+ #computeClassString() {
77
+ return [
78
+ 'cfpb-checkbox-icon',
79
+ this.checked && 'checked',
80
+ this.disabled && 'disabled',
81
+ this.borderless && 'borderless',
82
+ this.#validValidation && `validation-${this.#validValidation}`,
83
+ this.#hover && 'hover',
84
+ this.#focus && 'focus',
85
+ ]
86
+ .filter(Boolean)
87
+ .join(' ');
88
+ }
89
+
90
+ render() {
91
+ return html`
92
+ <div
93
+ class=${this.#computeClassString()}
94
+ ?disabled=${this.disabled}
95
+ aria-hidden="true"
96
+ ></div>
97
+ `;
98
+ }
99
+
100
+ static init() {
101
+ window.customElements.get('cfpb-checkbox-icon') ||
102
+ window.customElements.define('cfpb-checkbox-icon', CfpbCheckboxIcon);
103
+ }
104
+ }