@fui-org/fui-cli 1.3.2 → 2.1.0

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 (115) hide show
  1. package/README.md +21 -3
  2. package/dist/fui-cx180e19.js +379 -0
  3. package/dist/fui.js +1 -1
  4. package/package.json +3 -6
  5. package/skills/fui/SKILL.md +9 -41
  6. package/skills/fui-skill/SKILL.md +95 -225
  7. package/skills/fui-skill/assets/projectdefaultstyle-3.0.css +555 -0
  8. package/skills/fui-skill/assets/projectdefaultstyle.css +207 -235
  9. package/skills/fui-skill/references/INDEX.md +105 -137
  10. package/skills/fui-skill/references/advanced-techniques.md +76 -68
  11. package/skills/fui-skill/references/coding-standards.md +56 -56
  12. package/skills/fui-skill/references/component-design.md +166 -173
  13. package/skills/fui-skill/references/component-quickref.md +61 -60
  14. package/skills/fui-skill/references/component-table.md +128 -117
  15. package/skills/fui-skill/references/components-dialog.md +55 -56
  16. package/skills/fui-skill/references/components-display.md +24 -30
  17. package/skills/fui-skill/references/components-echart.md +186 -261
  18. package/skills/fui-skill/references/components-input.md +72 -96
  19. package/skills/fui-skill/references/controls-patterns.md +196 -342
  20. package/skills/fui-skill/references/controls-styling-vocabulary.md +130 -97
  21. package/skills/fui-skill/references/db-table-design.md +24 -28
  22. package/skills/fui-skill/references/db-workflow.md +191 -390
  23. package/skills/fui-skill/references/default-function.md +169 -128
  24. package/skills/fui-skill/references/design-modes.md +35 -63
  25. package/skills/fui-skill/references/echart-templates.md +204 -196
  26. package/skills/fui-skill/references/fastproject.md +62 -60
  27. package/skills/fui-skill/references/fsheet.md +109 -124
  28. package/skills/fui-skill/references/fullstack-workflow.md +90 -128
  29. package/skills/fui-skill/references/module-data-patterns.md +31 -40
  30. package/skills/fui-skill/references/module-json-anatomy.md +47 -52
  31. package/skills/fui-skill/references/module-structure.md +80 -196
  32. package/skills/fui-skill/references/new-session.md +49 -51
  33. package/skills/fui-skill/references/pdfmake.md +17 -17
  34. package/skills/fui-skill/references/permission-system.md +89 -108
  35. package/skills/fui-skill/references/platform-architecture.md +128 -153
  36. package/skills/fui-skill/references/project-config.md +102 -134
  37. package/skills/fui-skill/references/project-provisioning.md +139 -244
  38. package/skills/fui-skill/references/script-map.md +208 -242
  39. package/skills/fui-skill/references/sql-clr-functions.md +98 -97
  40. package/skills/fui-skill/references/system-design.md +63 -88
  41. package/skills/fui-skill/references/tapi-file-api.md +46 -52
  42. package/skills/fui-skill/references/tapi-permission-patterns.md +51 -53
  43. package/skills/fui-skill/references/tapi-reference.md +132 -207
  44. package/skills/fui-skill/references/tools-registry.md +84 -460
  45. package/skills/fui-skill/references/ui-crosswindow-patterns.md +79 -75
  46. package/skills/fui-skill/references/ui-dialog-patterns.md +98 -72
  47. package/skills/fui-skill/references/ui-layout-patterns.md +26 -26
  48. package/skills/fui-skill/references/ui-patterns.md +71 -83
  49. package/skills/fui-skill/references/ui-screenshot-review.md +63 -62
  50. package/skills/fui-skill/references/ui-table-cell-patterns.md +61 -59
  51. package/skills/fui-skill/references/ui-templates.md +16 -23
  52. package/skills/fui-skill/references/verification.md +236 -246
  53. package/skills/fui-skill/references/watcher-patterns.md +30 -63
  54. package/skills/fui-skill/references/websocket-realtime.md +83 -66
  55. package/skills/fui-skill/scripts/component-3.0.js +298 -131
  56. package/skills/fui-skill/scripts/component.js +277 -271
  57. package/skills/fui-skill/scripts/componentTable-3.0.js +182 -53
  58. package/skills/fui-skill/scripts/componentTable.js +171 -49
  59. package/skills/fui-skill/scripts/defaultfunction-3.0.js +88 -3
  60. package/skills/fui-skill/scripts/defaultfunction.js +88 -3
  61. package/skills/fui-skill/scripts/fsheet.js +38 -0
  62. package/skills/fui-target/.claude-plugin/plugin.json +6 -0
  63. package/skills/fui-target/hooks/hooks.json +1 -0
  64. package/skills/fui-target/hooks/register.tsx +71 -0
  65. package/skills/fui-target/types/index.d.ts +7 -0
  66. package/dist/fui-y8an39cn.js +0 -420
  67. package/skills/fui-skill/README.md +0 -112
  68. package/skills/fui-skill/metadata.json +0 -75
  69. package/skills/fui-skill-cli/SKILL.md +0 -139
  70. package/skills/fui-skill-cli/references/INDEX.md +0 -110
  71. package/skills/fui-skill-cli/references/advanced-techniques.md +0 -168
  72. package/skills/fui-skill-cli/references/coding-standards.md +0 -112
  73. package/skills/fui-skill-cli/references/component-design.md +0 -448
  74. package/skills/fui-skill-cli/references/component-quickref.md +0 -78
  75. package/skills/fui-skill-cli/references/component-table.md +0 -248
  76. package/skills/fui-skill-cli/references/components-dialog.md +0 -191
  77. package/skills/fui-skill-cli/references/components-display.md +0 -141
  78. package/skills/fui-skill-cli/references/components-echart.md +0 -316
  79. package/skills/fui-skill-cli/references/components-input.md +0 -335
  80. package/skills/fui-skill-cli/references/controls-patterns.md +0 -701
  81. package/skills/fui-skill-cli/references/controls-styling-vocabulary.md +0 -137
  82. package/skills/fui-skill-cli/references/db-table-design.md +0 -73
  83. package/skills/fui-skill-cli/references/db-workflow.md +0 -288
  84. package/skills/fui-skill-cli/references/default-function.md +0 -425
  85. package/skills/fui-skill-cli/references/design-modes.md +0 -57
  86. package/skills/fui-skill-cli/references/echart-templates.md +0 -489
  87. package/skills/fui-skill-cli/references/fastproject.md +0 -99
  88. package/skills/fui-skill-cli/references/fsheet.md +0 -203
  89. package/skills/fui-skill-cli/references/fullstack-workflow.md +0 -313
  90. package/skills/fui-skill-cli/references/module-data-patterns.md +0 -117
  91. package/skills/fui-skill-cli/references/module-json-anatomy.md +0 -132
  92. package/skills/fui-skill-cli/references/module-structure.md +0 -141
  93. package/skills/fui-skill-cli/references/new-session.md +0 -85
  94. package/skills/fui-skill-cli/references/pdfmake.md +0 -60
  95. package/skills/fui-skill-cli/references/permission-system.md +0 -150
  96. package/skills/fui-skill-cli/references/platform-architecture.md +0 -269
  97. package/skills/fui-skill-cli/references/project-config.md +0 -303
  98. package/skills/fui-skill-cli/references/project-provisioning.md +0 -278
  99. package/skills/fui-skill-cli/references/script-map.md +0 -262
  100. package/skills/fui-skill-cli/references/sql-clr-functions.md +0 -225
  101. package/skills/fui-skill-cli/references/system-design.md +0 -89
  102. package/skills/fui-skill-cli/references/tapi-file-api.md +0 -185
  103. package/skills/fui-skill-cli/references/tapi-permission-patterns.md +0 -156
  104. package/skills/fui-skill-cli/references/tapi-reference.md +0 -474
  105. package/skills/fui-skill-cli/references/tools-registry.md +0 -84
  106. package/skills/fui-skill-cli/references/ui-crosswindow-patterns.md +0 -321
  107. package/skills/fui-skill-cli/references/ui-dialog-patterns.md +0 -255
  108. package/skills/fui-skill-cli/references/ui-layout-patterns.md +0 -176
  109. package/skills/fui-skill-cli/references/ui-patterns.md +0 -303
  110. package/skills/fui-skill-cli/references/ui-screenshot-review.md +0 -95
  111. package/skills/fui-skill-cli/references/ui-table-cell-patterns.md +0 -318
  112. package/skills/fui-skill-cli/references/ui-templates.md +0 -22
  113. package/skills/fui-skill-cli/references/verification.md +0 -236
  114. package/skills/fui-skill-cli/references/watcher-patterns.md +0 -163
  115. package/skills/fui-skill-cli/references/websocket-realtime.md +0 -271
