From c5355e0a05c88bac19915f82d06b23653b7007e7 Mon Sep 17 00:00:00 2001 From: xelaint Date: Mon, 10 Nov 2025 16:02:24 -0600 Subject: [PATCH 1/3] feat(design): update checkbox implementation --- .../src/app/checkbox/checkbox.component.html | 15 +- .../basic-checkbox.component.html | 9 +- .../basic-checkbox.component.ts | 29 +-- .../checkbox-set-orientations.component.html | 13 ++ .../checkbox-set-orientations.component.ts | 31 +++ .../checkbox-set-with-error.component.html | 7 + .../checkbox-set-with-error.component.ts | 31 +++ .../checkbox-set-with-hint.component.html | 7 + .../checkbox-set-with-hint.component.ts | 31 +++ .../checkbox-set/checkbox-set.component.html | 19 +- .../checkbox-set/checkbox-set.component.ts | 36 ++-- .../checkbox-with-error.component.html | 4 + .../checkbox-with-error.component.ts | 16 ++ .../checkbox-with-hint.component.html | 4 + .../checkbox-with-hint.component.ts | 16 ++ .../disabled-checkbox.component.html | 7 + .../disabled-checkbox.component.ts | 24 +++ libs/design-examples/checkbox/src/examples.ts | 14 ++ .../required-checkbox.component.html | 7 + .../required-checkbox.component.ts | 24 +++ .../checkbox-set/checkbox-set.component.html | 24 ++- .../checkbox-set/checkbox-set.component.scss | 30 +++ .../checkbox-set.component.spec.ts | 74 +++++--- .../checkbox-set/checkbox-set.component.ts | 105 ++++++++-- libs/design/checkbox/src/checkbox-theme.scss | 44 +++++ libs/design/checkbox/src/checkbox.ts | 9 + .../src/checkbox/checkbox.component.html | 51 +++-- .../src/checkbox/checkbox.component.scss | 42 ++++ .../src/checkbox/checkbox.component.spec.ts | 40 +++- .../src/checkbox/checkbox.component.ts | 179 +++++++++++++----- .../src/helpers/checkbox-set-token.ts | 3 + .../src/label/label.directive.spec.ts | 45 +++++ .../checkbox/src/label/label.directive.ts | 10 + libs/design/checkbox/src/public_api.ts | 1 + .../checkbox/src/specs/accessibility.spec.ts | 60 ------ .../src/specs/checkbox-disabled.spec.ts | 133 +++++++++++++ .../src/specs/checkbox-required.spec.ts | 134 +++++++++++++ .../src/specs/checkbox-with-set.spec.ts | 71 ------- .../checkbox/src/specs/without-cva.spec.ts | 54 ------ libs/design/scss/theme.scss | 2 + 40 files changed, 1083 insertions(+), 372 deletions(-) create mode 100644 libs/design-examples/checkbox/src/checkbox-set-orientations/checkbox-set-orientations.component.html create mode 100644 libs/design-examples/checkbox/src/checkbox-set-orientations/checkbox-set-orientations.component.ts create mode 100644 libs/design-examples/checkbox/src/checkbox-set-with-error/checkbox-set-with-error.component.html create mode 100644 libs/design-examples/checkbox/src/checkbox-set-with-error/checkbox-set-with-error.component.ts create mode 100644 libs/design-examples/checkbox/src/checkbox-set-with-hint/checkbox-set-with-hint.component.html create mode 100644 libs/design-examples/checkbox/src/checkbox-set-with-hint/checkbox-set-with-hint.component.ts create mode 100644 libs/design-examples/checkbox/src/checkbox-with-error/checkbox-with-error.component.html create mode 100644 libs/design-examples/checkbox/src/checkbox-with-error/checkbox-with-error.component.ts create mode 100644 libs/design-examples/checkbox/src/checkbox-with-hint/checkbox-with-hint.component.html create mode 100644 libs/design-examples/checkbox/src/checkbox-with-hint/checkbox-with-hint.component.ts create mode 100644 libs/design-examples/checkbox/src/disabled-checkbox/disabled-checkbox.component.html create mode 100644 libs/design-examples/checkbox/src/disabled-checkbox/disabled-checkbox.component.ts create mode 100644 libs/design-examples/checkbox/src/required-checkbox/required-checkbox.component.html create mode 100644 libs/design-examples/checkbox/src/required-checkbox/required-checkbox.component.ts create mode 100644 libs/design/checkbox/src/checkbox-set/checkbox-set.component.scss create mode 100644 libs/design/checkbox/src/checkbox-theme.scss create mode 100644 libs/design/checkbox/src/checkbox/checkbox.component.scss create mode 100644 libs/design/checkbox/src/helpers/checkbox-set-token.ts create mode 100644 libs/design/checkbox/src/label/label.directive.spec.ts create mode 100644 libs/design/checkbox/src/label/label.directive.ts delete mode 100644 libs/design/checkbox/src/specs/accessibility.spec.ts create mode 100644 libs/design/checkbox/src/specs/checkbox-disabled.spec.ts create mode 100644 libs/design/checkbox/src/specs/checkbox-required.spec.ts delete mode 100644 libs/design/checkbox/src/specs/checkbox-with-set.spec.ts delete mode 100644 libs/design/checkbox/src/specs/without-cva.spec.ts diff --git a/apps/design-land/src/app/checkbox/checkbox.component.html b/apps/design-land/src/app/checkbox/checkbox.component.html index 4430358e4b..8ccc18cb8e 100644 --- a/apps/design-land/src/app/checkbox/checkbox.component.html +++ b/apps/design-land/src/app/checkbox/checkbox.component.html @@ -1,8 +1,19 @@

