@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.
- package/CHANGELOG.md +166 -1
- package/dist/components/cfpb-expandables/index.js +1 -1
- package/dist/components/cfpb-expandables/index.js.map +3 -3
- package/dist/components/cfpb-forms/index.js +1 -1
- package/dist/components/cfpb-forms/index.js.map +2 -2
- package/dist/elements/cfpb-button/index.js +4 -4
- package/dist/elements/cfpb-button/index.js.map +3 -3
- package/dist/elements/cfpb-checkbox-icon/index.js +29 -0
- package/dist/elements/{cfpb-checkbox → cfpb-checkbox-icon}/index.js.map +4 -4
- package/dist/elements/cfpb-expandable/index.css +2 -0
- package/dist/elements/cfpb-expandable/index.css.map +7 -0
- package/dist/elements/cfpb-expandable/index.js +33 -0
- package/dist/elements/cfpb-expandable/index.js.map +7 -0
- package/dist/elements/cfpb-file-upload/index.js +4 -4
- package/dist/elements/cfpb-file-upload/index.js.map +3 -3
- package/dist/elements/cfpb-form-alert/index.js +32 -0
- package/dist/elements/cfpb-form-alert/index.js.map +7 -0
- package/dist/elements/cfpb-form-choice/index.js +12 -3
- package/dist/elements/cfpb-form-choice/index.js.map +4 -4
- package/dist/elements/cfpb-form-search/index.js +41 -0
- package/dist/elements/cfpb-form-search/index.js.map +7 -0
- package/dist/elements/cfpb-form-search-input/index.js +41 -0
- package/dist/elements/cfpb-form-search-input/index.js.map +7 -0
- package/dist/elements/cfpb-icon-text/index.js +3 -3
- package/dist/elements/cfpb-icon-text/index.js.map +3 -3
- package/dist/elements/cfpb-label/index.js +3 -3
- package/dist/elements/cfpb-label/index.js.map +2 -2
- package/dist/elements/cfpb-list/index.js +39 -0
- package/dist/elements/cfpb-list/index.js.map +7 -0
- package/dist/elements/cfpb-list-item/index.js +39 -0
- package/dist/elements/cfpb-list-item/index.js.map +7 -0
- package/dist/elements/cfpb-multiselect/index.js +13 -4
- package/dist/elements/cfpb-multiselect/index.js.map +4 -4
- package/dist/elements/cfpb-pagination/index.js +3 -3
- package/dist/elements/cfpb-pagination/index.js.map +2 -2
- package/dist/elements/cfpb-select/index.css +2 -0
- package/dist/elements/cfpb-select/index.css.map +7 -0
- package/dist/elements/cfpb-select/index.js +42 -0
- package/dist/elements/cfpb-select/index.js.map +7 -0
- package/dist/elements/cfpb-select-list/index.js +39 -0
- package/dist/elements/cfpb-select-list/index.js.map +7 -0
- package/dist/elements/cfpb-tag-filter/index.js +3 -3
- package/dist/elements/cfpb-tag-filter/index.js.map +3 -3
- package/dist/elements/cfpb-tag-group/index.js +3 -3
- package/dist/elements/cfpb-tag-group/index.js.map +4 -4
- package/dist/elements/cfpb-tag-topic/index.js +4 -4
- package/dist/elements/cfpb-tag-topic/index.js.map +1 -1
- package/dist/elements/index.css +2 -0
- package/dist/elements/index.css.map +7 -0
- package/dist/elements/index.js +7 -6
- package/dist/elements/index.js.map +4 -4
- package/dist/index.js +7 -6
- package/dist/index.js.map +4 -4
- package/dist/utilities/index.js +1 -1
- package/dist/utilities/index.js.map +3 -3
- package/package.json +1 -1
- package/src/components/cfpb-expandables/expandable.js +3 -0
- package/src/components/cfpb-forms/multiselect.js +1 -1
- package/src/elements/abstracts/custom-props.css +123 -0
- package/src/elements/abstracts/grid-mixins.scss +83 -0
- package/src/elements/abstracts/heading-mixins.scss +346 -0
- package/src/elements/abstracts/index.scss +7 -0
- package/src/elements/abstracts/media-queries.scss +35 -0
- package/src/elements/abstracts/sizing-vars.scss +65 -0
- package/src/elements/abstracts/vars-breakpoints.scss +16 -0
- package/src/elements/abstracts/vars.css +79 -0
- package/src/elements/base/base.scss +375 -0
- package/src/elements/base/font.scss +27 -0
- package/src/elements/base/index.scss +3 -0
- package/src/elements/base/normalize.scss +290 -0
- package/src/elements/cfpb-button/cfpb-button-group.scss +10 -0
- package/src/elements/cfpb-button/cfpb-button-link.scss +96 -0
- package/src/elements/cfpb-button/cfpb-button.component.scss +11 -4
- package/src/elements/cfpb-button/cfpb-button.scss +222 -0
- package/src/elements/cfpb-button/index.js +28 -29
- package/src/elements/cfpb-button/vars.css +30 -0
- package/src/elements/cfpb-checkbox-icon/cfpb-checkbox-icon.component.scss +88 -0
- package/src/elements/cfpb-checkbox-icon/index.js +104 -0
- package/src/elements/cfpb-expandable/cfpb-expandable.component.scss +218 -0
- package/src/elements/cfpb-expandable/index.js +127 -0
- package/src/elements/cfpb-file-upload/cfpb-file-upload.component.scss +2 -2
- package/src/elements/cfpb-file-upload/index.js +16 -18
- package/src/elements/cfpb-form-alert/cfpb-form-alert.component.scss +36 -0
- package/src/elements/cfpb-form-alert/index.js +55 -0
- package/src/elements/cfpb-form-choice/cfpb-form-choice.component.scss +42 -81
- package/src/elements/cfpb-form-choice/index.js +58 -18
- package/src/elements/cfpb-form-search/cfpb-form-search.component.scss +54 -0
- package/src/elements/cfpb-form-search/index.js +194 -0
- package/src/elements/cfpb-form-search-input/cfpb-form-search-input.component.scss +217 -0
- package/src/elements/cfpb-form-search-input/index.js +136 -0
- package/src/elements/cfpb-icon-text/cfpb-icon-text.component.scss +32 -39
- package/src/elements/cfpb-icon-text/index.js +32 -104
- package/src/elements/cfpb-label/cfpb-label.component.scss +2 -2
- package/src/elements/cfpb-label/index.js +6 -9
- package/src/elements/cfpb-list/cfpb-list.component.scss +23 -0
- package/src/elements/cfpb-list/index.js +357 -0
- package/src/elements/cfpb-list/index.spec.js +169 -0
- package/src/elements/cfpb-list-item/cfpb-list-item.component.scss +69 -0
- package/src/elements/cfpb-list-item/index.js +215 -0
- package/src/elements/cfpb-pagination/cfpb-pagination.component.scss +2 -7
- package/src/elements/cfpb-pagination/index.js +6 -8
- package/src/elements/cfpb-select/cfpb-select.component.scss +241 -0
- package/src/elements/cfpb-select/index.js +381 -0
- package/src/elements/cfpb-tag-filter/cfpb-tag-filter.component.scss +6 -3
- package/src/elements/cfpb-tag-filter/index.js +15 -7
- package/src/elements/cfpb-tag-group/cfpb-tag-group.component.scss +2 -2
- package/src/elements/cfpb-tag-group/index.js +53 -6
- package/src/elements/cfpb-tag-topic/index.js +5 -7
- package/src/elements/cfpb-utilities/parse-child-data.js +50 -0
- package/src/elements/cfpb-utilities/parse-child-data.spec.js +56 -0
- package/src/elements/cfpb-utilities/search-service.js +46 -0
- package/src/elements/cfpb-utilities/search-service.spec.js +138 -0
- package/src/elements/cfpb-utilities/transition/transition.scss +98 -0
- package/src/elements/index.js +7 -1
- package/src/index.scss +11 -0
- package/src/tokens/abstracts/custom-props.json +1642 -0
- package/src/tokens/abstracts/vars.json +1319 -0
- package/src/tokens/cfpb-button/vars.json +436 -0
- package/src/utilities/transition/max-height-transition.js +74 -0
- package/dist/elements/cfpb-checkbox/index.js +0 -29
- package/src/elements/cfpb-multiselect/cfpb-multiselect.component.scss +0 -225
- package/src/elements/cfpb-multiselect/index.js +0 -444
- package/src/elements/cfpb-multiselect/multiselect-model.js +0 -288
- 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/
|
|
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
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
85
|
-
@input
|
|
86
|
-
@cancel
|
|
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
|
-
|
|
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
|
-
&--
|
|
131
|
-
|
|
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
|
|
142
|
-
|
|
143
|
-
|
|
91
|
+
border-color: var(--choice-border);
|
|
92
|
+
outline: none;
|
|
93
|
+
box-shadow: none; // Applies only to radio buttons.
|
|
144
94
|
}
|
|
145
95
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
233
|
-
box-shadow: inset 0 0 0 1px
|
|
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
|
|
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:
|
|
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
|
}
|