@@ -1,113 +1,145 @@
1
- # Controls Styling — Bộ từ vựng layout được duyệt (chỉ dùng thế này)
1
+ # Controls Styling — Approved Layout Vocabulary (use only this)
2
2
 
3
- > File này sở hữu: **bộ class/prop/style được duyệt cho `controls` và `.vue`, thứ tự ưu tiên khi trình bày**. Chọn chế độ thẩm mỹ + giới hạn `border-radius` xem [design-modes.md](design-modes.md).
3
+ > Owns: **approved class/prop/style set for `controls` and `.vue`, and presentation priority order**. Aesthetic mode + `border-radius` limits: [design-modes.md](design-modes.md).
4
4
 
5
- **Quy tắc số 1: KHÔNG tự thêm `style` và `class` để "làm đẹp" UI.** Chỉ dùng đúng bộ từ vựng dưới đây — được rút trích từ 78 file `module.json` thực tế của 5 dự án (contest-score, security-manager, fp, lhu-test, lhu-lib). Nếu người mô tả không yêu cầu một hiệu ứng/khoảng cách/màu cụ thể → **không thêm gì cả**. Layout của FUI (grid + Vuetify + theme project) đã đủ đẹp và nhất quán.
5
+ **Rule #1: do NOT add `style` or `class` to "beautify" UI.** Use only the vocabulary below (extracted from 78 real `module.json` files across 5 projects: contest-score, security-manager, fp, lhu-test, lhu-lib). If the user didn't ask for a specific effect/spacing/color → **add nothing**. FUI layout (grid + Vuetify + project theme) is already consistent.
6
6
 
