| name | component-development |
| description | Create new Angular components in the oilmod-web library. USE WHEN generating components, writing Storybook stories, or adding exports. Trigger words: new component, create component, add component, storybook story, export component. |
Component Development — oilmod-web
When to Use
- Creating a new component in any
libs/ library
- Adding a Storybook story for an existing component
- Wiring up a component's public API export
Procedure
1. Generate the Component
nx generate @nx/angular:component my-component --project=<lib> --export
Replace <lib> with the target library (core, common, datatable, drawer, form, popover).
2. Implement with Signal-Based API
@Component({
selector: 'sto-my-component',
standalone: true,
imports: [
],
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class StoMyComponent {
readonly data = input.required<MyData>();
readonly config = input<MyConfig>({});
readonly action = output<MyEvent>();
readonly derived = computed(() => transform(this.data()));
}
3. Accessibility Checklist
All components MUST meet WCAG 2.1 AA:
- Add appropriate
role attributes via host
- Bind
aria-label, aria-disabled as needed
- Support keyboard navigation (
Enter, Space, Escape)
- Ensure sufficient color contrast in styles
@Component({
host: {
'role': 'button',
'[attr.aria-label]': 'ariaLabel()',
'[attr.aria-disabled]': 'disabled()',
'(keydown.enter)': 'handleKeydown($event)',
'(keydown.space)': 'handleKeydown($event)'
}
})
4. Create a Storybook Story
Follow the actual project pattern — const meta + export default meta + moduleMetadata:
import type { Meta, StoryObj } from '@storybook/angular';
import { moduleMetadata } from '@storybook/angular';
import { StoMyComponent } from './my-component.component';
const meta: Meta<StoMyComponent> = {
title: '<Lib>/MyComponent',
component: StoMyComponent,
decorators: [
moduleMetadata({
imports: [StoMyComponent],
}),
],
argTypes: {
data: { control: 'object', description: 'The data to display' },
},
args: {
data: {
},
},
};
export default meta;
type StoryType = StoryObj<StoMyComponent>;
export const Default: StoryType = {
render: (args) => ({
props: args,
template: `<sto-my-component [data]="data" />`,
}),
};
5. Export from Library
Add the component to the library's public API:
export * from './lib/my-component/my-component.component';
6. Write Tests
describe('StoMyComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [StoMyComponent],
}).compileComponents();
});
it('should create', () => {
const fixture = TestBed.createComponent(StoMyComponent);
expect(fixture.componentInstance).toBeTruthy();
});
});