@cfpb/cfpb-design-system 4.0.2 → 4.0.3

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 (53) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/dist/components/cfpb-forms/index.css +1 -1
  3. package/dist/components/cfpb-forms/index.css.map +2 -2
  4. package/dist/components/cfpb-forms/index.js.map +1 -1
  5. package/dist/components/cfpb-layout/index.css +1 -1
  6. package/dist/components/cfpb-layout/index.css.map +2 -2
  7. package/dist/components/cfpb-layout/index.js.map +1 -1
  8. package/dist/components/cfpb-typography/index.css +1 -1
  9. package/dist/components/cfpb-typography/index.css.map +2 -2
  10. package/dist/components/cfpb-typography/index.js.map +1 -1
  11. package/dist/elements/cfpb-button/index.js +2 -2
  12. package/dist/elements/cfpb-button/index.js.map +1 -1
  13. package/dist/elements/cfpb-checkbox/index.js +29 -0
  14. package/dist/elements/cfpb-checkbox/index.js.map +7 -0
  15. package/dist/elements/cfpb-file-upload/index.js +2 -2
  16. package/dist/elements/cfpb-file-upload/index.js.map +1 -1
  17. package/dist/elements/cfpb-form-choice/index.js +29 -0
  18. package/dist/elements/cfpb-form-choice/index.js.map +7 -0
  19. package/dist/elements/cfpb-multiselect/index.js +30 -0
  20. package/dist/elements/cfpb-multiselect/index.js.map +7 -0
  21. package/dist/elements/cfpb-tag-filter/index.js +31 -0
  22. package/dist/elements/cfpb-tag-filter/index.js.map +7 -0
  23. package/dist/elements/cfpb-tag-group/index.js +29 -0
  24. package/dist/elements/cfpb-tag-group/index.js.map +7 -0
  25. package/dist/elements/cfpb-tag-topic/index.js +30 -0
  26. package/dist/elements/cfpb-tag-topic/index.js.map +7 -0
  27. package/dist/elements/index.js +42 -0
  28. package/dist/elements/index.js.map +7 -0
  29. package/dist/index.css +1 -1
  30. package/dist/index.css.map +2 -2
  31. package/dist/index.js +6 -4
  32. package/dist/index.js.map +4 -4
  33. package/package.json +1 -1
  34. package/src/components/cfpb-forms/multiselect-model.js +1 -1
  35. package/src/components/cfpb-forms/multiselect.js +1 -1
  36. package/src/components/cfpb-forms/multiselect.scss +2 -1
  37. package/src/components/cfpb-layout/card-group.scss +2 -2
  38. package/src/components/cfpb-typography/mixins.scss +1 -1
  39. package/src/components/cfpb-typography/tagline.scss +1 -1
  40. package/src/elements/cfpb-button/index.js +7 -3
  41. package/src/elements/cfpb-form-choice/cfpb-form-choice.component.scss +261 -0
  42. package/src/elements/cfpb-form-choice/index.js +103 -0
  43. package/src/elements/cfpb-tag-filter/cfpb-tag-filter.component.scss +51 -0
  44. package/src/elements/cfpb-tag-filter/index.js +55 -0
  45. package/src/elements/cfpb-tag-filter/index.spec.js +43 -0
  46. package/src/elements/cfpb-tag-group/cfpb-tag-group.component.scss +43 -0
  47. package/src/elements/cfpb-tag-group/index.js +311 -0
  48. package/src/elements/cfpb-tag-group/index.spec.js +160 -0
  49. package/src/elements/cfpb-tag-topic/cfpb-tag-topic.component.scss +88 -0
  50. package/src/elements/cfpb-tag-topic/index.js +62 -0
  51. package/src/elements/index.js +11 -0
  52. package/src/index.js +1 -2
  53. package/src/utilities/utilities.scss +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cfpb/cfpb-design-system",
3
- "version": "4.0.2",
3
+ "version": "4.0.3",
4
4
  "description": "CFPB's UI framework",