7
- > Thống kê thực tế: trong 1.284 control object, chỉ ~12% dùng `attr.style` (gần như chỉ để đặt `width`), và **không có class tùy chỉnh nào** — 100% là class tiện ích chuẩn của Vuetify. AI hay mắc lỗi thêm `style="padding/margin/border/box-shadow/border-radius/background"` và class tự chế → **đừng làm vậy.**
7
+ > Stats: of 1,284 control objects only ~12% use `attr.style` (almost only for `width`), and **zero custom classes** — 100% standard Vuetify utilities. Common AI mistake: adding `style="padding/margin/border/box-shadow/border-radius/background"` and invented classes → **don't.**
8
8
 
9
9
  ---
10
10
 
11
- ## Nguyên tắc
11
+ ## Principles
12
12
 
13
- 1. **Mặc định: không style, không class.** Chỉ đặt `el`, `attr` (v-model/label/:items/:action…), `w`, `col` khi cần chia cột.
14
- 2. Cần khoảng cách/căn lề → dùng **class tiện ích Vuetify** trong bảng dưới, KHÔNG viết `style`.
15
- 3. `style` chỉ dùng cho **`width` cố định** của field lọc (`style: "width:200px"`) — không dùng cho padding/margin/border/color/background.
16
- 4. Màu sắc: dùng prop component (`color="primary"`) hoặc class `primary--text`/`error--text` — không `style="color:#..."`.
17
- 5. **Không** tự thêm `border`, `border-radius`, `box-shadow`, `background`, `padding`, custom class → trừ khi user yêu cầu rõ.
18
- 6. **Padding gọn — mặc định `pa-2`.** Khi cần padding, dùng `pa-2` (hoặc `pa-1`/`pa-0`); **KHÔNG dùng padding lớn** (`pa-4`, `pa-6`, `pa-8`...) gây lãng phí không gian màn hình. Tương tự margin: ưu tiên `-1`/`-2`, tránh `-6`/`-8`.
19
- 7. **Khi user *có* yêu cầu trình bày cụ thể — theo đúng thứ tự ưu tiên này**, chỉ xuống nấc sau khi nấc trước không đáp ứng được:
20
- `prop của component` (`color`, `outlined`, `dense`, `elevation`) → `class tiện ích Vuetify` (`pa-*`, `ma-*`, `d-flex`, `text-*`, `primary--text`) → `mw-*` cho bề rộng → custom class → inline `style` (**cuối cùng**).
13
+ 1. **Default: no style, no class.** Set only `el`, `attr` (v-model/label/:items/:action…), `w`, and `col` when splitting columns.
14
+ 2. Spacing/alignment → **Vuetify utility classes** from the tables below, NOT `style`.
15
+ 3. `style` only for **fixed `width`** of a filter field (`style: "width:200px"`) — never padding/margin/border/color/background.
16
+ 4. Color: component prop (`color="primary"`) or class `primary--text`/`error--text` — no `style="color:#..."`.
17
+ 5. **Never** add `border`, `border-radius`, `box-shadow`, `background`, `padding`, custom classes unless the user explicitly asks.
18
+ 6. **Compact padding — default `pa-2`** (or `pa-1`/`pa-0`). **NO large padding** (`pa-4`, `pa-6`, `pa-8`...) — wastes screen space. Margin likewise: prefer `-1`/`-2`, avoid `-6`/`-8`.
19
+ 7. **When the user _does_ ask for specific presentation — follow this priority**, moving down only when the previous level can't do it:
20
+ `component prop` (`color`, `outlined`, `dense`, `elevation`) → `Vuetify utility class` (`pa-*`, `ma-*`, `d-flex`, `text-*`, `primary--text`) → `mw-*` for width → custom class → inline `style` (**last**).
21
21
 
22
22
  ---
23
23
 
