@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,218 @@
1
+ @use 'sass:math';
2
+ @use '@cfpb/cfpb-design-system/src/abstracts' as *;
3
+ @use '@cfpb/cfpb-design-system/src/base' as *;
4
+ @use '@cfpb/cfpb-design-system/src/utilities' as *;
5
+ @use '../cfpb-utilities/transition/transition.scss' as *;
6
+
7
+ :host {
8
+ // Theme
9
+
10
+ --expandable-border: var(--gray-40);
11
+
12
+ .cf-icon-svg {
13
+ height: 1.1875em;
14
+ vertical-align: middle;
15
+ fill: currentcolor;
16
+ }
17
+
18
+ // Overide heading defaults.
19
+ ::slotted([slot='header']) {
20
+ margin-bottom: 0 !important;
21
+ color: var(--black) !important;
22
+ font-weight: 500 !important;
23
+
24
+ // h4 size.
25
+ font-size: math.div(18px, $base-font-size-px) + em !important;
26
+
27
+ // Mobile only.
28
+ @include respond-to-max($bp-xs-max) {
29
+ font-size: math.div(16px, $base-font-size-px) + em !important;
30
+ }
31
+
32
+ .o-expandable--padded {
33
+ // h2 size.
34
+ font-size: math.div(26px, $base-font-size-px) + em !important;
35
+
36
+ // Mobile only.
37
+ @include respond-to-max($bp-xs-max) {
38
+ font-size: math.div(22px, $base-font-size-px) + em !important;
39
+ }
40
+ }
41
+ }
42
+
43
+ //
44
+ // Recommended expandable pattern
45
+ //
46
+
47
+ .o-expandable {
48
+ position: relative;
49
+
50
+ //
51
+ // Header
52
+ //
53
+
54
+ &__header {
55
+ display: flex;
56
+ justify-content: space-between;
57
+ gap: 10px;
58
+ padding: math.div(10px, $base-font-size-px) + em
59
+ math.div(15px, $base-font-size-px) + em;
60
+ border: 0;
61
+ background-color: transparent;
62
+ cursor: pointer;
63
+
64
+ &:focus {
65
+ outline: 1px dotted var(--black);
66
+ outline-offset: 2px;
67
+ }
68
+
69
+ .o-expandable__cue-close,
70
+ .o-expandable__cue-open {
71
+ display: none;
72
+ }
73
+
74
+ &[aria-expanded='false'] .o-expandable__cue-open {
75
+ display: block;
76
+ }
77
+
78
+ &[aria-expanded='true'] .o-expandable__cue-close {
79
+ display: block;
80
+ }
81
+ }
82
+
83
+ // Using the button element with .o-expandable__header requires setting
84
+ // an explicit width.
85
+ button.o-expandable__header {
86
+ width: 100%;
87
+ text-align: left;
88
+ }
89
+
90
+ //
91
+ // Expandable text elements
92
+ //
93
+
94
+ &__label {
95
+ // Grow to available width.
96
+ flex-grow: 1;
97
+ }
98
+
99
+ &__icon,
100
+ &__label {
101
+ // h4 size.
102
+ font-size: math.div(18px, $base-font-size-px) + em !important;
103
+
104
+ // Mobile only.
105
+ @include respond-to-max($bp-xs-max) {
106
+ font-size: math.div(16px, $base-font-size-px) + em !important;
107
+ }
108
+ }
109
+
110
+ &__cues {
111
+ align-self: center;
112
+ color: var(--pacific);
113
+ font-size: math.div(16px, $base-font-size-px) + em;
114
+ line-height: math.div($base-line-height-px, $base-font-size-px);
115
+ }
116
+
117
+ &__content {
118
+ padding: math.div(15px, $base-font-size-px) + em;
119
+ padding-top: 0;
120
+
121
+ // The divider between __header and __content.
122
+ &::before {
123
+ content: '';
124
+ display: block;
125
+ border-top: 1px solid var(--expandable-border);
126
+ padding-top: math.div(15px, $base-font-size-px) + em;
127
+ }
128
+
129
+ &::after {
130
+ padding-bottom: math.div(15px, $base-font-size-px) + em;
131
+ width: 100%;
132
+ }
133
+ }
134
+
135
+ //
136
+ // Padded expandable modifier
137
+ //
138
+
139
+ &--padded {
140
+ .o-expandable {
141
+ &__header {
142
+ padding: math.div(25px, $base-font-size-px) + em
143
+ math.div(15px, $base-font-size-px) + em;
144
+ }
145
+
146
+ &__icon,
147
+ &__label {
148
+ // h2 size.
149
+ font-size: math.div(26px, $base-font-size-px) + em !important;
150
+
151
+ // Mobile only.
152
+ @include respond-to-max($bp-xs-max) {
153
+ font-size: math.div(22px, $base-font-size-px) + em !important;
154
+ }
155
+ }
156
+ }
157
+ }
158
+
159
+ //
160
+ // Expandable with a background color modifier
161
+ //
162
+
163
+ &--background {
164
+ background: var(--gray-5);
165
+ }
166
+
167
+ //
168
+ // Expandable with a border modifier
169
+ //
170
+
171
+ &--border {
172
+ border: 1px solid var(--expandable-border);
173
+ }
174
+
175
+ //
176
+ // Expandable groups
177
+ //
178
+
179
+ &-group {
180
+ .o-expandable {
181
+ border-bottom: 1px solid var(--expandable-border);
182
+
183
+ &:first-child {
184
+ border-top: 1px solid var(--expandable-border);
185
+ }
186
+ }
187
+ }
188
+
189
+ @media print {
190
+ // Hide the interactive expandable cues when printing
191
+ &__header[aria-expanded='true'] &__cue-close,
192
+ &__header[aria-expanded='false'] &__cue-open {
193
+ display: none;
194
+ } // Ensure all expandables are expanded when printing.
195
+ // To accommodate print stylesheets that display the raw URL after links,
196
+ // set an enormous max height to accommodate expandables that have a lot of links.
197
+ &__content[aria-expanded='false'] {
198
+ display: block;
199
+ max-height: 99999px !important;
200
+ }
201
+ }
202
+ }
203
+ }
204
+
205
+ // Used when the set language reads right-to-left
206
+ html[lang='ar'] {
207
+ :host {
208
+ .o-expandable {
209
+ &__header {
210
+ text-align: right;
211
+ }
212
+
213
+ &__cues {
214
+ text-align: left;
215
+ }
216
+ }
217
+ }
218
+ }
@@ -0,0 +1,127 @@
1
+ import { html, LitElement, css, unsafeCSS } from 'lit';
2
+ import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
3
+ import styles from './cfpb-expandable.component.scss';
4
+ import expandIcon from '../../components/cfpb-icons/icons/plus-round.svg';
5
+ import collapseIcon from '../../components/cfpb-icons/icons/minus-round.svg';
6
+ import { MaxHeightTransition } from '../../utilities/transition/max-height-transition';
7
+ import { FlyoutMenu } from '../../utilities/behavior/flyout-menu';
8
+
9
+ /**
10
+ *
11
+ * @element cfpb-button
12
+ * @slot - The main content for the button.
13
+ */
14
+ export class CfpbExpandable extends LitElement {
15
+ static styles = css`
16
+ ${unsafeCSS(styles)}
17
+ `;
18
+
19
+ #flyoutMenu;
20
+ #transition;
21
+
22
+ /**
23
+ * @property {boolean} isExpanded - Whether the expandable is expanded or not.
24
+ * @returns {object} The map of properties.
25
+ */
26
+ static get properties() {
27
+ return {
28
+ isExpanded: { type: Boolean, attribute: 'open', reflect: true },
29
+ };
30
+ }
31
+
32
+ constructor() {
33
+ super();
34
+ }
35
+
36
+ firstUpdated() {
37
+ const root = this.shadowRoot.querySelector('div');
38
+ const contentDom = root.querySelector('.o-expandable__content');
39
+
40
+ // If it's expanded we don't set an initial height,
41
+ // as it will be calculated internally.
42
+ const initialClass = this.isExpanded
43
+ ? MaxHeightTransition.CLASSES.MH_DEFAULT
44
+ : MaxHeightTransition.CLASSES.MH_ZERO;
45
+ this.#transition = new MaxHeightTransition(contentDom).init(initialClass);
46
+
47
+ this.#flyoutMenu = new FlyoutMenu(root);
48
+
49
+ this.#flyoutMenu.setTransition(
50
+ this.#transition,
51
+ this.#transition.maxHeightZero,
52
+ this.#transition.maxHeightDefault,
53
+ );
54
+
55
+ this.#flyoutMenu.init(this.isExpanded);
56
+
57
+ // Add events.
58
+ this.#flyoutMenu.addEventListener('expandbegin', () => {
59
+ this.isExpanded = true;
60
+ contentDom.classList.remove('u-hidden');
61
+ this.dispatchEvent(
62
+ new CustomEvent('expandbegin', {
63
+ detail: { target: this },
64
+ bubbles: true,
65
+ composed: true,
66
+ }),
67
+ );
68
+ });
69
+ this.#flyoutMenu.addEventListener('collapseend', () => {
70
+ this.isExpanded = false;
71
+ contentDom.classList.add('u-hidden');
72
+ });
73
+ }
74
+
75
+ updated(changedProps) {
76
+ if (changedProps.has('isExpanded')) {
77
+ const oldVal = changedProps.get('isExpanded');
78
+ const newVal = this.isExpanded;
79
+
80
+ if (newVal !== oldVal) {
81
+ if (newVal) {
82
+ this.#flyoutMenu.expand();
83
+ } else {
84
+ this.#flyoutMenu.collapse();
85
+ }
86
+ }
87
+ }
88
+ }
89
+
90
+ render() {
91
+ return html`
92
+ <div
93
+ class="o-expandable o-expandable--background o-expandable--border"
94
+ data-js-hook="behavior_flyout-menu"
95
+ >
96
+ <button
97
+ class="o-expandable__header"
98
+ title="Expand content"
99
+ data-js-hook="behavior_flyout-menu_trigger"
100
+ >
101
+ <slot name="header" class="o-expandable__label"></slot>
102
+ <span class="o-expandable__cues">
103
+ <span class="o-expandable__cue-open" role="img" aria-label="Show">
104
+ ${unsafeSVG(expandIcon)}
105
+ <span class="u-visually-hidden">Show</span>
106
+ </span>
107
+ <span class="o-expandable__cue-close" role="img" aria-label="Hide">
108
+ ${unsafeSVG(collapseIcon)}
109
+ <span class="u-visually-hidden">Hide</span>
110
+ </span>
111
+ </span>
112
+ </button>
113
+ <div
114
+ class="o-expandable__content"
115
+ data-js-hook="behavior_flyout-menu_content"
116
+ >
117
+ <slot name="content"></slot>
118
+ </div>
119
+ </div>
120
+ `;
121
+ }
122
+
123
+ static init() {
124
+ window.customElements.get('cfpb-expandable') ||
125
+ window.customElements.define('cfpb-expandable', CfpbExpandable);
126
+ }
127
+ }
@@ -1,5 +1,5 @@
1
- @use '@cfpb/cfpb-design-system/src/abstracts' as *;
2
- @use '@cfpb/cfpb-design-system/src/components/cfpb-buttons/vars' as *;
1
+ @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
2
+ @use '@cfpb/cfpb-design-system/src/elements/cfpb-button/vars' as *;
3
3
 
