@libs-ui/services-config-project
v0.2.357-4
Published
> Service cấu hình toàn cục cho hệ sinh thái libs-ui: theme color, font family, heading styles, button colors/sizes/statuses/tabs — inject một lần, áp dụng toàn bộ ứng dụng qua CSS variables và Signal reactivity.
Downloads
3,904
Readme
@libs-ui/services-config-project
Service cấu hình toàn cục cho hệ sinh thái libs-ui: theme color, font family, heading styles, button colors/sizes/statuses/tabs — inject một lần, áp dụng toàn bộ ứng dụng qua CSS variables và Signal reactivity.
Giới thiệu
LibsUiConfigProjectService là service trung tâm quản lý design token và cấu hình giao diện cho toàn bộ ứng dụng sử dụng libs-ui. Service nhận một màu chủ đạo (ThemeColor) rồi tự động tính toán và thiết lập hơn 20 CSS custom variables tương ứng, đồng thời hỗ trợ load custom font family qua FontFace API, cấu hình heading typography (h1–h7), button color variants và button tab/status colors. Mọi thay đổi thông qua setter đều được phản ánh ngay lập tức nhờ Angular Signals + effect().
Tính năng
- ✅ Theme color — tự động tính 20+ CSS color variables từ một màu gốc duy nhất
- ✅ Custom font family — load dynamic qua FontFace API (không cần
@font-facetrong CSS) - ✅ Heading styles — 7 levels × 4 weights (h1r → h7b), áp dụng qua CSS class
libs-ui-font-* - ✅ Button colors — 14 built-in button types + extensible qua
FunctionGetConfigButtonIncludes - ✅ Button status colors — 8 màu mặc định (blue, green, red, orange, yellow, cyan, purple, brown) + custom
- ✅ Button tab colors — 8 màu với active background và badge background
- ✅ Button sizes — 4 kích thước (large, medium, small, smaller) cho icon và text
- ✅ Signal reactivity — setter nào thay đổi →
effect()tự cập nhật CSS vars tức thì - ✅ Global CSS utility classes — border, shadow, disable, readonly, selection highlight...
- ✅ Multi-tenant support — đổi toàn bộ brand color chỉ bằng một setter
Khi nào sử dụng
- Khởi tạo brand color và font family khi app load (trong
AppComponent) - Multi-tenant: đổi theme color theo tenant config từ API
- Override màu sắc đặc thù (error, disable, readonly, border) so với giá trị mặc định
- Thêm custom button color type ngoài 14 types có sẵn
- Cấu hình button status/tab colors cho các badge và tab component
- Truy xuất button config hiện tại dưới dạng Signal để dùng trong component tùy chỉnh
Cài đặt
npm install @libs-ui/services-config-projectImport
import { LibsUiConfigProjectService } from '@libs-ui/services-config-project';
// Import interfaces khi cần type cụ thể
import {
ILibsUiConfigFontFamily,
ILibsUiConfigFontHeading,
ILibsUiConfigFontHeadingStyle,
ILibsUiConfigButtonStatus,
ILibsUiConfigButtonTab,
IColorButton,
ILibsUiConfigButtonSize,
IColorButtonTab,
} from '@libs-ui/services-config-project';
// Import default data/config để tham khảo hoặc override một phần
import {
fontConfig,
configHeading,
sizeButtonConfig,
configButtonColor,
configLinkButton,
configButtonStatus,
configButtonTab,
} from '@libs-ui/services-config-project';Ví dụ sử dụng
Ví dụ 1 — Khởi tạo cơ bản trong AppComponent
Inject service và cấu hình brand color + font khi app khởi động:
import { Component, inject, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { LibsUiConfigProjectService } from '@libs-ui/services-config-project';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
template: '<router-outlet />',
})
export class AppComponent implements OnInit {
private readonly configService = inject(LibsUiConfigProjectService);
ngOnInit(): void {
// Set brand/theme color — tự động sinh 20+ CSS variables
this.configService.ThemeColor = '#226ff5';
// Set custom font family (tùy chọn — mặc định SVN-Poppins)
this.configService.ConfigFont = {
name: 'Inter',
uri_regular: '/assets/fonts/Inter-Regular.ttf',
uri_medium: '/assets/fonts/Inter-Medium.ttf',
uri_semibold: '/assets/fonts/Inter-SemiBold.ttf',
uri_bold: '/assets/fonts/Inter-Bold.ttf',
};
}
}Ví dụ 2 — Multi-tenant: đổi theme theo dữ liệu API
import { Component, inject, OnInit } from '@angular/core';
import { LibsUiConfigProjectService } from '@libs-ui/services-config-project';
@Component({
selector: 'app-root',
standalone: true,
template: '<router-outlet />',
})
export class AppComponent implements OnInit {
private readonly configService = inject(LibsUiConfigProjectService);
private readonly tenantService = inject(TenantService);
ngOnInit(): void {
this.tenantService.getTenantConfig().subscribe((tenant) => {
// Toàn bộ design token cập nhật ngay sau lệnh này
this.configService.ThemeColor = tenant.brandColor;
// Override các màu phụ trợ nếu tenant yêu cầu
this.configService.BorderColor = tenant.borderColor ?? '#e6e7ea';
this.configService.TextErrorColor = tenant.errorColor ?? '#ff5454';
});
}
}Ví dụ 3 — Thêm custom button color type
import { Component, inject, OnInit } from '@angular/core';
import { LibsUiConfigProjectService, IColorButton } from '@libs-ui/services-config-project';
@Component({
selector: 'app-root',
standalone: true,
template: '<router-outlet />',
})
export class AppComponent implements OnInit {
private readonly configService = inject(LibsUiConfigProjectService);
ngOnInit(): void {
this.configService.ThemeColor = '#226ff5';
// Thêm button type tùy chỉnh — key 'button-brand-pink' có thể dùng trong Button component
this.configService.FunctionGetConfigButtonIncludes = (rootColor: string): { [key: string]: IColorButton } => ({
'button-brand-pink': {
configStepColor: {
text: 'white',
text_hover: 'white',
text_active: 'white',
text_disable: '#CDD0D6',
background: 0,
background_hover: 20,
background_active: -20,
background_disable: '#F8F9FA',
border: 0,
border_hover: 20,
border_active: -20,
border_disable: '#F8F9FA',
},
rootColor: '#e91e63',
},
});
}
}Ví dụ 4 — Override màu cá nhân cho trạng thái đặc thù
import { Component, inject, OnInit } from '@angular/core';
import { LibsUiConfigProjectService } from '@libs-ui/services-config-project';
@Component({
selector: 'app-root',
standalone: true,
template: '<router-outlet />',
})
export class AppComponent implements OnInit {
private readonly configService = inject(LibsUiConfigProjectService);
ngOnInit(): void {
this.configService.ThemeColor = '#226ff5';
// Override từng màu trạng thái
this.configService.BackgroundDisableColor = '#f3f4f6';
this.configService.TextDisableColor = '#9ca3af';
this.configService.TextReadonlyColor = '#374151';
this.configService.BackgroundReadonlyColor = '#f9fafb';
this.configService.BorderErrorColor = '#dc2626';
this.configService.BackgroundListHover = '#eff6ff';
}
}Ví dụ 5 — Custom button status và tab colors
import { Component, inject, OnInit } from '@angular/core';
import { LibsUiConfigProjectService } from '@libs-ui/services-config-project';
@Component({
selector: 'app-root',
standalone: true,
template: '<router-outlet />',
})
export class AppComponent implements OnInit {
private readonly configService = inject(LibsUiConfigProjectService);
ngOnInit(): void {
this.configService.ThemeColor = '#226ff5';
// Custom button status colors (dùng cho badge/tag component)
this.configService.ConfigButtonStatus = {
active: { color: '#00D16D', background: '#E6FAF0' },
inactive: { color: '#9CA3AF', background: '#F3F4F6' },
pending: { color: '#F59E0B', background: '#FEF3C7' },
rejected: { color: '#EF4444', background: '#FEE2E2' },
};
// Custom button tab colors
this.configService.ConfigButtonTab = {
primary: {
color: '#226FF5',
background: '#F4F8FF',
background_badge: '#E9F1FE',
},
success: {
color: '#00D16D',
background: '#F2FCF7',
background_badge: '#E6FAF0',
},
};
}
}Ví dụ 6 — Dùng CSS variables trong SCSS của component
// Sử dụng CSS variables được tạo ra bởi service — không hardcode màu
.custom-card {
border: 1px solid var(--libs-ui-color-border, #e6e7ea);
background: var(--libs-ui-color-light-3, #f4f8ff);
&:hover {
background: var(--libs-ui-color-light-2, #dce9fd);
border-color: var(--libs-ui-color-light-1, #4e8cf7);
}
&.is-disabled {
background: var(--libs-ui-color-background-disable, #f8f9fa);
color: var(--libs-ui-color-text-disable, #9ca2ad);
cursor: not-allowed;
}
&.is-error {
border-color: var(--libs-ui-color-border-error, #ee2d41);
color: var(--libs-ui-color-text-error, #ff5454);
}
}Ví dụ 7 — Đọc ConfigButton Signal trong component tùy chỉnh
import { Component, inject } from '@angular/core';
import { LibsUiConfigProjectService } from '@libs-ui/services-config-project';
@Component({
selector: 'app-custom-button',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
@if (buttonConfig()['button-primary']) {
<button [style.background]="resolvedColor()">Click me</button>
}
`,
})
export class CustomButtonComponent {
private readonly configService = inject(LibsUiConfigProjectService);
// ConfigButton là Signal — reactive với mọi thay đổi ThemeColor
protected readonly buttonConfig = this.configService.ConfigButton;
protected readonly resolvedColor = computed(() => {
const config = this.buttonConfig();
return config['button-primary']?.rootColor ?? '#226ff5';
});
}Ví dụ 8 — Dùng global CSS utility classes trong template
<!-- Border utilities -->
<div class="libs-ui-border-general">Viền đơn chuẩn</div>
<div class="libs-ui-border-bottom-general">Chỉ viền dưới</div>
<div class="libs-ui-border-error-general">Viền lỗi màu đỏ</div>
<!-- Background utilities -->
<div class="libs-ui-bg-list">Nền list item</div>
<div class="libs-ui-bg-list-hover">Nền hover list item</div>
<div class="libs-ui-bg-list-active">Nền active list item</div>
<!-- Shadow utilities -->
<div class="libs-ui-shadow">Shadow chuẩn</div>
<div class="libs-ui-shadow-md">Shadow medium</div>
<div class="libs-ui-shadow-large">Shadow large</div>
<!-- State utilities -->
<span class="libs-ui-disable">Text disabled</span>
<span class="libs-ui-disable-background">Background disabled</span>
<span class="libs-ui-readonly">Text readonly</span>
<span class="libs-ui-readonly-background">Background readonly</span>
<span class="libs-ui-text-error">Text lỗi</span>Methods
| Method | Signature | Mô tả |
|---|---|---|
| colorStepContrastFromOrigin | (step: number, color?: string) => { light: string; dark: string } \| undefined | Tính màu lighter (light) hoặc darker (dark) với N step từ màu gốc. Nếu bỏ qua color, dùng ThemeColor hiện tại |
| setupFontFamily | (currentDoc?: Document) => void | Load font family vào document. Public để hỗ trợ shadow DOM (iframe, Web Component). Mặc định dùng document global |
Ví dụ sử dụng colorStepContrastFromOrigin
// Trong component inject service
private readonly configService = inject(LibsUiConfigProjectService);
// Tính màu sáng hơn ThemeColor 20 steps
const lighterColor = this.configService.colorStepContrastFromOrigin(20);
// → { light: '#4e8cf7', dark: '#1b59c4' }
// Tính màu từ một màu tùy ý
const customLight = this.configService.colorStepContrastFromOrigin(50, '#e91e63');
// → { light: '#f06292', dark: '#c2185b' }Setters (API cấu hình)
| Setter | Type | Mặc định | Mô tả | Ví dụ |
|---|---|---|---|---|
| ThemeColor | string | '#226ff5' | Màu chủ đạo — sinh toàn bộ CSS color variables | configService.ThemeColor = '#1a73e8' |
| BorderColor | string | '#e6e7ea' | Màu border toàn cục (--libs-ui-color-border) | configService.BorderColor = '#d1d5db' |
| BorderErrorColor | string | '#ee2d41' | Màu border khi lỗi (--libs-ui-color-border-error) | configService.BorderErrorColor = '#dc2626' |
| TextErrorColor | string | '#ff5454' | Màu text lỗi (--libs-ui-color-text-error) | configService.TextErrorColor = '#ef4444' |
| IconHoverDangerColor | string | '#f15767' | Màu icon khi hover trạng thái danger | configService.IconHoverDangerColor = '#f15767' |
| BackgroundDisableColor | string | '#f8f9fa' | Background khi disabled (--libs-ui-color-background-disable) | configService.BackgroundDisableColor = '#f3f4f6' |
| TextDisableColor | string | '#9ca2ad' | Text color khi disabled (--libs-ui-color-text-disable) | configService.TextDisableColor = '#9ca3af' |
| TextReadonlyColor | string | '#071631' | Text color khi readonly (--libs-ui-color-text-readonly) | configService.TextReadonlyColor = '#374151' |
| BackgroundReadonlyColor | string | '#f8f9fa' | Background khi readonly (--libs-ui-color-background-readonly) | configService.BackgroundReadonlyColor = '#f9fafb' |
| BackgroundUserSelection | string | '#00000040' | Màu nền khi user bôi chọn text (::selection) | configService.BackgroundUserSelection = '#bfdbfe' |
| BackgroundList | string | '#f8f9fa' | Background item trong list/dropdown | configService.BackgroundList = '#f8fafc' |
| BackgroundListHover | string | '#f8f9fa' | Background khi hover trên list item | configService.BackgroundListHover = '#eff6ff' |
| BackgroundListHoverDanger | string | '#fef5f6' | Background khi hover trạng thái nguy hiểm | configService.BackgroundListHoverDanger = '#fef2f2' |
| ConfigFont | ILibsUiConfigFontFamily | SVN-Poppins | Font family + đường dẫn file font | Xem ví dụ 1 |
| ConfigFontHead | ILibsUiConfigFontHeading | 7 levels × 4 weights | Toàn bộ heading styles (h1r → h7b) | Xem mục Heading Styles |
| ConfigButtonStatus | ILibsUiConfigButtonStatus | 8 màu built-in | Màu cho badge/status button | Xem ví dụ 5 |
| ConfigButtonTab | ILibsUiConfigButtonTab | 8 màu built-in | Màu cho tab button active | Xem ví dụ 5 |
| FunctionGetConfigButtonIncludes | (rootColor: string) => { [key: string]: IColorButton } | () => ({}) | Hàm mở rộng thêm custom button types | Xem ví dụ 3 |
Getters (đọc config hiện tại)
| Getter | Kiểu trả về | Mô tả |
|---|---|---|
| ConfigButton | Signal<{ [key: string]: IColorButton }> | Toàn bộ button color configs dưới dạng computed Signal — reactive với ThemeColor |
| ConfigButtonStatus | ILibsUiConfigButtonStatus | Config màu button status hiện tại |
Types & Interfaces
import {
ILibsUiConfigFontFamily,
ILibsUiConfigFontWeight,
ILibsUiConfigFontHeading,
ILibsUiConfigFontHeadingStyle,
ILibsUiConfigButtonStatus,
ILibsUiConfigButtonTab,
IColorButtonTab,
IColorButton,
ILibsUiConfigButtonSize,
} from '@libs-ui/services-config-project';
// Font family config
interface ILibsUiConfigFontFamily {
name: string; // Tên font (dùng cho font-family CSS)
uri_regular: string; // Đường dẫn file font weight 400
uri_medium: string; // Đường dẫn file font weight 500
uri_semibold: string; // Đường dẫn file font weight 600
uri_bold?: string; // Đường dẫn file font weight 700 (tùy chọn)
}
// Heading style cho một cấp (vd: h1r, h2m, h5s...)
interface ILibsUiConfigFontHeadingStyle {
'font-size': string; // VD: '16px'
'font-weight': string; // VD: '500'
'line-height': string; // VD: '24px'
'letter-spacing': string; // VD: 'calc(16px * (0.5 / 100))'
}
// Button status color (dùng cho badge, tag, label...)
interface ILibsUiConfigButtonStatus {
[key: string]: {
color: string; // Text/icon color
background?: string; // Background color
};
}
// Button tab color (dùng cho tab navigation)
interface ILibsUiConfigButtonTab {
[key: string]: {
color: string; // Text color khi active
background?: string; // Background khi active
background_badge?: string; // Background badge khi active
};
}
// Button color config (dùng để mở rộng custom button)
interface IColorButton {
configStepColor: {
text: string | number; // Text color (hex hoặc step number)
text_hover: string | number; // Text color khi hover
text_active: string | number; // Text color khi active/click
text_disable: string | number; // Text color khi disabled
background?: string | number; // Background (hex hoặc step)
background_hover?: string | number;
background_active?: string | number;
background_disable?: string | number;
border?: string | number;
border_hover?: string | number;
border_active?: string | number;
border_disable?: string | number;
};
rootColor: string; // Màu gốc để tính step
}CSS Variables được sinh ra
| Variable | Mô tả | Ví dụ giá trị |
|---|---|---|
| --libs-ui-color-default | ThemeColor gốc | #226ff5 |
| --libs-ui-color-light-1 | ThemeColor + 20 steps sáng | #4e8cf7 |
| --libs-ui-color-light-2 | ThemeColor + 90 steps sáng | #dce9fd |
| --libs-ui-color-light-3 | ThemeColor + 95 steps sáng (background nhẹ) | #f4f8ff |
| --libs-ui-color-light-4 | ThemeColor + 50 steps sáng (disabled active) | #91b7fa |
| --libs-ui-color-light-5 | ThemeColor + 70 steps sáng | #b8d2fb |
| --libs-ui-color-light-6 | ThemeColor + 80 steps sáng | #cfe0fd |
| --libs-ui-color-dark | ThemeColor - 20 steps tối | #1b59c4 |
| --libs-ui-color-border | BorderColor | #e6e7ea |
| --libs-ui-color-border-error | BorderErrorColor | #ee2d41 |
| --libs-ui-color-text-error | TextErrorColor | #ff5454 |
| --libs-ui-color-text-disable | TextDisableColor | #9ca2ad |
| --libs-ui-color-text-readonly | TextReadonlyColor | #071631 |
| --libs-ui-color-background-disable | BackgroundDisableColor | #f8f9fa |
| --libs-ui-color-background-readonly | BackgroundReadonlyColor | #f8f9fa |
| --libs-ui-color-background-selection | BackgroundUserSelection | #00000040 |
| --libs-ui-color-icon-hover-danger | IconHoverDangerColor | #f15767 |
| --libs-ui-color-gradient-from | Gradient start color | Tính từ ThemeColor |
| --libs-ui-color-gradient-to | Gradient end color | Tính từ ThemeColor |
| --libs-ui-font-family-name | Tên font family | Inter, Arial, Helvetica, sans-serif |
Heading Typography (CSS classes)
Service tự động sinh CSS class libs-ui-font-{level}{weight} cho toàn bộ 28 combinations:
| Level | Regular (r) | Medium (m) | Semibold (s) | Bold (b) |
|---|---|---|---|---|
| h1 | libs-ui-font-h1r (30px/400) | libs-ui-font-h1m (30px/500) | libs-ui-font-h1s (30px/600) | libs-ui-font-h1b (30px/700) |
| h2 | libs-ui-font-h2r (20px/400) | libs-ui-font-h2m (20px/500) | libs-ui-font-h2s (20px/600) | libs-ui-font-h2b (20px/700) |
| h3 | libs-ui-font-h3r (16px/400) | libs-ui-font-h3m (16px/500) | libs-ui-font-h3s (16px/600) | libs-ui-font-h3b (16px/700) |
| h4 | libs-ui-font-h4r (13px/400) | libs-ui-font-h4m (13px/500) | libs-ui-font-h4s (13px/600) | libs-ui-font-h4b (13px/700) |
| h5 | libs-ui-font-h5r (12px/400) | libs-ui-font-h5m (12px/500) | libs-ui-font-h5s (12px/600) | libs-ui-font-h5b (12px/700) |
| h6 | libs-ui-font-h6r (11px/400) | libs-ui-font-h6m (11px/500) | libs-ui-font-h6s (11px/600) | libs-ui-font-h6b (11px/700) |
| h7 | libs-ui-font-h7r (10px/400) | libs-ui-font-h7m (10px/500) | libs-ui-font-h7s (10px/600) | libs-ui-font-h7b (10px/700) |
Thêm hậu tố i để in nghiêng: libs-ui-font-h3mi, libs-ui-font-h5si, ...
<h1 class="libs-ui-font-h1b">Tiêu đề cấp 1 bold</h1>
<h2 class="libs-ui-font-h2s">Tiêu đề cấp 2 semibold</h2>
<p class="libs-ui-font-h4r">Văn bản body regular</p>
<small class="libs-ui-font-h6m">Caption medium</small>
<span class="libs-ui-font-h3si">Heading italic</span>Global CSS Utility Classes
Border
| Class | Mô tả |
|---|---|
| libs-ui-border-general | Border đầy đủ 4 cạnh |
| libs-ui-border-top-general | Chỉ border-top |
| libs-ui-border-right-general | Chỉ border-right |
| libs-ui-border-bottom-general | Chỉ border-bottom |
| libs-ui-border-left-general | Chỉ border-left |
| libs-ui-border-x-general | Border trái + phải |
| libs-ui-border-y-general | Border trên + dưới |
| libs-ui-border-dashed-general | Border nét đứt đầy đủ |
| libs-ui-border-error-general | Border màu lỗi (important) |
| libs-ui-border-primary-general | Border màu ThemeColor |
Shadow
| Class | Mô tả |
|---|---|
| libs-ui-shadow | Shadow chuẩn 0 2px 10px 1px rgba(51,51,51,0.1) |
| libs-ui-shadow-sm | Shadow nhỏ |
| libs-ui-shadow-md | Shadow medium |
| libs-ui-shadow-lg | Shadow lớn |
| libs-ui-shadow-small | Shadow tối ưu (design system) |
| libs-ui-shadow-medium | Shadow medium (design system) |
| libs-ui-shadow-large | Shadow lớn (design system) |
| libs-ui-shadow-extra-large | Shadow rất lớn (design system) |
| libs-ui-shadow-none | Tắt shadow (important) |
Background
| Class | Mô tả |
|---|---|
| libs-ui-bg-list | Background list item |
| libs-ui-bg-list-hover | Background hover list item |
| libs-ui-bg-list-active | Background active list item (ThemeColor-95) |
| libs-ui-bg-list-hover-active | Hover + active states kết hợp |
| libs-ui-bg-list-hover-danger | Hover với màu danger |
State
| Class | Mô tả |
|---|---|
| libs-ui-disable | Cursor not-allowed + text màu disable |
| libs-ui-disable-background | Background màu disable |
| libs-ui-disable-active | Disabled active state |
| libs-ui-readonly | Cursor not-allowed + text màu readonly |
| libs-ui-readonly-background | Background màu readonly |
| libs-ui-text-error | Text màu lỗi (important) |
| libs-ui-icon-hover-danger | Icon hover danger color |
Lưu ý quan trọng
⚠️ Inject một lần duy nhất: Service là providedIn: 'root' — chỉ inject trong AppComponent. Mọi component khác trong app đều tự động nhận cấu hình chung thông qua CSS variables.
⚠️ Setter syntax — không phải method: Dùng assignment configService.ThemeColor = '#color' (property setter), không phải configService.setThemeColor('#color').
⚠️ Font URIs phải accessible từ browser: Đường dẫn font có thể là URL tuyệt đối (https://...) hoặc tương đối từ gốc (/assets/fonts/...). Font được load qua FontFace API — không cần khai báo @font-face trong CSS.
⚠️ String.prototype được extend global: Khi service khởi tạo, String.prototype được bổ sung các method: replaceAt, replaceAll (override), occurrencesByCharacter, indexesOfCharacter, indexesByString. Cần lưu ý khi dùng trong môi trường có strict prototype protection.
⚠️ ConfigButton là Signal không phải giá trị thường: configService.ConfigButton trả về Signal<{...}>. Để đọc giá trị cần gọi configService.ConfigButton() hoặc dùng trong computed()/effect().
⚠️ ThemeColor gradient mặc định: Khi ThemeColor là #226FF5 (giá trị mặc định), gradient được tính theo công thức đặc biệt kết hợp với màu #5B2EBB. Với màu khác, gradient được tính thuần từ ThemeColor.