24
- ## 1. `prop` của container / row (grid wrapper)
25
-
26
- Container ngoài cùng và mỗi row chỉ dùng các token sau (theo tần suất thực tế):
27
-
28
- | Token | Dùng để | Tần suất |
29
- |---|---|---|
30
- | `grid-list-md` | Khoảng cách chuẩn giữa các cột (container) | rất cao |
31
- | `fluid` | Container rộng hết chiều ngang | cao |
32
- | `row` | Đánh dấu row | rất cao |
33
- | `align-center` | **Canh giữa theo chiều dọc** các control trong cùng một row, nhất là khi khác loại/khác chiều cao | cao |
34
- | `justify-center` | Căn giữa nội dung theo chiều ngang | rất cao |
35
- | `justify-left` / `justify-end` / `justify-start` | Căn trái / phải | vừa |
36
- | `text-center` / `text-left` | Căn text | vừa |
37
- | `mw-800` `mw-1000` `mw-1200` `mw-1400` | **Giới hạn bề rộng nội dung** (FUI class) — trang form/nhập liệu căn giữa | vừa |
38
- | `hidden-container` | Bọc dialog (v-dialog/f-dialog) — không chiếm layout | dùng cho dialog |
39
- | `grid-list-lg` | Khoảng cách rộng hơn grid-list-md | thấp |
40
- | `pa-0` / `py-0` | Bỏ padding container khi cần sát mép | thấp |
41
- | `page-container` / `page-navigation` | Layout filter-bar sticky (xem ui-layout-patterns.md) | hiếm |
42
-
43
- > **Công thức mặc định** cho một trang bình thường: container `"fluid grid-list-md"`, mỗi row `"row"`. Hàng có nhiều loại control/chiều cao khác nhau dùng `"row wrap align-center"` để cùng trục giữa theo chiều dọc; `justify-center` chỉ là căn giữa theo chiều ngang. Trang form nhập liệu: thêm `mw-1000`/`mw-1200` để giới hạn bề rộng.
44
-
45
- ## 2. `col` (cột grid bao ngoài control)
46
-
47
- `col` chỉ dùng cho: chia độ rộng, hoặc căn/thu gọn cột. Token thực dùng:
48
-
49
- | Token | Dùng để |
50
- |---|---|
51
- | `shrink` | **Field lọc bề rộng cố định** (không giãn) — phổ biến nhất. **Bắt buộc mỗi khi `w` là px**; viết `"class": "shrink"`, KHÔNG phải `"shrink": true` (dạng sau trơ ở V3) |
52
- | `text-end` / `text-start` / `text-center` | Căn nội dung trong cột |
53
- | `pa-0` | Bỏ padding cột |
54
- | `align-self-center` | Căn giữa theo chiều dọc |
55
-
56
- `col` có thể viết dạng chuỗi ngắn `"text-end"` hoặc object `{ "class": "shrink" }`. Thêm `"v-if": "..."` vào `col` để ẩn/hiện cả cột theo quyền/điều kiện.
57
-
58
- > Ưu tiên `align-center` trên row để canh đồng bộ cả hàng. Chỉ dùng `align-self-center` trên `col`
59
- > khi duy nhất một control cần sửa trục. Không bù lệch dọc bằng margin hoặc inline style.
60
-
61
- ## 3. `attr.class` (class trên chính control)
62
-
63
- Chỉ dùng class tiện ích Vuetify. Nhóm thực dùng:
64
-
65
- | Nhóm | Token |
66
- |---|---|
67
- | Margin | `mt-1 mt-2 mt-3` · `mb-1 mb-2 mb-4` · `my-2` · `ml-1 ml-2` · `mr-1 mr-2` |
68
- | Padding | `pa-0 pa-2` · `pt-3` · `py-1` — **tránh `pa-4/6/8`** (lãng phí không gian) |
69
- | Flex | `d-flex` · `flex-column` · `align-center` · `justify-center` · `justify-end` · `flex-grow-0` · `flex-wrap` · `flex-md-grow-0` |
70
- | Text | `text-center` · `text-left` · `text-right` |
71
- | Cỡ chữ / đậm | `text-h6` · `subtitle-1` · `body-2` · `caption` · `font-weight-bold` · `font-weight-medium` |
72
- | Màu chữ (V2) | `primary--text` · `error--text` · `grey--text` · `white--text` — **chỉ hoạt động trên FUI V2 (Vuetify 1.5)** (cú pháp `--text` suffix) |
73
- | Màu chữ (V3) | `text-primary` · `text-error` · `text-grey` · `text-white` — cú pháp utility class của **Vuetify 3** (`text-{color}`). Dùng sai version thì class không có effect, không báo lỗi |
74
- | Màu nền | prop `color="primary"` trên component, hoặc class nền Vuetify `primary` · `grey lighten-4` |
75
- | Bo góc | `rounded` · `rounded-lg` · `rounded-0` |
76
- | Đổ bóng / phẳng | prop `elevation="0"` / `flat` / `outlined` trên `v-card`/`v-btn` |
77
- | Ẩn/hiện theo breakpoint | `d-none d-md-flex`... |
78
- | Kích thước | prop component (`max-width`, `width`, `dense`, `small`, `x-large`) — không `style="width:..."` trừ khi cần px cố định. Riêng icon: giữ kích thước mặc định, **không tự thêm `small`/`:small`** |
79
-
80
- ### Kích thước icon
81
-
82
- - Khi thiết kế UI, icon dùng kích thước mặc định của component và theme.
83
- - **Không tự ý đặt `small` hoặc `:small`** cho `v-icon`, nút icon, hay button có icon chỉ để làm giao diện “gọn” hơn.
84
- - Chỉ thu nhỏ icon khi user yêu cầu rõ, hoặc một component/pattern chuyên biệt đã quy định kích thước đó; khi ấy ghi đúng prop ở đúng component, không thu nhỏ cả button ngoài ý muốn.
85
-
86
- **Trước khi đặt một class mới → tra bảng trên.** Chỉ được định nghĩa class riêng khi cần thứ Vuetify
87
- không có sẵn: grid-template phức tạp, animation, pseudo-element (`::before`), selector con đặc thù.
88
- Khi đó đặt trong `header.html`, tên class có prefix rõ ràng, **số lượng tối thiểu** — không tái tạo
89
- lại card/badge/spacing mà Vuetify đã có.
90
-
91
- > `flex-md-grow-0` + `col: { class: "shrink" }` + `style: "width:200px"` = **field lọc bề rộng cố định** — pattern chuẩn cho toolbar (xem [ui-patterns.md](ui-patterns.md) §4). Đây là chỗ hợp lệ duy nhất để dùng `style` (chỉ `width`).
24
+ ## 1. Container / row `prop` (grid wrapper)
25
+
26
+ Outer container and each row use only these tokens (by real frequency):
27
+
28
+ | Token | Purpose | Frequency |
29
+ | ------------------------------------------------ | --------------------------------------------------------------------- | --------- |
30
+ | `grid-list-md` | Standard column gap (container) | very high |
31
+ | `fluid` | Full-width container | high |
32
+ | `row` | Marks a row | very high |
33
+ | `align-center` | **Vertically center** controls in a row, esp. different types/heights | high |
34
+ | `justify-center` | Horizontal centering | very high |
35
+ | `justify-left` / `justify-end` / `justify-start` | Left / right align | medium |
36
+ | `text-center` / `text-left` | Text align | medium |
37
+ | `mw-800` `mw-1000` `mw-1200` `mw-1400` | **Limit content width** (FUI class) — centered form/data-entry pages | medium |
38
+ | `hidden-container` | Wraps dialogs (v-dialog/f-dialog) — takes no layout space | dialogs |
39
+ | `grid-list-lg` | Wider gap than grid-list-md | low |
40
+ | `pa-0` / `py-0` | Remove container padding to touch edges | low |
41
+ | `page-container` / `page-navigation` | Sticky filter-bar layout (see ui-layout-patterns.md) | rare |
42
+
43
+ > **Default formula**: container `"fluid grid-list-md"`, each row `"row"`. Rows mixing control types/heights: `"row wrap align-center"` for a shared vertical axis; `justify-center` is horizontal only. Form pages: add `mw-1000`/`mw-1200`.
44
+
45
+ ## 2. `col` (grid column wrapping a control)
46
+
47
+ `col` only for width splitting or aligning/shrinking the column:
48
+
49
+ | Token | Purpose |
50
+ | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
51
+ | `shrink` | **Fixed-width filter field** (doesn't grow) — most common. **Required whenever `w` is px**; write `"class": "shrink"`, NOT `"shrink": true` (inert on V3) |
52
+ | `text-end` / `text-start` / `text-center` | Align content in column |
53
+ | `pa-0` | Remove column padding |
54
+ | `align-self-center` | Vertical centering |
55
+
56
+ Short string `"text-end"` or object `{ "class": "shrink" }`. Add `"v-if": "..."` to `col` to show/hide the whole column by right/condition.
57
+
58
+ > Prefer `align-center` on the row to align the whole row. Use `align-self-center` on `col` only when a single control needs fixing. Never compensate vertical offset with margin or inline style.
59
+
60
+ ## 3. `attr.class` (on the control itself)
61
+
62
+ Vuetify utility classes only:
63
+
64
+ | Group | Tokens |
65
+ | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
66
+ | Margin | `mt-1 mt-2 mt-3` · `mb-1 mb-2 mb-4` · `my-2` · `ml-1 ml-2` · `mr-1 mr-2` |
67
+ | Padding | `pa-0 pa-2` · `pt-3` · `py-1` — **avoid `pa-4/6/8`** |
68
+ | Flex | `d-flex` · `flex-column` · `align-center` · `justify-center` · `justify-end` · `flex-grow-0` · `flex-wrap` · `flex-md-grow-0` |
69
+ | Text | `text-center` · `text-left` · `text-right` |
70
+ | Size / weight | `text-h6` · `subtitle-1` · `body-2` · `caption` · `font-weight-bold` · `font-weight-medium` |
71
+ | Text color (V2) | `primary--text` · `error--text` · `grey--text` · `white--text` — **FUI V2 (Vuetify 1.5) only** (`--text` suffix) |
72
+ | Text color (V3) | `text-primary` · `text-error` · `text-grey` · `text-white` — **Vuetify 3** `text-{color}`. Wrong version = no effect, no error |
73
+ | Background | prop `color="primary"`, or Vuetify bg classes `primary` · `grey lighten-4` |
74
+ | Rounding | `rounded` · `rounded-lg` · `rounded-0` |
75
+ | Shadow / flat | prop `elevation="0"` / `flat` / `outlined` on `v-card`/`v-btn` |
76
+ | Breakpoint visibility | `d-none d-md-flex`... |
77
+ | Size | component props (`max-width`, `width`, `dense`, `small`, `x-large`) — no `style="width:..."` unless fixed px needed. Icons: keep default size, **don't add `small`/`:small`** |
78
+ | Scrollbar | `fpScrollbar` — **the only class** for any area with its own scrollbar; see §Scrollbar right below |
79
+
80
+ ### Scrollbar — always the built-in `fpScrollbar`
81
+
82
+ `fpScrollbar` is predefined in the platform's `projectdefaultstyle.css` (V2 and V3): a thin bar, **hidden until hover**, fading in ~300ms on hover and out ~600ms on leave (thumb `rgba(0,0,0,.25)`, transparent track), working in Firefox and Chrome/Edge/Safari. The class sets `overflow-y: auto` itself. The width is the browser's `thin` (~10px on Chrome ≥121, which ignores `::-webkit-scrollbar` once `scrollbar-color` is set), not the 5px the webkit rule says. The left menu of `HeaderBar` (`.v-navigation-drawer__content`) **already has** this rule; add nothing there.
83
+
84
+ **Default — the element that REALLY scrolls gets `fpScrollbar`**, without the user asking: a list box with `max-height`, a side panel, the content area of a card/dialog, a long tag/chip list...
85
+
86
+ **Exactly ONE layer — never nest `fpScrollbar`.** Hovering the innermost area also `:hover`s every outer layer and runs their effect too ⇒ the bar shows late and drops frames (measured on a real project: 2 nested layers slowed show/hide from ~300/600ms to ~850/2000ms). Before adding it, ask:
87
+
88
+ - Does this element **have a height limit and content that exceeds it**? If not, don't add it; a panel/splitter that only divides the layout (height follows content) is not a scroll area.
89
+ - Does an ancestor already scroll (another `fpScrollbar`, **or `.v-navigation-drawer__content`**)? Then pick one layer: usually recompute the inner layer's height to fit (subtracting the tab bar/toolbar above) so the outer layer no longer overflows, and drop scrolling on the outer layer. An outer layer overflowing by a few dozen px means the inner height is miscalculated, not a reason to keep two scroll layers.
90
+
91
+ ```json
92
+ { "el": "div", "attr": { "class": "fpScrollbar", "style": "max-height: 400px" }, "innerHTML": [ ... ] }
93
+ { "el": "v-list", "attr": { "class": "fpScrollbar", "max-height": "300" }, "innerHTML": [ ... ] }
94
+ ```
95
+
96
+ - The class only styles **the scrollbar**; the element still needs a height limit (`max-height`/`height`, preferably a component prop like `max-height` of `v-list`/`v-card`) to have anything to scroll. No need to add `overflow-y: auto`.
97
+ - Same in `.vue`: `class="fpScrollbar"` on the scrolling element.
98
+
99
+ **User asks to "redo / prettify / restyle the scrollbar"** → still `fpScrollbar`; **NEVER** hand-write `::-webkit-scrollbar`, `scrollbar-width`, `scrollbar-color`. Each module drawing its own style breaks consistency, and hand-made rules easily break the shared class's show/hide effect. Only when the user explicitly asks for **another color** (e.g. a scrollbar on a dark background) override it, and only the **color variable**, in `header.html`:
100
+
101
+ ```css
102
+ /* dark background: translucent white thumb, keeps fpScrollbar's show/hide effect */
103
+ .my-dark-panel.fpScrollbar:hover {
104
+ --fp-scrollbar: rgba(255, 255, 255, 0.3);
105
+ }
106
+ ```
107
+
108
+ The override does **not** touch `transition`. In particular, never add `scrollbar-color` to the transition: the color already goes through the `--fp-scrollbar` variable (which is transitioning), and transitioning `scrollbar-color` too restarts it every frame ⇒ the color changes in steps, 2-3 times slower.
109
+
110
+ Do not use `fpScrollbar` for:
111
+
112
+ - **`f-table`/`f-sheet`**: the table scrolls internally by `:height` (see [ui-table-cell-patterns.md](ui-table-cell-patterns.md)); putting it on an outer wrapper only adds a nested scrollbar.
113
+ - **`HTMLOnly: true` modules**: they do not load `projectdefaultstyle.css`, so the class does not exist (see [module-structure.md](module-structure.md) §HTMLOnly=true). There, writing scrollbar CSS in the module is fine.
114
+
115
+ ### Icon size
116
+
117
+ - Icons use the component/theme default size.
118
+ - **Don't set `small` or `:small`** on `v-icon`, icon buttons, or buttons with icons just to look "compact".
119
+ - Shrink only when the user explicitly asks or a specialised component/pattern prescribes it; then set the prop on exactly that component — don't shrink the whole button unintentionally.
120
+
121
+ **Before adding a class → check the table above.** Define a custom class only for what Vuetify lacks: complex grid-template, animation, pseudo-element (`::before`), specific child selectors. Put it in `header.html`, clearly prefixed, **minimal count** — don't recreate card/badge/spacing Vuetify already has.
122
+
123
+ > `flex-md-grow-0` + `col: { class: "shrink" }` + `style: "width:200px"` = **fixed-width filter field** — standard toolbar pattern ([ui-patterns.md](ui-patterns.md) §4). The only valid place for `style` (width only).
92
124
 
93
125
  ---
94
126
 
95
- ## 4. Cách chia độ rộng: `w` (KHÔNG dùng style/class cho việc này)
127
+ ## 4. Width: `w` (NOT style/class)
96
128
 
97
- | `w` | Ý nghĩa |
98
- |---|---|
99
- | `1`–`12` | Số cột grid (12 = full row) |
100
- | `>= 25` (vd `250`) | Bề rộng cố định theo px — **bắt buộc kèm `col: { "class": "shrink" }`**, thiếu thì con số px vô tác dụng |
101
- | `13`–`24` | **Không dùng** — vùng chết, V2 ra px còn V3 ra class không tồn tại |
102
- | `""` (rỗng) | Tự co theo nội dung |
129
+ | `w` | Meaning |
130
+ | -------------------- | -------------------------------------------------------------------------------------- |
131
+ | `1`–`12` | Grid columns (12 = full row) |
132
+ | `>= 25` (e.g. `250`) | Fixed px width — **requires `col: { "class": "shrink" }`**, otherwise px has no effect |
133
+ | `13`–`24` | **Don't use** — dead zone: V2 yields px, V3 yields a non-existent class |
134
+ | `""` (empty) | Size to content |
103
135
 
104
- Chia cột **luôn dùng `w`**, không dùng `style="width:..%"` hay class `col-6` tự chế.
136
+ Always split columns with `w` — no `style="width:..%"`, no invented `col-6`.
105
137
 
106
- Số đo và lý do đầy đủ: [controls-patterns.md](controls-patterns.md) §`w` dạng pixel.
138
+ Measurements and reasons: [controls-patterns.md](controls-patterns.md) §Pixel `w`.
107
139
 
108
140
  ---
109
141
 
110
- ## 5. Đối chiếu ĐÚNG / SAI
142
+ ## 5. RIGHT / WRONG
111
143
 
112
144
  ```json
113
145
  // ✅ ĐÚNG — gọn, dùng w + prop chuẩn, không style thừa
@@ -130,11 +162,12 @@ Số đo và lý do đầy đủ: [controls-patterns.md](controls-patterns.md)
130
162
 
131
163
  ---
132
164
 
133
- ## 6. Khi nào ĐƯỢC thêm style/class
165
+ ## 6. When style/class IS allowed
166
+
167
+ Only when the user **explicitly requests** specific presentation (e.g. "grey background for this block", "limit width to 800px", "this text red"). Even then:
134
168
 
135
- Chỉ khi **người mô tả yêu cầu rõ** một yêu cầu trình bày cụ thể (ví dụ "cho khối này nền xám", "giới hạn bề rộng 800px", "chữ này màu đỏ"). Kể cả khi đó:
136
- - Ưu tiên prop component → class tiện ích Vuetify → `mw-*` cho bề rộng → cuối cùng mới `style`.
137
- - Nếu áp `border-radius` theo yêu cầu: tuân giới hạn trong [design-modes.md](design-modes.md) (khung lớn ≤12px, vừa ≤8px, nhỏ ≤6px).
138
- - Không viết `<style>` trong `.vue`; CSS đặt ở `header.html`.
169
+ - Prop → Vuetify utility class → `mw-*` for width → `style` last.
170
+ - `border-radius` on request: obey limits in [design-modes.md](design-modes.md) (large frame ≤12px, medium ≤8px, small ≤6px).
171
+ - No `<style>` in `.vue`; CSS goes in `header.html`.
139
172
 
140
- > Tóm lại: **thấy mình sắp gõ `style` hoặc đặt tên class mới → dừng lại và hỏi "user có yêu cầu cái này không?". Nếu không → bỏ đi.**
173
+ > **About to type `style` or name a new class → stop and ask "did the user request this?". If not → drop it.**
@@ -1,60 +1,56 @@
1
- # Quy tắc thiết kế bảng (Table Design Conventions)
1
+ # Table Design Conventions
2
2
 
3
- > File này sở hữu: **quy tắc thiết kế bảng: đặt tên, PK/FK, cột audit, kiểu dữ liệu**. Workflow kết nối/SP xem [db-workflow.md](db-workflow.md).
3
+ > Owns: **table design rules: naming, PK/FK, audit columns, data types**. Connection/SP workflow: [db-workflow.md](db-workflow.md). Load when designing a new schema.
4
4
 
5
- Quy ước đặt tên bảng, khóa chính, và cột audit khi thiết kế database cho FUI. Load file này khi thiết kế schema mới.
6
-
7
- > **Lưu ý về DDL — sửa cấu trúc thì được, mất dữ liệu thì không:** `ALTER TABLE ... ADD` (thêm cột/ràng buộc) và `DROP CONSTRAINT` **chạy thẳng qua tool**; `ALTER COLUMN` (đổi kiểu) chạy được nhưng **cần `confirmWrite: true`** vì thu hẹp độ chính xác số/thời gian mất dữ liệu âm thầm. `CREATE TABLE`, `DROP COLUMN`, `DROP TABLE` thì **chặn cứng**, phải do lập trình viên tự chạy. Quy ước đặt tên dưới đây là tài liệu — AI trình bày DDL để user duyệt trước khi chạy.
5
+ > **DDL — structure changes OK, data loss not:** `ALTER TABLE ... ADD` (column/constraint) and `DROP CONSTRAINT` run directly via fui. `ALTER COLUMN` (type change) runs but **needs `--confirm-write`** — narrowing numeric/time precision silently loses data. `CREATE TABLE`, `DROP COLUMN`, `DROP TABLE` are **hard-blocked**; the developer runs them. Conventions below are documentation — present DDL to the user for approval before running.
8
6
  >
9
- > Kết nối DB, dbToken, schema, workflow SP: xem [db-workflow.md](db-workflow.md). Thiết kế app nhiều bảng/module: xem [system-design.md](system-design.md).
7
+ > DB connection, dbToken, schema, SP workflow: [db-workflow.md](db-workflow.md). Multi-table/multi-module app design: [system-design.md](system-design.md).
10
8
 
11
9
  ---
12
10
 
13
- ## Đặt tên bảng
11
+ ## Table names
14
12
 
15
- | Nhóm | Quy tắc | Ví dụ |
16
- |---|---|---|
17
- | Bảng hệ thống / danh mục bổ trợ | Chữ thường, không tiền tố | `syslog`, `syslogtype`, `syspermission` |
18
- | Bảng nghiệp vụ / thực thể chính | Tiền tố `tbl` + PascalCase | `tblUsers`, `tblDepartments`, `tblSession` |
13
+ | Group | Rule | Example |
14
+ | -------------------------------- | ------------------------- | ------------------------------------------ |
15
+ | System / auxiliary lookup tables | Lowercase, no prefix | `syslog`, `syslogtype`, `syspermission` |
16
+ | Business / main entity tables | `tbl` prefix + PascalCase | `tblUsers`, `tblDepartments`, `tblSession` |
19
17
 
20
- **Khóa chính:** `[TênThựcThể]ID` — ghép tên thực thể + `ID`
18
+ **Primary key:** `[EntityName]ID`
21
19
 
22
- | Bảng | Khóa chính |
23
- |---|---|
24
- | `tblUsers` | `UserID` |
20
+ | Table | PK |
21
+ | ---------------- | -------------- |
22
+ | `tblUsers` | `UserID` |
25
23
  | `tblDepartments` | `DepartmentID` |
26
- | `tblSession` | `SessionID` |
24
+ | `tblSession` | `SessionID` |
27
25
 
28
- > Nhất quán: FK ở bảng con dùng cùng tên với PK bảng cha — `UserID` không đổi thành `CreatorID` hay `OwnerID`.
26
+ > FK in a child table uses the same name as the parent PK — `UserID`, never `CreatorID` or `OwnerID`.
29
27
 
30
28
  ---
31
29
 
32
- ## Trường thời gian (Timestamp)
30
+ ## Timestamp columns
33
31
 
34
- Mỗi bảng nên có ít nhất một trường timestamp để truy vết mốc thời gian:
32
+ Every table should have at least one timestamp:
35
33
 
36
34
  ```sql
37
35
  [CreateTime] [datetime] DEFAULT (getdate())
38
36
  [UpdateTime] [datetime] DEFAULT (getdate())
39
37
  ```
40
38
 
41
- - Kiểu dữ liệu: `datetime`
42
- - `DEFAULT (getdate())` — SQL Server **tự điền** khi INSERT, không cần truyền từ code
43
- - Dùng `CreateTime` cho bảng chỉ ghi một lần; `UpdateTime` cho bảng cập nhật thường xuyên; cả hai khi cần phân biệt ngày tạo vs ngày sửa cuối
39
+ - Type `datetime`; `DEFAULT (getdate())` — SQL Server **fills it** on INSERT, no need to pass from code.
40
+ - `CreateTime` for write-once tables; `UpdateTime` for frequently updated ones; both when created vs last-modified must differ.
44
41
 
45
42
  ---
46
43
 
47
- ## Trường định danh người thực hiện (User Tracking)
44
+ ## User tracking columns
48
45
 
49
46
  ```sql
50
47
  [CreateUser] [char](9) NULL
51
48
  [UpdateUser] [char](9) NULL
52
49
  ```
53
50
 
54
- - Kiểu dữ liệu: `char(9)` hoặc `varchar(20)` — **đồng bộ với kiểu dữ liệu của `UserID` trong `tblUsers`**
55
- - **Không có DEFAULT** — ứng dụng bắt buộc phải truyền `UserID` của user đang đăng nhập
56
- - SQL Server không tự biết user nào đang thao tác qua FUI/tAPI — trách nhiệm thuộc về code
57
- - Trong SP: nhận qua `@sys_UserID` (tAPI auto-inject), lưu vào `[CreateUser]` / `[UpdateUser]`
51
+ - Type `char(9)` or `varchar(20)` — **match the type of `UserID` in `tblUsers`**.
52
+ - **No DEFAULT** — the app must pass the logged-in `UserID`. SQL Server can't know the FUI/tAPI user; code is responsible.
53
+ - In SPs: receive via `@sys_UserID` (tAPI auto-injects), store into `[CreateUser]` / `[UpdateUser]`.
58
54
 
59
55
  ```sql
60
56
  CREATE PROCEDURE spAPI_EntityInsert
@@ -67,7 +63,7 @@ AS
67
63
 
68
64
  ---
69
65
 
70
- ## Template cột audit — copy-paste khi tạo bảng mới
66
+ ## Audit column template — paste into new tables
71
67
 
72
68
  ```sql
73
69
  [CreateUser] [char](9) NULL,