@starci/skills 1.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.
- package/INDEX.md +74 -0
- package/INDEX.vi.md +75 -0
- package/README.md +44 -0
- package/README.vi.md +43 -0
- package/SKILL.md +135 -0
- package/SKILL.vi.md +128 -0
- package/alias/INDEX.md +104 -0
- package/alias/INDEX.vi.md +104 -0
- package/alias/alias.json +297 -0
- package/bin/starci-skills.mjs +219 -0
- package/knowledge/INDEX.md +22 -0
- package/knowledge/INDEX.vi.md +22 -0
- package/knowledge/grammars/starci/DNA.md +146 -0
- package/knowledge/grammars/starci/DNA.vi.md +146 -0
- package/knowledge/grammars/starci/INDEX.md +25 -0
- package/knowledge/grammars/starci/INDEX.vi.md +25 -0
- package/knowledge/grammars/starci/family.md +50 -0
- package/knowledge/grammars/starci/family.vi.md +50 -0
- package/knowledge/grammars/starci/idioms.md +120 -0
- package/knowledge/grammars/starci/idioms.vi.md +121 -0
- package/knowledge/grammars/starci/playbook.md +36 -0
- package/knowledge/grammars/starci/playbook.vi.md +35 -0
- package/knowledge/patterns/be/INDEX.md +29 -0
- package/knowledge/patterns/be/INDEX.vi.md +29 -0
- package/knowledge/patterns/be/comment.md +80 -0
- package/knowledge/patterns/be/comment.vi.md +80 -0
- package/knowledge/patterns/be/error.md +86 -0
- package/knowledge/patterns/be/error.vi.md +86 -0
- package/knowledge/patterns/be/folder.md +87 -0
- package/knowledge/patterns/be/folder.vi.md +86 -0
- package/knowledge/patterns/be/function.md +80 -0
- package/knowledge/patterns/be/function.vi.md +80 -0
- package/knowledge/patterns/be/imports.md +79 -0
- package/knowledge/patterns/be/imports.vi.md +79 -0
- package/knowledge/patterns/be/naming.md +87 -0
- package/knowledge/patterns/be/naming.vi.md +87 -0
- package/knowledge/patterns/be/test.md +79 -0
- package/knowledge/patterns/be/test.vi.md +79 -0
- package/knowledge/patterns/be/typing.md +73 -0
- package/knowledge/patterns/be/typing.vi.md +73 -0
- package/knowledge/patterns/fe/INDEX.md +29 -0
- package/knowledge/patterns/fe/INDEX.vi.md +29 -0
- package/knowledge/patterns/fe/comment.md +70 -0
- package/knowledge/patterns/fe/comment.vi.md +70 -0
- package/knowledge/patterns/fe/error.md +61 -0
- package/knowledge/patterns/fe/error.vi.md +61 -0
- package/knowledge/patterns/fe/folder.md +98 -0
- package/knowledge/patterns/fe/folder.vi.md +95 -0
- package/knowledge/patterns/fe/function.md +70 -0
- package/knowledge/patterns/fe/function.vi.md +70 -0
- package/knowledge/patterns/fe/imports.md +87 -0
- package/knowledge/patterns/fe/imports.vi.md +87 -0
- package/knowledge/patterns/fe/naming.md +77 -0
- package/knowledge/patterns/fe/naming.vi.md +77 -0
- package/knowledge/patterns/fe/test.md +73 -0
- package/knowledge/patterns/fe/test.vi.md +73 -0
- package/knowledge/patterns/fe/typing.md +67 -0
- package/knowledge/patterns/fe/typing.vi.md +67 -0
- package/knowledge/ui/INDEX.md +101 -0
- package/knowledge/ui/INDEX.vi.md +101 -0
- package/knowledge/ui/composition/INDEX.md +60 -0
- package/knowledge/ui/composition/INDEX.vi.md +63 -0
- package/knowledge/ui/composition/accent.md +73 -0
- package/knowledge/ui/composition/accent.vi.md +74 -0
- package/knowledge/ui/composition/action.md +55 -0
- package/knowledge/ui/composition/action.vi.md +56 -0
- package/knowledge/ui/composition/coverage.md +37 -0
- package/knowledge/ui/composition/coverage.vi.md +37 -0
- package/knowledge/ui/composition/cta.md +79 -0
- package/knowledge/ui/composition/cta.vi.md +79 -0
- package/knowledge/ui/composition/feedback.md +55 -0
- package/knowledge/ui/composition/feedback.vi.md +56 -0
- package/knowledge/ui/composition/hierarchy.md +83 -0
- package/knowledge/ui/composition/hierarchy.vi.md +82 -0
- package/knowledge/ui/composition/layout.md +91 -0
- package/knowledge/ui/composition/layout.vi.md +93 -0
- package/knowledge/ui/composition/responsive.md +67 -0
- package/knowledge/ui/composition/responsive.vi.md +67 -0
- package/knowledge/ui/composition/state.md +105 -0
- package/knowledge/ui/composition/state.vi.md +106 -0
- package/knowledge/ui/presentation/INDEX.md +94 -0
- package/knowledge/ui/presentation/INDEX.vi.md +69 -0
- package/knowledge/ui/presentation/boundary.md +170 -0
- package/knowledge/ui/presentation/boundary.vi.md +169 -0
- package/knowledge/ui/presentation/font.md +155 -0
- package/knowledge/ui/presentation/font.vi.md +156 -0
- package/knowledge/ui/presentation/gap.md +181 -0
- package/knowledge/ui/presentation/gap.vi.md +181 -0
- package/knowledge/ui/presentation/margin.md +168 -0
- package/knowledge/ui/presentation/margin.vi.md +171 -0
- package/knowledge/ui/presentation/measure.md +174 -0
- package/knowledge/ui/presentation/measure.vi.md +178 -0
- package/knowledge/ui/presentation/overflow.md +142 -0
- package/knowledge/ui/presentation/overflow.vi.md +142 -0
- package/knowledge/ui/presentation/padding.md +293 -0
- package/knowledge/ui/presentation/padding.vi.md +292 -0
- package/knowledge/ui/presentation/surface.md +166 -0
- package/knowledge/ui/presentation/surface.vi.md +166 -0
- package/knowledge/ui/presentation/text-flow.md +123 -0
- package/knowledge/ui/presentation/text-flow.vi.md +123 -0
- package/knowledge/ui/presentation/tone.md +114 -0
- package/knowledge/ui/presentation/tone.vi.md +113 -0
- package/knowledge/ui/proof/INDEX.md +55 -0
- package/knowledge/ui/proof/INDEX.vi.md +55 -0
- package/knowledge/ui/proof/accessibility.md +67 -0
- package/knowledge/ui/proof/accessibility.vi.md +68 -0
- package/knowledge/ui/proof/contrast.md +58 -0
- package/knowledge/ui/proof/contrast.vi.md +57 -0
- package/knowledge/ui/proof/focus.md +76 -0
- package/knowledge/ui/proof/focus.vi.md +76 -0
- package/knowledge/ui/proof/motion.md +63 -0
- package/knowledge/ui/proof/motion.vi.md +64 -0
- package/knowledge/ui/proof/render-truth.md +63 -0
- package/knowledge/ui/proof/render-truth.vi.md +63 -0
- package/operators/INDEX.md +199 -0
- package/operators/INDEX.vi.md +199 -0
- package/operators/architecture-decide/errors.json +115 -0
- package/operators/architecture-decide/operator.json +20 -0
- package/operators/architecture-decide/operator.md +133 -0
- package/operators/architecture-decide/operator.vi.md +130 -0
- package/operators/architecture-decide/self-test.mjs +221 -0
- package/operators/architecture-decide/validate.mjs +112 -0
- package/operators/backend-source-apply/errors.json +66 -0
- package/operators/backend-source-apply/operator.json +20 -0
- package/operators/backend-source-apply/operator.md +189 -0
- package/operators/backend-source-apply/operator.vi.md +185 -0
- package/operators/backend-source-apply/self-test.mjs +257 -0
- package/operators/backend-source-apply/validate.mjs +240 -0
- package/operators/business-decide/errors.json +78 -0
- package/operators/business-decide/operator.json +20 -0
- package/operators/business-decide/operator.md +176 -0
- package/operators/business-decide/operator.vi.md +174 -0
- package/operators/business-decide/self-test.mjs +225 -0
- package/operators/business-decide/validate.mjs +277 -0
- package/operators/content-generate/errors.json +106 -0
- package/operators/content-generate/operator.json +21 -0
- package/operators/content-generate/operator.md +155 -0
- package/operators/content-generate/operator.vi.md +155 -0
- package/operators/content-generate/self-test.mjs +288 -0
- package/operators/content-generate/validate.mjs +196 -0
- package/operators/errors.json +178 -0
- package/operators/frontend-direction-decide/errors.json +135 -0
- package/operators/frontend-direction-decide/operator.json +21 -0
- package/operators/frontend-direction-decide/operator.md +167 -0
- package/operators/frontend-direction-decide/operator.vi.md +167 -0
- package/operators/frontend-direction-decide/self-test.mjs +226 -0
- package/operators/frontend-direction-decide/validate.mjs +146 -0
- package/operators/frontend-presentation-resolve/errors.json +42 -0
- package/operators/frontend-presentation-resolve/operator.json +19 -0
- package/operators/frontend-presentation-resolve/operator.md +142 -0
- package/operators/frontend-presentation-resolve/operator.vi.md +140 -0
- package/operators/frontend-presentation-resolve/self-test.mjs +163 -0
- package/operators/frontend-presentation-resolve/validate.mjs +143 -0
- package/operators/frontend-source-apply/errors.json +30 -0
- package/operators/frontend-source-apply/operator.json +20 -0
- package/operators/frontend-source-apply/operator.md +127 -0
- package/operators/frontend-source-apply/operator.vi.md +126 -0
- package/operators/frontend-source-apply/self-test.mjs +214 -0
- package/operators/frontend-source-apply/validate.mjs +133 -0
- package/operators/frontend-surface-audit/errors.json +5 -0
- package/operators/frontend-surface-audit/operator.json +22 -0
- package/operators/frontend-surface-audit/operator.md +121 -0
- package/operators/frontend-surface-audit/operator.vi.md +121 -0
- package/operators/frontend-surface-audit/self-test.mjs +185 -0
- package/operators/frontend-surface-audit/validate.mjs +127 -0
- package/operators/git-publish/errors.json +54 -0
- package/operators/git-publish/operator.json +20 -0
- package/operators/git-publish/operator.md +180 -0
- package/operators/git-publish/operator.vi.md +178 -0
- package/operators/git-publish/self-test.mjs +177 -0
- package/operators/git-publish/validate.mjs +106 -0
- package/operators/platform-operate/errors.json +90 -0
- package/operators/platform-operate/operator.json +22 -0
- package/operators/platform-operate/operator.md +162 -0
- package/operators/platform-operate/operator.vi.md +160 -0
- package/operators/platform-operate/self-test.mjs +202 -0
- package/operators/platform-operate/validate.mjs +193 -0
- package/operators/quality-verify/errors.json +54 -0
- package/operators/quality-verify/operator.json +20 -0
- package/operators/quality-verify/operator.md +185 -0
- package/operators/quality-verify/operator.vi.md +177 -0
- package/operators/quality-verify/self-test.mjs +210 -0
- package/operators/quality-verify/validate.mjs +197 -0
- package/operators/release-deploy/errors.json +158 -0
- package/operators/release-deploy/operator.json +23 -0
- package/operators/release-deploy/operator.md +183 -0
- package/operators/release-deploy/operator.vi.md +181 -0
- package/operators/release-deploy/self-test.mjs +235 -0
- package/operators/release-deploy/validate.mjs +129 -0
- package/operators/uat-verify/errors.json +78 -0
- package/operators/uat-verify/operator.json +25 -0
- package/operators/uat-verify/operator.md +162 -0
- package/operators/uat-verify/operator.vi.md +161 -0
- package/operators/uat-verify/self-test.mjs +270 -0
- package/operators/uat-verify/validate.mjs +202 -0
- package/operators/workspace-bind/errors.json +90 -0
- package/operators/workspace-bind/operator.json +21 -0
- package/operators/workspace-bind/operator.md +148 -0
- package/operators/workspace-bind/operator.vi.md +148 -0
- package/operators/workspace-bind/self-test.mjs +205 -0
- package/operators/workspace-bind/validate.mjs +152 -0
- package/package.json +50 -0
- package/readiness/initialization/workspaces/commit-policy.json +91 -0
- package/readiness/initialization/workspaces/config.schema.json +35 -0
- package/readiness/initialization/workspaces/device-state.schema.json +54 -0
- package/readiness/initialization/workspaces/local-route.schema.json +206 -0
- package/readiness/initialization/workspaces/portable-route.schema.json +200 -0
- package/resources/INDEX.md +96 -0
- package/resources/INDEX.vi.md +99 -0
- package/resources/agents/profiles/claude.json +131 -0
- package/resources/agents/profiles/openai.json +131 -0
- package/resources/orchestrator.json +71 -0
- package/resources/tools.json +85 -0
- package/routing.json +272 -0
- package/scripts/alias-registry.mjs +31 -0
- package/scripts/device-state.mjs +497 -0
- package/scripts/device-state.spec.mjs +18 -0
- package/scripts/errors-registry.mjs +68 -0
- package/scripts/generate-alias-doc.mjs +66 -0
- package/scripts/generate-grammar-dna.mjs +387 -0
- package/scripts/generate-operators-index.mjs +95 -0
- package/scripts/generate-presentation-owned.mjs +681 -0
- package/scripts/install-cli.spec.mjs +74 -0
- package/scripts/json-schema.mjs +94 -0
- package/scripts/operator-md.mjs +96 -0
- package/scripts/run-operator-self-tests.mjs +36 -0
- package/scripts/validate-alias.mjs +165 -0
- package/scripts/validate-defaults.mjs +72 -0
- package/scripts/validate-knowledge-citations.mjs +90 -0
- package/scripts/validate-operator.mjs +125 -0
- package/scripts/validate-request.mjs +80 -0
- package/scripts/validate-resources.mjs +117 -0
- package/scripts/validate-response.mjs +141 -0
- package/scripts/validate-routing.mjs +91 -0
- package/scripts/validate-step.mjs +50 -0
- package/scripts/validate-templates.mjs +226 -0
- package/scripts/validate-templates.spec.mjs +144 -0
- package/scripts/validate-workflows.mjs +106 -0
- package/scripts/workspace-portable.mjs +389 -0
- package/scripts/workspace-portable.spec.mjs +246 -0
- package/templates/README.md +47 -0
- package/templates/README.vi.md +45 -0
- package/templates/changes.example.md +27 -0
- package/templates/grammars.template.md +34 -0
- package/templates/kinds/architecture-decision.contract.json +14 -0
- package/templates/kinds/architecture-decision.skeleton.md +52 -0
- package/templates/kinds/backend-source-application.contract.json +10 -0
- package/templates/kinds/backend-source-application.skeleton.md +34 -0
- package/templates/kinds/business-promise-authority.contract.json +13 -0
- package/templates/kinds/business-promise-authority.skeleton.md +67 -0
- package/templates/kinds/capture.schema.json +33 -0
- package/templates/kinds/changes.contract.json +10 -0
- package/templates/kinds/changes.skeleton.md +26 -0
- package/templates/kinds/checks.schema.json +44 -0
- package/templates/kinds/claims.schema.json +165 -0
- package/templates/kinds/conformance.schema.json +15 -0
- package/templates/kinds/content-brief.contract.json +12 -0
- package/templates/kinds/content-brief.skeleton.md +45 -0
- package/templates/kinds/content-generation-receipt.contract.json +11 -0
- package/templates/kinds/content-generation-receipt.skeleton.md +40 -0
- package/templates/kinds/content-review.contract.json +11 -0
- package/templates/kinds/content-review.skeleton.md +45 -0
- package/templates/kinds/contract.schema.json +28 -0
- package/templates/kinds/coverage-matrix.schema.json +86 -0
- package/templates/kinds/coverage.schema.json +62 -0
- package/templates/kinds/current-state.schema.json +40 -0
- package/templates/kinds/delta.schema.json +95 -0
- package/templates/kinds/e2e.schema.json +63 -0
- package/templates/kinds/frontend-direction-decision.contract.json +93 -0
- package/templates/kinds/frontend-direction-decision.skeleton.md +68 -0
- package/templates/kinds/frontend-presentation-resolution.contract.json +11 -0
- package/templates/kinds/frontend-presentation-resolution.skeleton.md +32 -0
- package/templates/kinds/frontend-source-application.contract.json +10 -0
- package/templates/kinds/frontend-source-application.skeleton.md +30 -0
- package/templates/kinds/frontend-surface-audit.contract.json +52 -0
- package/templates/kinds/frontend-surface-audit.skeleton.md +32 -0
- package/templates/kinds/gate-result.schema.json +64 -0
- package/templates/kinds/git-publication.contract.json +82 -0
- package/templates/kinds/git-publication.skeleton.md +61 -0
- package/templates/kinds/independent-critique.contract.json +9 -0
- package/templates/kinds/independent-critique.skeleton.md +28 -0
- package/templates/kinds/inventory.schema.json +35 -0
- package/templates/kinds/model.schema.json +99 -0
- package/templates/kinds/mutations.schema.json +65 -0
- package/templates/kinds/platform-operation-receipt.contract.json +76 -0
- package/templates/kinds/platform-operation-receipt.skeleton.md +54 -0
- package/templates/kinds/probes.schema.json +130 -0
- package/templates/kinds/proof.schema.json +17 -0
- package/templates/kinds/quality-verification.contract.json +87 -0
- package/templates/kinds/quality-verification.skeleton.md +58 -0
- package/templates/kinds/release-deployment.contract.json +85 -0
- package/templates/kinds/release-deployment.skeleton.md +67 -0
- package/templates/kinds/route.schema.json +293 -0
- package/templates/kinds/stack-model.schema.json +90 -0
- package/templates/kinds/uat-capture.schema.json +35 -0
- package/templates/kinds/uat-flow-verification.contract.json +11 -0
- package/templates/kinds/uat-flow-verification.skeleton.md +47 -0
- package/templates/kinds/uat-snapshot.schema.json +96 -0
- package/templates/kinds/uat-verdicts.schema.json +41 -0
- package/templates/kinds/ui-coverage.schema.json +77 -0
- package/templates/kinds/verdicts.schema.json +39 -0
- package/templates/kinds/workspace-route-binding.contract.json +12 -0
- package/templates/kinds/workspace-route-binding.skeleton.md +60 -0
- package/templates/kinds/writes.schema.json +37 -0
- package/templates/operator.template.md +73 -0
- package/templates/patterns.template.md +31 -0
- package/templates/step/request.schema.json +42 -0
- package/templates/step/response.schema.json +144 -0
- package/templates/ui-composition.template.md +36 -0
- package/templates/ui-presentation.template.md +57 -0
- package/templates/ui-proof.template.md +34 -0
- package/workflows/README.md +37 -0
- package/workflows/README.vi.md +37 -0
- package/workflows/backend-feature.json +59 -0
- package/workflows/content-unit.json +19 -0
- package/workflows/frontend-new-surface.json +81 -0
- package/workflows/frontend-reconstruct.json +67 -0
- package/workflows/frontend-refine.json +67 -0
- package/workflows/frontend-with-uat.json +78 -0
- package/workflows/full-feature.json +104 -0
- package/workflows/release.json +29 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Layout composition
|
|
2
|
+
|
|
3
|
+
File này trả lời đúng một câu hỏi: trước khi có bất kỳ cây DOM nào, trang này có những vùng nhiệm vụ
|
|
4
|
+
nào mà người đọc nhìn thấy, và ai sở hữu từng vùng đó.
|
|
5
|
+
|
|
6
|
+
Layout là quyết định composition đầu tiên. Nó chốt xem người đọc thấy bao nhiêu vùng, composition
|
|
7
|
+
công khai nào sở hữu track và scroll của từng vùng, và chuyện gì xảy ra với một vùng khi nó rời khỏi
|
|
8
|
+
dòng chảy bình thường hoặc biến mất hẳn. Mọi thứ đo được sau khi trang render đều thuộc về operator
|
|
9
|
+
audit, không thuộc file này.
|
|
10
|
+
|
|
11
|
+
## Từ vựng owner
|
|
12
|
+
|
|
13
|
+
| Owner | Nghĩa |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| Tên một composition | `@starci/grammar/common` đã sở hữu track và geometry của vùng đó |
|
|
16
|
+
| `App` | Direction cấp nội dung, state và label vào một slot công khai |
|
|
17
|
+
| `—` | Chưa có composition công khai nào phủ được vùng này; direction ghi nhận gap |
|
|
18
|
+
|
|
19
|
+
Với ra một grid của vendor ở chỗ owner là tên một composition chính là `APP_REIMPLEMENTATION`. Với ra
|
|
20
|
+
một grid ở chỗ owner là `—` thì đó là `COMMON_CAPABILITY_MISSING`, và câu trả lời là bổ sung
|
|
21
|
+
composition dùng lại được, chứ không phải tự dựng grid trong ứng dụng.
|
|
22
|
+
|
|
23
|
+
## LAYOUT-1 — Trang có những vùng nào
|
|
24
|
+
|
|
25
|
+
Chi phối số vùng nhiệm vụ mà người đọc nhìn thấy và lý do tồn tại của từng vùng.
|
|
26
|
+
|
|
27
|
+
| Case | Dùng khi | Khẳng định |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| Case 1 | Nội dung business chỉ có một nhiệm vụ và không có phần bổ trợ | Receipt liệt kê đúng một vùng chủ đạo, và mọi vùng khác nó liệt kê đều mang một vai trò nhiệm vụ có tên |
|
|
30
|
+
| Case 2 | Nhiệm vụ chính có phần bổ trợ mà người đọc tra cứu song song | Phần bổ trợ là một rail, và receipt gọi tên vai trò nhiệm vụ đã xứng đáng có nó |
|
|
31
|
+
| Case 3 | Nội dung trang được route cần khung chrome bao quanh | `WorkspaceShell` sở hữu các vùng shell, và đúng một phần tử được gọi tên là landmark chính |
|
|
32
|
+
| Case 4 | Các điểm đến cần được gom nhóm để duyệt | `Sidebar` sở hữu việc gom nhóm; receipt chỉ cấp điểm đến và nhãn vào đó |
|
|
33
|
+
| Case 5 | Một cuộc hội thoại cần composer luôn nằm yên tại chỗ | `ChatWorkspace` sở hữu cặp hội thoại và composer |
|
|
34
|
+
| Case 6 | Cách sắp xếp cần dùng chưa có composition công khai nào | Một gap `GRAMMAR_REQUIRED` gọi tên composition còn thiếu, và không có cách sắp xếp thay thế nào xuất hiện trong cây |
|
|
35
|
+
|
|
36
|
+
Không phải rule này: vùng nào trong số các vùng mang anchor mạnh nhất thuộc HIERARCHY-2.
|
|
37
|
+
|
|
38
|
+
## LAYOUT-2 — Owner của mọi vùng là một composition công khai
|
|
39
|
+
|
|
40
|
+
Chi phối phần code nào quyết định track của một vùng, chứ không phải nội dung nào nằm trong đó.
|
|
41
|
+
|
|
42
|
+
| Case | Dùng khi | Khẳng định |
|
|
43
|
+
| --- | --- | --- |
|
|
44
|
+
| Case 1 | Một cột chính nằm cạnh một cột bổ trợ | `PrimaryRailLayout` sở hữu cả hai track; receipt chỉ gọi tên `railWidth` và `align`, và không công thức track nào đứng cạnh vùng đó |
|
|
45
|
+
| Case 2 | Các vùng shell và landmark chính cần được gọi tên | `WorkspaceShell` sở hữu các slot, và receipt cấp `primaryLabel` |
|
|
46
|
+
| Case 3 | Một surface hội thoại cần chiều cao có biên | `ChatWorkspace` sở hữu biên đó, và host cấp chiều cao mà nó yêu cầu |
|
|
47
|
+
| Case 4 | Direction bị cám dỗ dùng grid của vendor hoặc tự tính bề rộng con | Mọi vùng phân giải về một composition công khai hoặc về một gap đã ghi nhận; không grid vendor và không phép tính bề rộng nào sở hữu một vùng |
|
|
48
|
+
| Case 5 | Một family muốn một vùng trông khác đi | Delta của family chỉ thay renderer bằng props tương thích; vai trò của vùng và số lượng owner của nó không đổi |
|
|
49
|
+
|
|
50
|
+
Không phải rule này: khoảng cách giữa các object bên trong một vùng là quyết định của presentation.
|
|
51
|
+
|
|
52
|
+
## LAYOUT-3 — Mỗi vùng một owner, mỗi trục scroll một owner
|
|
53
|
+
|
|
54
|
+
Chi phối số thứ được phép nhận cùng một vùng hoặc cùng một trục tràn.
|
|
55
|
+
|
|
56
|
+
| Case | Dùng khi | Khẳng định |
|
|
57
|
+
| --- | --- | --- |
|
|
58
|
+
| Case 1 | Nhiều vùng cùng tồn tại trên một trang | Mỗi vùng nhìn thấy được phân giải về đúng một composition owner và đúng một track chủ đích |
|
|
59
|
+
| Case 2 | Nội dung rộng hơn cột của nó về bản chất, ví dụ một bảng | Đúng một `HorizontalScrollRegion` có tên sở hữu trục inline, và không tồn tại scroll ngang ở cấp trang |
|
|
60
|
+
| Case 3 | Dòng chảy dọc cần bị chặn biên bên trong một vùng | `VerticalScrollRegion isScrollable`, hoặc đúng composition có tên đó, sở hữu trục dọc ấy |
|
|
61
|
+
| Case 4 | Hội thoại phải scroll trong khi composer đứng yên | `ChatWorkspace` sở hữu scroll hội thoại, và composer là anh em của nó nằm ngoài scroller |
|
|
62
|
+
| Case 5 | Có đề xuất lồng thêm một scroller | Mỗi scroller lồng nhau mang một trục có tên khác hoặc một nhiệm vụ có tên khác so với tổ tiên của nó |
|
|
63
|
+
|
|
64
|
+
Không phải rule này: chuyện một vùng scroll có thật sự chạm tới và duyệt được bằng bàn phím sau khi
|
|
65
|
+
render thuộc FOCUS-2.
|
|
66
|
+
|
|
67
|
+
## LAYOUT-4 — Vùng rời khỏi dòng chảy bình thường
|
|
68
|
+
|
|
69
|
+
Chi phối các vùng sticky, fixed, drawer, floating, bị đảo thứ tự thị giác, và vùng vắng mặt có điều
|
|
70
|
+
kiện.
|
|
71
|
+
|
|
72
|
+
| Case | Dùng khi | Khẳng định |
|
|
73
|
+
| --- | --- | --- |
|
|
74
|
+
| Case 1 | Cột bổ trợ cần nằm trong tầm mắt khi cột chính cuộn | `Rail mode="sticky"` mang biên đã công bố của nó, và dưới ngưỡng hẹp vùng đó trở lại dòng chảy bình thường |
|
|
75
|
+
| Case 2 | Một overlay cần geometry fixed có biên | `WorkspaceShell.floatingLayer` chỉ cấp geometry; nếu còn cần giam focus và cách đóng, receipt gọi tên một modal owner hoặc ghi nhận gap |
|
|
76
|
+
| Case 3 | Không gian hẹp không chứa nổi rail hội thoại theo dạng inline | `ChatWorkspace` sở hữu drawer, và receipt cấp `isRailOpen` cùng `onRailOpenChange` |
|
|
77
|
+
| Case 4 | Một vùng vắng mặt ở trạng thái hiện tại | Không wrapper, track, divider, đường kẻ, spacer hay khoảng scroll đã đặt trước nào của vùng đó sống sót qua sự vắng mặt |
|
|
78
|
+
| Case 5 | Direction muốn thứ tự thị giác khác đi ở một bề rộng | Thứ tự DOM, thứ tự đọc, thứ tự focus và thứ tự hành động trùng khít thứ tự nhiệm vụ ở mọi bề rộng; composition khác đi, thứ tự thì không |
|
|
79
|
+
|
|
80
|
+
Không phải rule này: chuyện phần projection có thật sự chừa đủ chỗ cho nội dung bên dưới ở một
|
|
81
|
+
viewport cụ thể là việc operator audit quan sát, không chốt ở đây.
|
|
82
|
+
|
|
83
|
+
Retired: LAYOUT-5 đã nghỉ, gộp vào COVERAGE-1, và số này không được dùng lại; địa chỉ đó coi như đã tiêu.
|
|
84
|
+
|
|
85
|
+
## File này không quyết định
|
|
86
|
+
|
|
87
|
+
Nội dung bên trong một vùng mang cấp độ nào thuộc [Hierarchy](hierarchy.vi.md). Một vùng tái bố cục
|
|
88
|
+
ra sao khi không gian đổi thuộc [Responsive](responsive.vi.md). Action nào trong vùng là chủ đạo
|
|
89
|
+
thuộc [CTA](cta.vi.md) và [Accent](accent.vi.md). Receipt phải liệt kê những gì về các vùng này
|
|
90
|
+
thuộc [Coverage](coverage.vi.md). Chuyện kết quả render có khớp với direction này không là việc của
|
|
91
|
+
operator audit, trong [Focus](../proof/focus.vi.md),
|
|
92
|
+
[Accessibility](../proof/accessibility.vi.md), [Motion](../proof/motion.vi.md) và
|
|
93
|
+
[Render truth](../proof/render-truth.vi.md).
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Responsive composition
|
|
2
|
+
|
|
3
|
+
This file answers one question: as the space available to a task changes, what must survive, and
|
|
4
|
+
which published query owns the change?
|
|
5
|
+
|
|
6
|
+
Responsive decisions are made before any DOM exists, because they are decisions about which regions
|
|
7
|
+
recompose, which branch disappears, and what the reader must still be able to do afterwards. A
|
|
8
|
+
device name is never an answer here; the answer is always a named query on a named owner.
|
|
9
|
+
|
|
10
|
+
## RESPONSIVE-1 — What survives when space shrinks
|
|
11
|
+
|
|
12
|
+
Governs the floor the compact composition must keep.
|
|
13
|
+
|
|
14
|
+
| Case | When | Assert |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| Case 1 | A task must fit into markedly less space | The compact branch keeps the required meaning, the primary action, and the current state in one readable flow, and support remains reachable from it |
|
|
17
|
+
| Case 2 | Content would otherwise force the page to scroll sideways | The composition recomposes; no clipping, no squeezing, and no page-level inline overflow appears in that branch |
|
|
18
|
+
| Case 3 | A branch is hidden in compact space | The branch is genuinely absent, and a trigger with controlled state, focus return, and a recovery path stands in its place |
|
|
19
|
+
| Case 4 | Parallel regions are wanted at a wider width | Every parallel region at that width resolves to a published composition that already offers the mode |
|
|
20
|
+
| Case 5 | The required compact behaviour has no published composition | A `GRAMMAR_REQUIRED` gap names the missing behaviour, and no parallel breakpoint is authored in its place |
|
|
21
|
+
|
|
22
|
+
## RESPONSIVE-2 — The query owner is named, not the device
|
|
23
|
+
|
|
24
|
+
Governs which space is actually being observed.
|
|
25
|
+
|
|
26
|
+
| Case | When | Assert |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| Case 1 | A primary column sits beside a rail | The branch names the `PrimaryRailLayout` container query at inline-size `56rem` as its owner, so a narrow container stacks inside a wide window |
|
|
29
|
+
| Case 2 | Shell regions recompose | Each `WorkspaceShell` boundary is named separately: the named-container queries at `72rem` and `56rem`, and the viewport rule at `69.999rem` |
|
|
30
|
+
| Case 3 | Global navigation switches between full and compact | `NavigationFeatureNav` is named as the owner, observing the layout viewport around `48rem` |
|
|
31
|
+
| Case 4 | A conversation rail switches between persistent and drawer | `ChatWorkspace` is named as the owner, observing the layout viewport through `matchMedia("(max-width: 47.999rem)")` alongside a CSS rule from `48rem` |
|
|
32
|
+
| Case 5 | The direction wants a generic tablet breakpoint over these regions | No breakpoint outside the published owning queries governs those regions |
|
|
33
|
+
|
|
34
|
+
Not this rule: which regions exist for the query to act on is LAYOUT-1.
|
|
35
|
+
|
|
36
|
+
## RESPONSIVE-3 — Every compact branch has exactly one owner
|
|
37
|
+
|
|
38
|
+
Governs who holds the state when a composition has two forms.
|
|
39
|
+
|
|
40
|
+
| Case | When | Assert |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| Case 1 | `NavigationFeatureNav` exposes its compact trigger | The application owns the compact drawer through that extension point and supplies the same destinations, labels, state, focus return, and recovery |
|
|
43
|
+
| Case 2 | `ChatWorkspace` switches its rail between persistent and drawer | The composition owns the switch; the receipt passes controlled state and callbacks only, and declares no listener of its own |
|
|
44
|
+
| Case 3 | `PrimaryRailLayout` reflows a rail that is present | The published CSS owns the reflow, and a rail that is absent is absent in DOM rather than hidden |
|
|
45
|
+
| Case 4 | Both forms would render and one is merely hidden | Exactly one branch exists at a time, and the other leaves no layout and no accessibility footprint |
|
|
46
|
+
|
|
47
|
+
## RESPONSIVE-4 — Pressure that is not viewport width
|
|
48
|
+
|
|
49
|
+
Governs the other ways space runs out.
|
|
50
|
+
|
|
51
|
+
| Case | When | Assert |
|
|
52
|
+
| --- | --- | --- |
|
|
53
|
+
| Case 1 | The reader zooms, enlarges text, or applies their own text spacing | The composition recomposes; no fixed text height and no clipping carries that pressure |
|
|
54
|
+
| Case 2 | Copy grows because it was translated or because a state added words | The receipt names that growth inside the fit decision rather than as an exception to it |
|
|
55
|
+
| Case 3 | Content is essentially two-dimensional and cannot reflow | Exactly one named `HorizontalScrollRegion` owns it, and the surrounding page stays inside its inline bound |
|
|
56
|
+
| Case 4 | A virtual keyboard, an orientation change, or a safe-area inset reduces usable space | Persistent geometry still fits, stays visible, and occludes no part of the task; a layout query staying in wide mode is not accepted as proof of fit |
|
|
57
|
+
| Case 5 | A state expands the surface, as an error, an expanded panel, or an overlay does | The expanded form is decided in the same receipt entry as the resting one |
|
|
58
|
+
|
|
59
|
+
Retired: RESPONSIVE-5 is retired into COVERAGE-1 and is not reused; the address stays spent.
|
|
60
|
+
|
|
61
|
+
## What this file does not decide
|
|
62
|
+
|
|
63
|
+
Which regions exist and who owns their tracks is [Layout](layout.md). Whether meaning keeps its rank
|
|
64
|
+
through a reflow is [Hierarchy](hierarchy.md), and whether an action group keeps its order is
|
|
65
|
+
[CTA](cta.md). What the receipt must enumerate about these branches is [Coverage](coverage.md).
|
|
66
|
+
Whether a compact branch is genuinely absent is decided in [State](state.md) and evidenced in
|
|
67
|
+
[Focus](../proof/focus.md).
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Responsive composition
|
|
2
|
+
|
|
3
|
+
File này trả lời đúng một câu hỏi: khi không gian dành cho một nhiệm vụ thay đổi, cái gì phải sống
|
|
4
|
+
sót, và query công khai nào sở hữu thay đổi đó.
|
|
5
|
+
|
|
6
|
+
Quyết định responsive được đưa ra trước khi có DOM, vì chúng là quyết định về việc vùng nào tái bố
|
|
7
|
+
cục, nhánh nào biến mất, và sau đó người đọc vẫn phải làm được gì. Một cái tên thiết bị không bao
|
|
8
|
+
giờ là câu trả lời ở đây; câu trả lời luôn là một query có tên trên một owner có tên.
|
|
9
|
+
|
|
10
|
+
## RESPONSIVE-1 — Cái gì sống sót khi không gian co lại
|
|
11
|
+
|
|
12
|
+
Chi phối mức sàn mà bố cục hẹp phải giữ.
|
|
13
|
+
|
|
14
|
+
| Case | Dùng khi | Khẳng định |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| Case 1 | Một nhiệm vụ phải lọt vào không gian nhỏ hơn hẳn | Nhánh hẹp giữ nguyên ý nghĩa bắt buộc, action chính và trạng thái hiện tại trong một luồng đọc được, và phần bổ trợ vẫn chạm tới được từ đó |
|
|
17
|
+
| Case 2 | Nội dung sẽ khiến cả trang phải cuộn ngang | Composition tái bố cục; trong nhánh đó không có cắt xén, không có bóp lại và không có tràn inline ở cấp trang |
|
|
18
|
+
| Case 3 | Một nhánh bị ẩn đi trong không gian hẹp | Nhánh đó vắng mặt thật sự, và thay chỗ nó là một trigger có state điều khiển được, có đường trả focus và có lối phục hồi |
|
|
19
|
+
| Case 4 | Muốn có các vùng song song ở bề rộng lớn hơn | Mọi vùng song song ở bề rộng đó phân giải về một composition công khai vốn đã có sẵn chế độ ấy |
|
|
20
|
+
| Case 5 | Hành vi hẹp cần dùng chưa có composition công khai nào | Một gap `GRAMMAR_REQUIRED` gọi tên hành vi còn thiếu, và không breakpoint song song nào được tự dựng thay chỗ nó |
|
|
21
|
+
|
|
22
|
+
## RESPONSIVE-2 — Gọi tên owner của query, không gọi tên thiết bị
|
|
23
|
+
|
|
24
|
+
Chi phối việc không gian nào thật sự đang được quan sát.
|
|
25
|
+
|
|
26
|
+
| Case | Dùng khi | Khẳng định |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| Case 1 | Một cột chính nằm cạnh một rail | Nhánh đó gọi tên container query của `PrimaryRailLayout` ở inline-size `56rem` làm owner, nên một container hẹp vẫn xếp chồng bên trong cửa sổ rộng |
|
|
29
|
+
| Case 2 | Các vùng shell tái bố cục | Mỗi ngưỡng của `WorkspaceShell` được gọi tên riêng: container query có tên ở `72rem` và `56rem`, và rule theo viewport ở `69.999rem` |
|
|
30
|
+
| Case 3 | Navigation toàn cục đổi giữa dạng đầy đủ và dạng gọn | `NavigationFeatureNav` được gọi tên là owner, quan sát layout viewport quanh mốc `48rem` |
|
|
31
|
+
| Case 4 | Rail hội thoại đổi giữa dạng thường trực và drawer | `ChatWorkspace` được gọi tên là owner, quan sát layout viewport qua `matchMedia("(max-width: 47.999rem)")` đi kèm một rule CSS từ `48rem` |
|
|
32
|
+
| Case 5 | Direction muốn một breakpoint tablet chung phủ lên các vùng này | Không breakpoint nào ngoài các query sở hữu đã công bố chi phối những vùng đó |
|
|
33
|
+
|
|
34
|
+
Không phải rule này: trang có những vùng nào để query tác động lên thuộc LAYOUT-1.
|
|
35
|
+
|
|
36
|
+
## RESPONSIVE-3 — Mỗi nhánh hẹp có đúng một owner
|
|
37
|
+
|
|
38
|
+
Chi phối việc ai giữ state khi một composition có hai hình dạng.
|
|
39
|
+
|
|
40
|
+
| Case | Dùng khi | Khẳng định |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| Case 1 | `NavigationFeatureNav` để lộ trigger dạng gọn của nó | Ứng dụng sở hữu drawer gọn qua extension point đó và cấp đúng những điểm đến, nhãn, state, đường trả focus và lối phục hồi ấy |
|
|
43
|
+
| Case 2 | `ChatWorkspace` đổi rail giữa thường trực và drawer | Composition sở hữu việc đổi; receipt chỉ truyền state điều khiển và callback, và không khai báo listener nào của riêng nó |
|
|
44
|
+
| Case 3 | `PrimaryRailLayout` tái bố cục một rail đang hiện diện | CSS công khai sở hữu việc tái bố cục, còn một rail vắng mặt thì vắng mặt trong DOM chứ không bị ẩn |
|
|
45
|
+
| Case 4 | Cả hai hình dạng cùng render và một cái chỉ bị ẩn | Mỗi lúc tồn tại đúng một nhánh, và nhánh kia không để lại dấu vết layout hay accessibility nào |
|
|
46
|
+
|
|
47
|
+
## RESPONSIVE-4 — Áp lực không đến từ bề rộng viewport
|
|
48
|
+
|
|
49
|
+
Chi phối những cách khác khiến không gian cạn đi.
|
|
50
|
+
|
|
51
|
+
| Case | Dùng khi | Khẳng định |
|
|
52
|
+
| --- | --- | --- |
|
|
53
|
+
| Case 1 | Người đọc zoom, phóng chữ, hoặc tự đặt text spacing | Composition tái bố cục; không chiều cao chữ cố định và không cắt xén nào gánh áp lực đó |
|
|
54
|
+
| Case 2 | Copy dài ra vì đã dịch hoặc vì một state thêm chữ | Receipt gọi tên phần dài ra ngay trong quyết định vừa vặn, chứ không như một ngoại lệ của nó |
|
|
55
|
+
| Case 3 | Nội dung vốn hai chiều và không thể chảy lại | Đúng một `HorizontalScrollRegion` có tên sở hữu nó, và trang bao quanh vẫn nằm trong biên inline của mình |
|
|
56
|
+
| Case 4 | Bàn phím ảo, xoay màn hình hoặc safe-area làm hụt không gian dùng được | Geometry thường trực vẫn vừa, vẫn nhìn thấy và không che phần nào của nhiệm vụ; việc một layout query vẫn ở chế độ rộng không được nhận là bằng chứng vừa mắt |
|
|
57
|
+
| Case 5 | Một state làm surface nở ra, như lỗi, panel mở hay overlay | Hình dạng nở ra được chốt trong cùng mục receipt với hình dạng lúc nghỉ |
|
|
58
|
+
|
|
59
|
+
Retired: RESPONSIVE-5 đã nghỉ, gộp vào COVERAGE-1, và số này không được dùng lại; địa chỉ đó coi như đã tiêu.
|
|
60
|
+
|
|
61
|
+
## File này không quyết định
|
|
62
|
+
|
|
63
|
+
Trang có những vùng nào và ai sở hữu track thuộc [Layout](layout.vi.md). Ý nghĩa có giữ được cấp độ
|
|
64
|
+
qua một lần reflow không thuộc [Hierarchy](hierarchy.vi.md), còn một nhóm action có giữ được thứ tự
|
|
65
|
+
không thuộc [CTA](cta.vi.md). Receipt phải liệt kê những gì về các nhánh này thuộc
|
|
66
|
+
[Coverage](coverage.vi.md). Một nhánh hẹp có vắng mặt thật sự hay không được chốt ở
|
|
67
|
+
[State](state.vi.md) và được chứng minh ở [Focus](../proof/focus.vi.md).
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# State composition
|
|
2
|
+
|
|
3
|
+
This file answers one question: which distinct conditions can this feature be in, and which
|
|
4
|
+
published carrier holds each one?
|
|
5
|
+
|
|
6
|
+
State is compiled before anything renders. The direction lists the business facts and the
|
|
7
|
+
transitions between them first, then binds each to a real carrier. Two facts that share a carrier
|
|
8
|
+
become one fact, and a fact with no carrier becomes a guess, so the compiling step is the rule.
|
|
9
|
+
|
|
10
|
+
## The five kinds
|
|
11
|
+
|
|
12
|
+
| Kind | Examples | Nature |
|
|
13
|
+
| --- | --- | --- |
|
|
14
|
+
| Transient cue | hover, focus, pressed | Lasts only while the input lasts |
|
|
15
|
+
| Persistent value | selected, expanded | Survives blur, rerender, and reflow |
|
|
16
|
+
| Lifecycle fact | unavailable, pending, initially unresolved | Follows the work, not the pointer |
|
|
17
|
+
| Settled outcome | success, error, cancellation | Requires a real result from authority |
|
|
18
|
+
| Absence | the branch does not exist | Contributes nothing at all |
|
|
19
|
+
|
|
20
|
+
`PresentationState` publishes `neutral`, `informative`, `affirmative`, `cautionary`, `negative`,
|
|
21
|
+
`pending`, and `unavailable` for owners such as surfaces, rails, and static rows. Those values are
|
|
22
|
+
render-neutral: they paint a fact that authority already established, and they never create one.
|
|
23
|
+
|
|
24
|
+
## STATE-1 — Name the meanings before choosing carriers
|
|
25
|
+
|
|
26
|
+
Governs the order in which state decisions are made.
|
|
27
|
+
|
|
28
|
+
| Case | When | Assert |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| Case 1 | A feature has more than one reachable condition | Every business fact and every transition between them is named in the receipt before any carrier prop appears against it |
|
|
31
|
+
| Case 2 | The named facts are ready to bind | Each named fact resolves to its own carrier: `isDisabled`, `isPending`, or `isSkeleton` where the owner publishes them, `Tabs.selectedKey`, `SurfaceAccordionCard.isOpen`, or a `PresentationState` on its owner |
|
|
32
|
+
| Case 3 | A single generic flag would cover several of them | No carrier appears against more than one named fact, so disabled, pending, and unresolved never share one flag |
|
|
33
|
+
| Case 4 | A transient cue is available and looks convenient | No hover or focus cue carries a selected or expanded value |
|
|
34
|
+
| Case 5 | A presentation value is available before authority has spoken | Every `PresentationState` value in the tree traces to a fact authority already settled; none precedes it |
|
|
35
|
+
|
|
36
|
+
## STATE-2 — Accepted work and unresolved content have separate owners
|
|
37
|
+
|
|
38
|
+
Governs the boundary between progress and loading.
|
|
39
|
+
|
|
40
|
+
| Case | When | Assert |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| Case 1 | A command accepted work | `isPending` sits on the initiating command, or on the published forwarding prop such as `EmptyNotice.isActionPending` |
|
|
43
|
+
| Case 2 | Content has not resolved for the first time | `isSkeleton` sits on the content owner, and that owner renders inert geometry with no announced value |
|
|
44
|
+
| Case 3 | A measurement is unknown | No node states a value for it; a rendered zero appears nowhere in place of an unknown measurement |
|
|
45
|
+
| Case 4 | A peer control did not start the work | That control carries no progress cue of its own |
|
|
46
|
+
|
|
47
|
+
Not this rule: what the reader is told once the work settles is FEEDBACK-3.
|
|
48
|
+
|
|
49
|
+
## STATE-3 — Absence is complete
|
|
50
|
+
|
|
51
|
+
Governs what a branch leaves behind when it does not exist.
|
|
52
|
+
|
|
53
|
+
| Case | When | Assert |
|
|
54
|
+
| --- | --- | --- |
|
|
55
|
+
| Case 1 | Authority says an optional branch, control, region, or slot does not exist now | The branch is unmounted through the published optional contract, such as an omitted `ChatWorkspace` rail or an omitted `EmptyNotice.actionLabel` |
|
|
56
|
+
| Case 2 | Hiding it visually would be easier | No node for that branch remains in the tree, visible or not, and nothing invisible still responds to input |
|
|
57
|
+
| Case 3 | The branch sat inside a grid or a flex row | Its wrapper, track, spacer, divider, and reserved scroll range are absent with it |
|
|
58
|
+
| Case 4 | The branch contained anything focusable | Nothing from that branch is focusable and nothing from it appears in the accessibility tree |
|
|
59
|
+
|
|
60
|
+
Retired: STATE-4 is retired into COVERAGE-1 and is not reused; the address stays spent.
|
|
61
|
+
|
|
62
|
+
## STATE-5 — Whole-surface action or static surface
|
|
63
|
+
|
|
64
|
+
Governs whether a surface is itself one interactive thing.
|
|
65
|
+
|
|
66
|
+
| Case | When | Assert |
|
|
67
|
+
| --- | --- | --- |
|
|
68
|
+
| Case 1 | The entire surface leads to one destination | `SurfaceCard.wholeAction` is `{ kind: "link", href, label }`, giving exactly one semantic target with one accessible name |
|
|
69
|
+
| Case 2 | The entire surface runs one command | `SurfaceCard.wholeAction` is `{ kind: "button", press, label }` |
|
|
70
|
+
| Case 3 | The surface is not interactive | `wholeAction` is absent, and the surface carries no click handler and no hover response that implies interaction |
|
|
71
|
+
| Case 4 | The surface needs a smaller independent action inside it, such as a row menu | The whole-surface target and the smaller action occupy disjoint boundaries; neither encloses the other |
|
|
72
|
+
|
|
73
|
+
Not this rule: how many effects one activation may reach is ACTION-1.
|
|
74
|
+
|
|
75
|
+
## STATE-6 — Persistent peer choice
|
|
76
|
+
|
|
77
|
+
Governs a selected value shared by peer views.
|
|
78
|
+
|
|
79
|
+
| Case | When | Assert |
|
|
80
|
+
| --- | --- | --- |
|
|
81
|
+
| Case 1 | Peer views share one selection that must outlive hover, press, and focus | `Tabs` carries an application-owned `selectedKey` with ordered `items` and `onSelect` |
|
|
82
|
+
| Case 2 | Each peer controls a panel | `panelId` associates each tab with its panel, so the relationship is published rather than implied |
|
|
83
|
+
| Case 3 | The direction is tempted to keep a second selected value locally | Exactly one controlled value drives the rendering; no local copy of that selection exists |
|
|
84
|
+
| Case 4 | The direction is tempted to wrap the published tabs in its own tab roles | No node outside `Tabs` carries composite tab semantics for the same choice |
|
|
85
|
+
|
|
86
|
+
## STATE-7 — Controlled disclosure
|
|
87
|
+
|
|
88
|
+
Governs a summary that reveals a region.
|
|
89
|
+
|
|
90
|
+
| Case | When | Assert |
|
|
91
|
+
| --- | --- | --- |
|
|
92
|
+
| Case 1 | One summary reveals or hides one associated region | `SurfaceAccordionCard` carries `isOpen`, `summaryRender`, `bodyRender`, and `onOpenChange` |
|
|
93
|
+
| Case 2 | A list has several independently controlled disclosures | Controlled `items` with `onItemOpenChange` bind each open value to its own item |
|
|
94
|
+
| Case 3 | Hover would open it, or a second trigger would sit beside the published one | Disclosure changes only through the controlled value, from exactly one trigger; no hover path and no second trigger reaches it |
|
|
95
|
+
| Case 4 | The closed body contains links or controls | While closed, nothing inside the body is focusable or announced |
|
|
96
|
+
|
|
97
|
+
## What this file does not decide
|
|
98
|
+
|
|
99
|
+
Which regions exist to hold these states is [Layout](layout.md), and which branch survives a reflow
|
|
100
|
+
is [Responsive](responsive.md). Which control carries a decision, and who owns pending among several
|
|
101
|
+
controls, is [CTA](cta.md) and [Action](action.md). What the reader is told at each outcome is
|
|
102
|
+
[Feedback](feedback.md). What the receipt must enumerate about these states is
|
|
103
|
+
[Coverage](coverage.md). Whether the rendered state is announced, reachable, and truthful is
|
|
104
|
+
[Accessibility](../proof/accessibility.md), [Focus](../proof/focus.md), and
|
|
105
|
+
[Render truth](../proof/render-truth.md).
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# State composition
|
|
2
|
+
|
|
3
|
+
File này trả lời đúng một câu hỏi: tính năng này có thể rơi vào những điều kiện riêng biệt nào, và
|
|
4
|
+
carrier công khai nào giữ từng điều kiện đó.
|
|
5
|
+
|
|
6
|
+
State được biên dịch trước khi bất cứ thứ gì render. Direction liệt kê các dữ kiện business và các
|
|
7
|
+
bước chuyển giữa chúng trước, rồi mới gán từng cái vào một carrier thật. Hai dữ kiện dùng chung một
|
|
8
|
+
carrier sẽ hoá thành một dữ kiện, còn một dữ kiện không có carrier thì hoá thành phỏng đoán, nên
|
|
9
|
+
chính bước biên dịch đó mới là rule.
|
|
10
|
+
|
|
11
|
+
## Năm loại
|
|
12
|
+
|
|
13
|
+
| Loại | Ví dụ | Bản chất |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| Dấu hiệu thoáng qua | hover, focus, pressed | Chỉ tồn tại chừng nào thao tác còn tồn tại |
|
|
16
|
+
| Giá trị bền vững | selected, expanded | Sống sót qua blur, qua rerender và qua reflow |
|
|
17
|
+
| Dữ kiện vòng đời | không dùng được, đang chạy, chưa giải quyết lần đầu | Đi theo công việc, không đi theo con trỏ |
|
|
18
|
+
| Kết cục đã chốt | thành công, lỗi, huỷ | Đòi một kết quả thật từ authority |
|
|
19
|
+
| Vắng mặt | nhánh đó không tồn tại | Không đóng góp gì hết |
|
|
20
|
+
|
|
21
|
+
`PresentationState` công bố `neutral`, `informative`, `affirmative`, `cautionary`, `negative`,
|
|
22
|
+
`pending` và `unavailable` cho các owner như surface, rail và static row. Các giá trị đó trung tính
|
|
23
|
+
về mặt render: chúng sơn một dữ kiện mà authority đã xác lập, và không bao giờ tự tạo ra dữ kiện.
|
|
24
|
+
|
|
25
|
+
## STATE-1 — Gọi tên các ý nghĩa trước khi chọn carrier
|
|
26
|
+
|
|
27
|
+
Chi phối thứ tự đưa ra quyết định về state.
|
|
28
|
+
|
|
29
|
+
| Case | Dùng khi | Khẳng định |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| Case 1 | Một tính năng có hơn một điều kiện chạm tới được | Mọi dữ kiện business và mọi bước chuyển giữa chúng đã có tên trong receipt trước khi bất kỳ prop carrier nào đứng cạnh chúng |
|
|
32
|
+
| Case 2 | Các dữ kiện đã sẵn sàng để gán | Mỗi dữ kiện đã đặt tên phân giải về carrier riêng của nó: `isDisabled`, `isPending` hoặc `isSkeleton` ở nơi owner có công bố chúng, `Tabs.selectedKey`, `SurfaceAccordionCard.isOpen`, hoặc một `PresentationState` trên owner của nó |
|
|
33
|
+
| Case 3 | Một cờ chung có thể phủ được vài dữ kiện cùng lúc | Không carrier nào đứng cho quá một dữ kiện, nên disabled, pending và chưa giải quyết không bao giờ chung một cờ |
|
|
34
|
+
| Case 4 | Có sẵn một dấu hiệu thoáng qua trông rất tiện | Không có dấu hiệu hover hay focus nào mang giá trị selected hoặc expanded |
|
|
35
|
+
| Case 5 | Một giá trị presentation có sẵn trước khi authority lên tiếng | Mọi giá trị `PresentationState` trong cây đều truy về một dữ kiện authority đã chốt; không giá trị nào đi trước nó |
|
|
36
|
+
|
|
37
|
+
## STATE-2 — Việc đã nhận và nội dung chưa giải quyết có owner khác nhau
|
|
38
|
+
|
|
39
|
+
Chi phối ranh giới giữa tiến trình và tải nội dung.
|
|
40
|
+
|
|
41
|
+
| Case | Dùng khi | Khẳng định |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| Case 1 | Một câu lệnh đã nhận việc | `isPending` nằm trên chính câu lệnh khởi động, hoặc trên prop chuyển tiếp công khai như `EmptyNotice.isActionPending` |
|
|
44
|
+
| Case 2 | Nội dung chưa giải quyết lần đầu | `isSkeleton` nằm trên owner của nội dung, và owner đó cho ra hình khối trơ, không giá trị nào được đọc lên |
|
|
45
|
+
| Case 3 | Một phép đo chưa biết | Không node nào nêu giá trị cho nó, và không có số không nào được render thay cho một phép đo chưa biết |
|
|
46
|
+
| Case 4 | Một control ngang hàng không khởi động việc đó | Control đó không mang dấu hiệu tiến trình nào của riêng nó |
|
|
47
|
+
|
|
48
|
+
Không phải rule này: người đọc được nói gì khi việc kết thúc thuộc FEEDBACK-3.
|
|
49
|
+
|
|
50
|
+
## STATE-3 — Vắng mặt phải vắng mặt trọn vẹn
|
|
51
|
+
|
|
52
|
+
Chi phối thứ mà một nhánh để lại khi nó không tồn tại.
|
|
53
|
+
|
|
54
|
+
| Case | Dùng khi | Khẳng định |
|
|
55
|
+
| --- | --- | --- |
|
|
56
|
+
| Case 1 | Authority nói rằng một nhánh, control, vùng hay slot tuỳ chọn hiện không tồn tại | Nhánh đó không được mount, qua hợp đồng tuỳ chọn công khai, chẳng hạn rail của `ChatWorkspace` bị bỏ hoặc `EmptyNotice.actionLabel` bị bỏ |
|
|
57
|
+
| Case 2 | Ẩn nó đi bằng thị giác thì dễ hơn | Không node nào của nhánh đó còn trong cây, dù nhìn thấy hay không, và không thứ vô hình nào còn phản hồi thao tác |
|
|
58
|
+
| Case 3 | Nhánh đó từng nằm trong một grid hoặc một hàng flex | Wrapper, track, spacer, divider và khoảng scroll đã đặt trước đều vắng mặt cùng nó |
|
|
59
|
+
| Case 4 | Nhánh đó từng chứa thứ gì focus được | Không gì từ nhánh đó focus được và không gì từ nó xuất hiện trong accessibility tree |
|
|
60
|
+
|
|
61
|
+
Retired: STATE-4 đã nghỉ, gộp vào COVERAGE-1, và số này không được dùng lại; địa chỉ đó coi như đã tiêu.
|
|
62
|
+
|
|
63
|
+
## STATE-5 — Surface là một action, hoặc là tĩnh
|
|
64
|
+
|
|
65
|
+
Chi phối việc một surface có tự nó là một thứ tương tác hay không.
|
|
66
|
+
|
|
67
|
+
| Case | Dùng khi | Khẳng định |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| Case 1 | Toàn bộ surface dẫn tới một điểm đến | `SurfaceCard.wholeAction` là `{ kind: "link", href, label }`, cho ra đúng một mục tiêu ngữ nghĩa với một tên khả truy cập |
|
|
70
|
+
| Case 2 | Toàn bộ surface chạy một câu lệnh | `SurfaceCard.wholeAction` là `{ kind: "button", press, label }` |
|
|
71
|
+
| Case 3 | Surface không tương tác | `wholeAction` vắng mặt, và surface không mang click handler hay phản hồi hover nào gợi ra sự tương tác |
|
|
72
|
+
| Case 4 | Surface cần một action nhỏ độc lập bên trong, ví dụ menu của một hàng | Mục tiêu toàn surface và action nhỏ nằm trên hai ranh giới rời nhau; không cái nào bọc cái nào |
|
|
73
|
+
|
|
74
|
+
Không phải rule này: một lần kích hoạt chạm tới bao nhiêu hiệu ứng thuộc ACTION-1.
|
|
75
|
+
|
|
76
|
+
## STATE-6 — Lựa chọn bền vững giữa các view ngang hàng
|
|
77
|
+
|
|
78
|
+
Chi phối một giá trị selected mà các view ngang hàng dùng chung.
|
|
79
|
+
|
|
80
|
+
| Case | Dùng khi | Khẳng định |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| Case 1 | Các view ngang hàng dùng chung một lựa chọn phải sống lâu hơn hover, press và focus | `Tabs` mang `selectedKey` do ứng dụng sở hữu, cùng `items` có thứ tự và `onSelect` |
|
|
83
|
+
| Case 2 | Mỗi view ngang hàng điều khiển một panel | `panelId` gắn mỗi tab với panel của nó, nên quan hệ đó được công bố chứ không ngầm hiểu |
|
|
84
|
+
| Case 3 | Direction bị cám dỗ giữ thêm một giá trị selected cục bộ | Đúng một giá trị điều khiển lái phần render; không tồn tại bản sao cục bộ của lựa chọn đó |
|
|
85
|
+
| Case 4 | Direction bị cám dỗ bọc thêm role tab của riêng mình quanh tabs công khai | Không node nào ngoài `Tabs` mang ngữ nghĩa tab composite cho cùng lựa chọn đó |
|
|
86
|
+
|
|
87
|
+
## STATE-7 — Disclosure có điều khiển
|
|
88
|
+
|
|
89
|
+
Chi phối một phần tóm tắt làm hiện ra một vùng.
|
|
90
|
+
|
|
91
|
+
| Case | Dùng khi | Khẳng định |
|
|
92
|
+
| --- | --- | --- |
|
|
93
|
+
| Case 1 | Một phần tóm tắt làm hiện hoặc ẩn một vùng gắn với nó | `SurfaceAccordionCard` mang `isOpen`, `summaryRender`, `bodyRender` và `onOpenChange` |
|
|
94
|
+
| Case 2 | Một danh sách có nhiều disclosure điều khiển độc lập | `items` có điều khiển cùng `onItemOpenChange` gắn mỗi giá trị open vào đúng item của nó |
|
|
95
|
+
| Case 3 | Hover sẽ mở nó ra, hoặc có thêm một trigger thứ hai nằm cạnh trigger công khai | Disclosure chỉ đổi qua giá trị điều khiển, từ đúng một trigger; không đường hover nào và không trigger thứ hai nào chạm tới nó |
|
|
96
|
+
| Case 4 | Phần thân đang đóng có chứa link hoặc control | Khi đóng, không gì bên trong phần thân focus được hay được đọc lên |
|
|
97
|
+
|
|
98
|
+
## File này không quyết định
|
|
99
|
+
|
|
100
|
+
Trang có những vùng nào để chứa các state này thuộc [Layout](layout.vi.md), và nhánh nào sống sót
|
|
101
|
+
qua reflow thuộc [Responsive](responsive.vi.md). Control nào mang quyết định, và khi nhiều control
|
|
102
|
+
cùng tham gia thì ai giữ pending, thuộc [CTA](cta.vi.md) và [Action](action.vi.md). Người đọc được
|
|
103
|
+
nói gì ở mỗi kết cục thuộc [Feedback](feedback.vi.md). Receipt phải liệt kê những gì về các state
|
|
104
|
+
này thuộc [Coverage](coverage.vi.md). State sau khi render có được đọc lên, có chạm tới được và có
|
|
105
|
+
đúng sự thật không thuộc [Accessibility](../proof/accessibility.vi.md),
|
|
106
|
+
[Focus](../proof/focus.vi.md) và [Render truth](../proof/render-truth.vi.md).
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# UI presentation
|
|
2
|
+
|
|
3
|
+
Presentation is the last UI decision layer:
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
business
|
|
7
|
+
-> composition chooses the DOM structure, layout and Grammar objects
|
|
8
|
+
-> presentation resolves CSS values on app-owned boundaries
|
|
9
|
+
-> rendered UI
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Rules in this folder are conditionally mandatory: when a rule's `When` matches, the presentation
|
|
13
|
+
must use that rule or preserve an equivalent value already supplied by the public Grammar API.
|
|
14
|
+
|
|
15
|
+
## Authority
|
|
16
|
+
|
|
17
|
+
Presentation may:
|
|
18
|
+
|
|
19
|
+
- set relationships between already-chosen Grammar objects;
|
|
20
|
+
- style an app-owned page, section, container or content-region boundary;
|
|
21
|
+
- choose public `Text` and `Heading` hierarchy props from business information rank;
|
|
22
|
+
- resolve wrapping, measure and overflow for app-owned content.
|
|
23
|
+
|
|
24
|
+
Presentation must not:
|
|
25
|
+
|
|
26
|
+
- choose or rebuild the DOM structure, flex/grid layout or Grammar component;
|
|
27
|
+
- add padding, typography or paint inside `Card`, `Input`, `Button` or another Grammar object;
|
|
28
|
+
- reach through a Grammar component with selectors or consumer classes;
|
|
29
|
+
- decide responsive transformation, CTA priority, state, focus or motion; those belong to other
|
|
30
|
+
knowledge groups.
|
|
31
|
+
|
|
32
|
+
Layout classes may appear in examples because composition has already chosen them. Their presence
|
|
33
|
+
is context, not a presentation recommendation.
|
|
34
|
+
|
|
35
|
+
## Catalog
|
|
36
|
+
|
|
37
|
+
| Knowledge | Properties it decides | Rules |
|
|
38
|
+
| --- | --- | --- |
|
|
39
|
+
| [Gap](gap.md) | `gap`, `row-gap`, `column-gap` between Grammar objects | GAP-0 to GAP-6 |
|
|
40
|
+
| [Padding](padding.md) | Inset of app-owned pages, sections, and containers | PADDING-0 to PADDING-9 |
|
|
41
|
+
| [Margin](margin.md) | External offset and auto placement, as a named exception; gap comes first | MARGIN-0 to MARGIN-6, MARGIN-AUTO |
|
|
42
|
+
| [Font](font.md) | `font-size`, `font-weight`, `line-height`, `letter-spacing` by title, body, and meta rank | FONT-1 to FONT-6, plus weight |
|
|
43
|
+
| [Tone](tone.md) | Default, muted, and accent by information rank; never a raw colour | TONE-1 to TONE-3 |
|
|
44
|
+
| [Surface](surface.md) | Which semantic surface an app-owned region takes, with its paired foreground | SURFACE-1 to SURFACE-6 |
|
|
45
|
+
| [Boundary](boundary.md) | Which separator or border draws an app-owned edge, and which edge drops it | BOUNDARY-1 to BOUNDARY-6 |
|
|
46
|
+
| [Measure](measure.md) | `width`, `height`, and their minima and maxima for app-owned regions | MEASURE-1 to MEASURE-7 |
|
|
47
|
+
| [Text flow](text-flow.md) | `text-align`, wrapping, `white-space`, truncation, line clamping | FLOW-1 to FLOW-5 |
|
|
48
|
+
| [Overflow](overflow.md) | Scroll, clip, and containment boundaries owned by the app | OVERFLOW-1 to OVERFLOW-5 |
|
|
49
|
+
|
|
50
|
+
Gap, padding, and margin share `COMMON_SPACING_SCALE`, so their rule numbers are ordinal positions on
|
|
51
|
+
that one closed scale. Font and tone have their own closed scales. Measure, surface, boundary, text
|
|
52
|
+
flow, and overflow have no value ramp, so their numbers address constraint kinds instead, and each
|
|
53
|
+
file says so.
|
|
54
|
+
|
|
55
|
+
## Rule shape
|
|
56
|
+
|
|
57
|
+
`GAP-1`, `FONT-1`, and the other `PREFIX-n` names are stable ordinal addresses on their topic's closed
|
|
58
|
+
value scale. `GAP-1` is the first gap value, not a severity, component variant, or Tailwind step. The
|
|
59
|
+
ID and the class agree only while the scale and the Tailwind steps happen to run together; where they
|
|
60
|
+
diverge, the ID keeps counting and the class does not. Every heading therefore prints both, as
|
|
61
|
+
`## GAP-5 — gap-6 / 1.5rem`, and every topic opens with a scale table mapping rule to class to value,
|
|
62
|
+
naming the classes that fall outside the scale.
|
|
63
|
+
|
|
64
|
+
A rule is one value. Its cases are the situations that resolve to it, selected by an observable
|
|
65
|
+
property of the already-rendered tree. Two cases never describe the same situation.
|
|
66
|
+
|
|
67
|
+
Every rule contains its heading, one line naming the relationship the value expresses, and one table:
|
|
68
|
+
|
|
69
|
+
| Case | When | Owner | Render |
|
|
70
|
+
| --- | --- | --- | --- |
|
|
71
|
+
| Case 1 | The concrete condition that selects this value. | Who owns the distance. | Inline TSX, or nothing when a component owns it. |
|
|
72
|
+
|
|
73
|
+
The owner cell is one of three values, and every topic states them once near the top:
|
|
74
|
+
|
|
75
|
+
- `App`, so the application writes the class on its own container.
|
|
76
|
+
- A Common component name, so the distance already lives inside that component. The application
|
|
77
|
+
passes a prop and writes no class. Writing it anyway is `APP_REIMPLEMENTATION`.
|
|
78
|
+
- `—`, so Common exposes no public path. The class is a recorded workaround linked to
|
|
79
|
+
`COMMON_CAPABILITY_MISSING`.
|
|
80
|
+
|
|
81
|
+
Each topic also carries one table of the relationships Common already owns, mapping component to the
|
|
82
|
+
element or prop condition that carries the claim, to rule, so a reader can rule out writing anything
|
|
83
|
+
before reaching the cases. That table is generated from the `data-contract` claims the package
|
|
84
|
+
publishes, by `scripts/generate-presentation-owned.mjs`, so it is never edited by hand: a wrong row
|
|
85
|
+
is repaired in the component. A case below it is added only when two authorized evidence blocks show
|
|
86
|
+
the situation, the same evidence rule the family idioms use; one occurrence is a product decision,
|
|
87
|
+
not a rule.
|
|
88
|
+
|
|
89
|
+
A case belonging to a neighbouring value is not a table row. It goes on one line after the table, as
|
|
90
|
+
`Not this rule: <condition> uses GAP-n`.
|
|
91
|
+
|
|
92
|
+
Add `Case 2`, `Case 3`, and further rows only for materially different situations governed by the same
|
|
93
|
+
value. Code stays in the table. Do not add `Why`, `When not to use`, detached code blocks, audit
|
|
94
|
+
verdicts, imagined APIs, placeholder examples, or paragraphs about values that are not on the scale.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# UI presentation
|
|
2
|
+
|
|
3
|
+
Presentation là tầng quyết định UI cuối cùng:
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
business
|
|
7
|
+
-> composition chọn cấu trúc DOM, layout và Grammar object
|
|
8
|
+
-> presentation chốt giá trị CSS trên boundary do app sở hữu
|
|
9
|
+
-> UI đã render
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Các rule trong folder này là bắt buộc có điều kiện: khi phần `Khi nào` khớp, presentation phải dùng
|
|
13
|
+
rule đó hoặc giữ giá trị tương đương đã được public Grammar API cung cấp.
|
|
14
|
+
|
|
15
|
+
## Authority
|
|
16
|
+
|
|
17
|
+
Presentation được phép:
|
|
18
|
+
|
|
19
|
+
- đặt quan hệ giữa các Grammar object đã được composition chọn;
|
|
20
|
+
- style boundary page, section, container hoặc content region do app sở hữu;
|
|
21
|
+
- chọn public prop của `Text` và `Heading` dựa trên cấp độ thông tin business;
|
|
22
|
+
- chốt wrapping, measure và overflow cho content do app sở hữu.
|
|
23
|
+
|
|
24
|
+
Presentation không được:
|
|
25
|
+
|
|
26
|
+
- chọn lại hoặc dựng lại cấu trúc DOM, flex/grid layout hay Grammar component;
|
|
27
|
+
- thêm padding, typography hoặc paint vào bên trong `Card`, `Input`, `Button` hay Grammar object khác;
|
|
28
|
+
- reach-through vào Grammar component bằng selector hoặc consumer class;
|
|
29
|
+
- quyết định responsive transformation, CTA priority, state, focus hay motion; chúng thuộc nhóm
|
|
30
|
+
knowledge khác.
|
|
31
|
+
|
|
32
|
+
Layout class có thể xuất hiện trong ví dụ vì composition đã chọn chúng từ trước. Chúng chỉ là context,
|
|
33
|
+
không phải recommendation của presentation.
|
|
34
|
+
|
|
35
|
+
## Danh mục
|
|
36
|
+
|
|
37
|
+
| Quyết định | Knowledge |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| Khoảng cách giữa các object đã ghép | [Gap](gap.vi.md) |
|
|
40
|
+
| Inset page/section/container của app | [Padding](padding.vi.md) |
|
|
41
|
+
| External offset ngoại lệ hoặc auto placement | [Margin](margin.vi.md) |
|
|
42
|
+
| Cấp độ size, weight và heading | [Font](font.vi.md) |
|
|
43
|
+
| Nhấn mạnh text default, muted và accent | [Tone](tone.vi.md) |
|
|
44
|
+
| Surface ngữ nghĩa của vùng do app sở hữu, kèm foreground đi cặp | [Surface](surface.vi.md) |
|
|
45
|
+
| Separator hay border vẽ cạnh do app sở hữu, và cạnh nào bỏ đường kẻ | [Boundary](boundary.vi.md) |
|
|
46
|
+
| Giới hạn width và height của content region | [Measure](measure.vi.md) |
|
|
47
|
+
| Wrapping, alignment và truncation | [Text flow](text-flow.vi.md) |
|
|
48
|
+
| Scroll và clipping boundary do app sở hữu | [Overflow](overflow.vi.md) |
|
|
49
|
+
|
|
50
|
+
## Cấu trúc rule
|
|
51
|
+
|
|
52
|
+
`GAP-1`, `FONT-1` và các tên `PREFIX-n` khác là địa chỉ thứ tự ổn định. Con số không phải bước
|
|
53
|
+
Tailwind, giá trị CSS, component variant hay mức độ nghiêm trọng.
|
|
54
|
+
|
|
55
|
+
Bảng "Common đã sở hữu" trong mỗi topic được sinh ra từ claim `data-contract` mà package công bố,
|
|
56
|
+
bằng `scripts/generate-presentation-owned.mjs`, nên không ai sửa tay: một hàng sai thì sửa component,
|
|
57
|
+
không sửa bảng. Một case bên dưới bảng chỉ được thêm khi hai block bằng chứng được uỷ quyền cùng cho
|
|
58
|
+
thấy tình huống đó, đúng luật bằng chứng mà các idiom của family đang dùng; xuất hiện một lần là
|
|
59
|
+
quyết định sản phẩm, chưa phải rule.
|
|
60
|
+
|
|
61
|
+
Mỗi rule chỉ có heading và đúng một bảng:
|
|
62
|
+
|
|
63
|
+
| Case | When | Common render |
|
|
64
|
+
| --- | --- | --- |
|
|
65
|
+
| Case 1 | Điều kiện cụ thể chọn rule. | TSX inline qua API public hiện có của `@starci/grammar/common`, kèm prop, class hoặc giá trị đã resolve khi source chứng minh được. |
|
|
66
|
+
|
|
67
|
+
Chỉ thêm `Case 2`, `Case 3` và các row tiếp theo khi chúng là những đầu vào khác nhau nhưng cùng một
|
|
68
|
+
quyết định. Code nằm trong bảng. Không thêm `Why`, `When not to use`, code block rời, audit verdict,
|
|
69
|
+
API tưởng tượng hay ví dụ placeholder.
|