Rules for Angular components in packages/workbench. They describe the target
for new and touched code; existing components don’t all follow them yet
(OnPush, input()/output(), separate template files). Don’t refactor
untouched components just to comply.
Stencil components in packages/shared-components follow
their own conventions.
input()/output(), OnPush, separate template files, reactive forms.class/style bindings, signals over the async pipe, data-test.We use PrimeNG as our component library. Reach for a PrimeNG component before hand-rolling one. Don’t reinvent a control PrimeNG already provides — a bespoke version is more code to own, drifts from the app’s look and behaviour, and usually misses accessibility and keyboard support the library already ships.
Select / MultiSelect
(dropdowns and facets), InputText + IconField/InputIcon (text and search
fields), Button, Menu (kebab menus), Tag (badges), Card, Skeleton,
Toast/Message, Splitter, Tooltip, Dialog/DynamicDialog,
and so on. Native <select>, <input>, ad-hoc skeleton <div>s and custom
buttons are not the house style where a PrimeNG equivalent exists.--gw-* design tokens) and component style hooks rather than rebuilding the
component to change how it looks. See styling.DialogProviderService is one: open dialogs through it, not through
PrimeNG’s DialogService (see frontend-angular).input() and output() functions, not the @Input() / @Output()
decorators.computed() for derived state.changeDetection: ChangeDetectionStrategy.OnPush..ts file
(templateUrl / styleUrl). Don’t use inline templates or styles.@if, @for, @switch) — never *ngIf, *ngFor,
*ngSwitch.class bindings, not ngClass.style bindings, not ngStyle.computed(). If an observable is
unavoidable (some Angular/3rd-party APIs), convert it with toSignal() at the
edge rather than reaching for the async pipe.new Date()) are available in templates.data-test attribute (kebab-case, prefixed
with the component or page). Both the unit and the E2E specs select by it — see
e2e-testing.computed()
(isEditable, hasReadAccess, limitDisabled) and bind to them. A template doesn’t compare values
(linksLimit > 999) or apply defaults.<button> for actions, <a> only for navigation, h1–h6 for headings, not styled
divs. No Bootstrap classes in the workbench.