Skip to main content

Adding a Widget to upp-wdgt

This guide describes how to add a new reusable component to the upp-wdgt library.

Process Overview

Step 1 — Create the Component Files

Create a folder under libs/upp-wdgt/src/components/ with the naming convention upp-<name>/:

libs/upp-wdgt/src/components/upp-<name>/
├── upp-<name>.ts ← Component class(es)
├── upp-<name>.html ← Template
└── upp-<name>.scss ← Styles

Component class template

import { Component } from '@angular/core';
import { Input } from '@angular/core';

@Component({
selector: 'upp-<name>',
templateUrl: './upp-<name>.html',
styleUrls: ['./upp-<name>.scss'],
})
export class Upp<Name>Component {
@Input() title: string | null = null;
}

Follow existing conventions:

  • Use selector: 'upp-<name>' with the upp- prefix.
  • Reference the template and styles using relative paths.
  • If the component uses sub-components (e.g. upp-<name>-header), define them in the same .ts file and export them individually.

Step 2 — Declare in the Module

Open libs/upp-wdgt/src/lib/upp-wdgt.module.ts and:

  1. Import the component:
import { Upp<Name>Component } from '../components/upp-<name>/upp-<name>';
  1. Add to declarations:
declarations: [
// ... existing components
Upp<Name>Component,
],
  1. Add to exports (if the component should be publicly usable):
exports: [
// ... existing exports
Upp<Name>Component,
],

Step 3 — Export from index.ts

Add a re-export line to libs/upp-wdgt/src/index.ts:

export * from './components/upp-<name>/upp-<name>';

This makes the component available to consumers via:

import { Upp<Name>Component } from '@unpispas/upp-wdgt';

Step 4 — Styling

Component styles

Each component has its own .scss file. Use the component's selector as a :host context:

:host {
display: block;
}

Theme integration

If the component introduces new CSS custom properties or needs global theme tokens, add them to libs/upp-wdgt/src/styles/theme.scss. Reference existing variables from this file for colours, spacing, and typography.

Ionic integration

The module imports IonicModule, so you can freely use Ionic components (ion-button, ion-icon, ion-item, etc.) in your templates. Use the CUSTOM_ELEMENTS_SCHEMA (already registered in the module) to suppress unknown-element warnings for Ionic web components.

Step 5 — Multiple Components in One File

The library convention is to keep related components (parent + children for content projection) in a single .ts file. For example, upp-panel.ts exports UppPanelComponent, UppPanelHeaderComponent, UppPanelContentComponent, and UppPanelFooterComponent.

When doing this:

  • Export each class individually.
  • Import each one separately in the module file.

Step 6 — ControlValueAccessor (for form widgets)

If the new widget needs form integration, implement ControlValueAccessor:

import { forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
selector: 'upp-<name>',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => Upp<Name>Component),
multi: true,
},
],
})
export class Upp<Name>Component implements ControlValueAccessor {
writeValue(value: any) { /* ... */ }
registerOnChange(fn: any) { /* ... */ }
registerOnTouched(fn: any) { /* ... */ }
}

See UppInputComponent or UppSelectComponent for complete examples.

Checklist

  • Component files created under libs/upp-wdgt/src/components/upp-<name>/
  • Component declared and exported in UppWdgtModule
  • Re-exported from libs/upp-wdgt/src/index.ts
  • Styles follow the theme conventions
  • JSDoc/TSDoc documentation on the class and inputs
  • If form-integrated: ControlValueAccessor implemented