@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.
Files changed (166) hide show
  1. package/README.md +712 -712
  2. package/assets/STYLE-GUIDE.md +601 -601
  3. package/assets/images/coming-soon.svg +22 -22
  4. package/assets/images/data-empty.svg +20 -20
  5. package/assets/images/expired.svg +21 -21
  6. package/assets/images/file-error.svg +27 -27
  7. package/assets/images/filter-empty.svg +19 -19
  8. package/assets/images/filter-required.svg +20 -20
  9. package/assets/images/forbidden.svg +14 -14
  10. package/assets/images/image-error.svg +26 -26
  11. package/assets/images/maintenance.svg +22 -22
  12. package/assets/images/not-found.svg +19 -19
  13. package/assets/images/offline.svg +19 -19
  14. package/assets/images/submitted.svg +17 -17
  15. package/assets/images/success.svg +17 -17
  16. package/assets/images/unauthorized.svg +21 -21
  17. package/assets/images/unknown-error.svg +17 -17
  18. package/assets/scss/ckeditor5.scss +88 -88
  19. package/assets/scss/core/_inline-edit.scss +105 -105
  20. package/assets/scss/core/color.scss +73 -73
  21. package/assets/scss/core/form.scss +317 -317
  22. package/assets/scss/core/image.scss +35 -35
  23. package/assets/scss/core/utilities/_base.scss +333 -333
  24. package/assets/scss/core/utilities/_border.scss +22 -22
  25. package/assets/scss/core/utilities/_display.scss +10 -10
  26. package/assets/scss/core/utilities/_elevation.scss +80 -80
  27. package/assets/scss/core/utilities/_flexbox.scss +54 -54
  28. package/assets/scss/core/utilities/_gap.scss +9 -9
  29. package/assets/scss/core/utilities/_index.scss +17 -17
  30. package/assets/scss/core/utilities/_misc.scss +20 -20
  31. package/assets/scss/core/utilities/_overflow.scss +9 -9
  32. package/assets/scss/core/utilities/_position.scss +8 -8
  33. package/assets/scss/core/utilities/_sizing.scss +28 -28
  34. package/assets/scss/core/utilities/_spacing.scss +31 -31
  35. package/assets/scss/core/utilities/_typography.scss +99 -99
  36. package/assets/scss/sd-core.scss +16 -16
  37. package/assets/scss/themes/default.scss +45 -45
  38. package/assets/scss/themes/material-theme.scss +101 -101
  39. package/components/preview/src/preview-pdf/pdf-worker-inline.generated.d.ts +7 -0
  40. package/components/table/src/services/table-export/table-export.service.d.ts +3 -1
  41. package/components/table/src/table.component.d.ts +1 -1
  42. package/fesm2022/sd-angular-core-components-anchor.mjs +6 -6
  43. package/fesm2022/sd-angular-core-components-anchor.mjs.map +1 -1
  44. package/fesm2022/sd-angular-core-components-autoid-inspector.mjs +2 -2
  45. package/fesm2022/sd-angular-core-components-autoid-inspector.mjs.map +1 -1
  46. package/fesm2022/sd-angular-core-components-badge.mjs +2 -2
  47. package/fesm2022/sd-angular-core-components-badge.mjs.map +1 -1
  48. package/fesm2022/sd-angular-core-components-base.mjs.map +1 -1
  49. package/fesm2022/sd-angular-core-components-button.mjs +2 -2
  50. package/fesm2022/sd-angular-core-components-button.mjs.map +1 -1
  51. package/fesm2022/sd-angular-core-components-chart.mjs +40 -40
  52. package/fesm2022/sd-angular-core-components-chart.mjs.map +1 -1
  53. package/fesm2022/sd-angular-core-components-ckeditor-styles.mjs.map +1 -1
  54. package/fesm2022/sd-angular-core-components-code-editor.mjs +2 -2
  55. package/fesm2022/sd-angular-core-components-code-editor.mjs.map +1 -1
  56. package/fesm2022/sd-angular-core-components-document-builder.mjs +77 -77
  57. package/fesm2022/sd-angular-core-components-document-builder.mjs.map +1 -1
  58. package/fesm2022/sd-angular-core-components-editor.mjs +2 -2
  59. package/fesm2022/sd-angular-core-components-editor.mjs.map +1 -1
  60. package/fesm2022/sd-angular-core-components-form-generic.mjs +106 -106
  61. package/fesm2022/sd-angular-core-components-form-generic.mjs.map +1 -1
  62. package/fesm2022/sd-angular-core-components-history.mjs +2 -2
  63. package/fesm2022/sd-angular-core-components-history.mjs.map +1 -1
  64. package/fesm2022/sd-angular-core-components-import-excel.mjs +2 -2
  65. package/fesm2022/sd-angular-core-components-import-excel.mjs.map +1 -1
  66. package/fesm2022/sd-angular-core-components-inform.mjs.map +1 -1
  67. package/fesm2022/sd-angular-core-components-mini-editor.mjs +2 -2
  68. package/fesm2022/sd-angular-core-components-mini-editor.mjs.map +1 -1
  69. package/fesm2022/sd-angular-core-components-modal-resizable.mjs +2 -2
  70. package/fesm2022/sd-angular-core-components-modal-resizable.mjs.map +1 -1
  71. package/fesm2022/sd-angular-core-components-modal.mjs +2 -2
  72. package/fesm2022/sd-angular-core-components-modal.mjs.map +1 -1
  73. package/fesm2022/sd-angular-core-components-operator.mjs +2 -2
  74. package/fesm2022/sd-angular-core-components-operator.mjs.map +1 -1
  75. package/fesm2022/sd-angular-core-components-org-chart.mjs +2 -2
  76. package/fesm2022/sd-angular-core-components-org-chart.mjs.map +1 -1
  77. package/fesm2022/sd-angular-core-components-preview.mjs +32 -6
  78. package/fesm2022/sd-angular-core-components-preview.mjs.map +1 -1
  79. package/fesm2022/sd-angular-core-components-query-bar.mjs +10 -10
  80. package/fesm2022/sd-angular-core-components-query-bar.mjs.map +1 -1
  81. package/fesm2022/sd-angular-core-components-query-builder.mjs +2 -2
  82. package/fesm2022/sd-angular-core-components-query-builder.mjs.map +1 -1
  83. package/fesm2022/sd-angular-core-components-section.mjs +4 -4
  84. package/fesm2022/sd-angular-core-components-section.mjs.map +1 -1
  85. package/fesm2022/sd-angular-core-components-side-drawer.mjs +2 -2
  86. package/fesm2022/sd-angular-core-components-side-drawer.mjs.map +1 -1
  87. package/fesm2022/sd-angular-core-components-stepper.mjs +2 -2
  88. package/fesm2022/sd-angular-core-components-stepper.mjs.map +1 -1
  89. package/fesm2022/sd-angular-core-components-tab-router.mjs +6 -6
  90. package/fesm2022/sd-angular-core-components-tab-router.mjs.map +1 -1
  91. package/fesm2022/sd-angular-core-components-tab.mjs +2 -2
  92. package/fesm2022/sd-angular-core-components-tab.mjs.map +1 -1
  93. package/fesm2022/sd-angular-core-components-table.mjs +32 -17
  94. package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
  95. package/fesm2022/sd-angular-core-components-upload-file.mjs +4 -4
  96. package/fesm2022/sd-angular-core-components-upload-file.mjs.map +1 -1
  97. package/fesm2022/sd-angular-core-components-view.mjs +2 -2
  98. package/fesm2022/sd-angular-core-components-view.mjs.map +1 -1
  99. package/fesm2022/sd-angular-core-configurations.mjs.map +1 -1
  100. package/fesm2022/sd-angular-core-directives.mjs +20 -20
  101. package/fesm2022/sd-angular-core-directives.mjs.map +1 -1
  102. package/fesm2022/sd-angular-core-forms-autocomplete.mjs +2 -2
  103. package/fesm2022/sd-angular-core-forms-autocomplete.mjs.map +1 -1
  104. package/fesm2022/sd-angular-core-forms-checkbox.mjs +2 -2
  105. package/fesm2022/sd-angular-core-forms-checkbox.mjs.map +1 -1
  106. package/fesm2022/sd-angular-core-forms-chip-calendar.mjs +2 -2
  107. package/fesm2022/sd-angular-core-forms-chip-calendar.mjs.map +1 -1
  108. package/fesm2022/sd-angular-core-forms-chip.mjs +2 -2
  109. package/fesm2022/sd-angular-core-forms-chip.mjs.map +1 -1
  110. package/fesm2022/sd-angular-core-forms-date-range.mjs +2 -2
  111. package/fesm2022/sd-angular-core-forms-date-range.mjs.map +1 -1
  112. package/fesm2022/sd-angular-core-forms-date.mjs +114 -35
  113. package/fesm2022/sd-angular-core-forms-date.mjs.map +1 -1
  114. package/fesm2022/sd-angular-core-forms-datetime.mjs +6 -6
  115. package/fesm2022/sd-angular-core-forms-datetime.mjs.map +1 -1
  116. package/fesm2022/sd-angular-core-forms-directives.mjs.map +1 -1
  117. package/fesm2022/sd-angular-core-forms-inline-text.mjs +2 -2
  118. package/fesm2022/sd-angular-core-forms-inline-text.mjs.map +1 -1
  119. package/fesm2022/sd-angular-core-forms-input-color.mjs +2 -2
  120. package/fesm2022/sd-angular-core-forms-input-color.mjs.map +1 -1
  121. package/fesm2022/sd-angular-core-forms-input-number.mjs.map +1 -1
  122. package/fesm2022/sd-angular-core-forms-input.mjs +2 -2
  123. package/fesm2022/sd-angular-core-forms-input.mjs.map +1 -1
  124. package/fesm2022/sd-angular-core-forms-label.mjs +2 -2
  125. package/fesm2022/sd-angular-core-forms-label.mjs.map +1 -1
  126. package/fesm2022/sd-angular-core-forms-models.mjs.map +1 -1
  127. package/fesm2022/sd-angular-core-forms-radio.mjs +2 -2
  128. package/fesm2022/sd-angular-core-forms-radio.mjs.map +1 -1
  129. package/fesm2022/sd-angular-core-forms-select.mjs +2 -2
  130. package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
  131. package/fesm2022/sd-angular-core-forms-switch.mjs +2 -2
  132. package/fesm2022/sd-angular-core-forms-switch.mjs.map +1 -1
  133. package/fesm2022/sd-angular-core-forms-textarea.mjs +2 -2
  134. package/fesm2022/sd-angular-core-forms-textarea.mjs.map +1 -1
  135. package/fesm2022/sd-angular-core-handlers.mjs.map +1 -1
  136. package/fesm2022/sd-angular-core-i18n.mjs +20 -0
  137. package/fesm2022/sd-angular-core-i18n.mjs.map +1 -1
  138. package/fesm2022/sd-angular-core-interceptors.mjs.map +1 -1
  139. package/fesm2022/sd-angular-core-modules-auth.mjs.map +1 -1
  140. package/fesm2022/sd-angular-core-modules-authom.mjs.map +1 -1
  141. package/fesm2022/sd-angular-core-modules-keycloak.mjs.map +1 -1
  142. package/fesm2022/sd-angular-core-modules-layout.mjs +130 -43
  143. package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
  144. package/fesm2022/sd-angular-core-modules-permission.mjs.map +1 -1
  145. package/fesm2022/sd-angular-core-pipes.mjs.map +1 -1
  146. package/fesm2022/sd-angular-core-services-api.mjs.map +1 -1
  147. package/fesm2022/sd-angular-core-services-cache.mjs.map +1 -1
  148. package/fesm2022/sd-angular-core-services-confirm.mjs +2 -2
  149. package/fesm2022/sd-angular-core-services-confirm.mjs.map +1 -1
  150. package/fesm2022/sd-angular-core-services-docx.mjs.map +1 -1
  151. package/fesm2022/sd-angular-core-services-excel.mjs.map +1 -1
  152. package/fesm2022/sd-angular-core-services-license.mjs.map +1 -1
  153. package/fesm2022/sd-angular-core-services-loading.mjs +5 -5
  154. package/fesm2022/sd-angular-core-services-loading.mjs.map +1 -1
  155. package/fesm2022/sd-angular-core-services-notify.mjs +12 -12
  156. package/fesm2022/sd-angular-core-services-notify.mjs.map +1 -1
  157. package/fesm2022/sd-angular-core-services-storage.mjs.map +1 -1
  158. package/fesm2022/sd-angular-core-utilities-data-state.mjs.map +1 -1
  159. package/fesm2022/sd-angular-core-utilities-extensions.mjs.map +1 -1
  160. package/forms/date/src/date.component.d.ts +9 -1
  161. package/i18n/src/en.d.ts +4 -0
  162. package/modules/layout/index.d.ts +1 -0
  163. package/modules/layout/utils/index.d.ts +1 -0
  164. package/modules/layout/utils/tab-name.util.d.ts +8 -0
  165. package/package.json +73 -73
  166. package/sd-angular-core-19.0.13.tgz +0 -0
@@ -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
  ---