4
4
  :host {
5
5
  // This prevents the child button from having an empty gap after the button.
@@ -13,19 +13,17 @@ export class CfpbFileUpload extends LitElement {
13
13
  ${unsafeCSS(styles)}
14
14
  `;
15
15
 
16
- static get properties() {
17
- return {
18
- isDetailHidden: {
19
- type: Boolean,
20
- attribute: 'hidden', // Maps 'hidden' to 'isDetailHidden' property.
21
- reflect: true, // Reflects the property change back to the attribute.
22
- },
23
- fileName: { type: String }, // The file name.
24
- accept: { type: String }, // The accepted file types.
25
- value: { type: String }, // The raw file name.
26
- files: { type: FileList }, // A FileList object.
27
- };
28
- }
16
+ static properties = {
17
+ isDetailHidden: {
18
+ type: Boolean,
19
+ attribute: 'hidden', // Maps 'hidden' to 'isDetailHidden' property.
20
+ reflect: true, // Reflects the property change back to the attribute.
21
+ },
22
+ fileName: { type: String }, // The file name.
23
+ accept: { type: String }, // The accepted file types.
24
+ value: { type: String }, // The raw file name.
25
+ files: { type: FileList }, // A FileList object.
26
+ };
29
27
 
30
28
  constructor() {
31
29
  super();
@@ -71,9 +69,9 @@ export class CfpbFileUpload extends LitElement {
71
69
  return html`
72
70
  <cfpb-button
73
71
  variant="secondary"
74
- @click="${() => {
72
+ @click=${() => {
75
73
  this.fileInput.value.click();
76
- }}"
74
+ }}
77
75
  >
