Skip to content

Commit

Permalink
feat(radio): add component (#67)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kordrad authored Jul 11, 2024
1 parent eada555 commit 166d099
Show file tree
Hide file tree
Showing 9 changed files with 654 additions and 49 deletions.
535 changes: 486 additions & 49 deletions projects/cli/documentation.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions projects/cli/schematics/components/components-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface ComponentGeneratorSchema {
| 'button'
| 'checkbox'
| 'pin'
| 'radio'
| 'switch'
| 'tag'
)[];
Expand Down
10 changes: 10 additions & 0 deletions projects/cli/schematics/components/files/radio/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { NgModule } from '@angular/core';

import { ZenRadioComponent } from './radio.component';

@NgModule({
imports: [ZenRadioComponent],
exports: [ZenRadioComponent],
})
export class ZenRadioModule {}
export * from './radio.component';
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<input
[attr.aria-checked]="checked()"
[checked]="checked()"
[attr.aria-disabled]="zenDisabledDirective.disabledBoolean()"
[disabled]="zenDisabledDirective.disabledBoolean()"
[attr.id]="id()"
[attr.name]="name()"
type="radio"
/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
$radio-disabled-bg-color: lightgrey;

:host[aria-disabled='true'],
:host:has([aria-disabled='true']) {
&, & > * {
cursor: not-allowed;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ZenRadioComponent } from './radio.component';

describe('ZenRadioComponent', () => {
let component: ZenRadioComponent;
let fixture: ComponentFixture<ZenRadioComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ZenRadioComponent],
}).compileComponents();

fixture = TestBed.createComponent(ZenRadioComponent);
fixture.componentRef.setInput('name', 'name-value');
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
73 changes: 73 additions & 0 deletions projects/cli/schematics/components/files/radio/radio.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
ChangeDetectionStrategy,
Component,
forwardRef,
inject,
input,
model,
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import {
ZenDisabledDirective,
ZenHostDirective,
} from 'ng-zen/directives/disabled';

type OnChangeFn = (value: boolean) => void;
type OnTouchedFn = () => void;

@Component({
selector: 'zen-radio',
standalone: true,
templateUrl: './radio.component.html',
styleUrl: './radio.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ZenRadioComponent),
multi: true,
},
],
hostDirectives: [ZenHostDirective],
})
export class ZenRadioComponent implements ControlValueAccessor {
readonly name = input.required<string>();
readonly id = input<string | undefined>();

/** Model for the checked state of the checkbox. */
readonly checked = model<boolean>(false);

/** @ignore */
readonly zenDisabledDirective = inject(ZenDisabledDirective, { self: true });

private onChange: OnChangeFn = () => {};
private onTouched: OnTouchedFn = () => {};

/**
* Writes a new value to the component.
*/
writeValue(value: boolean): void {
this.checked.set(value);
}

/**
* Registers a function to be called when the value changes.
*/
registerOnChange(fn: OnChangeFn): void {
this.onChange = fn;
}

/**
* Registers a function to be called when the component is touched.
*/
registerOnTouched(fn: OnTouchedFn): void {
this.onTouched = fn;
}

/**
* Sets the disabled state of the component.
*/
setDisabledState(isDisabled: boolean): void {
this.zenDisabledDirective.disabled.set(isDisabled);
}
}
1 change: 1 addition & 0 deletions projects/cli/schematics/components/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"button",
"checkbox",
"pin",
"radio",
"switch",
"tag"
]
Expand Down
43 changes: 43 additions & 0 deletions projects/cli/stories/components/radio.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { Meta, StoryObj } from '@storybook/angular';
import { ZenRadioComponent } from 'ng-zen/components/radio';

export default {
title: 'Components/Radio',
component: ZenRadioComponent,
tags: ['autodocs'],
render: args => ({ props: { ...args } }),
} satisfies Meta<ZenRadioComponent>;

type Story = StoryObj<ZenRadioComponent>;

export const Default: Story = {
render: () => ({
template: `
<zen-radio name="group-1" />
<zen-radio name="group-1" [checked]="true" />
<zen-radio name="group-1" />
`,
}),
};

export const Disabled: Story = {
render: () => ({
template: `
<zen-radio disabled name="group-2"/>
<zen-radio disabled name="group-2"/>
<zen-radio disabled name="group-2"/>
`,
}),
};

export const Labeled: Story = {
render: () => ({
template: `
<div style="display: flex; flex-direction: column">
<label><zen-radio name="group-3"/> 1</label>
<label><zen-radio name="group-3"/> 2</label>
<label><zen-radio name="group-3"/> 3</label>
</div>
`,
}),
};

0 comments on commit 166d099

Please sign in to comment.