5
5
  "exports": {
6
6
  ".": "./src/index.js",
@@ -26,7 +26,7 @@ function stringMatch(x, y) {
26
26
  /**
27
27
  * @class
28
28
  * MultiselectModel
29
- * @param {HTMLOptionsCollection} options -
29
+ * @param {HTMLOptionsCollection} options
30
30
  * Set of options from a <select> element.
31
31
  * @param {string} name - a unique name for this multiselect.
32
32
  * @param {object} config - Customization of Multiselect behavior
@@ -172,7 +172,7 @@ function Multiselect(element) {
172
172
 
173
173
  /**
174
174
  * Highlights an option in the list.
175
- * @param {string} direction -
175
+ * @param {string} direction
176
176
  * Direction to highlight compared to the current focus.
177
177
  */
178
178
  function _highlight(direction) {
@@ -116,6 +116,8 @@ select.o-multiselect {
116
116
 
117
117
  &.u-no-results,
118
118
  &.u-max-selections {
119
+ padding: math.div(10px, $base-font-size-px) + em;
120
+
119
121
  li {
120
122
  display: none;
121
123
  }
@@ -130,7 +132,6 @@ select.o-multiselect {
130
132
  }
131
133
 
132
134
  &.u-max-selections {
133
- padding: math.div(10px, $base-font-size-px) + em;
134
135
  pointer-events: none;
135
136
 
136
137
  &::after {
@@ -22,8 +22,8 @@
22
22
 
23
23
  &__cards {
24
24
  display: grid;
25
- grid-column-gap: math.div(20px, $base-font-size-px) + em;
26
- grid-row-gap: math.div(20px, $base-font-size-px) + em;
25
+ column-gap: math.div(20px, $base-font-size-px) + em;
26
+ row-gap: math.div(20px, $base-font-size-px) + em;
27
27
 
28
28
  // Mobile only.
29
29
  @include respond-to-max($bp-xs-max) {
@@ -61,7 +61,7 @@
61
61
  }
62
62
  }
63
63
 
64
- // We need to separate out the jump link
64
+ // We need to separate out the jump link.
65
65
  a.#{$jump-link-class} {
66
66
  @if $is-gold {
67
67
  border-color: var(--gold-80);
@@ -6,7 +6,7 @@
6
6
 
7
7
  display: grid;
8
8
  grid-template-columns: 22px 1fr;
9
- grid-column-gap: 10px;
9
+ column-gap: 10px;
10
10
 
11
11
  &__text {
12
12
  // Needed for browsers with legacy/no grid support (e.g. IE11).
@@ -11,16 +11,20 @@ export class CfpbButton extends LitElement {
11
11
  ${unsafeCSS(styles)}
12
12
  `;
13
13
 
14
+ /**
15
+ * @property {boolean} disabled - Whether to stack the tags vertically.
16
+ * @property {string} type - The button type: secondary, warning, disabled.
17
+ */
14
18
  static get properties() {
15
19
  return {
16
- isDisabled: { type: Boolean },
20
+ disabled: { type: Boolean },
17
21
  type: { type: String },
18
22
  };
19
23
  }
20
24
 
21
25
  constructor() {
22
26
  super();
23
- this.isDisabled = false;
27
+ this.disabled = false;
24
28
  this.type = '';
25
29
  }
26
30
 
@@ -43,7 +47,7 @@ export class CfpbButton extends LitElement {
43
47
 
44
48
  render() {
45
49
  return html`
46
- <button class="${this._btnClass}" ?disabled=${this.isDisabled}>
50
+ <button class="${this._btnClass}" ?disabled=${this.disabled}>
47
51
  <slot></slot>
48
52
  </button>
49
53
  `;
@@ -0,0 +1,261 @@
1
+ @use 'sass:math';
2
+ @use '@cfpb/cfpb-design-system/src/abstracts' as *;
3
+ @use '@cfpb/cfpb-design-system/src/utilities' as *;
4
+
5
+ :host {
6
+ .m-form-field {
7
+ // Theme variables.
8
+ --choice-border: var(--choice-border-default);
9
+ --choice-border-hover: var(--choice-border-hover-default);
10
+ --choice-border-focus: var(--choice-border-focus-default);
11
+ --choice-outline-focus: var(--choice-outline-focus-default);
12
+ --choice-bg: var(--choice-bg-default);
13
+ --choice-bg-selected: var(--choice-bg-selected-default);
14
+ --choice-bg-selected-focus: var(--choice-bg-selected-focus-default);
15
+ --choice-label-disabled: var(--choice-label-disabled-default);
16
+
17
+ // Private variables.
18
+ --choice-border-width-addendum: 0;
19
+
20
+ .a-text-input--full {
21
+ width: 100%;
22
+ }
23
+
24
+ .a-label + .a-text-input {
25
+ margin-top: math.div(5px, $base-font-size-px) + em;
26
+ }
27
+
28
+ &--checkbox,
29
+ &--radio {
30
+ .a-label {
31
+ display: inline-grid;
32
+
33
+ // 30px is width of checkbox/radio button plus the needed padding.
34
+ grid-template-columns: math.div(30px, $base-font-size-px) + em auto;
35
+ vertical-align: top;
36
+ cursor: pointer;
37
+
38
+ // Wrap long words in narrow form fields to prevent clipping
39
+ overflow-wrap: anywhere;
40
+
41
+ &::before {
42
+ display: inline-block;
43
+ grid-row-start: 1;
44
+ grid-row-end: 3;
45
+ border: 1px solid var(--choice-border);
46
+ outline: var(--choice-border-width-addendum) solid
47
+ var(--choice-border);
48
+ height: math.div(18px, $base-font-size-px) + em;
49
+ width: math.div(18px, $base-font-size-px) + em;
50
+ margin-right: 10px;
51
+ background-color: var(--choice-bg);
52
+ content: '';
53
+ vertical-align: top;
54
+
55
+ // Offset so that the checkbox/radio fits within focused area.
56
+ position: relative;
57
+ top: 1px;
58
+ left: 1px;
59
+ }
60
+
61
+ &:hover::before,
62
+ &.hover::before {
63
+ border-color: var(--choice-border-hover);
64
+ }
65
+ }
66
+
67
+ .a-checkbox,
68
+ .a-radio {
69
+ @include u-visually-hidden;
70
+
71
+ &:focus + .a-label,
72
+ &.focus + .a-label {
73
+ outline: 1px dotted var(--choice-outline-focus);
74
+ outline-offset: 1px;
75
+ }
76
+
77
+ &:disabled {
78
+ &:checked + .a-label::before,
79
+ &:focus + .a-label::before,
80
+ &.focus + .a-label::before,
81
+ &:hover + .a-label::before,
82
+ &.hover + .a-label::before {
83
+ border-color: var(--choice-border);
84
+ outline: none;
85
+ box-shadow: none; // Applies only to radio buttons.
86
+ }
87
+
88
+ & + .a-label {
89
+ cursor: not-allowed;
90
+ color: var(--choice-label-disabled);
91
+
92
+ &::before {
93
+ outline: none;
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ &:has(.a-checkbox:disabled),
100
+ &:has(.a-radio:disabled) {
101
+ --choice-border: var(--choice-border-disabled);
102
+ --choice-bg: var(--choice-bg-disabled);
103
+ --choice-bg-selected: var(--choice-bg-selected-disabled);
104
+ }
105
+
106
+ &-success,
107
+ &-warning,
108
+ &-error {
109
+ --choice-border-width-addendum: 1px;
110
+ }
111
+
112
+ &-success {
113
+ --choice-border: var(--choice-border-success);
114
+ }
115
+
116
+ &-warning {
117
+ --choice-border: var(--choice-border-warning);
118
+ }
119
+
120
+ &-error {
121
+ --choice-border: var(--choice-border-error);
122
+ }
123
+ }
124
+
125
+ &--checkbox {
126
+ .a-checkbox {
127
+ &:focus + .a-label::before,
128
+ &.focus + .a-label::before {
129
+ border-color: var(--choice-border-focus);
130
+ box-shadow: 0 0 0 1px var(--choice-border-focus);
131
+ outline-color: var(--choice-border-focus);
132
+ }
133
+
134
+ &:hover + .a-label::before,
135
+ &.hover + .a-label::before {
136
+ border-color: var(--choice-border-hover);
137
+ box-shadow: 0 0 0 1px var(--choice-border-hover);
138
+ outline-color: var(--choice-border-hover);
139
+ }
140
+
141
+ &:checked + .a-label::before {
142
+ --cfpb-background-icon-svg: 'approved';
143
+
144
+ background-size: auto $cf-icon-height;
145
+ background-repeat: no-repeat;
146
+ background-position: center 0;
147
+ }
148
+ &:disabled:checked + .a-label::before {
149
+ // RGB values are CFPB gray (#5a5d61).
150
+ // For some reason SVG isn't accepting hex values for the fill.
151
+ --cfpb-background-icon-svg: 'approved rgb(90,93,97)';
152
+ }
153
+ }
154
+ }
155
+
156
+ &--radio {
157
+ .a-label {
158
+ &::before {
159
+ border-radius: 50%;
160
+
161
+ /* The rotate is needed to fix a bug in Firefox where radio
162
+ button was not centered. */
163
+ transform: rotate(0deg);
164
+ }
165
+ }
166
+
167
+ .a-radio {
168
+ &:focus + .a-label::before,
169
+ &.focus + .a-label::before {
170
+ outline: none;
171
+ border-color: var(--choice-border-focus);
172
+ box-shadow: 0 0 0 1px var(--choice-border-focus);
173
+ }
174
+
175
+ &:hover + .a-label::before,
176
+ &.hover + .a-label::before {
177
+ outline: none;
178
+ border-color: var(--choice-border-hover);
179
+ box-shadow: 0 0 0 1px var(--choice-border-hover);
180
+ }
181
+
182
+ &:checked + .a-label::before {
183
+ background-color: var(--choice-bg-selected);
184
+ box-shadow: inset 0 0 0 2px var(--white); // The radio button ring.
185
+ }
186
+
187
+ &:focus:checked + .a-label::before,
188
+ &.focus:checked + .a-label::before {
189
+ background-color: var(--choice-bg-selected-focus);
190
+ border-color: var(--choice-border-focus);
191
+ box-shadow:
192
+ 0 0 0 1px var(--choice-border-focus),
193
+ inset 0 0 0 2px var(--white); // The radio button ring.
194
+ }
195
+
196
+ &:hover:checked + .a-label::before,
197
+ &.hover:checked + .a-label::before {
198
+ border-color: var(--choice-border-hover);
199
+ box-shadow:
200
+ 0 0 0 1px var(--choice-border-hover),
201
+ inset 0 0 0 2px var(--white); // The radio button ring.
202
+ }
203
+
204
+ &:checked:disabled + .a-label::before,
205
+ &:hover:checked:disabled + .a-label::before,
206
+ &.hover:checked:disabled + .a-label::before {
207
+ background-color: var(--choice-bg-selected);
208
+ box-shadow: inset 0 0 0 2px var(--gray-10); // The radio button ring.
209
+ border-color: var(--choice-border-disabled);
210
+ }
211
+ }
212
+ }
213
+
214
+ &--lg-target {
215
+ display: block;
216
+
217
+ .a-label {
218
+ box-sizing: border-box;
219
+ width: 100%;
220
+ padding: 15px;
221
+ background-color: $form-field-input-lg-target-bg;
222
+ }
223
+
224
+ .a-checkbox,
225
+ .a-radio {
226
+ &:checked + .a-label {
227
+ background-color: $form-field-input-lg-target-bg-selected;
228
+ box-shadow: inset 0 0 0 1px $form-field-input-lg-target-border;
229
+ }
230
+
231
+ &:hover + .a-label,
232
+ &.hover + .a-label,
233
+ &:focus + .a-label,
234
+ &.focus + .a-label {
235
+ box-shadow: inset 0 0 0 2px $form-field-input-lg-target-border;
236
+ }
237
+
238
+ &:focus + .a-label,
239
+ &.focus + .a-label,
240
+ &:checked + .a-label {
241
+ outline-offset: 1px;
242
+ }
243
+
244
+ &:disabled + .a-label,
245
+ &:checked:disabled + .a-label,
246
+ &:hover:disabled + .a-label {
247
+ color: var(--choice-label-disabled);
248
+ box-shadow: none;
249
+ background-color: $form-field-input-lg-target-bg-disabled;
250
+ }
251
+
252
+ &:checked:disabled + .a-label {
253
+ &,
254
+ &::before {
255
+ border: 1px solid var(--form-field-border-disabled);
256
+ }
257
+ }
258
+ }
259
+ }
260
+ }
261
+ }
@@ -0,0 +1,103 @@
1
+ import { html, LitElement, css, unsafeCSS } from 'lit';
2
+ import styles from './cfpb-form-choice.component.scss';
3
+
4
+ /**
5
+ *
6
+ * @element cfpb-form-choice
7
+ * @slot - The label for the form input.
8
+ */
9
+ export class CfpbFormChoice extends LitElement {
10
+ static styles = css`
11
+ ${unsafeCSS(styles)}
12
+ `;
13
+
14
+ /**
15
+ * @property {boolean} checked - Whether the choice is checked or not.
16
+ * @property {boolean} disabled - Whether the choice is disabled or not.
17
+ * @property {boolean} large - Whether the choice has a large target area.
18
+ * @property {string} validation - Validation style: error, warning, success.
19
+ * @property {string} type - Choice type: checkbox or radio.
20
+ */
21
+ static get properties() {
22
+ return {
23
+ checked: { type: Boolean, reflect: true },
24
+ disabled: { type: Boolean },
25
+ large: { type: Boolean },
26
+ validation: { type: String },
27
+ type: { type: String },
28
+ };
29
+ }
30
+
31
+ constructor() {
32
+ super();
33
+ this.disabled = false;
34
+ this.large = false;
35
+ this.validation = '';
36
+ this.type = 'checkbox';
37
+ }
38
+
39
+ get #baseClass() {
40
+ let baseClass = `m-form-field m-form-field--${this.type}`;
41
+
42
+ switch (this.validation) {
43
+ case 'success':
44
+ baseClass += ` m-form-field--${this.type}-success`;
45
+ break;
46
+ case 'warning':
47
+ baseClass += ` m-form-field--${this.type}-warning`;
48
+ break;
49
+ case 'error':
50
+ baseClass += ` m-form-field--${this.type}-error`;
51
+ break;
52
+ }
53
+
54
+ if (this.large) {
55
+ baseClass += ' m-form-field--lg-target';
56
+ }
57
+
58
+ return baseClass;
59
+ }
60
+
61
+ #onChange(evt) {
62
+ evt.target.checked = this.checked;
63
+ this.dispatchEvent(
64
+ new Event('change', {
65
+ bubbles: true,
66
+ composed: true,
67
+ }),
68
+ );
69
+ }
70
+
71
+ #onInput() {
72
+ this.dispatchEvent(
73
+ new Event('input', {
74
+ bubbles: true,
75
+ composed: true,
76
+ }),
77
+ );
78
+ }
79
+
80
+ render() {
81
+ return html`
82
+ <div class="${this.#baseClass}" ?large=${this.large}>
83
+ <input
84
+ class="a-${this.type}"
85
+ type="${this.type}"
86
+ id="${this.type}"
87
+ ?disabled=${this.disabled}
88
+ .checked=${this.checked}
89
+ @change=${this.#onChange}
90
+ @input=${this.#onInput}
91
+ />
92
+ <label class="a-label" for="${this.type}">
93
+ <slot></slot>
94
+ </label>
95
+ </div>
96
+ `;
97
+ }
98
+
99
+ static init() {
100
+ window.customElements.get('cfpb-form-choice') ||
101
+ window.customElements.define('cfpb-form-choice', CfpbFormChoice);
102
+ }
103
+ }
@@ -0,0 +1,51 @@
1
+ @use 'sass:math';
2
+ @use '@cfpb/cfpb-design-system/src/abstracts' as *;
3
+ @use '@cfpb/cfpb-design-system/src/components/cfpb-buttons/vars' as *;
4
+
5
+ :host {
6
+ button {
7
+ // Filter tags appear in filtered contexts, often as part of multiselects.
8
+ line-height: math.div(19px, $base-font-size-px);
9
+ font-size: math.div(16px, $btn-font-size) + rem;
10
+
11
+ display: flex;
12
+ gap: math.div(10px, $btn-font-size) + rem;
13
+
14
+ border: 1px solid var(--teal);
15
+ padding: 4px 6px;
16
+ background-color: var(--teal-20);
17
+ border-radius: math.div(3px, $base-font-size-px) + rem;
18
+ color: var(--black);
19
+ text-align: left;
20
+ min-width: fit-content;
21
+
22
+ &:hover {
23
+ background-color: var(--teal-40);
24
+ cursor: pointer;
25
+ }
26
+
27
+ &:focus {
28
+ outline: 1px dotted var(--teal);
29
+ outline-offset: 1px;
30
+ }
31
+
32
+ &:active {
33
+ background-color: var(--teal-60);
34
+ }
35
+ }
36
+
37
+ svg {
38
+ pointer-events: none;
39
+
40
+ // Prevent flexbox from squishing icon when tag text is long.
41
+ flex: none;
42
+
43
+ height: math.div(19px, $btn-font-size) + rem;
44
+ }
45
+
46
+ // If the contents are wrapped in a label, negate the label's display.
47
+ label {
48
+ display: contents;
49
+ pointer-events: none;
50
+ }
51
+ }
@@ -0,0 +1,55 @@
1
+ import { html, LitElement, css, unsafeCSS } from 'lit';
2
+ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
3
+ import styles from './cfpb-tag-filter.component.scss';
4
+ import icon from '../../components/cfpb-icons/icons/error.svg';
5
+
6
+ /**
7
+ *
8
+ * @element cfpb-tag-filter.
9
+ * @slot - The content for the filter tag.
10
+ */
11
+ export class CfpbTagFilter extends LitElement {
12
+ static styles = css`
13
+ ${unsafeCSS(styles)}
14
+ `;
15
+
16
+ /**
17
+ * @property {string} for - Whether to stack the tags vertically.
18
+ */
19
+ static get properties() {
20
+ return {
21
+ for: { type: String },
22
+ };
23
+ }
24
+
25
+ constructor() {
26
+ super();
27
+ this.for = '';
28
+ }
29
+
30
+ #onClick() {
31
+ this.dispatchEvent(
32
+ new CustomEvent('tag-click', {
33
+ detail: { target: this },
34
+ bubbles: false,
35
+ composed: false,
36
+ }),
37
+ );
38
+ }
39
+
40
+ render() {
41
+ const slot =
42
+ this.for === ''
43
+ ? html`<slot></slot>`
44
+ : html`<label for="${this.for}"><slot></slot></label>`;
45
+ return html`<button @click=${this.#onClick}>
46
+ ${slot} ${unsafeHTML(icon)}
47
+ </button>`;
48
+ }
49
+
50
+ static init() {
51
+ // Initialize parent file upload.
52
+ window.customElements.get('cfpb-tag-filter') ||
53
+ window.customElements.define('cfpb-tag-filter', CfpbTagFilter);
54
+ }
55
+ }
@@ -0,0 +1,43 @@
1
+ import { jest } from '@jest/globals';
2
+ import { CfpbTagFilter } from './index.js';
3
+
4
+ describe('<cfpb-tag-filter>', () => {
5
+ let elm;
6
+
7
+ beforeEach(async () => {
8
+ CfpbTagFilter.init();
9
+ elm = document.createElement('cfpb-tag-filter');
10
+ document.body.appendChild(elm);
11
+
12
+ await customElements.whenDefined('cfpb-tag-filter');
13
+ await elm.updateComplete;
14
+ });
15
+
16
+ afterEach(() => {
17
+ document.body.removeChild(elm);
18
+ });
19
+
20
+ it('renders slotted content', async () => {
21
+ const slottedContent = document.createElement('span');
22
+ elm.setAttribute('for', 'unique-id');
23
+ slottedContent.textContent = 'Earth';
24
+ elm.appendChild(slottedContent);
25
+ await elm.updateComplete;
26
+
27
+ const slot = elm.shadowRoot.querySelector('slot');
28
+ const assignedNodes = slot.assignedNodes({ flatten: true });
29
+
30
+ expect(assignedNodes.length).toBe(1);
31
+ expect(assignedNodes[0].textContent).toBe('Earth');
32
+ });
33
+
34
+ xit('dispatches the correct event', async () => {
35
+ const mockHandler = jest.fn();
36
+ elm.addEventListener('tag-click', mockHandler);
37
+
38
+ elm.shadowRoot.querySelector('button').click();
39
+
40
+ expect(mockHandler).toHaveBeenCalledTimes(1);
41
+ expect(mockHandler.mock.calls[0][0].detail.target).toBe(elm);
42
+ });
43
+ });
@@ -0,0 +1,43 @@
1
+ @use 'sass:math';
2
+ @use '@cfpb/cfpb-design-system/src/abstracts' as *;
3
+ @use '@cfpb/cfpb-design-system/src/components/cfpb-buttons/vars' as *;
4
+
5
+ :host {
6
+ // Tag group sets the spacing between tags.
7
+ ul {
8
+ // Remove list ul bullets styles.
9
+ padding-left: 0;
10
+ list-style-type: none;
11
+
12
+ li {
13
+ margin-bottom: 0;
14
+ display: contents;
15
+ }
16
+
17
+ // Tablet and above.
18
+ @include respond-to-min($bp-sm-min) {
19
+ display: flex;
20
+ gap: math.div(15px, $btn-font-size) + rem;
21
+ flex-wrap: wrap;
22
+
23
+ &[stacked] {
24
+ flex-direction: column;
25
+ width: fit-content;
26
+ }
27
+ }
28
+
29
+ &:has(cfpb-tag-filter) {
30
+ display: flex;
31
+ gap: math.div(15px, $btn-font-size) + rem;
32
+ flex-wrap: wrap;
33
+ }
34
+ }
35
+
36
+ // Right-to-left (RTL) adjustments for arabic pages.
37
+ html[lang='ar'] {
38
+ direction: rtl;
39
+
40
+ // This is needed for right-to-left (RTL) lists.
41
+ padding-right: 0;
42
+ }
43
+ }