@sd-angular/core 19.0.13 → 19.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +712 -712
- package/assets/STYLE-GUIDE.md +601 -601
- package/assets/images/coming-soon.svg +22 -22
- package/assets/images/data-empty.svg +20 -20
- package/assets/images/expired.svg +21 -21
- package/assets/images/file-error.svg +27 -27
- package/assets/images/filter-empty.svg +19 -19
- package/assets/images/filter-required.svg +20 -20
- package/assets/images/forbidden.svg +14 -14
- package/assets/images/image-error.svg +26 -26
- package/assets/images/maintenance.svg +22 -22
- package/assets/images/not-found.svg +19 -19
- package/assets/images/offline.svg +19 -19
- package/assets/images/submitted.svg +17 -17
- package/assets/images/success.svg +17 -17
- package/assets/images/unauthorized.svg +21 -21
- package/assets/images/unknown-error.svg +17 -17
- package/assets/scss/ckeditor5.scss +88 -88
- package/assets/scss/core/_inline-edit.scss +105 -105
- package/assets/scss/core/color.scss +73 -73
- package/assets/scss/core/form.scss +317 -317
- package/assets/scss/core/image.scss +35 -35
- package/assets/scss/core/utilities/_base.scss +333 -333
- package/assets/scss/core/utilities/_border.scss +22 -22
- package/assets/scss/core/utilities/_display.scss +10 -10
- package/assets/scss/core/utilities/_elevation.scss +80 -80
- package/assets/scss/core/utilities/_flexbox.scss +54 -54
- package/assets/scss/core/utilities/_gap.scss +9 -9
- package/assets/scss/core/utilities/_index.scss +17 -17
- package/assets/scss/core/utilities/_misc.scss +20 -20
- package/assets/scss/core/utilities/_overflow.scss +9 -9
- package/assets/scss/core/utilities/_position.scss +8 -8
- package/assets/scss/core/utilities/_sizing.scss +28 -28
- package/assets/scss/core/utilities/_spacing.scss +31 -31
- package/assets/scss/core/utilities/_typography.scss +99 -99
- package/assets/scss/sd-core.scss +16 -16
- package/assets/scss/themes/default.scss +45 -45
- package/assets/scss/themes/material-theme.scss +101 -101
- package/components/preview/src/preview-pdf/pdf-worker-inline.generated.d.ts +7 -0
- package/components/table/src/services/table-export/table-export.service.d.ts +3 -1
- package/components/table/src/table.component.d.ts +1 -1
- package/fesm2022/sd-angular-core-components-anchor.mjs +6 -6
- package/fesm2022/sd-angular-core-components-anchor.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-autoid-inspector.mjs +2 -2
- package/fesm2022/sd-angular-core-components-autoid-inspector.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-badge.mjs +2 -2
- package/fesm2022/sd-angular-core-components-badge.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-base.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-button.mjs +2 -2
- package/fesm2022/sd-angular-core-components-button.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-chart.mjs +40 -40
- package/fesm2022/sd-angular-core-components-chart.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-ckeditor-styles.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-code-editor.mjs +2 -2
- package/fesm2022/sd-angular-core-components-code-editor.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-document-builder.mjs +77 -77
- package/fesm2022/sd-angular-core-components-document-builder.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-editor.mjs +2 -2
- package/fesm2022/sd-angular-core-components-editor.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-form-generic.mjs +106 -106
- package/fesm2022/sd-angular-core-components-form-generic.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-history.mjs +2 -2
- package/fesm2022/sd-angular-core-components-history.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-import-excel.mjs +2 -2
- package/fesm2022/sd-angular-core-components-import-excel.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-inform.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-mini-editor.mjs +2 -2
- package/fesm2022/sd-angular-core-components-mini-editor.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-modal-resizable.mjs +2 -2
- package/fesm2022/sd-angular-core-components-modal-resizable.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-modal.mjs +2 -2
- package/fesm2022/sd-angular-core-components-modal.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-operator.mjs +2 -2
- package/fesm2022/sd-angular-core-components-operator.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-org-chart.mjs +2 -2
- package/fesm2022/sd-angular-core-components-org-chart.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-preview.mjs +32 -6
- package/fesm2022/sd-angular-core-components-preview.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-query-bar.mjs +10 -10
- package/fesm2022/sd-angular-core-components-query-bar.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-query-builder.mjs +2 -2
- package/fesm2022/sd-angular-core-components-query-builder.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-section.mjs +4 -4
- package/fesm2022/sd-angular-core-components-section.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-side-drawer.mjs +2 -2
- package/fesm2022/sd-angular-core-components-side-drawer.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-stepper.mjs +2 -2
- package/fesm2022/sd-angular-core-components-stepper.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-tab-router.mjs +6 -6
- package/fesm2022/sd-angular-core-components-tab-router.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-tab.mjs +2 -2
- package/fesm2022/sd-angular-core-components-tab.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-table.mjs +32 -17
- package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-upload-file.mjs +4 -4
- package/fesm2022/sd-angular-core-components-upload-file.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-view.mjs +2 -2
- package/fesm2022/sd-angular-core-components-view.mjs.map +1 -1
- package/fesm2022/sd-angular-core-configurations.mjs.map +1 -1
- package/fesm2022/sd-angular-core-directives.mjs +20 -20
- package/fesm2022/sd-angular-core-directives.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-autocomplete.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-autocomplete.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-checkbox.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-checkbox.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-chip-calendar.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-chip-calendar.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-chip.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-chip.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-date-range.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-date-range.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-date.mjs +114 -35
- package/fesm2022/sd-angular-core-forms-date.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-datetime.mjs +6 -6
- package/fesm2022/sd-angular-core-forms-datetime.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-directives.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-inline-text.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-inline-text.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-input-color.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-input-color.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-input-number.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-input.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-input.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-label.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-label.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-models.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-radio.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-radio.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-select.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-switch.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-switch.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-textarea.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-textarea.mjs.map +1 -1
- package/fesm2022/sd-angular-core-handlers.mjs.map +1 -1
- package/fesm2022/sd-angular-core-i18n.mjs +20 -0
- package/fesm2022/sd-angular-core-i18n.mjs.map +1 -1
- package/fesm2022/sd-angular-core-interceptors.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-auth.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-authom.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-keycloak.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-layout.mjs +130 -43
- package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-permission.mjs.map +1 -1
- package/fesm2022/sd-angular-core-pipes.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-api.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-cache.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-confirm.mjs +2 -2
- package/fesm2022/sd-angular-core-services-confirm.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-docx.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-excel.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-license.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-loading.mjs +5 -5
- package/fesm2022/sd-angular-core-services-loading.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-notify.mjs +12 -12
- package/fesm2022/sd-angular-core-services-notify.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-storage.mjs.map +1 -1
- package/fesm2022/sd-angular-core-utilities-data-state.mjs.map +1 -1
- package/fesm2022/sd-angular-core-utilities-extensions.mjs.map +1 -1
- package/forms/date/src/date.component.d.ts +9 -1
- package/i18n/src/en.d.ts +4 -0
- package/modules/layout/index.d.ts +1 -0
- package/modules/layout/utils/index.d.ts +1 -0
- package/modules/layout/utils/tab-name.util.d.ts +8 -0
- package/package.json +73 -73
- package/sd-angular-core-19.0.13.tgz +0 -0
package/assets/STYLE-GUIDE.md
CHANGED
|
@@ -1,610 +1,610 @@
|
|
|
1
|
-
# `@sd-angular/core` — Assets & SCSS Reference
|
|
2
|
-
|
|
3
|
-
> **Mục đích tài liệu này (cho người + AI agent):** liệt kê chính xác mọi utility class, design token, font, image, theme mixin mà `@sd-angular/core` ship trong `assets/`. AI agent chỉ được sinh template dùng class **nằm trong danh sách dưới đây** — nếu cần class mới, phải tạo trong `core/utilities/*.scss` trước.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Mục lục
|
|
8
|
-
|
|
9
|
-
1. [Cài đặt vào Angular](#1-cài-đặt-vào-angular)
|
|
10
|
-
2. [Cấu trúc thư mục `assets/`](#2-cấu-trúc-thư-mục-assets)
|
|
11
|
-
3. [Hệ thống màu sắc](#3-hệ-thống-màu-sắc) — `--sd-*` tokens + `.text-*` / `.bg-*` / `.border-*`
|
|
12
|
-
4. [Typography tokens](#4-typography-tokens) — `T{size}{weight}` + `fs-*` + `font-weight-*`
|
|
13
|
-
5. [Layout & Grid](#5-layout--grid) — `row` / `col-*` / `grid-container` / `grid-cols-*`
|
|
14
|
-
6. [Flexbox utilities](#6-flexbox-utilities) — `d-flex` + `flex-*` + `align-*` + `justify-*`
|
|
15
|
-
7. [Spacing](#7-spacing) — `m-*` / `p-*` / `gap-*`
|
|
16
|
-
8. [Sizing](#8-sizing) — `w-*` / `h-*` / `min-*` / `max-*`
|
|
17
|
-
9. [Border & radius](#9-border--radius) — `border` / `border-{side}` / `rounded-*`
|
|
18
|
-
10. [Display, position, overflow, visibility](#10-display-position-overflow-visibility)
|
|
19
|
-
11. [Cursor, vertical-align, misc](#11-cursor-vertical-align-misc)
|
|
20
|
-
12. [Elevation (mat-elevation-z0–z8)](#12-elevation-mat-elevation-z0z8)
|
|
21
|
-
13. [Reset / Reboot baseline](#13-reset--reboot-baseline)
|
|
1
|
+
# `@sd-angular/core` — Assets & SCSS Reference
|
|
2
|
+
|
|
3
|
+
> **Mục đích tài liệu này (cho người + AI agent):** liệt kê chính xác mọi utility class, design token, font, image, theme mixin mà `@sd-angular/core` ship trong `assets/`. AI agent chỉ được sinh template dùng class **nằm trong danh sách dưới đây** — nếu cần class mới, phải tạo trong `core/utilities/*.scss` trước.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Mục lục
|
|
8
|
+
|
|
9
|
+
1. [Cài đặt vào Angular](#1-cài-đặt-vào-angular)
|
|
10
|
+
2. [Cấu trúc thư mục `assets/`](#2-cấu-trúc-thư-mục-assets)
|
|
11
|
+
3. [Hệ thống màu sắc](#3-hệ-thống-màu-sắc) — `--sd-*` tokens + `.text-*` / `.bg-*` / `.border-*`
|
|
12
|
+
4. [Typography tokens](#4-typography-tokens) — `T{size}{weight}` + `fs-*` + `font-weight-*`
|
|
13
|
+
5. [Layout & Grid](#5-layout--grid) — `row` / `col-*` / `grid-container` / `grid-cols-*`
|
|
14
|
+
6. [Flexbox utilities](#6-flexbox-utilities) — `d-flex` + `flex-*` + `align-*` + `justify-*`
|
|
15
|
+
7. [Spacing](#7-spacing) — `m-*` / `p-*` / `gap-*`
|
|
16
|
+
8. [Sizing](#8-sizing) — `w-*` / `h-*` / `min-*` / `max-*`
|
|
17
|
+
9. [Border & radius](#9-border--radius) — `border` / `border-{side}` / `rounded-*`
|
|
18
|
+
10. [Display, position, overflow, visibility](#10-display-position-overflow-visibility)
|
|
19
|
+
11. [Cursor, vertical-align, misc](#11-cursor-vertical-align-misc)
|
|
20
|
+
12. [Elevation (mat-elevation-z0–z8)](#12-elevation-mat-elevation-z0z8)
|
|
21
|
+
13. [Reset / Reboot baseline](#13-reset--reboot-baseline)
|
|
22
22
|
14. [Custom theme](#14-custom-theme)
|
|
23
23
|
15. [Fonts & Images shipped](#15-fonts--images-shipped)
|
|
24
24
|
16. [What is NOT shipped](#16-what-is-not-shipped) — anti-confusion cho AI
|
|
25
25
|
17. [AI rendering guardrails](#17-ai-rendering-guardrails) — ưu tiên Core UI trước khi viết CSS mới
|
|
26
26
|
|
|
27
27
|
---
|
|
28
|
-
|
|
29
|
-
## 1. Cài đặt vào Angular
|
|
30
|
-
|
|
31
|
-
`angular.json`:
|
|
32
|
-
|
|
33
|
-
```json
|
|
34
|
-
"styles": [
|
|
35
|
-
"./node_modules/@sd-angular/core/assets/scss/sd-core.scss",
|
|
36
|
-
"src/styles.scss"
|
|
37
|
-
]
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
`sd-core.scss` là entry point duy nhất — auto-load reset, utilities, color theme, form overrides, scrollbar, Angular Material theme. Không cần import partial nào riêng lẻ.
|
|
41
|
-
|
|
42
|
-
> Convention chung: **mọi utility class đều có `!important`** để đảm bảo override được Angular Material (thường có specificity cao).
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## 2. Cấu trúc thư mục `assets/`
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
projects/sd-angular/assets/
|
|
50
|
-
├── STYLE-GUIDE.md # Tài liệu này (assets + SCSS reference cho người + AI agent)
|
|
51
|
-
├── fonts/
|
|
52
|
-
│ ├── fonts.scss # @font-face khai báo cho Roboto + Material Icons + Material Symbols
|
|
53
|
-
│ ├── material-icons/ # 2 file .woff2 (icons-v145 + outlined-v110)
|
|
54
|
-
│ ├── material-symbols/ # 1 file .woff2 (symbols-v29)
|
|
55
|
-
│ └── roboto/ # 4 file .woff2 (regular, italic, 500, 600 — latin + vietnamese)
|
|
56
|
-
├── images/ # SVG illustrations (18 file — empty-state, error, success...)
|
|
57
|
-
│ ├── coming-soon.svg # Trang chưa sẵn sàng
|
|
58
|
-
│ ├── data-empty.svg # Empty state cho table/list
|
|
59
|
-
│ ├── expired.svg # Session expired
|
|
60
|
-
│ ├── file-error.svg # Upload file lỗi
|
|
61
|
-
│ ├── filter-empty.svg # Không match filter
|
|
62
|
-
│ ├── filter-required.svg # Yêu cầu bộ lọc trước khi load
|
|
63
|
-
│ ├── forbidden.svg # 403
|
|
64
|
-
│ ├── image-error.svg # Image load fail
|
|
65
|
-
│ ├── maintenance.svg # Trang đang bảo trì
|
|
66
|
-
│ ├── not-found.svg # 404
|
|
67
|
-
│ ├── offline.svg # Mất mạng
|
|
68
|
-
│ ├── submitted.svg # Gửi form thành công
|
|
69
|
-
│ ├── success.svg # Generic success
|
|
70
|
-
│ ├── unauthorized.svg # 401
|
|
71
|
-
│ └── unknown-error.svg # 500 / fallback
|
|
72
|
-
└── scss/
|
|
73
|
-
├── sd-core.scss # ENTRY (chỉ file này được import từ host app)
|
|
74
|
-
├── ckeditor5.scss # Override style cho CKEditor 5 (opt-in)
|
|
75
|
-
├── core/
|
|
76
|
-
│ ├── color.scss # Color map + CSS var declarations
|
|
77
|
-
│ ├── form.scss # Override Angular Material form (input/select/checkbox/radio)
|
|
78
|
-
│ ├── image.scss # Tiện ích background-image cho 18 illustration SVG ở trên
|
|
79
|
-
│ ├── scrollbar.scss # Custom scrollbar (webkit + firefox)
|
|
80
|
-
│ └── utilities/
|
|
81
|
-
│ ├── _index.scss # Forward toàn bộ partial bên dưới
|
|
82
|
-
│ ├── _base.scss # Reset/reboot baseline (box-sizing, body, headings, forms…)
|
|
83
|
-
│ ├── _border.scss # rounded-* + border + border-{side}
|
|
84
|
-
│ ├── _display.scss # d-none/block/inline/inline-block/flex/inline-flex/grid
|
|
85
|
-
│ ├── _elevation.scss # mat-elevation-z0–z8
|
|
86
|
-
│ ├── _flexbox.scss # flex-1/none/auto, direction, wrap, grow/shrink, align/justify
|
|
87
|
-
│ ├── _gap.scss # gap-* / gap-x-* / gap-y-*
|
|
88
|
-
│ ├── _grid.scss # row/col 12-column + .grid-container + col-span-*
|
|
89
|
-
│ ├── _misc.scss # align-{middle…}, cursor-*, visible/invisible
|
|
90
|
-
│ ├── _overflow.scss # overflow-*
|
|
91
|
-
│ ├── _position.scss # position-relative/absolute/fixed/sticky/static
|
|
92
|
-
│ ├── _sizing.scss # w-* / h-* + min/max + w-full/screen/auto/fit
|
|
93
|
-
│ ├── _spacing.scss # m-*, p-* (mt/mr/mb/ml/mx/my, pt/pr/pb/pl/px/py) + m-auto
|
|
94
|
-
│ └── _typography.scss # T{n}{M|R} tokens + fs-* + font-weight-* + text-*
|
|
95
|
-
└── themes/
|
|
96
|
-
├── default.scss # sd.theme() mixin — override `--sd-*` color tokens
|
|
97
|
-
└── material-theme.scss # Angular Material M2 theme baseline
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
## 3. Hệ thống màu sắc
|
|
103
|
-
|
|
104
|
-
Màu được định nghĩa dưới dạng **CSS custom properties** với prefix `--sd-*`, cho phép override runtime (không cần recompile SCSS).
|
|
105
|
-
|
|
106
|
-
### 3.1 Color tokens
|
|
107
|
-
|
|
108
|
-
| Token | CSS variable | Default | Dùng cho |
|
|
109
|
-
|---|---|---|---|
|
|
110
|
-
| `primary` | `--sd-primary` | `#2A66F4` | Màu chủ đạo — button, checkbox, accent |
|
|
111
|
-
| `primary-light` | `--sd-primary-light` | `#EAF1FF` | Background nhẹ của primary |
|
|
112
|
-
| `primary-dark` | `--sd-primary-dark` | `#1C4AD9` | Hover/active state của primary |
|
|
113
|
-
| `info` | `--sd-info` | `#2962FF` | Link, thông tin, badge info |
|
|
114
|
-
| `info-light` | `--sd-info-light` | `#E7E9FF` | Background nhẹ của info |
|
|
115
|
-
| `info-dark` | `--sd-info-dark` | `#2240CC` | Hover state của info |
|
|
116
|
-
| `success` | `--sd-success` | `#4CAF50` | Trạng thái thành công, validation OK |
|
|
117
|
-
| `success-light` | `--sd-success-light` | `#DBEFDC` | Background nhẹ của success |
|
|
118
|
-
| `success-dark` | `--sd-success-dark` | `#39833C` | Hover state của success |
|
|
119
|
-
| `warning` | `--sd-warning` | `#FF9600` | Cảnh báo, trạng thái cần chú ý |
|
|
120
|
-
| `warning-light` | `--sd-warning-light` | `#FFEACC` | Background nhẹ của warning |
|
|
121
|
-
| `warning-dark` | `--sd-warning-dark` | `#BF7000` | Hover state của warning |
|
|
122
|
-
| `error` | `--sd-error` | `#F82C13` | Lỗi, validation fail, trạng thái nguy hiểm |
|
|
123
|
-
| `error-light` | `--sd-error-light` | `#FED5D0` | Background nhẹ của error |
|
|
124
|
-
| `error-dark` | `--sd-error-dark` | `#BA200E` | Hover state của error |
|
|
125
|
-
| `secondary` | `--sd-secondary` | `#212121` | Text phụ, icon secondary |
|
|
126
|
-
| `secondary-light` | `--sd-secondary-light` | `#E9E9E9` | Background nhẹ |
|
|
127
|
-
| `secondary-dark` | `--sd-secondary-dark` | `#000000` | — |
|
|
128
|
-
| `light` | `--sd-light` | `#F8F9FA` | Background trang, surface nhẹ |
|
|
129
|
-
| `dark` | `--sd-dark` | `#343A40` | Text đậm, dark surface |
|
|
130
|
-
| `black500` | `--sd-black500` | `#212121` | Text chính |
|
|
131
|
-
| `black400` | `--sd-black400` | `#757575` | Text phụ, placeholder |
|
|
132
|
-
| `black300` | `--sd-black300` | `#BFBFBF` | Divider, border nhẹ |
|
|
133
|
-
| `black200` | `--sd-black200` | `#E6E6E6` | Border mặc định, separator |
|
|
134
|
-
| `black100` | `--sd-black100` | `#F2F2F2` | Background disabled, row hover |
|
|
135
|
-
|
|
136
|
-
### 3.2 Color utility classes
|
|
137
|
-
|
|
138
|
-
Mọi token ở §3.1 đều sinh 3 class:
|
|
139
|
-
|
|
140
|
-
| Pattern | Ví dụ |
|
|
141
|
-
|---|---|
|
|
142
|
-
| `.text-{token}` | `text-primary`, `text-error`, `text-black400` |
|
|
143
|
-
| `.bg-{token}` | `bg-primary-light`, `bg-error-light`, `bg-white` |
|
|
144
|
-
| `.border-{token}` | `border-primary`, `border-black200` |
|
|
145
|
-
|
|
146
|
-
`white` / `black` luôn có sẵn ngoài bảng trên: `.text-white` / `.text-black` / `.bg-white` / `.bg-black`.
|
|
147
|
-
|
|
148
|
-
### 3.3 Dùng màu trong component SCSS
|
|
149
|
-
|
|
150
|
-
```scss
|
|
151
|
-
@use '@sd-angular/core/assets/scss/core/color.scss' as color;
|
|
152
|
-
@use 'sass:map';
|
|
153
|
-
|
|
154
|
-
.my-element {
|
|
155
|
-
color: map.get(color.$color_map, 'primary');
|
|
156
|
-
background: map.get(color.$color_map, 'primary-light');
|
|
157
|
-
border-color: map.get(color.$color_map, 'black200');
|
|
158
|
-
}
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
Hoặc đọc trực tiếp CSS var (recommended cho runtime override):
|
|
162
|
-
|
|
163
|
-
```scss
|
|
164
|
-
.my-element {
|
|
165
|
-
color: var(--sd-primary);
|
|
166
|
-
background: var(--sd-primary-light);
|
|
167
|
-
}
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
---
|
|
171
|
-
|
|
172
|
-
## 4. Typography tokens
|
|
173
|
-
|
|
174
|
-
### 4.1 Design token classes — `T{size}{weight}`
|
|
175
|
-
|
|
176
|
-
Quy ước: `M` = Medium (500), `R` = Regular (400). Mỗi class gồm `font-size` + `font-weight` + `line-height` chuẩn hóa.
|
|
177
|
-
|
|
178
|
-
| Class | Font size | Weight | Line height |
|
|
179
|
-
|---|---|---|---|
|
|
180
|
-
| `T48M` / `T48R` | 48px | 500 / 400 | 56px |
|
|
181
|
-
| `T32M` / `T32R` | 32px | 500 / 400 | 48px |
|
|
182
|
-
| `T24M` / `T24R` | 24px / 20px* | 500 / 400 | 28px |
|
|
183
|
-
| `T20M` / `T20R` | 20px | 500 / 400 | 28px |
|
|
184
|
-
| `T18M` / `T18R` | 18px | 500 / 400 | 28px |
|
|
185
|
-
| `T16M` / `T16R` | 16px | 500 / 400 | 24px |
|
|
186
|
-
| `T14M` / `T14R` | 14px | 500 / 400 | 20px |
|
|
187
|
-
| `T12M` / `T12R`† | 12px | 500 / 400 | 16px |
|
|
188
|
-
| `T10M` / `T10R` | 10px | 500 / 400 | 12px |
|
|
189
|
-
|
|
190
|
-
\* `T24R` font-size 20px (quirk lịch sử — `T24M` là 24px). Khi cần 24px/400, dùng `T20R` 20px hoặc cặp `fs-24 + font-weight-normal`.
|
|
191
|
-
† `T12R` dùng `!important` vì hay bị Angular Material override.
|
|
192
|
-
|
|
193
|
-
### 4.2 Font-size utilities (px-based)
|
|
194
|
-
|
|
195
|
-
```
|
|
196
|
-
fs-0 fs-1 … fs-200
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
Dùng khi cần override nhanh, **không thay** design token. Output: `font-size: {n}px !important`.
|
|
200
|
-
|
|
201
|
-
### 4.3 Font-weight
|
|
202
|
-
|
|
203
|
-
| Class | weight |
|
|
204
|
-
|---|---|
|
|
205
|
-
| `font-weight-light` | 300 |
|
|
206
|
-
| `font-weight-normal` | 400 |
|
|
207
|
-
| `font-weight-medium` | 500 |
|
|
208
|
-
| `font-weight-bold` | 600 |
|
|
209
|
-
| `font-weight-bolder` | 700 |
|
|
210
|
-
|
|
211
|
-
### 4.4 Text alignment / wrap / transform
|
|
212
|
-
|
|
213
|
-
```
|
|
214
|
-
text-left text-center text-right text-justify
|
|
215
|
-
text-wrap text-nowrap text-ellipsis text-break
|
|
216
|
-
text-uppercase text-lowercase text-capitalize
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
| Class | Output |
|
|
220
|
-
|---|---|
|
|
221
|
-
| `text-ellipsis` | `white-space: nowrap; overflow: hidden; text-overflow: ellipsis` (yêu cầu container có width cố định) |
|
|
222
|
-
| `text-break` | `overflow-wrap: break-word; word-break: break-word` (xuống dòng giữa ký tự — URL, hash, mã dài) |
|
|
223
|
-
|
|
224
|
-
---
|
|
225
|
-
|
|
226
|
-
## 5. Layout & Grid
|
|
227
|
-
|
|
228
|
-
### 5.1 Flexbox row/col 12-column
|
|
229
|
-
|
|
230
|
-
```html
|
|
231
|
-
<div class="row">
|
|
232
|
-
<div class="col-6">50%</div>
|
|
233
|
-
<div class="col-6">50%</div>
|
|
234
|
-
</div>
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
`.row` là flex container có gutter `16px` (margin âm trừ gutter + padding nửa gutter trên `> *`).
|
|
238
|
-
|
|
239
|
-
**Gutter variants:**
|
|
240
|
-
|
|
241
|
-
| Class | Gutter |
|
|
242
|
-
|---|---|
|
|
243
|
-
| `row` | 16px (mặc định) |
|
|
244
|
-
| `row-md` | 8px |
|
|
245
|
-
| `row-sm` | 4px |
|
|
246
|
-
| `row-xs` | 2px |
|
|
247
|
-
|
|
248
|
-
**Auto-width column:** `.col` (chiếm phần còn lại, `flex: 1 1 0%`).
|
|
249
|
-
|
|
250
|
-
**Responsive columns** (mobile-first — class chỉ kích hoạt khi viewport ≥ breakpoint):
|
|
251
|
-
|
|
252
|
-
| Pattern | Min-width |
|
|
253
|
-
|---|---|
|
|
254
|
-
| `col-sm-{1-12}` / `col-sm` | ≥ 576px |
|
|
255
|
-
| `col-md-{1-12}` / `col-md` | ≥ 768px |
|
|
256
|
-
| `col-lg-{1-12}` / `col-lg` | ≥ 992px |
|
|
257
|
-
| `col-xl-{1-12}` / `col-xl` | ≥ 1200px |
|
|
258
|
-
|
|
259
|
-
```html
|
|
260
|
-
<div class="row">
|
|
261
|
-
<!-- 100% trên mobile, 50% từ md+, 33% từ lg+ -->
|
|
262
|
-
<div class="col-md-6 col-lg-4">...</div>
|
|
263
|
-
</div>
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
### 5.2 CSS Grid container
|
|
267
|
-
|
|
268
|
-
```html
|
|
269
|
-
<div class="grid-container grid-cols-3">
|
|
270
|
-
<div class="col-span-2">Chiếm 2 cột</div>
|
|
271
|
-
<div class="col-span-1">Chiếm 1 cột</div>
|
|
272
|
-
<div class="col-span-full">Full width</div>
|
|
273
|
-
</div>
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
| Class | Mô tả |
|
|
277
|
-
|---|---|
|
|
278
|
-
| `grid-container` | `display: grid`, `column-gap: 8px`, `row-gap: 0` |
|
|
279
|
-
| `grid-cols-{1-12}` | Số cột |
|
|
280
|
-
| `col-span-{1-12}` | Item chiếm n cột |
|
|
281
|
-
| `col-span-full` | Item chiếm toàn bộ chiều ngang |
|
|
282
|
-
| `row-span-{1-12}` | Item chiếm n hàng |
|
|
283
|
-
| `row-span-full` | Item chiếm toàn bộ chiều dọc |
|
|
284
|
-
|
|
285
|
-
> Các class `col-span-*` / `row-span-*` chỉ có hiệu lực **bên trong** `.grid-container` (selector nested).
|
|
286
|
-
|
|
287
|
-
---
|
|
288
|
-
|
|
289
|
-
## 6. Flexbox utilities
|
|
290
|
-
|
|
291
|
-
| Class | CSS |
|
|
292
|
-
|---|---|
|
|
293
|
-
| `flex-1` | `flex: 1` |
|
|
294
|
-
| `flex-none` | `flex: none` |
|
|
295
|
-
| `flex-auto` | `flex: auto` |
|
|
296
|
-
| `flex-row` | `flex-direction: row` |
|
|
297
|
-
| `flex-column` | `flex-direction: column` |
|
|
298
|
-
| `flex-row-reverse` | `flex-direction: row-reverse` |
|
|
299
|
-
| `flex-column-reverse` | `flex-direction: column-reverse` |
|
|
300
|
-
| `flex-wrap` | `flex-wrap: wrap` |
|
|
301
|
-
| `flex-nowrap` | `flex-wrap: nowrap` |
|
|
302
|
-
| `flex-grow-0` / `flex-grow-1` | `flex-grow: 0 / 1` |
|
|
303
|
-
| `flex-shrink-0` / `flex-shrink-1` | `flex-shrink: 0 / 1` |
|
|
304
|
-
|
|
305
|
-
**align-items:** `align-items-start`, `align-items-end`, `align-items-center`, `align-items-baseline`, `align-items-stretch`.
|
|
306
|
-
|
|
307
|
-
**align-self:** `align-self-start`, `align-self-end`, `align-self-center`, `align-self-stretch`, `align-self-auto`.
|
|
308
|
-
|
|
309
|
-
**align-content:** `align-content-start`, `align-content-end`, `align-content-center`, `align-content-between`, `align-content-around`, `align-content-stretch`.
|
|
310
|
-
|
|
311
|
-
**justify-content:** `justify-content-start`, `justify-content-end`, `justify-content-center`, `justify-content-between`, `justify-content-around`, `justify-content-evenly`.
|
|
312
|
-
|
|
313
|
-
---
|
|
314
|
-
|
|
315
|
-
## 7. Spacing
|
|
316
|
-
|
|
317
|
-
### 7.1 Margin / Padding (px-based, 0–200)
|
|
318
|
-
|
|
319
|
-
```
|
|
320
|
-
m-{n} mt-{n} mr-{n} mb-{n} ml-{n} mx-{n} my-{n}
|
|
321
|
-
p-{n} pt-{n} pr-{n} pb-{n} pl-{n} px-{n} py-{n}
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
Ví dụ: `m-0`, `mt-8`, `px-16`, `py-24`, `mb-4`.
|
|
325
|
-
|
|
326
|
-
**Spacing scale rule:** với spacing dùng cho layout element, chỉ dùng giá trị là **bội số của 4px**: `m-4`, `m-8`, `m-12`, `m-16`, `p-4`, `p-8`, `px-16`, `py-24`, `gap-8`, `gap-16`... Tránh sinh các class lẻ như `m-3`, `p-5`, `gap-7` trừ khi đang xử lý pixel-perfect exception đã được review rõ ràng.
|
|
327
|
-
|
|
328
|
-
**Auto margin:** `m-auto`, `mt-auto`, `mr-auto`, `mb-auto`, `ml-auto`, `mx-auto`, `my-auto`.
|
|
329
|
-
|
|
330
|
-
### 7.2 Gap (px-based, 0–200)
|
|
331
|
-
|
|
332
|
-
```
|
|
333
|
-
gap-{n} gap-x-{n} gap-y-{n}
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
Ví dụ: `gap-8`, `gap-x-16`, `gap-y-4`.
|
|
337
|
-
|
|
338
|
-
---
|
|
339
|
-
|
|
340
|
-
## 8. Sizing
|
|
341
|
-
|
|
342
|
-
### 8.1 Width / Height theo px (0–200)
|
|
343
|
-
|
|
344
|
-
```
|
|
345
|
-
w-{n} h-{n}
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
### 8.2 Width / Height theo %/keyword
|
|
349
|
-
|
|
350
|
-
| Class | CSS |
|
|
351
|
-
|---|---|
|
|
352
|
-
| `w-full` / `w-100` | `width: 100%` (`w-100` là alias của `w-full`) |
|
|
353
|
-
| `w-auto` | `width: auto` |
|
|
354
|
-
| `w-screen` | `width: 100vw` |
|
|
355
|
-
| `w-fit` | `width: fit-content` |
|
|
356
|
-
| `h-full` / `h-100` | `height: 100%` |
|
|
357
|
-
| `h-auto` | `height: auto` |
|
|
358
|
-
| `h-screen` | `height: 100vh` |
|
|
359
|
-
| `h-fit` | `height: fit-content` |
|
|
360
|
-
| `min-h-full` | `min-height: 100%` |
|
|
361
|
-
| `min-h-screen` | `min-height: 100vh` |
|
|
362
|
-
| `min-w-full` | `min-width: 100%` |
|
|
363
|
-
| `max-h-full` | `max-height: 100%` |
|
|
364
|
-
| `max-w-full` | `max-width: 100%` |
|
|
365
|
-
|
|
366
|
-
---
|
|
367
|
-
|
|
368
|
-
## 9. Border & radius
|
|
369
|
-
|
|
370
|
-
### 9.1 Border-radius (px-based, 0–200)
|
|
371
|
-
|
|
372
|
-
```
|
|
373
|
-
rounded-{n} // border-radius: {n}px
|
|
374
|
-
rounded-full // border-radius: 9999px (pill / circle)
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
### 9.2 Border utilities
|
|
378
|
-
|
|
379
|
-
Border color default = `var(--sd-black200)`.
|
|
380
|
-
|
|
381
|
-
| Class | CSS |
|
|
382
|
-
|---|---|
|
|
383
|
-
| `border` | `border: 1px solid var(--sd-black200)` |
|
|
384
|
-
| `border-0` | `border: 0` |
|
|
385
|
-
| `border-top` | `border-top: 1px solid var(--sd-black200)` |
|
|
386
|
-
| `border-bottom` | `border-bottom: 1px solid var(--sd-black200)` |
|
|
387
|
-
| `border-left` | `border-left: 1px solid var(--sd-black200)` |
|
|
388
|
-
| `border-right` | `border-right: 1px solid var(--sd-black200)` |
|
|
389
|
-
|
|
390
|
-
Đổi màu border: kết hợp `.border` với `.border-{token}` (xem §3.2).
|
|
391
|
-
|
|
392
|
-
---
|
|
393
|
-
|
|
394
|
-
## 10. Display, position, overflow, visibility
|
|
395
|
-
|
|
396
|
-
### 10.1 Display
|
|
397
|
-
|
|
398
|
-
| Class | CSS |
|
|
399
|
-
|---|---|
|
|
400
|
-
| `d-none` | `display: none` |
|
|
401
|
-
| `d-block` | `display: block` |
|
|
402
|
-
| `d-inline` | `display: inline` |
|
|
403
|
-
| `d-inline-block` | `display: inline-block` |
|
|
404
|
-
| `d-flex` | `display: flex` |
|
|
405
|
-
| `d-inline-flex` | `display: inline-flex` |
|
|
406
|
-
| `d-grid` | `display: grid` |
|
|
407
|
-
|
|
408
|
-
### 10.2 Position
|
|
409
|
-
|
|
410
|
-
```
|
|
411
|
-
position-relative position-absolute position-fixed
|
|
412
|
-
position-sticky position-static
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
### 10.3 Overflow
|
|
416
|
-
|
|
417
|
-
| Class | CSS |
|
|
418
|
-
|---|---|
|
|
419
|
-
| `overflow-auto` | `overflow: auto` |
|
|
420
|
-
| `overflow-hidden` | `overflow: hidden` |
|
|
421
|
-
| `overflow-visible` | `overflow: visible` |
|
|
422
|
-
| `overflow-scroll` | `overflow: scroll` |
|
|
423
|
-
| `overflow-x-auto` | `overflow-x: auto` |
|
|
424
|
-
| `overflow-y-auto` | `overflow-y: auto` |
|
|
425
|
-
|
|
426
|
-
### 10.4 Visibility
|
|
427
|
-
|
|
428
|
-
| Class | CSS |
|
|
429
|
-
|---|---|
|
|
430
|
-
| `visible` | `visibility: visible` |
|
|
431
|
-
| `invisible` | `visibility: hidden` |
|
|
432
|
-
|
|
433
|
-
---
|
|
434
|
-
|
|
435
|
-
## 11. Cursor, vertical-align, misc
|
|
436
|
-
|
|
437
|
-
**Vertical-align:**
|
|
438
|
-
|
|
439
|
-
```
|
|
440
|
-
align-middle align-top align-bottom align-baseline
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
**Cursor:**
|
|
444
|
-
|
|
445
|
-
```
|
|
446
|
-
cursor-pointer cursor-default cursor-not-allowed
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
---
|
|
450
|
-
|
|
451
|
-
## 12. Elevation (`mat-elevation-z0`–`z8`)
|
|
452
|
-
|
|
453
|
-
CSS shadow tĩnh, tương đương Angular Material `mat.elevation()` mixin nhưng **không cần** import Material SCSS.
|
|
454
|
-
|
|
455
|
-
| Class | Dùng cho |
|
|
456
|
-
|---|---|
|
|
457
|
-
| `mat-elevation-z0` | Reset shadow |
|
|
458
|
-
| `mat-elevation-z1` | Card, chip |
|
|
459
|
-
| `mat-elevation-z2` | Button raised |
|
|
460
|
-
| `mat-elevation-z3` | Card hover |
|
|
461
|
-
| `mat-elevation-z4` | App bar |
|
|
462
|
-
| `mat-elevation-z5` | — |
|
|
463
|
-
| `mat-elevation-z6` | Floating action button |
|
|
464
|
-
| `mat-elevation-z7` | — |
|
|
465
|
-
| `mat-elevation-z8` | Dialog, drawer |
|
|
466
|
-
|
|
467
|
-
---
|
|
468
|
-
|
|
469
|
-
## 13. Reset / Reboot baseline
|
|
470
|
-
|
|
471
|
-
`_base.scss` chạy trước mọi utility, thiết lập rendering chuẩn:
|
|
472
|
-
|
|
473
|
-
| Rule | Mục đích |
|
|
474
|
-
|---|---|
|
|
475
|
-
| `*, *::before, *::after { box-sizing: border-box }` | Bắt buộc — thiếu là layout lệch |
|
|
476
|
-
| `html { -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: transparent; line-height: 1.15 }` | iOS rotation + ẩn tap highlight |
|
|
477
|
-
| `body { font-family: Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 1.5; color: #212529 }` | Baseline typography |
|
|
478
|
-
| `h1…h6` | `margin-top: 0; margin-bottom: 0.5rem` |
|
|
479
|
-
| `p, ol, ul, dl` | `margin-top: 0; margin-bottom: 1rem` |
|
|
480
|
-
| `a { color: #007bff; text-decoration: none }`, `a:hover { text-decoration: underline }` | Link mặc định |
|
|
481
|
-
| `label { display: inline-block; margin-bottom: 0.5rem }` | Form layout (mat-checkbox override ở `core/form.scss`) |
|
|
482
|
-
| `button { border-radius: 0 }`, `button:focus:not(:focus-visible) { outline: 0 }` | Reset native button |
|
|
483
|
-
| `table { border-collapse: collapse }` | Tránh double border |
|
|
484
|
-
| `th { font-weight: 600; text-align: inherit }` | Bỏ bold native browser |
|
|
485
|
-
| `textarea { overflow: auto; resize: vertical }` | Bỏ scrollbar dọc mặc định IE, chỉ resize chiều dọc |
|
|
486
|
-
| `[role="button"] { cursor: pointer }` | A11y |
|
|
487
|
-
| `[hidden] { display: none !important }` | IE10 fallback |
|
|
488
|
-
|
|
489
|
-
---
|
|
490
|
-
|
|
491
|
-
## 14. Custom theme
|
|
492
|
-
|
|
493
|
-
Trong `styles.scss` của host app, gọi `sd.theme()` để override màu, sau đó cấu hình Angular Material M2 palette tương ứng:
|
|
494
|
-
|
|
495
|
-
```scss
|
|
496
|
-
@use '@sd-angular/core/assets/scss/themes/default' as sd;
|
|
497
|
-
@use '@angular/material' as mat;
|
|
498
|
-
@include mat.core();
|
|
499
|
-
|
|
500
|
-
html {
|
|
501
|
-
@include sd.theme(
|
|
502
|
-
(
|
|
503
|
-
primary: #AE7129,
|
|
504
|
-
primary-light: #F4F2F1,
|
|
505
|
-
primary-dark: #6B4414,
|
|
506
|
-
)
|
|
507
|
-
);
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// --- Angular Material M2 palette ---
|
|
511
|
-
|
|
512
|
-
$custom-primary-palette: mat.m2-define-palette((
|
|
513
|
-
50: #F4F2F1, 100: #E7E1DA, 200: #DAC8B4, 300: #D1AC80, 400: #CD9450,
|
|
514
|
-
500: #AE7129, 600: #8D5A1E, 700: #6B4414, 800: #4B2F0E, 900: #34210A,
|
|
515
|
-
contrast: ( 600: white, 700: white, 800: white, 900: white )
|
|
516
|
-
));
|
|
517
|
-
|
|
518
|
-
$custom-accent-palette: mat.m2-define-palette((
|
|
519
|
-
50: #F1F3F1, 100: #DCE5DD, 200: #BBD3BC, 300: #8FC291, 400: #67B76A,
|
|
520
|
-
500: #4CAF50, 600: #3A8C3D, 700: #29692C, 800: #1C471E, 900: #132F14,
|
|
521
|
-
contrast: ( 700: white, 800: white, 900: white )
|
|
522
|
-
));
|
|
523
|
-
|
|
524
|
-
$custom-warn-palette: mat.m2-define-palette((
|
|
525
|
-
50: #F5F0F0, 100: #EAD9D6, 200: #E4B0AA, 300: #E6786B, 400: #EE4430,
|
|
526
|
-
500: #F82C13, 600: #D11801, 700: #9A1100, 800: #680B00, 900: #440700,
|
|
527
|
-
contrast: ( 600: white, 700: white, 800: white, 900: white )
|
|
528
|
-
));
|
|
529
|
-
|
|
530
|
-
$custom-theme: mat.m2-define-light-theme((
|
|
531
|
-
color: ( primary: $custom-primary-palette, accent: $custom-accent-palette, warn: $custom-warn-palette ),
|
|
532
|
-
density: -3,
|
|
533
|
-
));
|
|
534
|
-
|
|
535
|
-
@include mat.all-component-themes($custom-theme);
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
> `sd.theme()` chỉ cần khai báo những token muốn override — token không khai báo giữ default.
|
|
539
|
-
> Cả `sd.theme()` và `mat.all-component-themes()` **phải** gọi trong `styles.scss`, không phải component SCSS.
|
|
540
|
-
|
|
541
|
-
---
|
|
542
|
-
|
|
543
|
-
## 15. Fonts & images shipped
|
|
544
|
-
|
|
545
|
-
### 15.1 Fonts
|
|
546
|
-
|
|
547
|
-
`fonts.scss` declare `@font-face` cho 3 family — host app **không cần** thêm Google Fonts link.
|
|
548
|
-
|
|
549
|
-
| Family | Variants | File path |
|
|
550
|
-
|---|---|---|
|
|
551
|
-
| Roboto | regular (400), 500, 600, italic | `assets/fonts/roboto/roboto-v50-latin_vietnamese-*.woff2` (4 file, latin + vietnamese subset) |
|
|
552
|
-
| Material Icons | regular + outlined | `assets/fonts/material-icons/{material-icons-v145,material-icons-outlined-v110}-latin-regular.woff2` |
|
|
553
|
-
| Material Symbols | regular | `assets/fonts/material-symbols/material-symbols-v29-latin-regular.woff2` |
|
|
554
|
-
|
|
555
|
-
### 15.2 Image assets (18 SVG illustrations)
|
|
556
|
-
|
|
557
|
-
Tham chiếu qua `core/image.scss` utility hoặc trực tiếp `assets/images/<name>.svg`:
|
|
558
|
-
|
|
559
|
-
| File | Dùng cho |
|
|
560
|
-
|---|---|
|
|
561
|
-
| `coming-soon.svg` | Trang chưa sẵn sàng |
|
|
562
|
-
| `data-empty.svg` | Empty state cho table / list |
|
|
563
|
-
| `expired.svg` | Session expired |
|
|
564
|
-
| `file-error.svg` | Upload file lỗi |
|
|
565
|
-
| `filter-empty.svg` | Không kết quả khớp filter |
|
|
566
|
-
| `filter-required.svg` | Yêu cầu chọn filter trước khi load data |
|
|
567
|
-
| `forbidden.svg` | 403 Forbidden |
|
|
568
|
-
| `image-error.svg` | Image load fail |
|
|
569
|
-
| `maintenance.svg` | Đang bảo trì |
|
|
570
|
-
| `not-found.svg` | 404 Not Found |
|
|
571
|
-
| `offline.svg` | Mất mạng |
|
|
572
|
-
| `submitted.svg` | Form gửi thành công |
|
|
573
|
-
| `success.svg` | Generic success |
|
|
574
|
-
| `unauthorized.svg` | 401 Unauthorized |
|
|
575
|
-
| `unknown-error.svg` | 500 / fallback |
|
|
576
|
-
|
|
577
|
-
---
|
|
578
|
-
|
|
579
|
-
## 16. What is NOT shipped
|
|
580
|
-
|
|
581
|
-
Để AI agent không sinh class lạ:
|
|
582
|
-
|
|
583
|
-
- ❌ **Không có Bootstrap, Tailwind, Bulma, Foundation.** Tất cả utility ở §3–§13 là code thuần SCSS của `@sd-angular/core`. Class như `.btn`, `.btn-primary`, `.card`, `.alert`, `.navbar`, `.form-control`, `.input-group`, `.modal`, `.dropdown`, `.list-group`, `.breadcrumb`, `.carousel`, `.popover`, `.tooltip`, `.progress`, `.spinner-border`, `.badge` (Bootstrap) **KHÔNG tồn tại**.
|
|
584
|
-
- ❌ **Không có Tailwind escape syntax** (`md:flex`, `hover:bg-red-500`, `text-[14px]`…). Responsive class duy nhất là `col-sm-*` / `col-md-*` / `col-lg-*` / `col-xl-*` ở §5.1.
|
|
585
|
-
- ❌ **Không có dark mode token** sẵn — phải tự khai báo nếu cần.
|
|
586
|
-
- ❌ **Không có animation utility class** (kiểu `.fade`, `.slide-in`). Animation handle qua Angular `[@trigger]` hoặc CSS riêng của component.
|
|
587
|
-
- ❌ **Không sinh class theo px arbitrary** — `m-{n}`, `p-{n}`, `w-{n}`, `h-{n}`, `fs-{n}`, `gap-{n}`, `rounded-{n}` chỉ chạy từ **0 → 200** integer. Cần `w-250` thì phải tự viết SCSS hoặc dùng inline style.
|
|
588
|
-
- ❌ **Không có shorthand position** (kiểu `top-0`, `left-50`). Set `position-absolute` rồi viết CSS riêng cho offset.
|
|
589
|
-
- ❌ **Component selector không phải utility class.** `sd-button`, `sd-input`, `sd-anchor`… là Angular component (xem `components/*/sd-*.md`), không phải CSS class.
|
|
590
|
-
|
|
591
|
-
### Migration check khi đọc code cũ
|
|
592
|
-
|
|
593
|
-
| Class cũ (Bootstrap) | Thay thế bằng |
|
|
594
|
-
|---|---|
|
|
595
|
-
| `d-flex` | `d-flex` (giữ nguyên — đã port) |
|
|
596
|
-
| `text-center` | `text-center` (giữ nguyên) |
|
|
597
|
-
| `text-truncate` | `text-ellipsis` |
|
|
598
|
-
| `font-weight-normal` | `font-weight-normal` (giữ nguyên) |
|
|
599
|
-
| `mt-2` / `mt-3` … | `mt-8` / `mt-16` … (px-based 0–200, không phải multiplier 4) |
|
|
600
|
-
| `pl-2` | `pl-8` (đổi đơn vị) |
|
|
601
|
-
| `w-100` | `w-100` hoặc `w-full` |
|
|
602
|
-
| `border-secondary` | `border-secondary` (vẫn có — secondary là token màu, không phải utility riêng) |
|
|
603
|
-
| `btn`, `btn-primary` | dùng `<sd-button [color]="primary">` |
|
|
604
|
-
| `form-control` | dùng `<sd-input>` / `<sd-select>` … |
|
|
605
|
-
| `alert` | dùng `<sd-notify>` service |
|
|
606
|
-
| `modal` | dùng `<sd-modal>` |
|
|
607
|
-
|
|
28
|
+
|
|
29
|
+
## 1. Cài đặt vào Angular
|
|
30
|
+
|
|
31
|
+
`angular.json`:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
"styles": [
|
|
35
|
+
"./node_modules/@sd-angular/core/assets/scss/sd-core.scss",
|
|
36
|
+
"src/styles.scss"
|
|
37
|
+
]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`sd-core.scss` là entry point duy nhất — auto-load reset, utilities, color theme, form overrides, scrollbar, Angular Material theme. Không cần import partial nào riêng lẻ.
|
|
41
|
+
|
|
42
|
+
> Convention chung: **mọi utility class đều có `!important`** để đảm bảo override được Angular Material (thường có specificity cao).
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 2. Cấu trúc thư mục `assets/`
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
projects/sd-angular/assets/
|
|
50
|
+
├── STYLE-GUIDE.md # Tài liệu này (assets + SCSS reference cho người + AI agent)
|
|
51
|
+
├── fonts/
|
|
52
|
+
│ ├── fonts.scss # @font-face khai báo cho Roboto + Material Icons + Material Symbols
|
|
53
|
+
│ ├── material-icons/ # 2 file .woff2 (icons-v145 + outlined-v110)
|
|
54
|
+
│ ├── material-symbols/ # 1 file .woff2 (symbols-v29)
|
|
55
|
+
│ └── roboto/ # 4 file .woff2 (regular, italic, 500, 600 — latin + vietnamese)
|
|
56
|
+
├── images/ # SVG illustrations (18 file — empty-state, error, success...)
|
|
57
|
+
│ ├── coming-soon.svg # Trang chưa sẵn sàng
|
|
58
|
+
│ ├── data-empty.svg # Empty state cho table/list
|
|
59
|
+
│ ├── expired.svg # Session expired
|
|
60
|
+
│ ├── file-error.svg # Upload file lỗi
|
|
61
|
+
│ ├── filter-empty.svg # Không match filter
|
|
62
|
+
│ ├── filter-required.svg # Yêu cầu bộ lọc trước khi load
|
|
63
|
+
│ ├── forbidden.svg # 403
|
|
64
|
+
│ ├── image-error.svg # Image load fail
|
|
65
|
+
│ ├── maintenance.svg # Trang đang bảo trì
|
|
66
|
+
│ ├── not-found.svg # 404
|
|
67
|
+
│ ├── offline.svg # Mất mạng
|
|
68
|
+
│ ├── submitted.svg # Gửi form thành công
|
|
69
|
+
│ ├── success.svg # Generic success
|
|
70
|
+
│ ├── unauthorized.svg # 401
|
|
71
|
+
│ └── unknown-error.svg # 500 / fallback
|
|
72
|
+
└── scss/
|
|
73
|
+
├── sd-core.scss # ENTRY (chỉ file này được import từ host app)
|
|
74
|
+
├── ckeditor5.scss # Override style cho CKEditor 5 (opt-in)
|
|
75
|
+
├── core/
|
|
76
|
+
│ ├── color.scss # Color map + CSS var declarations
|
|
77
|
+
│ ├── form.scss # Override Angular Material form (input/select/checkbox/radio)
|
|
78
|
+
│ ├── image.scss # Tiện ích background-image cho 18 illustration SVG ở trên
|
|
79
|
+
│ ├── scrollbar.scss # Custom scrollbar (webkit + firefox)
|
|
80
|
+
│ └── utilities/
|
|
81
|
+
│ ├── _index.scss # Forward toàn bộ partial bên dưới
|
|
82
|
+
│ ├── _base.scss # Reset/reboot baseline (box-sizing, body, headings, forms…)
|
|
83
|
+
│ ├── _border.scss # rounded-* + border + border-{side}
|
|
84
|
+
│ ├── _display.scss # d-none/block/inline/inline-block/flex/inline-flex/grid
|
|
85
|
+
│ ├── _elevation.scss # mat-elevation-z0–z8
|
|
86
|
+
│ ├── _flexbox.scss # flex-1/none/auto, direction, wrap, grow/shrink, align/justify
|
|
87
|
+
│ ├── _gap.scss # gap-* / gap-x-* / gap-y-*
|
|
88
|
+
│ ├── _grid.scss # row/col 12-column + .grid-container + col-span-*
|
|
89
|
+
│ ├── _misc.scss # align-{middle…}, cursor-*, visible/invisible
|
|
90
|
+
│ ├── _overflow.scss # overflow-*
|
|
91
|
+
│ ├── _position.scss # position-relative/absolute/fixed/sticky/static
|
|
92
|
+
│ ├── _sizing.scss # w-* / h-* + min/max + w-full/screen/auto/fit
|
|
93
|
+
│ ├── _spacing.scss # m-*, p-* (mt/mr/mb/ml/mx/my, pt/pr/pb/pl/px/py) + m-auto
|
|
94
|
+
│ └── _typography.scss # T{n}{M|R} tokens + fs-* + font-weight-* + text-*
|
|
95
|
+
└── themes/
|
|
96
|
+
├── default.scss # sd.theme() mixin — override `--sd-*` color tokens
|
|
97
|
+
└── material-theme.scss # Angular Material M2 theme baseline
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 3. Hệ thống màu sắc
|
|
103
|
+
|
|
104
|
+
Màu được định nghĩa dưới dạng **CSS custom properties** với prefix `--sd-*`, cho phép override runtime (không cần recompile SCSS).
|
|
105
|
+
|
|
106
|
+
### 3.1 Color tokens
|
|
107
|
+
|
|
108
|
+
| Token | CSS variable | Default | Dùng cho |
|
|
109
|
+
|---|---|---|---|
|
|
110
|
+
| `primary` | `--sd-primary` | `#2A66F4` | Màu chủ đạo — button, checkbox, accent |
|
|
111
|
+
| `primary-light` | `--sd-primary-light` | `#EAF1FF` | Background nhẹ của primary |
|
|
112
|
+
| `primary-dark` | `--sd-primary-dark` | `#1C4AD9` | Hover/active state của primary |
|
|
113
|
+
| `info` | `--sd-info` | `#2962FF` | Link, thông tin, badge info |
|
|
114
|
+
| `info-light` | `--sd-info-light` | `#E7E9FF` | Background nhẹ của info |
|
|
115
|
+
| `info-dark` | `--sd-info-dark` | `#2240CC` | Hover state của info |
|
|
116
|
+
| `success` | `--sd-success` | `#4CAF50` | Trạng thái thành công, validation OK |
|
|
117
|
+
| `success-light` | `--sd-success-light` | `#DBEFDC` | Background nhẹ của success |
|
|
118
|
+
| `success-dark` | `--sd-success-dark` | `#39833C` | Hover state của success |
|
|
119
|
+
| `warning` | `--sd-warning` | `#FF9600` | Cảnh báo, trạng thái cần chú ý |
|
|
120
|
+
| `warning-light` | `--sd-warning-light` | `#FFEACC` | Background nhẹ của warning |
|
|
121
|
+
| `warning-dark` | `--sd-warning-dark` | `#BF7000` | Hover state của warning |
|
|
122
|
+
| `error` | `--sd-error` | `#F82C13` | Lỗi, validation fail, trạng thái nguy hiểm |
|
|
123
|
+
| `error-light` | `--sd-error-light` | `#FED5D0` | Background nhẹ của error |
|
|
124
|
+
| `error-dark` | `--sd-error-dark` | `#BA200E` | Hover state của error |
|
|
125
|
+
| `secondary` | `--sd-secondary` | `#212121` | Text phụ, icon secondary |
|
|
126
|
+
| `secondary-light` | `--sd-secondary-light` | `#E9E9E9` | Background nhẹ |
|
|
127
|
+
| `secondary-dark` | `--sd-secondary-dark` | `#000000` | — |
|
|
128
|
+
| `light` | `--sd-light` | `#F8F9FA` | Background trang, surface nhẹ |
|
|
129
|
+
| `dark` | `--sd-dark` | `#343A40` | Text đậm, dark surface |
|
|
130
|
+
| `black500` | `--sd-black500` | `#212121` | Text chính |
|
|
131
|
+
| `black400` | `--sd-black400` | `#757575` | Text phụ, placeholder |
|
|
132
|
+
| `black300` | `--sd-black300` | `#BFBFBF` | Divider, border nhẹ |
|
|
133
|
+
| `black200` | `--sd-black200` | `#E6E6E6` | Border mặc định, separator |
|
|
134
|
+
| `black100` | `--sd-black100` | `#F2F2F2` | Background disabled, row hover |
|
|
135
|
+
|
|
136
|
+
### 3.2 Color utility classes
|
|
137
|
+
|
|
138
|
+
Mọi token ở §3.1 đều sinh 3 class:
|
|
139
|
+
|
|
140
|
+
| Pattern | Ví dụ |
|
|
141
|
+
|---|---|
|
|
142
|
+
| `.text-{token}` | `text-primary`, `text-error`, `text-black400` |
|
|
143
|
+
| `.bg-{token}` | `bg-primary-light`, `bg-error-light`, `bg-white` |
|
|
144
|
+
| `.border-{token}` | `border-primary`, `border-black200` |
|
|
145
|
+
|
|
146
|
+
`white` / `black` luôn có sẵn ngoài bảng trên: `.text-white` / `.text-black` / `.bg-white` / `.bg-black`.
|
|
147
|
+
|
|
148
|
+
### 3.3 Dùng màu trong component SCSS
|
|
149
|
+
|
|
150
|
+
```scss
|
|
151
|
+
@use '@sd-angular/core/assets/scss/core/color.scss' as color;
|
|
152
|
+
@use 'sass:map';
|
|
153
|
+
|
|
154
|
+
.my-element {
|
|
155
|
+
color: map.get(color.$color_map, 'primary');
|
|
156
|
+
background: map.get(color.$color_map, 'primary-light');
|
|
157
|
+
border-color: map.get(color.$color_map, 'black200');
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Hoặc đọc trực tiếp CSS var (recommended cho runtime override):
|
|
162
|
+
|
|
163
|
+
```scss
|
|
164
|
+
.my-element {
|
|
165
|
+
color: var(--sd-primary);
|
|
166
|
+
background: var(--sd-primary-light);
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 4. Typography tokens
|
|
173
|
+
|
|
174
|
+
### 4.1 Design token classes — `T{size}{weight}`
|
|
175
|
+
|
|
176
|
+
Quy ước: `M` = Medium (500), `R` = Regular (400). Mỗi class gồm `font-size` + `font-weight` + `line-height` chuẩn hóa.
|
|
177
|
+
|
|
178
|
+
| Class | Font size | Weight | Line height |
|
|
179
|
+
|---|---|---|---|
|
|
180
|
+
| `T48M` / `T48R` | 48px | 500 / 400 | 56px |
|
|
181
|
+
| `T32M` / `T32R` | 32px | 500 / 400 | 48px |
|
|
182
|
+
| `T24M` / `T24R` | 24px / 20px* | 500 / 400 | 28px |
|
|
183
|
+
| `T20M` / `T20R` | 20px | 500 / 400 | 28px |
|
|
184
|
+
| `T18M` / `T18R` | 18px | 500 / 400 | 28px |
|
|
185
|
+
| `T16M` / `T16R` | 16px | 500 / 400 | 24px |
|
|
186
|
+
| `T14M` / `T14R` | 14px | 500 / 400 | 20px |
|
|
187
|
+
| `T12M` / `T12R`† | 12px | 500 / 400 | 16px |
|
|
188
|
+
| `T10M` / `T10R` | 10px | 500 / 400 | 12px |
|
|
189
|
+
|
|
190
|
+
\* `T24R` font-size 20px (quirk lịch sử — `T24M` là 24px). Khi cần 24px/400, dùng `T20R` 20px hoặc cặp `fs-24 + font-weight-normal`.
|
|
191
|
+
† `T12R` dùng `!important` vì hay bị Angular Material override.
|
|
192
|
+
|
|
193
|
+
### 4.2 Font-size utilities (px-based)
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
fs-0 fs-1 … fs-200
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Dùng khi cần override nhanh, **không thay** design token. Output: `font-size: {n}px !important`.
|
|
200
|
+
|
|
201
|
+
### 4.3 Font-weight
|
|
202
|
+
|
|
203
|
+
| Class | weight |
|
|
204
|
+
|---|---|
|
|
205
|
+
| `font-weight-light` | 300 |
|
|
206
|
+
| `font-weight-normal` | 400 |
|
|
207
|
+
| `font-weight-medium` | 500 |
|
|
208
|
+
| `font-weight-bold` | 600 |
|
|
209
|
+
| `font-weight-bolder` | 700 |
|
|
210
|
+
|
|
211
|
+
### 4.4 Text alignment / wrap / transform
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
text-left text-center text-right text-justify
|
|
215
|
+
text-wrap text-nowrap text-ellipsis text-break
|
|
216
|
+
text-uppercase text-lowercase text-capitalize
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
| Class | Output |
|
|
220
|
+
|---|---|
|
|
221
|
+
| `text-ellipsis` | `white-space: nowrap; overflow: hidden; text-overflow: ellipsis` (yêu cầu container có width cố định) |
|
|
222
|
+
| `text-break` | `overflow-wrap: break-word; word-break: break-word` (xuống dòng giữa ký tự — URL, hash, mã dài) |
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## 5. Layout & Grid
|
|
227
|
+
|
|
228
|
+
### 5.1 Flexbox row/col 12-column
|
|
229
|
+
|
|
230
|
+
```html
|
|
231
|
+
<div class="row">
|
|
232
|
+
<div class="col-6">50%</div>
|
|
233
|
+
<div class="col-6">50%</div>
|
|
234
|
+
</div>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
`.row` là flex container có gutter `16px` (margin âm trừ gutter + padding nửa gutter trên `> *`).
|
|
238
|
+
|
|
239
|
+
**Gutter variants:**
|
|
240
|
+
|
|
241
|
+
| Class | Gutter |
|
|
242
|
+
|---|---|
|
|
243
|
+
| `row` | 16px (mặc định) |
|
|
244
|
+
| `row-md` | 8px |
|
|
245
|
+
| `row-sm` | 4px |
|
|
246
|
+
| `row-xs` | 2px |
|
|
247
|
+
|
|
248
|
+
**Auto-width column:** `.col` (chiếm phần còn lại, `flex: 1 1 0%`).
|
|
249
|
+
|
|
250
|
+
**Responsive columns** (mobile-first — class chỉ kích hoạt khi viewport ≥ breakpoint):
|
|
251
|
+
|
|
252
|
+
| Pattern | Min-width |
|
|
253
|
+
|---|---|
|
|
254
|
+
| `col-sm-{1-12}` / `col-sm` | ≥ 576px |
|
|
255
|
+
| `col-md-{1-12}` / `col-md` | ≥ 768px |
|
|
256
|
+
| `col-lg-{1-12}` / `col-lg` | ≥ 992px |
|
|
257
|
+
| `col-xl-{1-12}` / `col-xl` | ≥ 1200px |
|
|
258
|
+
|
|
259
|
+
```html
|
|
260
|
+
<div class="row">
|
|
261
|
+
<!-- 100% trên mobile, 50% từ md+, 33% từ lg+ -->
|
|
262
|
+
<div class="col-md-6 col-lg-4">...</div>
|
|
263
|
+
</div>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### 5.2 CSS Grid container
|
|
267
|
+
|
|
268
|
+
```html
|
|
269
|
+
<div class="grid-container grid-cols-3">
|
|
270
|
+
<div class="col-span-2">Chiếm 2 cột</div>
|
|
271
|
+
<div class="col-span-1">Chiếm 1 cột</div>
|
|
272
|
+
<div class="col-span-full">Full width</div>
|
|
273
|
+
</div>
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
| Class | Mô tả |
|
|
277
|
+
|---|---|
|
|
278
|
+
| `grid-container` | `display: grid`, `column-gap: 8px`, `row-gap: 0` |
|
|
279
|
+
| `grid-cols-{1-12}` | Số cột |
|
|
280
|
+
| `col-span-{1-12}` | Item chiếm n cột |
|
|
281
|
+
| `col-span-full` | Item chiếm toàn bộ chiều ngang |
|
|
282
|
+
| `row-span-{1-12}` | Item chiếm n hàng |
|
|
283
|
+
| `row-span-full` | Item chiếm toàn bộ chiều dọc |
|
|
284
|
+
|
|
285
|
+
> Các class `col-span-*` / `row-span-*` chỉ có hiệu lực **bên trong** `.grid-container` (selector nested).
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## 6. Flexbox utilities
|
|
290
|
+
|
|
291
|
+
| Class | CSS |
|
|
292
|
+
|---|---|
|
|
293
|
+
| `flex-1` | `flex: 1` |
|
|
294
|
+
| `flex-none` | `flex: none` |
|
|
295
|
+
| `flex-auto` | `flex: auto` |
|
|
296
|
+
| `flex-row` | `flex-direction: row` |
|
|
297
|
+
| `flex-column` | `flex-direction: column` |
|
|
298
|
+
| `flex-row-reverse` | `flex-direction: row-reverse` |
|
|
299
|
+
| `flex-column-reverse` | `flex-direction: column-reverse` |
|
|
300
|
+
| `flex-wrap` | `flex-wrap: wrap` |
|
|
301
|
+
| `flex-nowrap` | `flex-wrap: nowrap` |
|
|
302
|
+
| `flex-grow-0` / `flex-grow-1` | `flex-grow: 0 / 1` |
|
|
303
|
+
| `flex-shrink-0` / `flex-shrink-1` | `flex-shrink: 0 / 1` |
|
|
304
|
+
|
|
305
|
+
**align-items:** `align-items-start`, `align-items-end`, `align-items-center`, `align-items-baseline`, `align-items-stretch`.
|
|
306
|
+
|
|
307
|
+
**align-self:** `align-self-start`, `align-self-end`, `align-self-center`, `align-self-stretch`, `align-self-auto`.
|
|
308
|
+
|
|
309
|
+
**align-content:** `align-content-start`, `align-content-end`, `align-content-center`, `align-content-between`, `align-content-around`, `align-content-stretch`.
|
|
310
|
+
|
|
311
|
+
**justify-content:** `justify-content-start`, `justify-content-end`, `justify-content-center`, `justify-content-between`, `justify-content-around`, `justify-content-evenly`.
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## 7. Spacing
|
|
316
|
+
|
|
317
|
+
### 7.1 Margin / Padding (px-based, 0–200)
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
m-{n} mt-{n} mr-{n} mb-{n} ml-{n} mx-{n} my-{n}
|
|
321
|
+
p-{n} pt-{n} pr-{n} pb-{n} pl-{n} px-{n} py-{n}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Ví dụ: `m-0`, `mt-8`, `px-16`, `py-24`, `mb-4`.
|
|
325
|
+
|
|
326
|
+
**Spacing scale rule:** với spacing dùng cho layout element, chỉ dùng giá trị là **bội số của 4px**: `m-4`, `m-8`, `m-12`, `m-16`, `p-4`, `p-8`, `px-16`, `py-24`, `gap-8`, `gap-16`... Tránh sinh các class lẻ như `m-3`, `p-5`, `gap-7` trừ khi đang xử lý pixel-perfect exception đã được review rõ ràng.
|
|
327
|
+
|
|
328
|
+
**Auto margin:** `m-auto`, `mt-auto`, `mr-auto`, `mb-auto`, `ml-auto`, `mx-auto`, `my-auto`.
|
|
329
|
+
|
|
330
|
+
### 7.2 Gap (px-based, 0–200)
|
|
331
|
+
|
|
332
|
+
```
|
|
333
|
+
gap-{n} gap-x-{n} gap-y-{n}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Ví dụ: `gap-8`, `gap-x-16`, `gap-y-4`.
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## 8. Sizing
|
|
341
|
+
|
|
342
|
+
### 8.1 Width / Height theo px (0–200)
|
|
343
|
+
|
|
344
|
+
```
|
|
345
|
+
w-{n} h-{n}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### 8.2 Width / Height theo %/keyword
|
|
349
|
+
|
|
350
|
+
| Class | CSS |
|
|
351
|
+
|---|---|
|
|
352
|
+
| `w-full` / `w-100` | `width: 100%` (`w-100` là alias của `w-full`) |
|
|
353
|
+
| `w-auto` | `width: auto` |
|
|
354
|
+
| `w-screen` | `width: 100vw` |
|
|
355
|
+
| `w-fit` | `width: fit-content` |
|
|
356
|
+
| `h-full` / `h-100` | `height: 100%` |
|
|
357
|
+
| `h-auto` | `height: auto` |
|
|
358
|
+
| `h-screen` | `height: 100vh` |
|
|
359
|
+
| `h-fit` | `height: fit-content` |
|
|
360
|
+
| `min-h-full` | `min-height: 100%` |
|
|
361
|
+
| `min-h-screen` | `min-height: 100vh` |
|
|
362
|
+
| `min-w-full` | `min-width: 100%` |
|
|
363
|
+
| `max-h-full` | `max-height: 100%` |
|
|
364
|
+
| `max-w-full` | `max-width: 100%` |
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## 9. Border & radius
|
|
369
|
+
|
|
370
|
+
### 9.1 Border-radius (px-based, 0–200)
|
|
371
|
+
|
|
372
|
+
```
|
|
373
|
+
rounded-{n} // border-radius: {n}px
|
|
374
|
+
rounded-full // border-radius: 9999px (pill / circle)
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### 9.2 Border utilities
|
|
378
|
+
|
|
379
|
+
Border color default = `var(--sd-black200)`.
|
|
380
|
+
|
|
381
|
+
| Class | CSS |
|
|
382
|
+
|---|---|
|
|
383
|
+
| `border` | `border: 1px solid var(--sd-black200)` |
|
|
384
|
+
| `border-0` | `border: 0` |
|
|
385
|
+
| `border-top` | `border-top: 1px solid var(--sd-black200)` |
|
|
386
|
+
| `border-bottom` | `border-bottom: 1px solid var(--sd-black200)` |
|
|
387
|
+
| `border-left` | `border-left: 1px solid var(--sd-black200)` |
|
|
388
|
+
| `border-right` | `border-right: 1px solid var(--sd-black200)` |
|
|
389
|
+
|
|
390
|
+
Đổi màu border: kết hợp `.border` với `.border-{token}` (xem §3.2).
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## 10. Display, position, overflow, visibility
|
|
395
|
+
|
|
396
|
+
### 10.1 Display
|
|
397
|
+
|
|
398
|
+
| Class | CSS |
|
|
399
|
+
|---|---|
|
|
400
|
+
| `d-none` | `display: none` |
|
|
401
|
+
| `d-block` | `display: block` |
|
|
402
|
+
| `d-inline` | `display: inline` |
|
|
403
|
+
| `d-inline-block` | `display: inline-block` |
|
|
404
|
+
| `d-flex` | `display: flex` |
|
|
405
|
+
| `d-inline-flex` | `display: inline-flex` |
|
|
406
|
+
| `d-grid` | `display: grid` |
|
|
407
|
+
|
|
408
|
+
### 10.2 Position
|
|
409
|
+
|
|
410
|
+
```
|
|
411
|
+
position-relative position-absolute position-fixed
|
|
412
|
+
position-sticky position-static
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### 10.3 Overflow
|
|
416
|
+
|
|
417
|
+
| Class | CSS |
|
|
418
|
+
|---|---|
|
|
419
|
+
| `overflow-auto` | `overflow: auto` |
|
|
420
|
+
| `overflow-hidden` | `overflow: hidden` |
|
|
421
|
+
| `overflow-visible` | `overflow: visible` |
|
|
422
|
+
| `overflow-scroll` | `overflow: scroll` |
|
|
423
|
+
| `overflow-x-auto` | `overflow-x: auto` |
|
|
424
|
+
| `overflow-y-auto` | `overflow-y: auto` |
|
|
425
|
+
|
|
426
|
+
### 10.4 Visibility
|
|
427
|
+
|
|
428
|
+
| Class | CSS |
|
|
429
|
+
|---|---|
|
|
430
|
+
| `visible` | `visibility: visible` |
|
|
431
|
+
| `invisible` | `visibility: hidden` |
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## 11. Cursor, vertical-align, misc
|
|
436
|
+
|
|
437
|
+
**Vertical-align:**
|
|
438
|
+
|
|
439
|
+
```
|
|
440
|
+
align-middle align-top align-bottom align-baseline
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
**Cursor:**
|
|
444
|
+
|
|
445
|
+
```
|
|
446
|
+
cursor-pointer cursor-default cursor-not-allowed
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## 12. Elevation (`mat-elevation-z0`–`z8`)
|
|
452
|
+
|
|
453
|
+
CSS shadow tĩnh, tương đương Angular Material `mat.elevation()` mixin nhưng **không cần** import Material SCSS.
|
|
454
|
+
|
|
455
|
+
| Class | Dùng cho |
|
|
456
|
+
|---|---|
|
|
457
|
+
| `mat-elevation-z0` | Reset shadow |
|
|
458
|
+
| `mat-elevation-z1` | Card, chip |
|
|
459
|
+
| `mat-elevation-z2` | Button raised |
|
|
460
|
+
| `mat-elevation-z3` | Card hover |
|
|
461
|
+
| `mat-elevation-z4` | App bar |
|
|
462
|
+
| `mat-elevation-z5` | — |
|
|
463
|
+
| `mat-elevation-z6` | Floating action button |
|
|
464
|
+
| `mat-elevation-z7` | — |
|
|
465
|
+
| `mat-elevation-z8` | Dialog, drawer |
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## 13. Reset / Reboot baseline
|
|
470
|
+
|
|
471
|
+
`_base.scss` chạy trước mọi utility, thiết lập rendering chuẩn:
|
|
472
|
+
|
|
473
|
+
| Rule | Mục đích |
|
|
474
|
+
|---|---|
|
|
475
|
+
| `*, *::before, *::after { box-sizing: border-box }` | Bắt buộc — thiếu là layout lệch |
|
|
476
|
+
| `html { -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: transparent; line-height: 1.15 }` | iOS rotation + ẩn tap highlight |
|
|
477
|
+
| `body { font-family: Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 1.5; color: #212529 }` | Baseline typography |
|
|
478
|
+
| `h1…h6` | `margin-top: 0; margin-bottom: 0.5rem` |
|
|
479
|
+
| `p, ol, ul, dl` | `margin-top: 0; margin-bottom: 1rem` |
|
|
480
|
+
| `a { color: #007bff; text-decoration: none }`, `a:hover { text-decoration: underline }` | Link mặc định |
|
|
481
|
+
| `label { display: inline-block; margin-bottom: 0.5rem }` | Form layout (mat-checkbox override ở `core/form.scss`) |
|
|
482
|
+
| `button { border-radius: 0 }`, `button:focus:not(:focus-visible) { outline: 0 }` | Reset native button |
|
|
483
|
+
| `table { border-collapse: collapse }` | Tránh double border |
|
|
484
|
+
| `th { font-weight: 600; text-align: inherit }` | Bỏ bold native browser |
|
|
485
|
+
| `textarea { overflow: auto; resize: vertical }` | Bỏ scrollbar dọc mặc định IE, chỉ resize chiều dọc |
|
|
486
|
+
| `[role="button"] { cursor: pointer }` | A11y |
|
|
487
|
+
| `[hidden] { display: none !important }` | IE10 fallback |
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
## 14. Custom theme
|
|
492
|
+
|
|
493
|
+
Trong `styles.scss` của host app, gọi `sd.theme()` để override màu, sau đó cấu hình Angular Material M2 palette tương ứng:
|
|
494
|
+
|
|
495
|
+
```scss
|
|
496
|
+
@use '@sd-angular/core/assets/scss/themes/default' as sd;
|
|
497
|
+
@use '@angular/material' as mat;
|
|
498
|
+
@include mat.core();
|
|
499
|
+
|
|
500
|
+
html {
|
|
501
|
+
@include sd.theme(
|
|
502
|
+
(
|
|
503
|
+
primary: #AE7129,
|
|
504
|
+
primary-light: #F4F2F1,
|
|
505
|
+
primary-dark: #6B4414,
|
|
506
|
+
)
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// --- Angular Material M2 palette ---
|
|
511
|
+
|
|
512
|
+
$custom-primary-palette: mat.m2-define-palette((
|
|
513
|
+
50: #F4F2F1, 100: #E7E1DA, 200: #DAC8B4, 300: #D1AC80, 400: #CD9450,
|
|
514
|
+
500: #AE7129, 600: #8D5A1E, 700: #6B4414, 800: #4B2F0E, 900: #34210A,
|
|
515
|
+
contrast: ( 600: white, 700: white, 800: white, 900: white )
|
|
516
|
+
));
|
|
517
|
+
|
|
518
|
+
$custom-accent-palette: mat.m2-define-palette((
|
|
519
|
+
50: #F1F3F1, 100: #DCE5DD, 200: #BBD3BC, 300: #8FC291, 400: #67B76A,
|
|
520
|
+
500: #4CAF50, 600: #3A8C3D, 700: #29692C, 800: #1C471E, 900: #132F14,
|
|
521
|
+
contrast: ( 700: white, 800: white, 900: white )
|
|
522
|
+
));
|
|
523
|
+
|
|
524
|
+
$custom-warn-palette: mat.m2-define-palette((
|
|
525
|
+
50: #F5F0F0, 100: #EAD9D6, 200: #E4B0AA, 300: #E6786B, 400: #EE4430,
|
|
526
|
+
500: #F82C13, 600: #D11801, 700: #9A1100, 800: #680B00, 900: #440700,
|
|
527
|
+
contrast: ( 600: white, 700: white, 800: white, 900: white )
|
|
528
|
+
));
|
|
529
|
+
|
|
530
|
+
$custom-theme: mat.m2-define-light-theme((
|
|
531
|
+
color: ( primary: $custom-primary-palette, accent: $custom-accent-palette, warn: $custom-warn-palette ),
|
|
532
|
+
density: -3,
|
|
533
|
+
));
|
|
534
|
+
|
|
535
|
+
@include mat.all-component-themes($custom-theme);
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
> `sd.theme()` chỉ cần khai báo những token muốn override — token không khai báo giữ default.
|
|
539
|
+
> Cả `sd.theme()` và `mat.all-component-themes()` **phải** gọi trong `styles.scss`, không phải component SCSS.
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
## 15. Fonts & images shipped
|
|
544
|
+
|
|
545
|
+
### 15.1 Fonts
|
|
546
|
+
|
|
547
|
+
`fonts.scss` declare `@font-face` cho 3 family — host app **không cần** thêm Google Fonts link.
|
|
548
|
+
|
|
549
|
+
| Family | Variants | File path |
|
|
550
|
+
|---|---|---|
|
|
551
|
+
| Roboto | regular (400), 500, 600, italic | `assets/fonts/roboto/roboto-v50-latin_vietnamese-*.woff2` (4 file, latin + vietnamese subset) |
|
|
552
|
+
| Material Icons | regular + outlined | `assets/fonts/material-icons/{material-icons-v145,material-icons-outlined-v110}-latin-regular.woff2` |
|
|
553
|
+
| Material Symbols | regular | `assets/fonts/material-symbols/material-symbols-v29-latin-regular.woff2` |
|
|
554
|
+
|
|
555
|
+
### 15.2 Image assets (18 SVG illustrations)
|
|
556
|
+
|
|
557
|
+
Tham chiếu qua `core/image.scss` utility hoặc trực tiếp `assets/images/<name>.svg`:
|
|
558
|
+
|
|
559
|
+
| File | Dùng cho |
|
|
560
|
+
|---|---|
|
|
561
|
+
| `coming-soon.svg` | Trang chưa sẵn sàng |
|
|
562
|
+
| `data-empty.svg` | Empty state cho table / list |
|
|
563
|
+
| `expired.svg` | Session expired |
|
|
564
|
+
| `file-error.svg` | Upload file lỗi |
|
|
565
|
+
| `filter-empty.svg` | Không kết quả khớp filter |
|
|
566
|
+
| `filter-required.svg` | Yêu cầu chọn filter trước khi load data |
|
|
567
|
+
| `forbidden.svg` | 403 Forbidden |
|
|
568
|
+
| `image-error.svg` | Image load fail |
|
|
569
|
+
| `maintenance.svg` | Đang bảo trì |
|
|
570
|
+
| `not-found.svg` | 404 Not Found |
|
|
571
|
+
| `offline.svg` | Mất mạng |
|
|
572
|
+
| `submitted.svg` | Form gửi thành công |
|
|
573
|
+
| `success.svg` | Generic success |
|
|
574
|
+
| `unauthorized.svg` | 401 Unauthorized |
|
|
575
|
+
| `unknown-error.svg` | 500 / fallback |
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
579
|
+
## 16. What is NOT shipped
|
|
580
|
+
|
|
581
|
+
Để AI agent không sinh class lạ:
|
|
582
|
+
|
|
583
|
+
- ❌ **Không có Bootstrap, Tailwind, Bulma, Foundation.** Tất cả utility ở §3–§13 là code thuần SCSS của `@sd-angular/core`. Class như `.btn`, `.btn-primary`, `.card`, `.alert`, `.navbar`, `.form-control`, `.input-group`, `.modal`, `.dropdown`, `.list-group`, `.breadcrumb`, `.carousel`, `.popover`, `.tooltip`, `.progress`, `.spinner-border`, `.badge` (Bootstrap) **KHÔNG tồn tại**.
|
|
584
|
+
- ❌ **Không có Tailwind escape syntax** (`md:flex`, `hover:bg-red-500`, `text-[14px]`…). Responsive class duy nhất là `col-sm-*` / `col-md-*` / `col-lg-*` / `col-xl-*` ở §5.1.
|
|
585
|
+
- ❌ **Không có dark mode token** sẵn — phải tự khai báo nếu cần.
|
|
586
|
+
- ❌ **Không có animation utility class** (kiểu `.fade`, `.slide-in`). Animation handle qua Angular `[@trigger]` hoặc CSS riêng của component.
|
|
587
|
+
- ❌ **Không sinh class theo px arbitrary** — `m-{n}`, `p-{n}`, `w-{n}`, `h-{n}`, `fs-{n}`, `gap-{n}`, `rounded-{n}` chỉ chạy từ **0 → 200** integer. Cần `w-250` thì phải tự viết SCSS hoặc dùng inline style.
|
|
588
|
+
- ❌ **Không có shorthand position** (kiểu `top-0`, `left-50`). Set `position-absolute` rồi viết CSS riêng cho offset.
|
|
589
|
+
- ❌ **Component selector không phải utility class.** `sd-button`, `sd-input`, `sd-anchor`… là Angular component (xem `components/*/sd-*.md`), không phải CSS class.
|
|
590
|
+
|
|
591
|
+
### Migration check khi đọc code cũ
|
|
592
|
+
|
|
593
|
+
| Class cũ (Bootstrap) | Thay thế bằng |
|
|
594
|
+
|---|---|
|
|
595
|
+
| `d-flex` | `d-flex` (giữ nguyên — đã port) |
|
|
596
|
+
| `text-center` | `text-center` (giữ nguyên) |
|
|
597
|
+
| `text-truncate` | `text-ellipsis` |
|
|
598
|
+
| `font-weight-normal` | `font-weight-normal` (giữ nguyên) |
|
|
599
|
+
| `mt-2` / `mt-3` … | `mt-8` / `mt-16` … (px-based 0–200, không phải multiplier 4) |
|
|
600
|
+
| `pl-2` | `pl-8` (đổi đơn vị) |
|
|
601
|
+
| `w-100` | `w-100` hoặc `w-full` |
|
|
602
|
+
| `border-secondary` | `border-secondary` (vẫn có — secondary là token màu, không phải utility riêng) |
|
|
603
|
+
| `btn`, `btn-primary` | dùng `<sd-button [color]="primary">` |
|
|
604
|
+
| `form-control` | dùng `<sd-input>` / `<sd-select>` … |
|
|
605
|
+
| `alert` | dùng `<sd-notify>` service |
|
|
606
|
+
| `modal` | dùng `<sd-modal>` |
|
|
607
|
+
|
|
608
608
|
> Lưu ý lớn nhất: **spacing scale đã đổi từ Bootstrap multiplier (1=4px, 2=8px…) sang px tuyệt đối**. `mb-3` trong Bootstrap = 16px; trong `@sd-angular/core` `mb-3` = **3px**. Reading code cũ cần convert (× 4) cẩn thận hoặc thay bằng `mb-16`.
|
|
609
609
|
|
|
610
610
|
---
|