@cfpb/cfpb-design-system 5.1.0 → 5.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 (73) hide show
  1. package/CHANGELOG.md +87 -1
  2. package/dist/index.css +1 -1
  3. package/dist/index.js +1761 -1708
  4. package/package.json +1 -1
  5. package/src/components/cfpb-forms/form-field.scss +3 -4
  6. package/src/components/cfpb-forms/multiselect.js +1 -2
  7. package/src/components/cfpb-forms/multiselect.scss +3 -2
  8. package/src/components/cfpb-forms/select.scss +3 -2
  9. package/src/components/cfpb-icons/icons-lib.js +680 -0
  10. package/src/components/cfpb-icons/icons-lib.scss +679 -0
  11. package/src/elements/abstracts/custom-props.css +2 -1
  12. package/src/elements/abstracts/vars.css +1 -6
  13. package/src/elements/base/base.scss +3 -0
  14. package/src/elements/base/font.scss +1 -1
  15. package/src/elements/cfpb-button/cfpb-button.scss +1 -1
  16. package/src/elements/cfpb-button/index.js +1 -1
  17. package/src/elements/cfpb-checkbox-icon/index.js +1 -1
  18. package/src/elements/cfpb-checkbox-icon/{cfpb-checkbox-icon.component.scss → styles.component.scss} +3 -4
  19. package/src/elements/cfpb-expandable/index.js +6 -6
  20. package/src/elements/cfpb-expandable/{cfpb-expandable.component.scss → styles.component.scss} +1 -1
  21. package/src/elements/cfpb-file-upload/index.js +1 -1
  22. package/src/elements/cfpb-file-upload/styles.component.css +7 -0
  23. package/src/elements/cfpb-flag-usa/index.js +1 -1
  24. package/src/elements/cfpb-flag-usa/{cfpb-flag-usa.component.scss → styles.component.css} +2 -2
  25. package/src/elements/cfpb-form-alert/index.js +21 -9
  26. package/src/elements/cfpb-form-alert/styles.component.scss +14 -0
  27. package/src/elements/cfpb-form-choice/index.js +1 -1
  28. package/src/elements/cfpb-form-choice/{cfpb-form-choice.component.scss → styles.component.scss} +5 -6
  29. package/src/elements/cfpb-form-search/index.js +5 -5
  30. package/src/elements/cfpb-form-search/skeleton.css +8 -0
  31. package/src/elements/cfpb-form-search/{cfpb-form-search.component.scss → styles.component.scss} +3 -3
  32. package/src/elements/cfpb-form-search-input/index.js +6 -7
  33. package/src/elements/cfpb-form-search-input/{cfpb-form-search-input.component.scss → styles.component.scss} +6 -8
  34. package/src/elements/cfpb-icon/index.js +43 -0
  35. package/src/elements/cfpb-icon/styles.component.css +48 -0
  36. package/src/elements/cfpb-icon-text/index.js +1 -1
  37. package/src/elements/cfpb-icon-text/{cfpb-icon-text.component.scss → styles.component.scss} +2 -3
  38. package/src/elements/cfpb-label/index.js +1 -1
  39. package/src/elements/cfpb-label/{cfpb-label.component.scss → styles.component.scss} +5 -5
  40. package/src/elements/{cfpb-list → cfpb-listbox}/index.js +10 -9
  41. package/src/elements/{cfpb-list → cfpb-listbox}/index.spec.js +9 -9
  42. package/src/elements/{cfpb-list/cfpb-list.component.scss → cfpb-listbox/styles.component.scss} +1 -5
  43. package/src/elements/{cfpb-list-item → cfpb-listbox-item}/index.js +5 -5
  44. package/src/elements/{cfpb-list-item/cfpb-list-item.component.scss → cfpb-listbox-item/styles.component.scss} +4 -3
  45. package/src/elements/cfpb-pagination/index.js +6 -6
  46. package/src/elements/cfpb-pagination/{cfpb-pagination.component.scss → styles.component.scss} +6 -6
  47. package/src/elements/cfpb-select/index.js +9 -10
  48. package/src/elements/cfpb-select/multiple-select-event-proxy.js +2 -2
  49. package/src/elements/cfpb-select/single-select-event-proxy.js +1 -1
  50. package/src/elements/cfpb-select/{cfpb-select.component.scss → styles.component.scss} +5 -6
  51. package/src/elements/cfpb-tag-filter/index.js +2 -2
  52. package/src/elements/cfpb-tag-filter/{cfpb-tag-filter.component.scss → styles.component.scss} +6 -8
  53. package/src/elements/cfpb-tag-group/index.js +1 -1
  54. package/src/elements/cfpb-tag-group/{cfpb-tag-group.component.scss → styles.component.scss} +3 -4
  55. package/src/elements/cfpb-tag-topic/index.js +1 -1
  56. package/src/elements/cfpb-tag-topic/{cfpb-tag-topic.component.scss → styles.component.scss} +2 -2
  57. package/src/elements/cfpb-tagline/index.js +1 -1
  58. package/src/elements/cfpb-tagline/skeleton.css +7 -0
  59. package/src/elements/cfpb-tagline/{cfpb-tagline.component.scss → styles.component.scss} +3 -4
  60. package/src/elements/cfpb-utilities/fallback/wc-fallback.css +31 -0
  61. package/src/elements/cfpb-utilities/fallback/wc-fallback.js +65 -0
  62. package/src/elements/cfpb-utilities/shared-config.js +41 -0
  63. package/src/elements/cfpb-utilities/skeleton.css +33 -0
  64. package/src/elements/cfpb-utilities/transition/{transition.scss → transition.css} +11 -11
  65. package/src/elements/index.js +11 -2
  66. package/src/index.js +1 -5
  67. package/src/index.scss +1 -1
  68. package/src/tokens/abstracts/custom-props.json +13 -1
  69. package/src/utilities/functions.scss +20 -0
  70. package/src/elements/base/index.js +0 -2
  71. package/src/elements/cfpb-file-upload/cfpb-file-upload.component.scss +0 -10
  72. package/src/elements/cfpb-form-alert/cfpb-form-alert.component.scss +0 -36
  73. /package/src/elements/cfpb-button/{cfpb-button.component.scss → styles.component.scss} +0 -0
