diff --git a/packages/web-components/src/components/va-checkbox-group/test/va-checkbox-group.e2e.ts b/packages/web-components/src/components/va-checkbox-group/test/va-checkbox-group.e2e.ts index 3b6d99835..1096ee58f 100644 --- a/packages/web-components/src/components/va-checkbox-group/test/va-checkbox-group.e2e.ts +++ b/packages/web-components/src/components/va-checkbox-group/test/va-checkbox-group.e2e.ts @@ -86,7 +86,7 @@ describe('va-checkbox-group', () => { `); const analyticsSpy = await page.spyOnEvent('component-library-analytics'); - const checkboxEl = await page.find('va-checkbox >>> .usa-checkbox__label'); + const checkboxEl = await page.find('va-checkbox >>> .va-checkbox__label'); await checkboxEl.click(); expect(analyticsSpy).toHaveReceivedEventDetail({ @@ -109,7 +109,7 @@ describe('va-checkbox-group', () => { `); const analyticsSpy = await page.spyOnEvent('component-library-analytics'); - const inputEl = await page.find('va-checkbox >>> .usa-checkbox__label'); + const inputEl = await page.find('va-checkbox >>> .va-checkbox__label'); await inputEl.click(); expect(analyticsSpy).not.toHaveReceivedEvent(); }); diff --git a/packages/web-components/src/components/va-checkbox/test/va-checkbox.e2e.ts b/packages/web-components/src/components/va-checkbox/test/va-checkbox.e2e.ts index ae0c28ca1..26f21cee2 100644 --- a/packages/web-components/src/components/va-checkbox/test/va-checkbox.e2e.ts +++ b/packages/web-components/src/components/va-checkbox/test/va-checkbox.e2e.ts @@ -22,12 +22,10 @@ describe('va-checkbox', () => { it('has tile class added', async () => { const page = await newE2EPage(); - await page.setContent( - '', - ); + await page.setContent(''); - const input = await page.find('va-checkbox >>> .usa-checkbox__input'); - expect(input).toHaveClass("usa-checkbox__input--tile"); + const input = await page.find('va-checkbox >>> .va-checkbox__container'); + expect(input).toHaveClass('va-checkbox__container--tile'); }); it('renders with aria-invalid set to false by default', async () => { @@ -53,7 +51,9 @@ describe('va-checkbox', () => { const element = await page.find('va-checkbox >>> #checkbox-error-message'); const input = await page.find('va-checkbox >>> input'); expect(input.getAttribute('aria-invalid')).toEqual('true'); - expect(input.getAttribute('aria-describedby')).toEqual('checkbox-error-message'); + expect(input.getAttribute('aria-describedby')).toEqual( + 'checkbox-error-message', + ); expect(element.textContent).toContain('Something went horribly wrong'); }); @@ -95,7 +95,7 @@ describe('va-checkbox', () => { const inputEl = await page.find('va-checkbox >>> input'); const descriptionDiv = await page.find('va-checkbox >>> div#description'); expect(element).toEqualText('This is a description!'); - expect(descriptionDiv).not.toBeNull();; + expect(descriptionDiv).not.toBeNull(); // should still add the description aria-describedby with one empty slot expect(inputEl.getAttribute('aria-describedby')).toEqual('description'); }); @@ -133,7 +133,9 @@ describe('va-checkbox', () => { await page.setContent(''); const inputEl = await page.find('va-checkbox >>> input'); - expect(inputEl.getAttribute('aria-describedby')).toContain('checkbox-error-message'); + expect(inputEl.getAttribute('aria-describedby')).toContain( + 'checkbox-error-message', + ); }); it('passes an aXe check', async () => { @@ -156,7 +158,9 @@ describe('va-checkbox', () => { // Render the error message text const inputEl = await page.find('va-checkbox >>> input'); - expect(inputEl.getAttribute('aria-describedby')).toEqual('input-message checkbox-error-message description'); + expect(inputEl.getAttribute('aria-describedby')).toEqual( + 'input-message checkbox-error-message description', + ); }); it('fires an analytics event when enableAnalytics is true', async () => { @@ -165,7 +169,7 @@ describe('va-checkbox', () => { '', ); const analyticsSpy = await page.spyOnEvent('component-library-analytics'); - const checkboxEl = await page.find('va-checkbox >>> .usa-checkbox__label'); + const checkboxEl = await page.find('va-checkbox >>> .va-checkbox__label'); await checkboxEl.click(); expect(analyticsSpy).toHaveReceivedEventDetail({ @@ -189,7 +193,7 @@ describe('va-checkbox', () => { >> .usa-checkbox__label'); + const checkboxEl = await page.find('va-checkbox >>> .va-checkbox__label'); await checkboxEl.click(); expect(analyticsSpy).toHaveReceivedEventDetail({ @@ -211,7 +215,7 @@ describe('va-checkbox', () => { '', ); const analyticsSpy = await page.spyOnEvent('component-library-analytics'); - const checkboxEl = await page.find('va-checkbox >>> .usa-checkbox__label'); + const checkboxEl = await page.find('va-checkbox >>> .va-checkbox__label'); await checkboxEl.click(); expect(analyticsSpy).not.toHaveReceivedEvent(); @@ -223,7 +227,7 @@ describe('va-checkbox', () => { '', ); const changeSpy = await page.spyOnEvent('vaChange'); - const checkboxEl = await page.find('va-checkbox >>> .usa-checkbox__label'); + const checkboxEl = await page.find('va-checkbox >>> .va-checkbox__label'); await checkboxEl.click(); expect(changeSpy).toHaveReceivedEventDetail({ checked: true }); @@ -235,7 +239,7 @@ describe('va-checkbox', () => { '', ); const blurSpy = await page.spyOnEvent('blur'); - const checkboxEl = await page.find('va-checkbox >>> .usa-checkbox__label'); + const checkboxEl = await page.find('va-checkbox >>> .va-checkbox__label'); await checkboxEl.click(); // Focus on the element await checkboxEl.press('Tab'); // Blur the element @@ -250,7 +254,9 @@ describe('va-checkbox', () => { const checkboxEl = await page.find('va-checkbox >>> input'); expect(await checkboxEl.getProperty('checked')).toBeTruthy(); - const checkboxLabelEl = await page.find('va-checkbox >>> .usa-checkbox__label'); + const checkboxLabelEl = await page.find( + 'va-checkbox >>> .va-checkbox__label', + ); await checkboxLabelEl.click(); expect(await checkboxEl.getProperty('checked')).toBeFalsy(); @@ -272,7 +278,7 @@ describe('va-checkbox', () => { await page.setContent( '', ); - const checkboxEl = await page.find('va-checkbox >>> label'); + const checkboxEl = await page.find('va-checkbox >>> input'); expect(checkboxEl).toEqualAttribute('aria-checked', 'mixed'); }); diff --git a/packages/web-components/src/components/va-checkbox/va-checkbox.scss b/packages/web-components/src/components/va-checkbox/va-checkbox.scss index cc02df250..2d5ed63eb 100644 --- a/packages/web-components/src/components/va-checkbox/va-checkbox.scss +++ b/packages/web-components/src/components/va-checkbox/va-checkbox.scss @@ -8,6 +8,7 @@ @use 'usa-hint/src/styles/usa-hint'; @use 'usa-error-message/src/styles/usa-error-message'; +@import '../../mixins/focusable.css'; @import '../../mixins/uswds-error-border.scss'; :host { @@ -15,11 +16,57 @@ max-width: 480px; } -.usa-checkbox { +.va-checkbox__container { background: transparent; + display: flex; + margin: 0.5rem 0; } -.usa-checkbox__input:focus + [class*='__label']::before { - outline: 2px solid var(--vads-color-action-focus-on-light); - outline-offset: 4px; +.va-checkbox__container--tile { + border-radius: 0.25rem; + background-color: white; + border: 2px solid #c9c9c9; + color: #1b1b1b; + padding: 0.75rem 0 0.75rem 0.5rem; +} + +.va-checkbox__input { + height: 20px; + width: 20px; + min-width: 20px; + background: white; + border: 2px solid #1b1b1b; + border-radius: 2px; + appearance: none; + -webkit-appearance: none; + margin: 0.064rem 0.5rem 0 0; + opacity: unset; + position: initial; + + &:checked { + background: #005ea2; + background-image: url("data:image/svg+xml,%3C%3Fxml version%3D%221.0%22 encoding%3D%22UTF-8%22%3F%3E%3Csvg xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22 width%3D%2265%22 height%3D%2250%22 viewBox%3D%220 0 65 50%22%3E%3Ctitle%3Ecorrect8%3C%2Ftitle%3E%3Cpath fill%3D%22%23FFF%22 fill-rule%3D%22evenodd%22 d%3D%22M63.268 7.063l-5.616-5.61C56.882.685 55.946.3 54.845.3s-2.038.385-2.808 1.155L24.951 28.552 12.81 16.385c-.77-.77-1.707-1.155-2.808-1.155-1.1 0-2.037.385-2.807 1.154l-5.616 5.61C.81 22.764.425 23.7.425 24.8s.385 2.035 1.155 2.805l14.947 14.93 5.616 5.61c.77.77 1.706 1.154 2.807 1.154s2.038-.384 2.808-1.154l5.616-5.61 29.894-29.86c.77-.77 1.157-1.707 1.157-2.805 0-1.101-.385-2.036-1.156-2.805l-.001-.002z%22%2F%3E%3C%2Fsvg%3E"), linear-gradient(transparent, transparent); + background-position: center center; + background-size: 0.75rem auto; + background-repeat: no-repeat; + border: none; + } + + &[data-indeterminate]:not([data-indeterminate=false]) { + background: #005ea2; + background-image: url("data:image/svg+xml,%3C%3Fxml version%3D%221.0%22 encoding%3D%22utf-8%22%3F%3E%3C!-- Generator%3A Adobe Illustrator 26.3.1%2C SVG Export Plug-In . SVG Version%3A 6.00 Build 0) --%3E%3Csvg version%3D%221.1%22 id%3D%22Layer_1%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22 xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22 x%3D%220px%22 y%3D%220px%22%09 viewBox%3D%220 0 64 64%22 style%3D%22enable-background%3Anew 0 0 64 64%3B%22 xml%3Aspace%3D%22preserve%22%3E%3Cstyle type%3D%22text%2Fcss%22%3E%09.st0%7Bfill-rule%3Aevenodd%3Bclip-rule%3Aevenodd%3Bfill%3A%23FFFFFF%3B%7D%3C%2Fstyle%3E%3Cpath class%3D%22st0%22 d%3D%22M2.9%2C35.9c0%2C1.1%2C0.4%2C2%2C1.2%2C2.8c0.8%2C0.8%2C1.7%2C1.2%2C2.8%2C1.2h7.9h42.3c1.1%2C0%2C2-0.4%2C2.8-1.2s1.2-1.7%2C1.2-2.8l0%2C0V28%09c0-1.1-0.4-2-1.2-2.8S58.2%2C24%2C57.1%2C24H6.9c-1.1%2C0-2%2C0.4-2.8%2C1.2S2.9%2C26.9%2C2.9%2C28V35.9z%22%2F%3E%3C%2Fsvg%3E"), linear-gradient(transparent, transparent); + background-position: center center; + background-size: 0.75rem auto; + background-repeat: no-repeat; + border: none; + } +} + +.va-checkbox__label { + margin: 0; + max-width: 480px; + padding-left: 0; + box-sizing: border-box; + font-size: 1.06rem; + line-height: 1.3; } \ No newline at end of file diff --git a/packages/web-components/src/components/va-checkbox/va-checkbox.tsx b/packages/web-components/src/components/va-checkbox/va-checkbox.tsx index 68ab744ad..cbf9a3dfd 100644 --- a/packages/web-components/src/components/va-checkbox/va-checkbox.tsx +++ b/packages/web-components/src/components/va-checkbox/va-checkbox.tsx @@ -209,21 +209,23 @@ export class VaCheckbox { !description && this.el.querySelectorAll('[slot="description"]:not(:empty)').length > 0; - const inputClass = classnames({ - 'usa-checkbox__input': true, - 'usa-checkbox__input--tile': tile, + const containerClass = classnames('va-checkbox__container', { + 'va-checkbox__container--tile': tile, }); const descriptionClass = classnames({ 'usa-legend': true, - 'usa-label--error': error + 'usa-label--error': error, }); - const ariaDescribedbyIds = [ - messageAriaDescribedby ? 'input-message' : '', - error ? 'checkbox-error-message' : '', - description || hasDescriptionSlot ? 'description' : '', - // Return null so we don't add the attribute if we have an empty string - ].filter(Boolean).join(' ').trim() || null; - const ariaChecked = checked ? 'true' : 'false'; + const ariaDescribedbyIds = + [ + messageAriaDescribedby ? 'input-message' : '', + error ? 'checkbox-error-message' : '', + description || hasDescriptionSlot ? 'description' : '', + ] + .filter(Boolean) + .join(' ') + // Return null so we don't add the attribute if we have an empty string + .trim() || null; return ( @@ -247,9 +249,9 @@ export class VaCheckbox { )} -
+