@saitec/ui
v0.1.12
Published
SAITEC Angular UI component library
Readme
@saitec/ui
Reusable Angular UI component library developed by SAITEC Ingeniería S.A.S.
@saitec/ui provides standalone Angular components, shared design tokens, light/dark themes, and reusable interaction patterns for SAITEC applications.
The library is designed so consuming applications depend on the public @saitec/ui/* API instead of third-party component suites or internal source paths.
Features
- Standalone Angular components
- Angular Forms and
ControlValueAccessorsupport - Signal-based APIs
- Light and dark themes
- CSS custom-property design tokens
- Global, component, and instance-level customization
- Angular CDK for overlay-based components where appropriate
- No Tailwind dependency inside SUI
- Secondary entry points such as
@saitec/ui/buttonand@saitec/ui/table
Installation
npm install @saitec/uiSome components use Angular CDK. If needed:
npm install @angular/cdkAngular framework packages are provided by the consuming application.
Global styles
Import SUI once from the application's global stylesheet:
@import '@saitec/ui/styles.css';If the application uses Tailwind:
@import 'tailwindcss';
@import '@saitec/ui/styles.css';SUI itself does not require Tailwind.
Basic usage
import { Component } from '@angular/core';
import { SuiButton } from '@saitec/ui/button';
import { SuiTag } from '@saitec/ui/tag';
@Component({
selector: 'app-example',
standalone: true,
imports: [SuiButton, SuiTag],
template: `
<button suiButton>Save</button>
<sui-tag severity="success"> Active </sui-tag>
`,
})
export class ExampleComponent {}Secondary entry points
Import components through their public package entry points:
import { SuiButton } from '@saitec/ui/button';
import { SuiInput } from '@saitec/ui/input';
import { SuiDialog } from '@saitec/ui/dialog';
import { SuiTable, SuiColumn, SuiCell } from '@saitec/ui/table';Shared types are exposed from:
import { SuiOption } from '@saitec/ui/core';Do not import internal source files.
Bad:
import { SuiButton } from '@saitec/ui/button/src/button.component';Good:
import { SuiButton } from '@saitec/ui/button';Themes
SUI uses the data-theme attribute.
Light:
<html data-theme="light"></html>Dark:
<html data-theme="dark"></html>Runtime switch:
document.documentElement.setAttribute('data-theme', 'dark');SUI components consume semantic variables such as:
--sui-color-background
--sui-color-surface
--sui-color-content
--sui-color-border
--sui-color-primary
--sui-color-dangerChanging the theme updates those semantic values globally.
Design tokens
The design-token system is organized into layers:
Primitive tokens
↓
Theme semantic tokens
↓
Foundation tokens
↓
Component tokens
↓
Component CSSMain files:
src/lib/core/tokens/
├── primitives.css
├── foundations.css
├── components.css
└── components/
├── button.css
├── input.css
├── table.css
└── ...
src/lib/core/themes/
├── light.css
└── dark.cssPrimitive tokens
Raw design values:
--sui-palette-brand-600
--sui-palette-neutral-900
--sui-radius-md
--sui-shadow-smSemantic theme tokens
Theme-level meaning:
--sui-color-primary
--sui-color-surface
--sui-color-content
--sui-color-success
--sui-color-warning
--sui-color-danger
--sui-color-infoFoundation tokens
Shared control and layout values:
--sui-control-height-md
--sui-control-padding-x-md
--sui-space-4
--sui-focus-ring-width
--sui-duration-normal
--sui-z-dialogComponent tokens
Each component exposes its own styling contract:
--sui-button-primary-background
--sui-button-radius
--sui-table-header-background
--sui-dialog-backgroundCustomization
Global brand customization
:root {
--sui-color-primary: #0057b8;
--sui-color-primary-hover: #004a9d;
--sui-color-primary-active: #003d82;
}Component-level customization
:root {
--sui-button-radius: 9999px;
}Single-instance customization
<button suiButton class="special-button">Save</button>.special-button {
--sui-button-primary-background: #7c3aed;
--sui-button-primary-background-hover: #6d28d9;
--sui-button-radius: 0;
}This avoids ::ng-deep and keeps consumers independent from internal component markup.
Forms
Form controls implement Angular ControlValueAccessor where appropriate.
<sui-input formControlName="customerName" placeholder="Customer name"> </sui-input>Shared options
Selection components share a common option contract:
import { SuiOption } from '@saitec/ui/core';
const countries: SuiOption<string>[] = [
{
label: 'Colombia',
value: 'CO',
},
{
label: 'Ecuador',
value: 'EC',
},
{
label: 'Peru',
value: 'PE',
},
];The same collection can be used with components such as:
<sui-select [options]="countries" />
<sui-autocomplete [options]="countries" />
<sui-multiselect [options]="countries" />Table
import { SuiCell, SuiColumn, SuiTable } from '@saitec/ui/table';
import { SuiTag } from '@saitec/ui/tag';<sui-table [value]="products" [striped]="true" [hoverable]="true">
<sui-column field="code" header="Product" [sortable]="true"> </sui-column>
<sui-column field="weight" header="Weight" align="right" [sortable]="true"> </sui-column>
<sui-column field="status" header="Status">
<ng-template suiCell let-value="value">
<sui-tag severity="success"> {{ value }} </sui-tag>
</ng-template>
</sui-column>
</sui-table>When using suiCell, remember to import SuiCell.
Toast and confirm
Place one instance near the root of the application:
<router-outlet />
<sui-toast />
<sui-confirm />Then inject the corresponding service:
private readonly toast =
inject(SuiToastService);
private readonly confirm =
inject(SuiConfirmService);File upload
SuiFileUpload manages file selection and UI behavior. HTTP upload remains the responsibility of the consuming application.
<sui-file-upload
[multiple]="true"
accept=".pdf,.png,.jpg"
[maxFileSize]="10 * 1024 * 1024"
(filesChange)="files = $event"
>
</sui-file-upload>Available components
| Category | Components | | ---------- | --------------------------------------------------------------------------- | | Form | FormField, Input, Textarea, Checkbox, ToggleSwitch, InputNumber, DatePicker | | Selection | Select, Autocomplete, MultiSelect | | Actions | Button | | Data | Table | | Navigation | Menu, Menubar, Tabs | | Status | Badge, Tag, Message, ProgressSpinner | | Containers | Card, Panel, Fieldset, Toolbar, Divider | | Overlay | Dialog, Drawer, Tooltip, Toast, Confirm | | Files | FileUpload | | Content | Chip |
Development
Build the library in watch mode:
ng build ui --watch --configuration developmentRun the showcase separately:
ng serve showcaseProduction build:
ng build ui --configuration productionThe distributable package is generated under:
dist/uiPublishing
Publish the compiled package, not projects/ui.
ng build ui --configuration production
cd dist/ui
npm publish --dry-run --access public
npm publish --access publicThe version must be incremented before publishing another release.
Recommended versioning while the API is still evolving:
0.1.xThen move to 1.0.0 when the public API is considered stable.
Architecture guidelines
When adding components:
- Expose a small application-focused API instead of cloning a third-party component API.
- Prefer native HTML semantics when they already provide good accessibility and behavior.
- Use Angular CDK where robust overlay, focus, or positioning infrastructure is needed.
- Implement
ControlValueAccessorfor form controls. - Keep Angular components standalone.
- Prefer signals for inputs, models, outputs, and internal state where appropriate.
- Reuse shared contracts such as
SuiOption<T>. - Keep visual design decisions in design tokens.
- Keep component CSS focused on layout, structure, and state behavior.
- Never require consuming applications to import internal source paths.
Styling rule
A core SUI rule is:
Component CSS describes how a component behaves and is laid out. Design tokens describe what it looks like.
Prefer:
.sui-button--primary {
background-color: var(--sui-button-primary-background);
color: var(--sui-button-primary-text);
}instead of:
.sui-button--primary {
background-color: #2563eb;
color: #ffffff;
}License
@saitec/ui is released under the MIT License.
Copyright © 2026 SAITEC Ingeniería S.A.S.