Daff Checkbox

-

Basic Checkbox

-

Checkbox Set

+ + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/design-examples/checkbox/src/basic-checkbox/basic-checkbox.component.html b/libs/design-examples/checkbox/src/basic-checkbox/basic-checkbox.component.html index a024ff9301..afbb1eb376 100644 --- a/libs/design-examples/checkbox/src/basic-checkbox/basic-checkbox.component.html +++ b/libs/design-examples/checkbox/src/basic-checkbox/basic-checkbox.component.html @@ -1,6 +1,3 @@ -Checkbox -
- {{checkboxExample.value}} -
- - \ No newline at end of file + + Accept terms and conditions + \ No newline at end of file diff --git a/libs/design-examples/checkbox/src/basic-checkbox/basic-checkbox.component.ts b/libs/design-examples/checkbox/src/basic-checkbox/basic-checkbox.component.ts index 30d7da1d02..8f737824bb 100644 --- a/libs/design-examples/checkbox/src/basic-checkbox/basic-checkbox.component.ts +++ b/libs/design-examples/checkbox/src/basic-checkbox/basic-checkbox.component.ts @@ -1,39 +1,16 @@ import { ChangeDetectionStrategy, Component, - OnInit, } from '@angular/core'; -import { - UntypedFormControl, - ReactiveFormsModule, -} from '@angular/forms'; -import { DaffButtonComponent } from '@daffodil/design/button'; -import { DaffCheckboxModule } from '@daffodil/design/checkbox'; +import { DAFF_CHECKBOX_COMPONENTS } from '@daffodil/design/checkbox'; @Component({ selector: 'basic-checkbox-example', templateUrl: './basic-checkbox.component.html', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ - DaffCheckboxModule, - ReactiveFormsModule, - DaffButtonComponent, + DAFF_CHECKBOX_COMPONENTS, ], }) -export class BasicCheckboxExampleComponent implements OnInit { - checkboxExample = new UntypedFormControl(); - - /** - * @docs-private - */ - ngOnInit() { - this.checkboxExample.setValue(true); - } - setFalse() { - this.checkboxExample.setValue(false); - } - setTrue() { - this.checkboxExample.setValue(true); - } -} +export class BasicCheckboxExampleComponent {} diff --git a/libs/design-examples/checkbox/src/checkbox-set-orientations/checkbox-set-orientations.component.html b/libs/design-examples/checkbox/src/checkbox-set-orientations/checkbox-set-orientations.component.html new file mode 100644 index 0000000000..644db02cd7 --- /dev/null +++ b/libs/design-examples/checkbox/src/checkbox-set-orientations/checkbox-set-orientations.component.html @@ -0,0 +1,13 @@ + + Sizes + Extra small + Small + Medium + Large + + + \ No newline at end of file diff --git a/libs/design-examples/checkbox/src/checkbox-set-orientations/checkbox-set-orientations.component.ts b/libs/design-examples/checkbox/src/checkbox-set-orientations/checkbox-set-orientations.component.ts new file mode 100644 index 0000000000..886a77c9bf --- /dev/null +++ b/libs/design-examples/checkbox/src/checkbox-set-orientations/checkbox-set-orientations.component.ts @@ -0,0 +1,31 @@ +import { + ChangeDetectionStrategy, + Component, +} from '@angular/core'; +import { + ReactiveFormsModule, + UntypedFormControl, +} from '@angular/forms'; + +import { DaffButtonComponent } from '@daffodil/design/button'; +import { DAFF_CHECKBOX_COMPONENTS } from '@daffodil/design/checkbox'; + +@Component({ + selector: 'checkbox-set-orientations', + templateUrl: './checkbox-set-orientations.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + ReactiveFormsModule, + DaffButtonComponent, + DAFF_CHECKBOX_COMPONENTS, + ], +}) +export class CheckboxSetOrientationsExampleComponent { + orientationControl: UntypedFormControl = new UntypedFormControl(''); + + options = [ + { value: '', label: 'Default' }, + { value: 'vertical', label: 'Vertical' }, + { value: 'horizontal', label: 'Horizontal' }, + ]; +} diff --git a/libs/design-examples/checkbox/src/checkbox-set-with-error/checkbox-set-with-error.component.html b/libs/design-examples/checkbox/src/checkbox-set-with-error/checkbox-set-with-error.component.html new file mode 100644 index 0000000000..1221adc366 --- /dev/null +++ b/libs/design-examples/checkbox/src/checkbox-set-with-error/checkbox-set-with-error.component.html @@ -0,0 +1,7 @@ + + Choices + Choice 1 + Choice 2 + Choice 3 + Error message + \ No newline at end of file diff --git a/libs/design-examples/checkbox/src/checkbox-set-with-error/checkbox-set-with-error.component.ts b/libs/design-examples/checkbox/src/checkbox-set-with-error/checkbox-set-with-error.component.ts new file mode 100644 index 0000000000..7ba6180d34 --- /dev/null +++ b/libs/design-examples/checkbox/src/checkbox-set-with-error/checkbox-set-with-error.component.ts @@ -0,0 +1,31 @@ +import { + ChangeDetectionStrategy, + Component, +} from '@angular/core'; +import { + ReactiveFormsModule, + UntypedFormControl, + UntypedFormGroup, + Validators, +} from '@angular/forms'; + +import { DaffButtonComponent } from '@daffodil/design/button'; +import { DAFF_CHECKBOX_COMPONENTS } from '@daffodil/design/checkbox'; + +@Component({ + selector: 'checkbox-set-with-error', + templateUrl: './checkbox-set-with-error.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + ReactiveFormsModule, + DaffButtonComponent, + DAFF_CHECKBOX_COMPONENTS, + ], +}) +export class CheckboxSetWithErrorExampleComponent { + choices = new UntypedFormGroup({ + choiceOne: new UntypedFormControl('', Validators.required), + choiceTwo: new UntypedFormControl('', Validators.required), + choiceThree: new UntypedFormControl('', Validators.required), + }); +} diff --git a/libs/design-examples/checkbox/src/checkbox-set-with-hint/checkbox-set-with-hint.component.html b/libs/design-examples/checkbox/src/checkbox-set-with-hint/checkbox-set-with-hint.component.html new file mode 100644 index 0000000000..16f047c3eb --- /dev/null +++ b/libs/design-examples/checkbox/src/checkbox-set-with-hint/checkbox-set-with-hint.component.html @@ -0,0 +1,7 @@ + + Choices + Choice 1 + Choice 2 + Choice 3 + Choices hint + \ No newline at end of file diff --git a/libs/design-examples/checkbox/src/checkbox-set-with-hint/checkbox-set-with-hint.component.ts b/libs/design-examples/checkbox/src/checkbox-set-with-hint/checkbox-set-with-hint.component.ts new file mode 100644 index 0000000000..252e5147a9 --- /dev/null +++ b/libs/design-examples/checkbox/src/checkbox-set-with-hint/checkbox-set-with-hint.component.ts @@ -0,0 +1,31 @@ +import { + ChangeDetectionStrategy, + Component, +} from '@angular/core'; +import { + ReactiveFormsModule, + UntypedFormControl, + UntypedFormGroup, + Validators, +} from '@angular/forms'; + +import { DaffButtonComponent } from '@daffodil/design/button'; +import { DAFF_CHECKBOX_COMPONENTS } from '@daffodil/design/checkbox'; + +@Component({ + selector: 'checkbox-set-with-hint', + templateUrl: './checkbox-set-with-hint.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + ReactiveFormsModule, + DaffButtonComponent, + DAFF_CHECKBOX_COMPONENTS, + ], +}) +export class CheckboxSetWithHintExampleComponent { + choices = new UntypedFormGroup({ + choiceOne: new UntypedFormControl('', Validators.required), + choiceTwo: new UntypedFormControl('', Validators.required), + choiceThree: new UntypedFormControl('', Validators.required), + }); +} diff --git a/libs/design-examples/checkbox/src/checkbox-set/checkbox-set.component.html b/libs/design-examples/checkbox/src/checkbox-set/checkbox-set.component.html index a37ebd199d..6bf7495468 100644 --- a/libs/design-examples/checkbox/src/checkbox-set/checkbox-set.component.html +++ b/libs/design-examples/checkbox/src/checkbox-set/checkbox-set.component.html @@ -1,13 +1,6 @@ - - Option 1 - Option 2 - Option 3 - - -
- {{checkboxArray.value}} -
- -
- List of selected values: {{selectedValues}} -
\ No newline at end of file + + Choices + Choice 1 + Choice 2 + Choice 3 + \ No newline at end of file diff --git a/libs/design-examples/checkbox/src/checkbox-set/checkbox-set.component.ts b/libs/design-examples/checkbox/src/checkbox-set/checkbox-set.component.ts index 1f84c310e4..811b2cdaa1 100644 --- a/libs/design-examples/checkbox/src/checkbox-set/checkbox-set.component.ts +++ b/libs/design-examples/checkbox/src/checkbox-set/checkbox-set.component.ts @@ -1,45 +1,31 @@ import { ChangeDetectionStrategy, Component, - OnInit, - ViewChild, } from '@angular/core'; import { - UntypedFormArray, - UntypedFormControl, ReactiveFormsModule, + UntypedFormControl, + UntypedFormGroup, + Validators, } from '@angular/forms'; import { DaffButtonComponent } from '@daffodil/design/button'; -import { - DaffCheckboxSetComponent, - DaffCheckboxModule, -} from '@daffodil/design/checkbox'; +import { DAFF_CHECKBOX_COMPONENTS } from '@daffodil/design/checkbox'; @Component({ selector: 'checkbox-set-example', templateUrl: './checkbox-set.component.html', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ - DaffCheckboxModule, ReactiveFormsModule, DaffButtonComponent, + DAFF_CHECKBOX_COMPONENTS, ], }) -export class CheckboxSetExampleComponent implements OnInit { - - @ViewChild(DaffCheckboxSetComponent) - private checkboxSet: DaffCheckboxSetComponent; - checkboxArray = new UntypedFormArray([new UntypedFormControl(), new UntypedFormControl(), new UntypedFormControl()]); - selectedValues = []; - - /** - * @docs-private - */ - ngOnInit() { - this.checkboxArray.setValue([false, false, false]); - } - displayList() { - this.selectedValues = this.checkboxSet.getValues(); - } +export class CheckboxSetExampleComponent { + choices = new UntypedFormGroup({ + choiceOne: new UntypedFormControl('', Validators.required), + choiceTwo: new UntypedFormControl('', Validators.required), + choiceThree: new UntypedFormControl('', Validators.required), + }); } diff --git a/libs/design-examples/checkbox/src/checkbox-with-error/checkbox-with-error.component.html b/libs/design-examples/checkbox/src/checkbox-with-error/checkbox-with-error.component.html new file mode 100644 index 0000000000..7aeff66a3e --- /dev/null +++ b/libs/design-examples/checkbox/src/checkbox-with-error/checkbox-with-error.component.html @@ -0,0 +1,4 @@ + + Accept terms and conditions + Error + \ No newline at end of file diff --git a/libs/design-examples/checkbox/src/checkbox-with-error/checkbox-with-error.component.ts b/libs/design-examples/checkbox/src/checkbox-with-error/checkbox-with-error.component.ts new file mode 100644 index 0000000000..f2668c3c37 --- /dev/null +++ b/libs/design-examples/checkbox/src/checkbox-with-error/checkbox-with-error.component.ts @@ -0,0 +1,16 @@ +import { + ChangeDetectionStrategy, + Component, +} from '@angular/core'; + +import { DAFF_CHECKBOX_COMPONENTS } from '@daffodil/design/checkbox'; + +@Component({ + selector: 'checkbox-with-error', + templateUrl: './checkbox-with-error.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + DAFF_CHECKBOX_COMPONENTS, + ], +}) +export class CheckboxWithErrorExampleComponent {} diff --git a/libs/design-examples/checkbox/src/checkbox-with-hint/checkbox-with-hint.component.html b/libs/design-examples/checkbox/src/checkbox-with-hint/checkbox-with-hint.component.html new file mode 100644 index 0000000000..215eb9c821 --- /dev/null +++ b/libs/design-examples/checkbox/src/checkbox-with-hint/checkbox-with-hint.component.html @@ -0,0 +1,4 @@ + + Accept terms and conditions + Hint + \ No newline at end of file diff --git a/libs/design-examples/checkbox/src/checkbox-with-hint/checkbox-with-hint.component.ts b/libs/design-examples/checkbox/src/checkbox-with-hint/checkbox-with-hint.component.ts new file mode 100644 index 0000000000..e7a9cf9580 --- /dev/null +++ b/libs/design-examples/checkbox/src/checkbox-with-hint/checkbox-with-hint.component.ts @@ -0,0 +1,16 @@ +import { + ChangeDetectionStrategy, + Component, +} from '@angular/core'; + +import { DAFF_CHECKBOX_COMPONENTS } from '@daffodil/design/checkbox'; + +@Component({ + selector: 'checkbox-with-hint', + templateUrl: './checkbox-with-hint.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + DAFF_CHECKBOX_COMPONENTS, + ], +}) +export class CheckboxWithHintExampleComponent {} diff --git a/libs/design-examples/checkbox/src/disabled-checkbox/disabled-checkbox.component.html b/libs/design-examples/checkbox/src/disabled-checkbox/disabled-checkbox.component.html new file mode 100644 index 0000000000..14490629b1 --- /dev/null +++ b/libs/design-examples/checkbox/src/disabled-checkbox/disabled-checkbox.component.html @@ -0,0 +1,7 @@ + + Accept terms and conditions + + + + Accept terms and conditions + diff --git a/libs/design-examples/checkbox/src/disabled-checkbox/disabled-checkbox.component.ts b/libs/design-examples/checkbox/src/disabled-checkbox/disabled-checkbox.component.ts new file mode 100644 index 0000000000..0c132854ef --- /dev/null +++ b/libs/design-examples/checkbox/src/disabled-checkbox/disabled-checkbox.component.ts @@ -0,0 +1,24 @@ +import { + ChangeDetectionStrategy, + Component, +} from '@angular/core'; +import { + ReactiveFormsModule, + UntypedFormControl, + Validators, +} from '@angular/forms'; + +import { DAFF_CHECKBOX_COMPONENTS } from '@daffodil/design/checkbox'; + +@Component({ + selector: 'disabled-checkbox', + templateUrl: './disabled-checkbox.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + DAFF_CHECKBOX_COMPONENTS, + ReactiveFormsModule, + ], +}) +export class DisabledCheckboxExampleComponent { + terms = new UntypedFormControl(false, Validators.requiredTrue); +} diff --git a/libs/design-examples/checkbox/src/examples.ts b/libs/design-examples/checkbox/src/examples.ts index e6a344e0e7..c15d764cb2 100644 --- a/libs/design-examples/checkbox/src/examples.ts +++ b/libs/design-examples/checkbox/src/examples.ts @@ -1,7 +1,21 @@ import { BasicCheckboxExampleComponent } from './basic-checkbox/basic-checkbox.component'; import { CheckboxSetExampleComponent } from './checkbox-set/checkbox-set.component'; +import { CheckboxSetOrientationsExampleComponent } from './checkbox-set-orientations/checkbox-set-orientations.component'; +import { CheckboxSetWithErrorExampleComponent } from './checkbox-set-with-error/checkbox-set-with-error.component'; +import { CheckboxSetWithHintExampleComponent } from './checkbox-set-with-hint/checkbox-set-with-hint.component'; +import { CheckboxWithErrorExampleComponent } from './checkbox-with-error/checkbox-with-error.component'; +import { CheckboxWithHintExampleComponent } from './checkbox-with-hint/checkbox-with-hint.component'; +import { DisabledCheckboxExampleComponent } from './disabled-checkbox/disabled-checkbox.component'; +import { RequiredCheckboxExampleComponent } from './required-checkbox/required-checkbox.component'; export const CHECKBOX_EXAMPLES = [ CheckboxSetExampleComponent, BasicCheckboxExampleComponent, + CheckboxSetOrientationsExampleComponent, + DisabledCheckboxExampleComponent, + CheckboxSetWithHintExampleComponent, + CheckboxSetWithErrorExampleComponent, + RequiredCheckboxExampleComponent, + CheckboxWithHintExampleComponent, + CheckboxWithErrorExampleComponent, ]; diff --git a/libs/design-examples/checkbox/src/required-checkbox/required-checkbox.component.html b/libs/design-examples/checkbox/src/required-checkbox/required-checkbox.component.html new file mode 100644 index 0000000000..83049de3c1 --- /dev/null +++ b/libs/design-examples/checkbox/src/required-checkbox/required-checkbox.component.html @@ -0,0 +1,7 @@ + + Accept terms and conditions + + + + Accept terms and conditions + diff --git a/libs/design-examples/checkbox/src/required-checkbox/required-checkbox.component.ts b/libs/design-examples/checkbox/src/required-checkbox/required-checkbox.component.ts new file mode 100644 index 0000000000..7ca7c1d211 --- /dev/null +++ b/libs/design-examples/checkbox/src/required-checkbox/required-checkbox.component.ts @@ -0,0 +1,24 @@ +import { + ChangeDetectionStrategy, + Component, +} from '@angular/core'; +import { + UntypedFormControl, + ReactiveFormsModule, + Validators, +} from '@angular/forms'; + +import { DAFF_CHECKBOX_COMPONENTS } from '@daffodil/design/checkbox'; + +@Component({ + selector: 'required-checkbox', + templateUrl: './required-checkbox.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + DAFF_CHECKBOX_COMPONENTS, + ReactiveFormsModule, + ], +}) +export class RequiredCheckboxExampleComponent { + terms = new UntypedFormControl(false, Validators.requiredTrue); +} diff --git a/libs/design/checkbox/src/checkbox-set/checkbox-set.component.html b/libs/design/checkbox/src/checkbox-set/checkbox-set.component.html index 95a0b70bdc..c23e7b5ae3 100644 --- a/libs/design/checkbox/src/checkbox-set/checkbox-set.component.html +++ b/libs/design/checkbox/src/checkbox-set/checkbox-set.component.html @@ -1 +1,23 @@ - \ No newline at end of file +
+ + @if (required) { + + } +
+
+ +
+@if (hasHint()) { +
+ +
+} +@if (hasErrorMessage()) { +
+ +
+} \ No newline at end of file diff --git a/libs/design/checkbox/src/checkbox-set/checkbox-set.component.scss b/libs/design/checkbox/src/checkbox-set/checkbox-set.component.scss new file mode 100644 index 0000000000..21619a67d6 --- /dev/null +++ b/libs/design/checkbox/src/checkbox-set/checkbox-set.component.scss @@ -0,0 +1,30 @@ +.daff-checkbox-set { + $root: &; + display: flex; + flex-direction: column; + gap: 0.5rem; + + &__label { + font-weight: 500; + } + + &__wrapper { + display: flex; + } + + &.daff-vertical { + #{$root}__wrapper { + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + } + } + + &.daff-horizontal { + #{$root}__wrapper { + flex-direction: row; + flex-wrap: wrap; + gap: 0.5rem 1rem; + } + } +} diff --git a/libs/design/checkbox/src/checkbox-set/checkbox-set.component.spec.ts b/libs/design/checkbox/src/checkbox-set/checkbox-set.component.spec.ts index f2f82eed05..6d4e7418ba 100644 --- a/libs/design/checkbox/src/checkbox-set/checkbox-set.component.spec.ts +++ b/libs/design/checkbox/src/checkbox-set/checkbox-set.component.spec.ts @@ -1,7 +1,6 @@ import { Component, - ViewChild, - OnInit, + DebugElement, } from '@angular/core'; import { waitForAsync, @@ -11,7 +10,7 @@ import { import { UntypedFormControl, ReactiveFormsModule, - UntypedFormArray, + UntypedFormGroup, } from '@angular/forms'; import { By } from '@angular/platform-browser'; @@ -22,10 +21,12 @@ import { @Component({ template: ` - - Option 1 - Option 2 - Option 3 + + Choice 1 + Choice 2 + Choice 3 + Hint + Error `, imports: [ @@ -33,28 +34,18 @@ import { ReactiveFormsModule, ], }) -class WrapperComponent implements OnInit { - @ViewChild(DaffCheckboxSetComponent) - private checkboxSet: DaffCheckboxSetComponent; - checkboxArray = new UntypedFormArray([new UntypedFormControl(), new UntypedFormControl(), new UntypedFormControl()]); - - - selectedValues = []; - - /** - * @docs-private - */ - ngOnInit() { - this.checkboxArray.setValue([false, true, true]); - } - displayList() { - this.selectedValues = this.checkboxSet.getValues(); - } +class WrapperComponent { + example = new UntypedFormGroup({ + choiceOne: new UntypedFormControl(''), + choiceTwo: new UntypedFormControl(''), + choiceThree: new UntypedFormControl(''), + }); } -describe('@daffodil/design/checkbox | DaffCheckboxSetComponent', () => { +describe('@daffodil/design/checkbox | DaffCheckboxSetComponent | Defaults', () => { let component: DaffCheckboxSetComponent; let fixture: ComponentFixture; + let de: DebugElement; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ @@ -67,7 +58,8 @@ describe('@daffodil/design/checkbox | DaffCheckboxSetComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(WrapperComponent); - component = fixture.debugElement.query(By.css('daff-checkbox-set')).componentInstance; + de = fixture.debugElement.query(By.css('daff-checkbox-set')); + component = de.componentInstance; fixture.detectChanges(); }); @@ -75,11 +67,33 @@ describe('@daffodil/design/checkbox | DaffCheckboxSetComponent', () => { expect(component).toBeTruthy(); }); - it('should take a name as an input', () => { - expect(component.name).toBe('example'); + it('should add a class of "daff-checkbox-set" to the host element', () => { + expect(de.classes).toEqual(jasmine.objectContaining({ + 'daff-checkbox-set': true, + })); + }); + + it('should have a role of group', () => { + expect(de.nativeElement.getAttribute('role')).toBe('group'); + }); + + it('should have a generated id', () => { + expect(component.id).toMatch('daff-checkbox-set-[0-9]*'); + }); + + it('should set the aria-labelledby to the id', () => { + expect(de.nativeElement.getAttribute('aria-labelledby')).toEqual(component.id); }); - it('should return a list of selected values', () => { - expect(component.getValues()).toEqual(['option2', 'option3']); + it('should have a generated id for the hint', () => { + const hint = fixture.debugElement.query(By.css('.daff-checkbox-set__hint-wrapper')); + + expect(hint.nativeElement.id).toMatch('daff-checkbox-set-[0-9]*-hint'); + }); + + it('should have a generated id for the error message', () => { + const error = fixture.debugElement.query(By.css('.daff-checkbox-set__error-wrapper')); + + expect(error.nativeElement.id).toMatch('daff-checkbox-set-[0-9]*-error'); }); }); diff --git a/libs/design/checkbox/src/checkbox-set/checkbox-set.component.ts b/libs/design/checkbox/src/checkbox-set/checkbox-set.component.ts index c85e18065b..1852869a8c 100644 --- a/libs/design/checkbox/src/checkbox-set/checkbox-set.component.ts +++ b/libs/design/checkbox/src/checkbox-set/checkbox-set.component.ts @@ -1,48 +1,121 @@ import { Component, Input, - HostBinding, ChangeDetectionStrategy, ContentChildren, QueryList, - Output, - EventEmitter, + ContentChild, + ViewEncapsulation, + booleanAttribute, } from '@angular/core'; -import { UntypedFormArray } from '@angular/forms'; + +import { DaffOrientableDirective } from '@daffodil/design'; +import { + DaffErrorMessageComponent, + DaffHintComponent, +} from '@daffodil/design/form-field'; import { DaffCheckboxComponent } from '../checkbox/checkbox.component'; +import { DAFF_CHECKBOX_SET } from '../helpers/checkbox-set-token'; + +let uniqueCheckboxSetId = 0; @Component({ selector: 'daff-checkbox-set', templateUrl: './checkbox-set.component.html', + styleUrl: './checkbox-set.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None, + host: { + class: 'daff-checkbox-set', + role: 'group', + '[attr.aria-labelledby]': 'id', + }, + hostDirectives: [ + { + directive: DaffOrientableDirective, + inputs: ['orientation'], + }, + ], + providers: [ + { + provide: DAFF_CHECKBOX_SET, + useExisting: DaffCheckboxSetComponent, + }, + ], }) export class DaffCheckboxSetComponent { - @Input() formArray: UntypedFormArray; + constructor( + private orientation: DaffOrientableDirective, + ) { + this.orientation.defaultOrientation = 'vertical'; + } + /** - * The name of the checkbox-set + * @docs-private + * + * The list of checkboxes in the set. */ - @Input() name: string; + @ContentChildren(DaffCheckboxComponent) checkboxes: QueryList; /** - * The role of the component. Set to "checkbox". + * The unique id of the checkbox set. Defaults to an autogenerated value. When using this, + * it's your responsibility to ensure that the id for each checkbox set is unique. * + * It gets assigned to the `for` attribute on the `