78
76
  <slot></slot>
79
77
  </cfpb-button>
@@ -81,9 +79,9 @@ export class CfpbFileUpload extends LitElement {
81
79
  class="a-btn a-btn--secondary"
82
80
  type="file"
83
81
  hidden
84
- accept="${this.accept}"
85
- @input="${() => this.#checkStatus()}"
86
- @cancel="${() => this.#checkStatus()}"
82
+ accept=${this.accept}
83
+ @input=${() => this.#checkStatus()}
84
+ @cancel=${() => this.#checkStatus()}
87
85
  ${ref(this.fileInput)}
88
86
  />
89
87
  <div
@@ -0,0 +1,36 @@
1
+ @use 'sass:math';
2
+ @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
3
+ @use '@cfpb/cfpb-design-system/src/components/cfpb-icons/icon' as *;
4
+
5
+ :host {
6
+ .a-form-alert {
7
+ // Theme
8
+ --form-alert-icon-color: var(--form-alert-icon-color-default);
9
+
10
+ margin-top: math.div(15px, $base-font-size-px) + rem;
11
+ display: flex;
12
+ gap: math.div(5px, $base-font-size-px) + rem;
13
+
14
+ .cf-icon-svg {
15
+ color: var(--form-alert-icon-color);
16
+ flex: none;
17
+ margin-top: math.div(1px, $base-font-size-px) + rem;
18
+ }
19
+
20
+ &__text {
21
+ display: block;
22
+ }
23
+
24
+ &--success .cf-icon-svg {
25
+ --form-alert-icon-color: var(--form-alert-icon-color-success);
26
+ }
27
+
28
+ &--warning .cf-icon-svg {
29
+ --form-alert-icon-color: var(--form-alert-icon-color-warning);
30
+ }
31
+
32
+ &--error .cf-icon-svg {
33
+ --form-alert-icon-color: var(--form-alert-icon-color-error);
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,55 @@
1
+ import { html, LitElement, css, unsafeCSS } from 'lit';
2
+ import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
3
+ import styles from './cfpb-form-alert.component.scss';
4
+ import errorIcon from '../../components/cfpb-icons/icons/error-round.svg';
5
+ import warningIcon from '../../components/cfpb-icons/icons/warning-round.svg';
6
+ import successIcon from '../../components/cfpb-icons/icons/approved-round.svg';
7
+
8
+ /**
9
+ * @element cfpb-form-search
10
+ * @slot - The label for the form input.
11
+ */
12
+ export class CfpbFormAlert extends LitElement {
13
+ static styles = css`
14
+ ${unsafeCSS(styles)}
15
+ `;
16
+
17
+ /**
18
+ * @property {string} validation - Validation style: error, warning, success.
19
+ * @returns {object} The map of properties.
20
+ */
21
+ static properties = {
22
+ validation: { type: String },
23
+ };
24
+
25
+ constructor() {
26
+ super();
27
+ this.validation = 'error';
28
+ }
29
+
30
+ get icon() {
31
+ let icon = errorIcon;
32
+ if (this.validation === 'warning') {
33
+ icon = warningIcon;
34
+ } else if (this.validation === 'success') {
35
+ icon = successIcon;
36
+ }
37
+
38
+ return icon;
39
+ }
40
+
41
+ render() {
42
+ return html`<div
43
+ class="a-form-alert a-form-alert--${this.validation}"
44
+ role="alert"
45
+ >
46
+ ${unsafeSVG(this.icon)}
47
+ <div class="a-form-alert__text"><slot></slot></div>
48
+ </div>`;
49
+ }
50
+
51
+ static init() {
52
+ window.customElements.get('cfpb-form-alert') ||
53
+ window.customElements.define('cfpb-form-alert', CfpbFormAlert);
54
+ }
55
+ }
@@ -1,5 +1,5 @@
1
1
  @use 'sass:math';
2
- @use '@cfpb/cfpb-design-system/src/abstracts' as *;
2
+ @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
3
3
  @use '@cfpb/cfpb-design-system/src/utilities' as *;
4
4
 
5
5
  :host {
@@ -17,14 +17,7 @@
17
17
  // Private variables.
18
18
  --choice-border-width-addendum: 0;
19
19
 
20
- &--in-list label {
21
- box-sizing: border-box;
22
- padding-top: math.div(5px, $base-font-size-px) + em;
23
- padding-right: 0;
24
- padding-bottom: math.div(5px, $base-font-size-px) + em;
25
- padding-left: math.div(10px, $base-font-size-px) + em;
26
- width: 100%;
27
- }
20
+ width: max-content;
28
21
 
29
22
  .a-label + .a-text-input {
30
23
  margin-top: math.div(5px, $base-font-size-px) + em;
@@ -42,31 +35,6 @@
42
35
 
43
36
  // Wrap long words in narrow form fields to prevent clipping
44
37
  overflow-wrap: anywhere;
45
-
46
- &::before {
47
- display: inline-block;
48
- grid-row-start: 1;
49
- grid-row-end: 3;
50
- border: 1px solid var(--choice-border);
51
- outline: var(--choice-border-width-addendum) solid
52
- var(--choice-border);
53
- height: math.div(18px, $base-font-size-px) + em;
54
- width: math.div(18px, $base-font-size-px) + em;
55
- margin-right: 10px;
56
- background-color: var(--choice-bg);
57
- content: '';
58
- vertical-align: top;
59
-
60
- // Offset so that the checkbox/radio fits within focused area.
61
- position: relative;
62
- top: 1px;
63
- left: 1px;
64
- }
65
-
66
- &:hover::before,
67
- &.hover::before {
68
- border-color: var(--choice-border-hover);
69
- }
70
38
  }
71
39
 
72
40
  .a-checkbox,
@@ -80,23 +48,9 @@
80
48
  }
81
49
 
82
50
  &:disabled {
83
- &:checked + .a-label::before,
84
- &:focus + .a-label::before,
85
- &.focus + .a-label::before,
86
- &:hover + .a-label::before,
87
- &.hover + .a-label::before {
88
- border-color: var(--choice-border);
89
- outline: none;
90
- box-shadow: none; // Applies only to radio buttons.
91
- }
92
-
93
51
  & + .a-label {
94
52
  cursor: not-allowed;
95
53
  color: var(--choice-label-disabled);
96
-
97
- &::before {
98
- outline: none;
99
- }
100
54
  }
101
55
  }
102
56
  }
@@ -127,40 +81,49 @@
127
81
  }
128
82
  }
129
83
 
130
- &--checkbox {
131
- .a-checkbox {
84
+ &--radio {
85
+ input:disabled {
86
+ &:checked + .a-label::before,
132
87
  &:focus + .a-label::before,
133
- &.focus + .a-label::before {
134
- border-color: var(--choice-border-focus);
135
- box-shadow: 0 0 0 1px var(--choice-border-focus);
136
- outline-color: var(--choice-border-focus);
137
- }
138
-
88
+ &.focus + .a-label::before,
139
89
  &:hover + .a-label::before,
140
90
  &.hover + .a-label::before {
141
- border-color: var(--choice-border-hover);
142
- box-shadow: 0 0 0 1px var(--choice-border-hover);
143
- outline-color: var(--choice-border-hover);
91
+ border-color: var(--choice-border);
92
+ outline: none;
93
+ box-shadow: none; // Applies only to radio buttons.
144
94
  }
145
95
 
146
- &:checked + .a-label::before {
147
- --cfpb-background-icon-svg: 'approved';
148
-
149
- background-size: auto $cf-icon-height;
150
- background-repeat: no-repeat;
151
- background-position: center 0;
152
- }
153
- &:disabled:checked + .a-label::before {
154
- // RGB values are CFPB gray (#5a5d61).
155
- // For some reason SVG isn't accepting hex values for the fill.
156
- --cfpb-background-icon-svg: 'approved rgb(90,93,97)';
96
+ & + .a-label {
97
+ &::before {
98
+ outline: none;
99
+ }
157
100
  }
158
101
  }
159
- }
160
102
 
161
- &--radio {
103
+ &:hover::before,
104
+ &.hover::before {
105
+ border-color: var(--choice-border-hover);
106
+ }
107
+
162
108
  .a-label {
163
109
  &::before {
110
+ display: inline-block;
111
+ grid-row-start: 1;
112
+ grid-row-end: 3;
113
+ border: 1px solid var(--choice-border);
114
+ outline: var(--choice-border-width-addendum) solid
115
+ var(--choice-border);
116
+ height: math.div(18px, $base-font-size-px) + em;
117
+ width: math.div(18px, $base-font-size-px) + em;
118
+ margin-right: 10px;
119
+ background-color: var(--choice-bg);
120
+ content: '';
121
+ vertical-align: top;
122
+
123
+ // Offset so that the checkbox/radio fits within focused area.
124
+ position: relative;
125
+ top: 1px;
126
+ left: 1px;
164
127
  border-radius: 50%;
165
128
 
166
129
  /* The rotate is needed to fix a bug in Firefox where radio
@@ -217,27 +180,28 @@
217
180
  }
218
181
 
219
182
  &--lg-target {
183
+ width: 100%;
220
184
  display: block;
221
185
 
222
186
  .a-label {
223
187
  box-sizing: border-box;
224
188
  width: 100%;
225
189
  padding: 15px;
226
- background-color: $form-field-input-lg-target-bg;
190
+ background-color: var(--form-field-input-lg-target-bg);
227
191
  }
228
192
 
229
193
  .a-checkbox,
230
194
  .a-radio {
231
195
  &:checked + .a-label {
232
- background-color: $form-field-input-lg-target-bg-selected;
233
- box-shadow: inset 0 0 0 1px $form-field-input-lg-target-border;
196
+ background-color: var(--form-field-input-lg-target-bg-selected);
197
+ box-shadow: inset 0 0 0 1px var(--form-field-input-lg-target-border);
234
198
  }
235
199
 
236
200
  &:hover + .a-label,
237
201
  &.hover + .a-label,
238
202
  &:focus + .a-label,
239
203
  &.focus + .a-label {
240
- box-shadow: inset 0 0 0 2px $form-field-input-lg-target-border;
204
+ box-shadow: inset 0 0 0 2px var(--form-field-input-lg-target-border);
241
205
  }
242
206
 
243
207
  &:focus + .a-label,
@@ -251,14 +215,11 @@
251
215
  &:hover:disabled + .a-label {
252
216
  color: var(--choice-label-disabled);
253
217
  box-shadow: none;
254
- background-color: $form-field-input-lg-target-bg-disabled;
218
+ background-color: var(--form-field-input-lg-target-bg-disabled);
255
219
  }
256
220
 
257
221
  &:checked:disabled + .a-label {
258
- &,
259
- &::before {
260
- border: 1px solid var(--form-field-border-disabled);
261
- }
222
+ border: 1px solid var(--form-field-border-disabled);
262
223
  }
263
224
  }
264
225
  }