@@ -1,10 +1,10 @@
1
1
  import { LitElement, html, css, unsafeCSS } from 'lit';
2
2
  import { ref, createRef } from 'lit/directives/ref.js';
3
- import styles from './cfpb-list.component.scss?inline';
4
- import { CfpbListItem } from '../cfpb-list-item';
3
+ import styles from './styles.component.scss?inline';
4
+ import { CfpbListboxItem } from '../cfpb-listbox-item';
5
5
  import { parseChildData } from '../cfpb-utilities/parse-child-data';
6
6
 
7
- export class CfpbList extends LitElement {
7
+ export class CfpbListbox extends LitElement {
8
8
  static styles = css`
9
9
  ${unsafeCSS(styles)}
10
10
  `;
@@ -84,7 +84,7 @@ export class CfpbList extends LitElement {
84
84
 
85
85
  let firstChecked = null;
86
86
  itemsArray.forEach((data) => {
87
- const item = document.createElement('cfpb-list-item');
87
+ const item = document.createElement('cfpb-listbox-item');
88
88
  item.textContent = data.value ?? '';
89
89
  if ('disabled' in data) item.disabled = data.disabled;
90
90
  if ('hidden' in data) item.hidden = data.hidden;
@@ -109,7 +109,7 @@ export class CfpbList extends LitElement {
109
109
  // -------------------------
110
110
  #syncItems() {
111
111
  // Collect items.
112
- this.#items = [...this.querySelectorAll('cfpb-list-item')];
112
+ this.#items = [...this.querySelectorAll('cfpb-listbox-item')];
113
113
 
114
114
  // Ensure each item has a type.
115
115
  this.#items.forEach((item) => {
@@ -187,7 +187,7 @@ export class CfpbList extends LitElement {
187
187
  #applyTypeToItems() {
188
188
  if (!['plain', 'check', 'checkbox'].includes(this.type)) {
189
189
  // eslint-disable-next-line no-console
190
- console.warn(`<cfpb-list>: invalid type "${this.type}".`);
190
+ console.warn(`<cfpb-listbox>: invalid type "${this.type}".`);
191
191
  return;
192
192
  }
193
193
  this.#items.forEach((item) => (item.type = this.type));
@@ -372,9 +372,10 @@ export class CfpbList extends LitElement {
372
372
  }
373
373
 
374
374
  static init() {
375
- CfpbListItem.init();
376
- if (!window.customElements.get('cfpb-list')) {
377
- window.customElements.define('cfpb-list', CfpbList);
375
+ CfpbListboxItem.init();
376
+
377
+ if (!window.customElements.get('cfpb-listbox')) {
378
+ window.customElements.define('cfpb-listbox', CfpbListbox);
378
379
  }
379
380
  }
380
381
  }
@@ -1,15 +1,15 @@
1
1
  import { jest } from '@jest/globals';
2
- import { CfpbList } from './index';
2
+ import { CfpbListbox } from './index';
3
3
 
4
4
  beforeAll(() => {
5
- CfpbList.init();
5
+ CfpbListbox.init();
6
6
  });
7
7
 
8
- describe('<cfpb-list> tests', () => {
8
+ describe('<cfpb-listbox> tests', () => {
9
9
  let list;
10
10
 
11
11
  beforeEach(() => {
12
- list = document.createElement('cfpb-list');
12
+ list = document.createElement('cfpb-listbox');
13
13
  document.body.appendChild(list);
14
14
  });
15
15
 
@@ -123,7 +123,7 @@ describe('<cfpb-list> tests', () => {
123
123
 
124
124
  const container = list.shadowRoot.querySelector('div');
125
125
  container.focus();
126
- expect(document.activeElement.tagName).toBe('CFPB-LIST');
126
+ expect(document.activeElement.tagName).toBe('CFPB-LISTBOX');
127
127
 
128
128
  // ArrowDown → first visible
129
129
  container.dispatchEvent(
@@ -141,7 +141,7 @@ describe('<cfpb-list> tests', () => {
141
141
  container.dispatchEvent(
142
142
  new KeyboardEvent('keydown', { key: 'ArrowUp', bubbles: true }),
143
143
  );
144
- expect(document.activeElement.tagName).toBe('CFPB-LIST');
144
+ expect(document.activeElement.tagName).toBe('CFPB-LISTBOX');
145
145
  });
146
146
 
147
147
  test('showAllItems unhides all items', async () => {
@@ -173,21 +173,21 @@ describe('<cfpb-list> tests', () => {
173
173
  list.childData = JSON.stringify([{ value: 'A' }, { value: 'B' }]);
174
174
  await list.updateComplete;
175
175
  list.focusItemAt(-1);
176
- expect(document.activeElement.tagName).toBe('CFPB-LIST');
176
+ expect(document.activeElement.tagName).toBe('CFPB-LISTBOX');
177
177
  });
178
178
 
179
179
  test('focusItemAt(null) focuses the container', async () => {
180
180
  list.childData = JSON.stringify([{ value: 'A' }]);
181
181
  await list.updateComplete;
182
182
  list.focusItemAt(null);
183
- expect(document.activeElement.tagName).toBe('CFPB-LIST');
183
+ expect(document.activeElement.tagName).toBe('CFPB-LISTBOX');
184
184
  });
185
185
 
186
186
  test('focusItemAt(undefined) focuses the container', async () => {
187
187
  list.childData = JSON.stringify([{ value: 'A' }]);
188
188
  await list.updateComplete;
189
189
  list.focusItemAt(undefined);
190
- expect(document.activeElement.tagName).toBe('CFPB-LIST');
190
+ expect(document.activeElement.tagName).toBe('CFPB-LISTBOX');
191
191
  });
192
192
 
193
193
  test('ArrowDown from container focuses first visible item', async () => {
@@ -1,9 +1,5 @@
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';
4
-
5
1
  :host {
6
- ::slotted(cfpb-list-item) {
2
+ ::slotted(cfpb-listbox-item) {
7
3
  position: relative;
8
4
  margin-top: 1px;
9
5
 
@@ -1,13 +1,13 @@
1
1
  import { LitElement, html, css, unsafeCSS } from 'lit';
2
- import styles from './cfpb-list-item.component.scss?inline';
2
+ import styles from './styles.component.scss?inline';
3
3
  import { ref, createRef } from 'lit/directives/ref.js';
4
4
  import { CfpbCheckboxIcon } from '../cfpb-checkbox-icon';
5
5
 
6
6
  /**
7
- * @element cfpb-list-item.
7
+ * @element cfpb-listbox-item.
8
8
  * @slot - The text for the list item.
9
9
  */
10
- export class CfpbListItem extends LitElement {
10
+ export class CfpbListboxItem extends LitElement {
11
11
  static styles = css`
12
12
  ${unsafeCSS(styles)}
13
13
  `;
@@ -208,8 +208,8 @@ export class CfpbListItem extends LitElement {
208
208
  static init() {
209
209
  CfpbCheckboxIcon.init();
210
210
 
211
- if (!window.customElements.get('cfpb-list-item')) {
212
- window.customElements.define('cfpb-list-item', CfpbListItem);
211
+ if (!window.customElements.get('cfpb-listbox-item')) {
212
+ window.customElements.define('cfpb-listbox-item', CfpbListboxItem);
213
213
  }
214
214
  }
215
215
  }
@@ -1,5 +1,6 @@
1
- @use 'sass:math';
2
1
  @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
2
+ @use '@cfpb/cfpb-design-system/src/components/cfpb-icons/icons-lib' as *;
3
+ @use '../../utilities/functions' as *;
3
4
 
4
5
  :host {
5
6
  // Theme variables.
@@ -17,7 +18,7 @@
17
18
  display: inline-grid;
18
19
 
19
20
  // 30px is width of checkbox/radio button plus the needed padding.
20
- grid-template-columns: math.div(30px, $base-font-size-px) + em auto;
21
+ grid-template-columns: rem-from-px(30px) auto;
21
22
  vertical-align: top;
22
23
 
23
24
  // Wrap long words in narrow form fields to prevent clipping
@@ -48,7 +49,7 @@
48
49
 
49
50
  :host([checked]) {
50
51
  .checkbox::before {
51
- --cfpb-background-icon-svg: 'approved';
52
+ background-image: $cfpb-background-icon-svg-approved;
52
53
 
53
54
  background-size: auto $cf-icon-height;
54
55
  background-repeat: no-repeat;
@@ -1,8 +1,6 @@
1
1
  import { LitElement, html, css, unsafeCSS } from 'lit';
2
- import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
3
- import styles from './cfpb-pagination.component.scss?inline';
4
- import leftIcon from '../../components/cfpb-icons/icons/left.svg?raw';
5
- import rightIcon from '../../components/cfpb-icons/icons/right.svg?raw';
2
+ import styles from './styles.component.scss?inline';
3
+ import { CfpbIcon } from '../cfpb-icon';
6
4
  import { I18nService, MediaQueryService } from '../cfpb-utilities/';
7
5
 
8
6
  /**
@@ -154,7 +152,7 @@ export class CfpbPagination extends LitElement {
154
152
  ?disabled=${this.isAtMin}
155
153
  @click=${() => this.#goto(this.currentPage - 1)}
156
154
  >
157
- ${unsafeSVG(leftIcon)} ${trans('next')}
155
+ <cfpb-icon name="left" color="white"></cfpb-icon> ${trans('next')}
158
156
  </cfpb-button>
159
157
 
160
158
  <form
@@ -194,13 +192,15 @@ export class CfpbPagination extends LitElement {
194
192
  ?disabled=${this.isAtMax}
195
193
  @click=${() => this.#goto(this.currentPage + 1)}
196
194
  >
197
- ${trans('previous')} ${unsafeSVG(rightIcon)}
195
+ ${trans('previous')}
196
+ <cfpb-icon name="right" color="white"></cfpb-icon>
198
197
  </cfpb-button>
199
198
  </nav>
200
199
  `;
201
200
  }
202
201
 
203
202
  static init() {
203
+ CfpbIcon.init();
204
204
  I18nService.init();
205
205
 
206
206
  window.customElements.get('cfpb-pagination') ||
@@ -1,7 +1,7 @@
1
- @use 'sass:math';
2
1
  @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
3
2
  @use '@cfpb/cfpb-design-system/src/utilities' as *;
4
3
  @use '@cfpb/cfpb-design-system/src/components/cfpb-icons/icon' as *;
4
+ @use '../../utilities/functions' as *;
5
5
 
6
6
  :host {
7
7
  width: 100%;
@@ -12,17 +12,17 @@
12
12
  grid-template-areas:
13
13
  'pag-btn-prev . pag-btn-next'
14
14
  'pag-form pag-form pag-form';
15
- row-gap: math.div(15px, $base-font-size-px) + rem;
15
+ row-gap: rem-from-px(15px);
16
16
 
17
17
  &__form {
18
18
  grid-area: pag-form;
19
19
  display: flex;
20
20
  flex-flow: wrap;
21
21
  place-content: center;
22
- gap: math.div(10px, $base-font-size-px) + rem;
22
+ gap: rem-from-px(10px);
23
23
 
24
- padding: math.div(5px, $base-font-size-px) + rem;
25
- border-radius: math.div(4px, $base-font-size-px) + rem;
24
+ padding: rem-from-px(5px);
25
+ border-radius: rem-from-px(4px);
26
26
  background: var(--gray-5);
27
27
  color: var(--gray);
28
28
  }
@@ -30,7 +30,7 @@
30
30
  &__current-page {
31
31
  // 45px is a magic number to provide enough room for three digits
32
32
  // and the number spinners for type="number" inputs on desktop
33
- width: math.div(45px, $base-font-size-px) + rem;
33
+ width: rem-from-px(45px);
34
34
 
35
35
  font-weight: 500;
36
36
  text-align: right;
@@ -1,14 +1,12 @@
1
1
  import { html, LitElement, css, unsafeCSS, nothing } from 'lit';
2
2
  import { ref, createRef } from 'lit/directives/ref.js';
3
- import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
4
- import styles from './cfpb-select.component.scss?inline';
5
- import expandIcon from '../../components/cfpb-icons/icons/down.svg?raw';
6
- import collapseIcon from '../../components/cfpb-icons/icons/up.svg?raw';
3
+ import styles from './styles.component.scss?inline';
4
+ import { CfpbIcon } from '../cfpb-icon';
7
5
  import { CfpbFormSearchInput } from '../cfpb-form-search-input';
8
6
  import { SearchService } from '../cfpb-utilities/search-service.js';
9
7
  import { MaxHeightTransition } from '../../utilities/transition/max-height-transition';
10
8
  import { FlyoutMenu } from '../../utilities/behavior/flyout-menu';
11
- import { CfpbList } from '../cfpb-list';
9
+ import { CfpbListbox } from '../cfpb-listbox';
12
10
  import { CfpbTagGroup } from '../cfpb-tag-group';
13
11
 
14
12
  import { SingleSelectEventProxy } from './single-select-event-proxy.js';
@@ -312,11 +310,11 @@ export class CfpbSelect extends LitElement {
312
310
  @click=${this.#onClick}
313
311
  >
314
312
  <span class="o-select__cue-open" role="img" aria-label="Show">
315
- ${unsafeSVG(expandIcon)}
313
+ <cfpb-icon name="down"></cfpb-icon>
316
314
  <span class="u-visually-hidden">Show</span>
317
315
  </span>
318
316
  <span class="o-select__cue-close" role="img" aria-label="Hide">
319
- ${unsafeSVG(collapseIcon)}
317
+ <cfpb-icon name="up"></cfpb-icon>
320
318
  <span class="u-visually-hidden">Hide</span>
321
319
  </span>
322
320
  </button>
@@ -325,7 +323,7 @@ export class CfpbSelect extends LitElement {
325
323
  data-js-hook="behavior_flyout-menu_content"
326
324
  ${ref(this.#contentDom)}
327
325
  >
328
- <cfpb-list
326
+ <cfpb-listbox
329
327
  tabindex=${this.#noResults ? '-1' : '0'}
330
328
  @item-click=${this.#onItemClick}
331
329
  ?multiple=${this.multiple}
@@ -336,7 +334,7 @@ export class CfpbSelect extends LitElement {
336
334
  : 'Choose an item…'}
337
335
  ${ref(this.#list)}
338
336
  >
339
- </cfpb-list>
337
+ </cfpb-listbox>
340
338
  <div class=${this.#noResults ? 'no-results' : 'u-hidden'}>
341
339
  No results found
342
340
  </div>
@@ -371,8 +369,9 @@ export class CfpbSelect extends LitElement {
371
369
  }
372
370
 
373
371
  static init() {
372
+ CfpbIcon.init();
374
373
  CfpbFormSearchInput.init();
375
- CfpbList.init();
374
+ CfpbListbox.init();
376
375
  CfpbTagGroup.init();
377
376
 
378
377
  window.customElements.get('cfpb-select') ||
@@ -11,7 +11,7 @@ export class MultipleSelectEventProxy {
11
11
  }
12
12
 
13
13
  onBlur() {
14
- // In multiselect, blur happens when inside the list, so we ignore any
14
+ // In multiselect, blur happens when inside the listbox, so we ignore any
15
15
  // blur actions.
16
16
  }
17
17
 
@@ -72,7 +72,7 @@ export class MultipleSelectEventProxy {
72
72
  host.isExpanded = !host.isExpanded;
73
73
  break;
74
74
  }
75
- } else if (focused === 'CFPB-LIST-ITEM') {
75
+ } else if (focused === 'CFPB-LISTBOX-ITEM') {
76
76
  switch (evt.key) {
77
77
  case 'Tab':
78
78
  if (evt.shiftKey) {
@@ -42,7 +42,7 @@ export class SingleSelectEventProxy {
42
42
  case 'ArrowDown':
43
43
  evt.preventDefault();
44
44
  host.isExpanded = true;
45
- this.list.querySelector('cfpb-list-item')?.focus();
45
+ this.list.querySelector('cfpb-listbox-item')?.focus();
46
46
  break;
47
47
  }
48
48
  }
@@ -1,9 +1,8 @@
1
- @use 'sass:math';
2
- @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
3
1
  @use '@cfpb/cfpb-design-system/src/elements/base' as *;
4
2
  @use '@cfpb/cfpb-design-system/src/utilities' as *;
5
3
  @use '@cfpb/cfpb-design-system/src/components/cfpb-icons/icon';
6
- @use '../cfpb-utilities/transition/transition.scss' as *;
4
+ @use '../cfpb-utilities/transition/transition.css' as *;
5
+ @use '../../utilities/functions' as *;
7
6
 
8
7
  :host {
9
8
  // Theme
@@ -51,7 +50,7 @@
51
50
  button {
52
51
  // This line-height settings is larger than base.scss to
53
52
  // accommodate the SVG height.
54
- line-height: math.div(21px, $base-font-size-px);
53
+ line-height: unitless-from-px(21px);
55
54
 
56
55
  // Remove default focus ring.
57
56
  outline: none;
@@ -133,7 +132,7 @@
133
132
  justify-content: space-between;
134
133
  align-items: center;
135
134
  gap: 10px;
136
- padding-left: math.div(10px, $base-font-size-px) + em;
135
+ padding-left: rem-from-px(10px);
137
136
 
138
137
  cursor: pointer;
139
138
  }
@@ -151,7 +150,7 @@
151
150
  padding: 0;
152
151
 
153
152
  &::after {
154
- padding-bottom: math.div(15px, $base-font-size-px) + em;
153
+ padding-bottom: rem-from-px(15px);
155
154
  width: 100%;
156
155
  }
157
156
  }
@@ -1,7 +1,7 @@
1
1
  import { LitElement, html, css, unsafeCSS } from 'lit';
2
2
  import { unsafeHTML } from 'lit/directives/unsafe-html.js';
3
- import styles from './cfpb-tag-filter.component.scss?inline';
4
- import icon from '../../components/cfpb-icons/icons/error.svg?raw';
3
+ import styles from './styles.component.scss?inline';
4
+ import { errorIcon as icon } from '../../components/cfpb-icons/icons-lib';
5
5
 
6
6
  /**
7
7
  *
@@ -1,23 +1,21 @@
1
- @use 'sass:math';
2
- @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
3
- @use '@cfpb/cfpb-design-system/src/elements/cfpb-button/vars' as *;
1
+ @use '../../utilities/functions' as *;
4
2
 
5
3
  :host {
6
4
  button {
7
5
  // This line-height isn't 19 or 22, as 20 creates a 30px high tag.
8
- line-height: math.div(20px, $base-font-size-px);
6
+ line-height: unitless-from-px(20px);
9
7
 
10
8
  // Filter tags appear in filtered contexts, often as part of multiselects.
11
- font-size: math.div(16px, $btn-font-size) + rem;
9
+ font-size: rem-from-px(16px);
12
10
 
13
11
  display: flex;
14
- gap: math.div(10px, $btn-font-size) + rem;
12
+ gap: rem-from-px(10px);
15
13
  align-items: center;
16
14
 
17
15
  border: 1px solid var(--teal);
18
16
  padding: 4px 6px;
19
17
  background-color: var(--teal-20);
20
- border-radius: math.div(3px, $base-font-size-px) + rem;
18
+ border-radius: rem-from-px(3px);
21
19
  color: var(--black);
22
20
  text-align: left;
23
21
  min-width: fit-content;
@@ -43,7 +41,7 @@
43
41
  // Prevent flexbox from squishing icon when tag text is long.
44
42
  flex: none;
45
43
 
46
- height: math.div(19px, $btn-font-size) + rem;
44
+ height: rem-from-px(19px);
47
45
  }
48
46
 
49
47
  // If the contents are wrapped in a label, negate the label's display.
@@ -1,5 +1,5 @@
1
1
  import { LitElement, html, css, unsafeCSS } from 'lit';
2
- import styles from './cfpb-tag-group.component.scss?inline';
2
+ import styles from './styles.component.scss?inline';
3
3
  import { parseChildData } from '../cfpb-utilities/parse-child-data';
4
4
 
5
5
  const SUPPORTED_TAG_LIST = ['CFPB-TAG-FILTER', 'CFPB-TAG-TOPIC'];
@@ -1,6 +1,5 @@
1
- @use 'sass:math';
2
1
  @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
3
- @use '@cfpb/cfpb-design-system/src/elements/cfpb-button/vars' as *;
2
+ @use '../../utilities/functions' as *;
4
3
 
5
4
  :host {
6
5
  // Tag group sets the spacing between tags.
@@ -17,7 +16,7 @@
17
16
  // Tablet and above.
18
17
  @include respond-to-min($bp-sm-min) {
19
18
  display: flex;
20
- gap: math.div(15px, $btn-font-size) + rem;
19
+ gap: rem-from-px(15px);
21
20
  flex-wrap: wrap;
22
21
 
23
22
  &[stacked] {
@@ -28,7 +27,7 @@
28
27
 
29
28
  &:has(cfpb-tag-filter) {
30
29
  display: flex;
31
- gap: math.div(15px, $btn-font-size) + rem;
30
+ gap: rem-from-px(15px);
32
31
  flex-wrap: wrap;
33
32
  }
34
33
  }
@@ -1,5 +1,5 @@
1
1
  import { LitElement, html, css, unsafeCSS } from 'lit';
2
- import styles from './cfpb-tag-topic.component.scss?inline';
2
+ import styles from './styles.component.scss?inline';
3
3
 
4
4
  /**
5
5
  *
@@ -1,15 +1,15 @@
1
- @use 'sass:math';
2
1
  @use '@cfpb/cfpb-design-system/src/elements/base' as *;
3
2
  @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
4
3
  @use '@cfpb/cfpb-design-system/src/utilities' as *;
5
4
  @use '@cfpb/cfpb-design-system/src/components/cfpb-typography/mixins' as *;
5
+ @use '../../utilities/functions' as *;
6
6
 
7
7
  :host {
8
8
  // Topic tags
9
9
  .a-tag-topic {
10
10
  text-decoration: none;
11
11
  display: flex;
12
- gap: math.div(5px, $btn-font-size) + rem;
12
+ gap: rem-from-px(5px);
13
13
  }
14
14
 
15
15
  @include u-jump-link(
@@ -1,6 +1,6 @@
1
1
  import { LitElement, html, css, unsafeCSS } from 'lit';
2
2
  import { CfpbFlagUsa } from '../cfpb-flag-usa';
3
- import styles from './cfpb-tagline.component.scss?inline';
3
+ import styles from './styles.component.scss?inline';
4
4
 
5
5
  /**
6
6
  * @element cfpb-icon-text
@@ -0,0 +1,7 @@
1
+ cfpb-tagline:not(:defined) {
2
+ min-height: 16.5px;
3
+ }
4
+
5
+ cfpb-tagline[islarge]:not(:defined) {
6
+ min-height: 22px;
7
+ }
@@ -1,9 +1,8 @@
1
- @use 'sass:math';
2
- @use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
1
+ @use '../../utilities/functions' as *;
3
2
 
4
3
  :host {
5
4
  .a-tagline {
6
- font-size: math.div(12px, $base-font-size-px) + rem;
5
+ font-size: rem-from-px(12px);
7
6
 
8
7
  display: grid;
9
8
  grid-template-columns: 22px 1fr;
@@ -19,7 +18,7 @@
19
18
  }
20
19
 
21
20
  &--large {
22
- font-size: math.div(16px, $base-font-size-px) + rem;
21
+ font-size: rem-from-px(16px);
23
22
 
24
23
  & cfpb-flag-usa {
25
24
  margin-top: 4px;
@@ -0,0 +1,31 @@
1
+ /*
2
+ This fallback CSS assumes a web component that contains a <noscript> fallback,
3
+ as well as author-supplied content, and separately has a script to swap the
4
+ <noscript> with `<div class="fallback">` if JS is enabled, but the web component
5
+ definition is not defined.
6
+
7
+ Ex.
8
+
9
+ <cfpb-example-btn hasfallback>
10
+ <!-- author-supplied no-js fallback -->
11
+ <noscript><button>Click this basic button!</button>
12
+
13
+ <!-- author-supplied slotted content -->
14
+ Click this fancy button!
15
+ </cfpb-example-btn>
16
+ */
17
+
18
+ /* 1. If JS is disabled, hide everything except <noscript> */
19
+ [hasfallback] > :not(noscript) {
20
+ display: none;
21
+ }
22
+
23
+ /* 2. If JS is enabled, but web component definition is not defined, show fallback. */
24
+ [hasfallback] > .fallback {
25
+ display: block;
26
+ }
27
+
28
+ /* 3. If JS is enabled and web component definition is defined, operate as normal. */
29
+ [hasfallback]:defined > :not(noscript) {
30
+ display: block;
31
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * This utility IIFE function can be added to a page with web components
3
+ * to support the display of any fallback content in `<noscript>` tags
4
+ * that would otherwise not appear if JavaScript was enabled, but
5
+ * the Web Component APIs were not supported.
6
+ */
7
+ (function () {
8
+ /**
9
+ * Within a custom element (web component),
10
+ * convert any `<noscript>` tags into `<div class="fallback">`,
11
+ * so that the fallback content appears in environments where
12
+ * JavaScript is enabled, but web component APIs are not supported.
13
+ * @param {HTMLElement} el - A custom element.
14
+ */
15
+ function applyFallback(el) {
16
+ if (!el) return;
17
+
18
+ const tag = el.tagName.toLowerCase();
19
+ const isDefined = !!customElements.get(tag);
20
+ const noscript = el.querySelector('noscript');
21
+
22
+ // Only act if the element is NOT defined and there is a <noscript>
23
+ if (!isDefined && noscript) {
24
+ // Create a <div> with the fallback content.
25
+ const fallbackDiv = document.createElement('div');
26
+ fallbackDiv.className = 'fallback';
27
+ fallbackDiv.innerHTML = noscript.innerHTML;
28
+
29
+ // Insert fallback at the top.
30
+ el.insertBefore(fallbackDiv, el.firstChild);
31
+
32
+ // Hide the original <noscript> to avoid duplicates.
33
+ noscript.style.display = 'none';
34
+
35
+ /*
36
+ // Hide other non-fallback children (optional; wc-fallback.css handles this).
37
+ Array.from(el.children).forEach((child) => {
38
+ if (child !== fallbackDiv && child !== noscript) {
39
+ child.style.display = 'none';
40
+ }
41
+ });
42
+ */
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Query the document for custom elements that have the "fallback" attribute,
48
+ * e.g. <my-custom-btn fallback>
49
+ * @param {string} selector - The CSS selector to search for on the page.
50
+ */
51
+ function applyAllFallbacks(selector = '[fallback]') {
52
+ document.querySelectorAll(selector).forEach((el) => applyFallback(el));
53
+ }
54
+
55
+ // Check for browser support of the Web Component APIs.
56
+ const supportsWC =
57
+ 'customElements' in window &&
58
+ 'attachShadow' in Element.prototype &&
59
+ 'content' in document.createElement('template');
60
+
61
+ // Only run the fallback utility script globally if web components are NOT supported.
62
+ if (!supportsWC) {
63
+ document.addEventListener('DOMContentLoaded', applyAllFallbacks);
64
+ }
65
+ })();