@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.
Files changed (321) hide show
  1. package/INDEX.md +74 -0
  2. package/INDEX.vi.md +75 -0
  3. package/README.md +44 -0
  4. package/README.vi.md +43 -0
  5. package/SKILL.md +135 -0
  6. package/SKILL.vi.md +128 -0
  7. package/alias/INDEX.md +104 -0
  8. package/alias/INDEX.vi.md +104 -0
  9. package/alias/alias.json +297 -0
  10. package/bin/starci-skills.mjs +219 -0
  11. package/knowledge/INDEX.md +22 -0
  12. package/knowledge/INDEX.vi.md +22 -0
  13. package/knowledge/grammars/starci/DNA.md +146 -0
  14. package/knowledge/grammars/starci/DNA.vi.md +146 -0
  15. package/knowledge/grammars/starci/INDEX.md +25 -0
  16. package/knowledge/grammars/starci/INDEX.vi.md +25 -0
  17. package/knowledge/grammars/starci/family.md +50 -0
  18. package/knowledge/grammars/starci/family.vi.md +50 -0
  19. package/knowledge/grammars/starci/idioms.md +120 -0
  20. package/knowledge/grammars/starci/idioms.vi.md +121 -0
  21. package/knowledge/grammars/starci/playbook.md +36 -0
  22. package/knowledge/grammars/starci/playbook.vi.md +35 -0
  23. package/knowledge/patterns/be/INDEX.md +29 -0
  24. package/knowledge/patterns/be/INDEX.vi.md +29 -0
  25. package/knowledge/patterns/be/comment.md +80 -0
  26. package/knowledge/patterns/be/comment.vi.md +80 -0
  27. package/knowledge/patterns/be/error.md +86 -0
  28. package/knowledge/patterns/be/error.vi.md +86 -0
  29. package/knowledge/patterns/be/folder.md +87 -0
  30. package/knowledge/patterns/be/folder.vi.md +86 -0
  31. package/knowledge/patterns/be/function.md +80 -0
  32. package/knowledge/patterns/be/function.vi.md +80 -0
  33. package/knowledge/patterns/be/imports.md +79 -0
  34. package/knowledge/patterns/be/imports.vi.md +79 -0
  35. package/knowledge/patterns/be/naming.md +87 -0
  36. package/knowledge/patterns/be/naming.vi.md +87 -0
  37. package/knowledge/patterns/be/test.md +79 -0
  38. package/knowledge/patterns/be/test.vi.md +79 -0
  39. package/knowledge/patterns/be/typing.md +73 -0
  40. package/knowledge/patterns/be/typing.vi.md +73 -0
  41. package/knowledge/patterns/fe/INDEX.md +29 -0
  42. package/knowledge/patterns/fe/INDEX.vi.md +29 -0
  43. package/knowledge/patterns/fe/comment.md +70 -0
  44. package/knowledge/patterns/fe/comment.vi.md +70 -0
  45. package/knowledge/patterns/fe/error.md +61 -0
  46. package/knowledge/patterns/fe/error.vi.md +61 -0
  47. package/knowledge/patterns/fe/folder.md +98 -0
  48. package/knowledge/patterns/fe/folder.vi.md +95 -0
  49. package/knowledge/patterns/fe/function.md +70 -0
  50. package/knowledge/patterns/fe/function.vi.md +70 -0
  51. package/knowledge/patterns/fe/imports.md +87 -0
  52. package/knowledge/patterns/fe/imports.vi.md +87 -0
  53. package/knowledge/patterns/fe/naming.md +77 -0
  54. package/knowledge/patterns/fe/naming.vi.md +77 -0
  55. package/knowledge/patterns/fe/test.md +73 -0
  56. package/knowledge/patterns/fe/test.vi.md +73 -0
  57. package/knowledge/patterns/fe/typing.md +67 -0
  58. package/knowledge/patterns/fe/typing.vi.md +67 -0
  59. package/knowledge/ui/INDEX.md +101 -0
  60. package/knowledge/ui/INDEX.vi.md +101 -0
  61. package/knowledge/ui/composition/INDEX.md +60 -0
  62. package/knowledge/ui/composition/INDEX.vi.md +63 -0
  63. package/knowledge/ui/composition/accent.md +73 -0
  64. package/knowledge/ui/composition/accent.vi.md +74 -0
  65. package/knowledge/ui/composition/action.md +55 -0
  66. package/knowledge/ui/composition/action.vi.md +56 -0
  67. package/knowledge/ui/composition/coverage.md +37 -0
  68. package/knowledge/ui/composition/coverage.vi.md +37 -0
  69. package/knowledge/ui/composition/cta.md +79 -0
  70. package/knowledge/ui/composition/cta.vi.md +79 -0
  71. package/knowledge/ui/composition/feedback.md +55 -0
  72. package/knowledge/ui/composition/feedback.vi.md +56 -0
  73. package/knowledge/ui/composition/hierarchy.md +83 -0
  74. package/knowledge/ui/composition/hierarchy.vi.md +82 -0
  75. package/knowledge/ui/composition/layout.md +91 -0
  76. package/knowledge/ui/composition/layout.vi.md +93 -0
  77. package/knowledge/ui/composition/responsive.md +67 -0
  78. package/knowledge/ui/composition/responsive.vi.md +67 -0
  79. package/knowledge/ui/composition/state.md +105 -0
  80. package/knowledge/ui/composition/state.vi.md +106 -0
  81. package/knowledge/ui/presentation/INDEX.md +94 -0
  82. package/knowledge/ui/presentation/INDEX.vi.md +69 -0
  83. package/knowledge/ui/presentation/boundary.md +170 -0
  84. package/knowledge/ui/presentation/boundary.vi.md +169 -0
  85. package/knowledge/ui/presentation/font.md +155 -0
  86. package/knowledge/ui/presentation/font.vi.md +156 -0
  87. package/knowledge/ui/presentation/gap.md +181 -0
  88. package/knowledge/ui/presentation/gap.vi.md +181 -0
  89. package/knowledge/ui/presentation/margin.md +168 -0
  90. package/knowledge/ui/presentation/margin.vi.md +171 -0
  91. package/knowledge/ui/presentation/measure.md +174 -0
  92. package/knowledge/ui/presentation/measure.vi.md +178 -0
  93. package/knowledge/ui/presentation/overflow.md +142 -0
  94. package/knowledge/ui/presentation/overflow.vi.md +142 -0
  95. package/knowledge/ui/presentation/padding.md +293 -0
  96. package/knowledge/ui/presentation/padding.vi.md +292 -0
  97. package/knowledge/ui/presentation/surface.md +166 -0
  98. package/knowledge/ui/presentation/surface.vi.md +166 -0
  99. package/knowledge/ui/presentation/text-flow.md +123 -0
  100. package/knowledge/ui/presentation/text-flow.vi.md +123 -0
  101. package/knowledge/ui/presentation/tone.md +114 -0
  102. package/knowledge/ui/presentation/tone.vi.md +113 -0
  103. package/knowledge/ui/proof/INDEX.md +55 -0
  104. package/knowledge/ui/proof/INDEX.vi.md +55 -0
  105. package/knowledge/ui/proof/accessibility.md +67 -0
  106. package/knowledge/ui/proof/accessibility.vi.md +68 -0
  107. package/knowledge/ui/proof/contrast.md +58 -0
  108. package/knowledge/ui/proof/contrast.vi.md +57 -0
  109. package/knowledge/ui/proof/focus.md +76 -0
  110. package/knowledge/ui/proof/focus.vi.md +76 -0
  111. package/knowledge/ui/proof/motion.md +63 -0
  112. package/knowledge/ui/proof/motion.vi.md +64 -0
  113. package/knowledge/ui/proof/render-truth.md +63 -0
  114. package/knowledge/ui/proof/render-truth.vi.md +63 -0
  115. package/operators/INDEX.md +199 -0
  116. package/operators/INDEX.vi.md +199 -0
  117. package/operators/architecture-decide/errors.json +115 -0
  118. package/operators/architecture-decide/operator.json +20 -0
  119. package/operators/architecture-decide/operator.md +133 -0
  120. package/operators/architecture-decide/operator.vi.md +130 -0
  121. package/operators/architecture-decide/self-test.mjs +221 -0
  122. package/operators/architecture-decide/validate.mjs +112 -0
  123. package/operators/backend-source-apply/errors.json +66 -0
  124. package/operators/backend-source-apply/operator.json +20 -0
  125. package/operators/backend-source-apply/operator.md +189 -0
  126. package/operators/backend-source-apply/operator.vi.md +185 -0
  127. package/operators/backend-source-apply/self-test.mjs +257 -0
  128. package/operators/backend-source-apply/validate.mjs +240 -0
  129. package/operators/business-decide/errors.json +78 -0
  130. package/operators/business-decide/operator.json +20 -0
  131. package/operators/business-decide/operator.md +176 -0
  132. package/operators/business-decide/operator.vi.md +174 -0
  133. package/operators/business-decide/self-test.mjs +225 -0
  134. package/operators/business-decide/validate.mjs +277 -0
  135. package/operators/content-generate/errors.json +106 -0
  136. package/operators/content-generate/operator.json +21 -0
  137. package/operators/content-generate/operator.md +155 -0
  138. package/operators/content-generate/operator.vi.md +155 -0
  139. package/operators/content-generate/self-test.mjs +288 -0
  140. package/operators/content-generate/validate.mjs +196 -0
  141. package/operators/errors.json +178 -0
  142. package/operators/frontend-direction-decide/errors.json +135 -0
  143. package/operators/frontend-direction-decide/operator.json +21 -0
  144. package/operators/frontend-direction-decide/operator.md +167 -0
  145. package/operators/frontend-direction-decide/operator.vi.md +167 -0
  146. package/operators/frontend-direction-decide/self-test.mjs +226 -0
  147. package/operators/frontend-direction-decide/validate.mjs +146 -0
  148. package/operators/frontend-presentation-resolve/errors.json +42 -0
  149. package/operators/frontend-presentation-resolve/operator.json +19 -0
  150. package/operators/frontend-presentation-resolve/operator.md +142 -0
  151. package/operators/frontend-presentation-resolve/operator.vi.md +140 -0
  152. package/operators/frontend-presentation-resolve/self-test.mjs +163 -0
  153. package/operators/frontend-presentation-resolve/validate.mjs +143 -0
  154. package/operators/frontend-source-apply/errors.json +30 -0
  155. package/operators/frontend-source-apply/operator.json +20 -0
  156. package/operators/frontend-source-apply/operator.md +127 -0
  157. package/operators/frontend-source-apply/operator.vi.md +126 -0
  158. package/operators/frontend-source-apply/self-test.mjs +214 -0
  159. package/operators/frontend-source-apply/validate.mjs +133 -0
  160. package/operators/frontend-surface-audit/errors.json +5 -0
  161. package/operators/frontend-surface-audit/operator.json +22 -0
  162. package/operators/frontend-surface-audit/operator.md +121 -0
  163. package/operators/frontend-surface-audit/operator.vi.md +121 -0
  164. package/operators/frontend-surface-audit/self-test.mjs +185 -0
  165. package/operators/frontend-surface-audit/validate.mjs +127 -0
  166. package/operators/git-publish/errors.json +54 -0
  167. package/operators/git-publish/operator.json +20 -0
  168. package/operators/git-publish/operator.md +180 -0
  169. package/operators/git-publish/operator.vi.md +178 -0
  170. package/operators/git-publish/self-test.mjs +177 -0
  171. package/operators/git-publish/validate.mjs +106 -0
  172. package/operators/platform-operate/errors.json +90 -0
  173. package/operators/platform-operate/operator.json +22 -0
  174. package/operators/platform-operate/operator.md +162 -0
  175. package/operators/platform-operate/operator.vi.md +160 -0
  176. package/operators/platform-operate/self-test.mjs +202 -0
  177. package/operators/platform-operate/validate.mjs +193 -0
  178. package/operators/quality-verify/errors.json +54 -0
  179. package/operators/quality-verify/operator.json +20 -0
  180. package/operators/quality-verify/operator.md +185 -0
  181. package/operators/quality-verify/operator.vi.md +177 -0
  182. package/operators/quality-verify/self-test.mjs +210 -0
  183. package/operators/quality-verify/validate.mjs +197 -0
  184. package/operators/release-deploy/errors.json +158 -0
  185. package/operators/release-deploy/operator.json +23 -0
  186. package/operators/release-deploy/operator.md +183 -0
  187. package/operators/release-deploy/operator.vi.md +181 -0
  188. package/operators/release-deploy/self-test.mjs +235 -0
  189. package/operators/release-deploy/validate.mjs +129 -0
  190. package/operators/uat-verify/errors.json +78 -0
  191. package/operators/uat-verify/operator.json +25 -0
  192. package/operators/uat-verify/operator.md +162 -0
  193. package/operators/uat-verify/operator.vi.md +161 -0
  194. package/operators/uat-verify/self-test.mjs +270 -0
  195. package/operators/uat-verify/validate.mjs +202 -0
  196. package/operators/workspace-bind/errors.json +90 -0
  197. package/operators/workspace-bind/operator.json +21 -0
  198. package/operators/workspace-bind/operator.md +148 -0
  199. package/operators/workspace-bind/operator.vi.md +148 -0
  200. package/operators/workspace-bind/self-test.mjs +205 -0
  201. package/operators/workspace-bind/validate.mjs +152 -0
  202. package/package.json +50 -0
  203. package/readiness/initialization/workspaces/commit-policy.json +91 -0
  204. package/readiness/initialization/workspaces/config.schema.json +35 -0
  205. package/readiness/initialization/workspaces/device-state.schema.json +54 -0
  206. package/readiness/initialization/workspaces/local-route.schema.json +206 -0
  207. package/readiness/initialization/workspaces/portable-route.schema.json +200 -0
  208. package/resources/INDEX.md +96 -0
  209. package/resources/INDEX.vi.md +99 -0
  210. package/resources/agents/profiles/claude.json +131 -0
  211. package/resources/agents/profiles/openai.json +131 -0
  212. package/resources/orchestrator.json +71 -0
  213. package/resources/tools.json +85 -0
  214. package/routing.json +272 -0
  215. package/scripts/alias-registry.mjs +31 -0
  216. package/scripts/device-state.mjs +497 -0
  217. package/scripts/device-state.spec.mjs +18 -0
  218. package/scripts/errors-registry.mjs +68 -0
  219. package/scripts/generate-alias-doc.mjs +66 -0
  220. package/scripts/generate-grammar-dna.mjs +387 -0
  221. package/scripts/generate-operators-index.mjs +95 -0
  222. package/scripts/generate-presentation-owned.mjs +681 -0
  223. package/scripts/install-cli.spec.mjs +74 -0
  224. package/scripts/json-schema.mjs +94 -0
  225. package/scripts/operator-md.mjs +96 -0
  226. package/scripts/run-operator-self-tests.mjs +36 -0
  227. package/scripts/validate-alias.mjs +165 -0
  228. package/scripts/validate-defaults.mjs +72 -0
  229. package/scripts/validate-knowledge-citations.mjs +90 -0
  230. package/scripts/validate-operator.mjs +125 -0
  231. package/scripts/validate-request.mjs +80 -0
  232. package/scripts/validate-resources.mjs +117 -0
  233. package/scripts/validate-response.mjs +141 -0
  234. package/scripts/validate-routing.mjs +91 -0
  235. package/scripts/validate-step.mjs +50 -0
  236. package/scripts/validate-templates.mjs +226 -0
  237. package/scripts/validate-templates.spec.mjs +144 -0
  238. package/scripts/validate-workflows.mjs +106 -0
  239. package/scripts/workspace-portable.mjs +389 -0
  240. package/scripts/workspace-portable.spec.mjs +246 -0
  241. package/templates/README.md +47 -0
  242. package/templates/README.vi.md +45 -0
  243. package/templates/changes.example.md +27 -0
  244. package/templates/grammars.template.md +34 -0
  245. package/templates/kinds/architecture-decision.contract.json +14 -0
  246. package/templates/kinds/architecture-decision.skeleton.md +52 -0
  247. package/templates/kinds/backend-source-application.contract.json +10 -0
  248. package/templates/kinds/backend-source-application.skeleton.md +34 -0
  249. package/templates/kinds/business-promise-authority.contract.json +13 -0
  250. package/templates/kinds/business-promise-authority.skeleton.md +67 -0
  251. package/templates/kinds/capture.schema.json +33 -0
  252. package/templates/kinds/changes.contract.json +10 -0
  253. package/templates/kinds/changes.skeleton.md +26 -0
  254. package/templates/kinds/checks.schema.json +44 -0
  255. package/templates/kinds/claims.schema.json +165 -0
  256. package/templates/kinds/conformance.schema.json +15 -0
  257. package/templates/kinds/content-brief.contract.json +12 -0
  258. package/templates/kinds/content-brief.skeleton.md +45 -0
  259. package/templates/kinds/content-generation-receipt.contract.json +11 -0
  260. package/templates/kinds/content-generation-receipt.skeleton.md +40 -0
  261. package/templates/kinds/content-review.contract.json +11 -0
  262. package/templates/kinds/content-review.skeleton.md +45 -0
  263. package/templates/kinds/contract.schema.json +28 -0
  264. package/templates/kinds/coverage-matrix.schema.json +86 -0
  265. package/templates/kinds/coverage.schema.json +62 -0
  266. package/templates/kinds/current-state.schema.json +40 -0
  267. package/templates/kinds/delta.schema.json +95 -0
  268. package/templates/kinds/e2e.schema.json +63 -0
  269. package/templates/kinds/frontend-direction-decision.contract.json +93 -0
  270. package/templates/kinds/frontend-direction-decision.skeleton.md +68 -0
  271. package/templates/kinds/frontend-presentation-resolution.contract.json +11 -0
  272. package/templates/kinds/frontend-presentation-resolution.skeleton.md +32 -0
  273. package/templates/kinds/frontend-source-application.contract.json +10 -0
  274. package/templates/kinds/frontend-source-application.skeleton.md +30 -0
  275. package/templates/kinds/frontend-surface-audit.contract.json +52 -0
  276. package/templates/kinds/frontend-surface-audit.skeleton.md +32 -0
  277. package/templates/kinds/gate-result.schema.json +64 -0
  278. package/templates/kinds/git-publication.contract.json +82 -0
  279. package/templates/kinds/git-publication.skeleton.md +61 -0
  280. package/templates/kinds/independent-critique.contract.json +9 -0
  281. package/templates/kinds/independent-critique.skeleton.md +28 -0
  282. package/templates/kinds/inventory.schema.json +35 -0
  283. package/templates/kinds/model.schema.json +99 -0
  284. package/templates/kinds/mutations.schema.json +65 -0
  285. package/templates/kinds/platform-operation-receipt.contract.json +76 -0
  286. package/templates/kinds/platform-operation-receipt.skeleton.md +54 -0
  287. package/templates/kinds/probes.schema.json +130 -0
  288. package/templates/kinds/proof.schema.json +17 -0
  289. package/templates/kinds/quality-verification.contract.json +87 -0
  290. package/templates/kinds/quality-verification.skeleton.md +58 -0
  291. package/templates/kinds/release-deployment.contract.json +85 -0
  292. package/templates/kinds/release-deployment.skeleton.md +67 -0
  293. package/templates/kinds/route.schema.json +293 -0
  294. package/templates/kinds/stack-model.schema.json +90 -0
  295. package/templates/kinds/uat-capture.schema.json +35 -0
  296. package/templates/kinds/uat-flow-verification.contract.json +11 -0
  297. package/templates/kinds/uat-flow-verification.skeleton.md +47 -0
  298. package/templates/kinds/uat-snapshot.schema.json +96 -0
  299. package/templates/kinds/uat-verdicts.schema.json +41 -0
  300. package/templates/kinds/ui-coverage.schema.json +77 -0
  301. package/templates/kinds/verdicts.schema.json +39 -0
  302. package/templates/kinds/workspace-route-binding.contract.json +12 -0
  303. package/templates/kinds/workspace-route-binding.skeleton.md +60 -0
  304. package/templates/kinds/writes.schema.json +37 -0
  305. package/templates/operator.template.md +73 -0
  306. package/templates/patterns.template.md +31 -0
  307. package/templates/step/request.schema.json +42 -0
  308. package/templates/step/response.schema.json +144 -0
  309. package/templates/ui-composition.template.md +36 -0
  310. package/templates/ui-presentation.template.md +57 -0
  311. package/templates/ui-proof.template.md +34 -0
  312. package/workflows/README.md +37 -0
  313. package/workflows/README.vi.md +37 -0
  314. package/workflows/backend-feature.json +59 -0
  315. package/workflows/content-unit.json +19 -0
  316. package/workflows/frontend-new-surface.json +81 -0
  317. package/workflows/frontend-reconstruct.json +67 -0
  318. package/workflows/frontend-refine.json +67 -0
  319. package/workflows/frontend-with-uat.json +78 -0
  320. package/workflows/full-feature.json +104 -0
  321. package/workflows/release.json +29 -0
@@ -0,0 +1,170 @@
1
+ # Boundary presentation
2
+
3
+ This file answers one question: given an edge the application owns, which separator or border draws
4
+ it, and which edge in a repeating set drops it?
5
+
6
+ The theme publishes two hairline tokens and they mean different things: `--separator` draws the line
7
+ between things, and `--border` draws the outline of one thing. A boundary inside a Grammar component
8
+ is that component's, never the application's, and no application edge may be drawn with a raw colour
9
+ value.
10
+
11
+ ## Catalog
12
+
13
+ Boundaries have no value ramp, so the rule ID is an address over edge kinds rather than a position on
14
+ a scale. Prefer the earliest rule that works: one seam before a per-row seam, a per-row seam before a
15
+ parent declaration, a hairline before an outline.
16
+
17
+ | Rule | Edge kind | Draws |
18
+ | --- | --- | --- |
19
+ | BOUNDARY-1 | One seam | The single line between two stacked bands |
20
+ | BOUNDARY-2 | Per-row seam | Each row's own trailing line, dropped on the last row |
21
+ | BOUNDARY-3 | Set seam | One declaration on the parent for every line inside a set |
22
+ | BOUNDARY-4 | Inline seam | The line between columns of a grid or a split region |
23
+ | BOUNDARY-5 | Outline | The border enclosing one object |
24
+ | BOUNDARY-6 | No border | An object separated by elevation instead of a line |
25
+
26
+ A repeating set has one line fewer than it has rows. Whichever rule draws the set, the outer edge of
27
+ the last row is closed by the surface itself, so a set that renders a trailing line at its own edge
28
+ has one boundary too many.
29
+
30
+ ## Owner
31
+
32
+ Each case names who owns the edge. The owner decides whether the application writes a class at all.
33
+
34
+ | Owner | Meaning | Application writes |
35
+ | --- | --- | --- |
36
+ | `App` | The edge belongs to the application | The class |
37
+ | A component name | Common already draws this edge inside that component | Nothing. Pass the prop |
38
+ | `—` | Common exposes no public path for this edge | The class, recorded as a workaround |
39
+
40
+ Writing a class where a component is the owner is `APP_REIMPLEMENTATION`. Writing one where the owner
41
+ is `—` stays linked to `COMMON_CAPABILITY_MISSING`. Adding an application line beside one a component
42
+ already draws is `DOUBLE_OWNER`, and it renders as a visible double hairline.
43
+
44
+ ## Boundaries Common already owns
45
+
46
+ Generated from `@grammar/core` claims by `scripts/generate-presentation-owned.mjs`; edit the component, not this table.
47
+
48
+ | Component | Element or condition | Rule |
49
+ | --- | --- | --- |
50
+ | `ChatWorkspace` | composer | BOUNDARY-1 |
51
+ | `ChatWorkspace` | rail trigger boundary, hasRail, isCompactRail | BOUNDARY-1 |
52
+ | `Divider` | span | BOUNDARY-5 |
53
+ | `MediaFrame` | root, treatment!="plain" | BOUNDARY-5 |
54
+ | `NavigationFeatureNav` | root | BOUNDARY-1 |
55
+ | `StaticStateRow` | root | BOUNDARY-3 |
56
+ | `Subnav` | root | BOUNDARY-1 |
57
+ | `SurfaceAccordionCard` | accordion row | BOUNDARY-3 |
58
+ | `SurfaceAccordionCard` | accordion shell, depth="nested" | BOUNDARY-5 |
59
+ | `SurfaceAccordionCard` | accordion shell, depth="top" | BOUNDARY-6 |
60
+ | `SurfaceCard` | card content, depth!="nested" | BOUNDARY-6 |
61
+ | `SurfaceCard` | card content, depth="nested" | BOUNDARY-5 |
62
+ | `WorkspaceShell` | compact navigation, hasCompactNavigation | BOUNDARY-1 |
63
+ | `WorkspaceShell` | leading rule, railPosition="leading" | BOUNDARY-4 |
64
+
65
+ ## BOUNDARY-1 — `border-t border-separator` / `--separator`
66
+
67
+ One seam between two stacked bands inside a flush surface. The bands touch, and the line is what
68
+ tells them apart.
69
+
70
+ | Case | When | Owner | Render |
71
+ | --- | --- | --- | --- |
72
+ | Case 1 | Two app-owned bands stacked inside one joined card | `—` | `<div aria-hidden className="border-t border-separator" />` between them |
73
+ | Case 2 | A band that carries its own leading seam rather than a separate element | `—` | `<div className="min-w-0 border-t border-separator">` on the band itself |
74
+ | Case 3 | A card's closing action band, separated from the content above it | `—` | `<div className="border-t border-separator px-4 pb-4 pt-3">` |
75
+ | Case 4 | The block edge of page chrome against the content below it | `Subnav`, `NavigationFeatureNav` | Compose the component; no border class |
76
+
77
+ Not this rule: three or more rows of the same kind. Use BOUNDARY-2 or BOUNDARY-3.
78
+
79
+ A separator element is decorative and takes `aria-hidden`; the bands it divides carry the meaning.
80
+
81
+ ## BOUNDARY-2 — `border-b border-separator last:border-b-0` / `--separator`
82
+
83
+ A repeating set where every row draws its own trailing line, and the last row drops it because the
84
+ surface's own edge already closes the set.
85
+
86
+ | Case | When | Owner | Render |
87
+ | --- | --- | --- | --- |
88
+ | Case 1 | Rows of one collection rendered edge to edge inside a joined card | `—` | `<li className="border-b border-separator px-4 py-3 last:border-b-0">` |
89
+ | Case 2 | The same set where the trailing row also opens up to the card's outer inset | `—` | The same class plus `last:pb-4` |
90
+ | Case 3 | A grid of the same rows, where the last full row of the set drops the line | `—` | `sm:[&:nth-last-child(-n+2)]:border-b-0` on a two-column set |
91
+
92
+ Not this rule: a set whose rows carry no class of their own. Use BOUNDARY-3.
93
+
94
+ `last:border-b-0` is the whole point of this rule, not an embellishment. Without it the set renders a
95
+ line against the surface edge and the card reads as unfinished. Case 3 exists because in a two-column
96
+ grid the last row is the last two children, so `last:` alone drops one line and leaves its neighbour.
97
+
98
+ ## BOUNDARY-3 — `divide-y divide-separator` / `--separator`
99
+
100
+ One declaration on the parent draws every line inside a set. The rows say nothing, so no row can be
101
+ missed and no row can render a line the set did not intend.
102
+
103
+ | Case | When | Owner | Render |
104
+ | --- | --- | --- | --- |
105
+ | Case 1 | A list whose rows are uniform and need no per-row exception | `—` | `<ul className="m-0 list-none p-0 divide-y divide-separator">` |
106
+ | Case 2 | A grid of peer measures stacked on one axis | `—` | `<div className="grid min-w-0 grid-cols-1 divide-y divide-separator">` |
107
+ | Case 3 | A list or disclosure whose rows Common already separates | `StaticStateRow`, `SurfaceAccordionCard` | Compose the rows; no divide class |
108
+
109
+ Not this rule: a set where individual rows need a different edge. Use BOUNDARY-2.
110
+
111
+ Common draws Case 3 with an adjacent-sibling rule rather than a parent declaration. Both mean the same
112
+ thing, one line between consecutive rows and none at either outer edge, so both satisfy this rule.
113
+
114
+ ## BOUNDARY-4 — `border-l` / `divide-x` / `--separator`
115
+
116
+ A seam on the inline axis, between columns of a grid or between the two halves of a split region. It
117
+ appears only at the width where the columns exist.
118
+
119
+ | Case | When | Owner | Render |
120
+ | --- | --- | --- | --- |
121
+ | Case 1 | A set that stacks on narrow widths and becomes columns on wide ones | `—` | `divide-y divide-separator lg:divide-y-0 lg:divide-x` on the parent |
122
+ | Case 2 | A two-column grid where only the starting column carries the column seam | `—` | `sm:[&:nth-child(odd)]:border-r` on the row class |
123
+ | Case 3 | A panel that becomes a side region and needs one seam against the primary column | `—` | `lg:border-l lg:border-separator` on the panel |
124
+ | Case 4 | A shell whose leading rail is separated from the primary region by a rule | `WorkspaceShell` | Compose the shell; no border class |
125
+
126
+ Not this rule: the block-axis lines of the same set. Those stay BOUNDARY-2 or BOUNDARY-3, and the two
127
+ axes each name their own case.
128
+
129
+ The `nth-child` selector in Case 2 is what keeps the trailing column from drawing a line against the
130
+ surface edge. It is the inline-axis form of `last:border-b-0`.
131
+
132
+ ## BOUNDARY-5 — `border` / `--border`
133
+
134
+ The outline enclosing one object, rather than a line between two. Every case belongs to a Grammar
135
+ component, because the objects that need an outline are Grammar's.
136
+
137
+ | Case | When | Owner | Render |
138
+ | --- | --- | --- | --- |
139
+ | Case 1 | A card nested inside another bounded surface | `SurfaceCard` | `depth="nested"` already draws the outline |
140
+ | Case 2 | A framed media viewport | `MediaFrame` | Compose the frame; no border class |
141
+ | Case 3 | A code block or a table frame inside article content | `FencedCodeBlock`, `MarkdownTableFrame` | Compose the block; no border class |
142
+ | Case 4 | A labelled boundary offering an alternative between two paths | `Divider` | `<Divider label="or" />` |
143
+
144
+ Not this rule: the line between two touching bands. That is a hairline on `--separator`, so use
145
+ BOUNDARY-1.
146
+
147
+ ## BOUNDARY-6 — no border / `--shadow-surface`
148
+
149
+ An object separated from the page by elevation rather than by a line. This is the default face of a
150
+ top-level card, and it is a boundary decision even though it draws no border.
151
+
152
+ | Case | When | Owner | Render |
153
+ | --- | --- | --- | --- |
154
+ | Case 1 | A top-level card sitting directly on the page canvas | `SurfaceCard` | `depth="top"` already clears the border and applies the shadow |
155
+ | Case 2 | The same card once it is nested inside another surface | `SurfaceCard` | `depth="nested"` replaces the shadow with BOUNDARY-5 |
156
+
157
+ Not this rule: adding an outline to a top-level card. The border and the shadow are alternatives, and
158
+ drawing both is `DOUBLE_OWNER`.
159
+
160
+ `--shadow-surface` is a theme hook rather than a fixed value, and a theme may resolve it to no shadow
161
+ at all. A top-level card is then separated by its face against the page canvas alone, which is a
162
+ surface decision and belongs to [Surface](surface.md).
163
+
164
+ ## What this file does not decide
165
+
166
+ Which face sits on either side of an edge is [Surface](surface.md). The space between an edge and its
167
+ content is [Padding](padding.md), and a boundary drawn by a line rather than by space is why a
168
+ separator-facing side takes less inset than an outer edge. Distance between siblings that need no line
169
+ is [Gap](gap.md), and the clipping that keeps a full-bleed band inside its card is
170
+ [Overflow](overflow.md).
@@ -0,0 +1,169 @@
1
+ # Boundary presentation
2
+
3
+ File này trả lời đúng một câu hỏi: một cạnh mà ứng dụng sở hữu thì được vẽ bằng separator hay border
4
+ nào, và cạnh nào trong một tập lặp lại thì bỏ đường kẻ đó.
5
+
6
+ Theme công bố hai token đường mảnh và chúng mang hai nghĩa khác nhau: `--separator` vẽ đường giữa
7
+ những thứ khác nhau, còn `--border` vẽ đường viền của một thứ. Ranh giới bên trong một Grammar
8
+ component là của chính component đó, không bao giờ của ứng dụng, và không cạnh nào của ứng dụng được
9
+ vẽ bằng một giá trị màu thô.
10
+
11
+ ## Danh mục
12
+
13
+ Boundary không có thang giá trị, nên số của rule là địa chỉ trên tập các loại cạnh chứ không phải vị
14
+ trí trên một dải. Ưu tiên rule đứng trước nếu nó đủ dùng: một đường trước đường theo từng hàng, đường
15
+ theo từng hàng trước khai báo ở cha, đường mảnh trước đường viền.
16
+
17
+ | Rule | Loại cạnh | Vẽ cái gì |
18
+ | --- | --- | --- |
19
+ | BOUNDARY-1 | Một đường | Đường duy nhất giữa hai dải xếp chồng |
20
+ | BOUNDARY-2 | Đường theo từng hàng | Đường cuối của mỗi hàng, bỏ ở hàng cuối |
21
+ | BOUNDARY-3 | Đường của cả tập | Một khai báo ở cha vẽ mọi đường bên trong tập |
22
+ | BOUNDARY-4 | Đường theo trục inline | Đường giữa các cột của grid hoặc của một vùng chẻ đôi |
23
+ | BOUNDARY-5 | Đường viền | Border bao quanh một đối tượng |
24
+ | BOUNDARY-6 | Không border | Đối tượng được tách bằng độ nổi thay vì bằng đường kẻ |
25
+
26
+ Một tập lặp lại có số đường ít hơn số hàng đúng một. Rule nào vẽ tập cũng vậy, mép ngoài của hàng cuối
27
+ đã do chính surface đóng lại, nên một tập còn vẽ đường ở mép của chính nó là thừa một ranh giới.
28
+
29
+ ## Owner
30
+
31
+ Mỗi case gọi tên ai sở hữu cạnh đó. Owner quyết định ứng dụng có được viết class hay không.
32
+
33
+ | Owner | Nghĩa | Ứng dụng viết |
34
+ | --- | --- | --- |
35
+ | `App` | Cạnh thuộc về ứng dụng | Viết class |
36
+ | Tên component | Common đã vẽ cạnh này bên trong component đó | Không viết gì, chỉ truyền prop |
37
+ | `—` | Common chưa có đường dùng công khai cho cạnh này | Viết class, ghi nhận là workaround |
38
+
39
+ Viết class ở chỗ owner là một component chính là `APP_REIMPLEMENTATION`. Viết class ở chỗ owner là `—`
40
+ thì gắn liền với `COMMON_CAPABILITY_MISSING`. Thêm một đường của ứng dụng cạnh đường mà component đã
41
+ vẽ là `DOUBLE_OWNER`, và nó hiện ra thành một đường mảnh đôi nhìn thấy được.
42
+
43
+ ## Boundary mà Common đã sở hữu
44
+
45
+ Sinh từ claim của `@grammar/core` bằng `scripts/generate-presentation-owned.mjs`; muốn đổi thì sửa component, đừng sửa bảng này.
46
+
47
+ | Component | Phần tử hoặc điều kiện | Rule |
48
+ | --- | --- | --- |
49
+ | `ChatWorkspace` | composer | BOUNDARY-1 |
50
+ | `ChatWorkspace` | rail trigger boundary, hasRail, isCompactRail | BOUNDARY-1 |
51
+ | `Divider` | span | BOUNDARY-5 |
52
+ | `MediaFrame` | root, treatment!="plain" | BOUNDARY-5 |
53
+ | `NavigationFeatureNav` | root | BOUNDARY-1 |
54
+ | `StaticStateRow` | root | BOUNDARY-3 |
55
+ | `Subnav` | root | BOUNDARY-1 |
56
+ | `SurfaceAccordionCard` | accordion row | BOUNDARY-3 |
57
+ | `SurfaceAccordionCard` | accordion shell, depth="nested" | BOUNDARY-5 |
58
+ | `SurfaceAccordionCard` | accordion shell, depth="top" | BOUNDARY-6 |
59
+ | `SurfaceCard` | card content, depth!="nested" | BOUNDARY-6 |
60
+ | `SurfaceCard` | card content, depth="nested" | BOUNDARY-5 |
61
+ | `WorkspaceShell` | compact navigation, hasCompactNavigation | BOUNDARY-1 |
62
+ | `WorkspaceShell` | leading rule, railPosition="leading" | BOUNDARY-4 |
63
+
64
+ ## BOUNDARY-1 — `border-t border-separator` / `--separator`
65
+
66
+ Một đường giữa hai dải xếp chồng bên trong một surface tràn viền. Hai dải chạm nhau, và đường kẻ là
67
+ thứ phân biệt chúng.
68
+
69
+ | Case | Dùng khi | Owner | Render |
70
+ | --- | --- | --- | --- |
71
+ | Case 1 | Hai dải do app sở hữu xếp chồng trong một card nối liền | `—` | `<div aria-hidden className="border-t border-separator" />` đặt giữa hai dải |
72
+ | Case 2 | Một dải tự mang đường dẫn đầu của nó thay vì một phần tử riêng | `—` | `<div className="min-w-0 border-t border-separator">` trên chính dải đó |
73
+ | Case 3 | Dải action đóng lại của một card, tách khỏi nội dung phía trên | `—` | `<div className="border-t border-separator px-4 pb-4 pt-3">` |
74
+ | Case 4 | Mép block của chrome trang đối với nội dung bên dưới | `Subnav`, `NavigationFeatureNav` | Ghép component, không viết class border |
75
+
76
+ Không phải rule này: từ ba hàng cùng loại trở lên thì dùng BOUNDARY-2 hoặc BOUNDARY-3.
77
+
78
+ Một phần tử separator là trang trí và phải mang `aria-hidden`; nghĩa nằm ở các dải mà nó chia.
79
+
80
+ ## BOUNDARY-2 — `border-b border-separator last:border-b-0` / `--separator`
81
+
82
+ Một tập lặp lại mà mỗi hàng tự vẽ đường kết của nó, còn hàng cuối bỏ đường đó vì mép của chính surface
83
+ đã đóng tập lại rồi.
84
+
85
+ | Case | Dùng khi | Owner | Render |
86
+ | --- | --- | --- | --- |
87
+ | Case 1 | Các hàng của một tập hợp render sát hai mép trong card nối liền | `—` | `<li className="border-b border-separator px-4 py-3 last:border-b-0">` |
88
+ | Case 2 | Cũng tập đó, khi hàng cuối còn mở ra tới inset mép ngoài của card | `—` | Cùng class, thêm `last:pb-4` |
89
+ | Case 3 | Một lưới cùng loại hàng, nơi hàng đầy đủ cuối cùng của tập bỏ đường kẻ | `—` | `sm:[&:nth-last-child(-n+2)]:border-b-0` trên tập hai cột |
90
+
91
+ Không phải rule này: một tập mà các hàng không mang class riêng thì dùng BOUNDARY-3.
92
+
93
+ `last:border-b-0` chính là trọng tâm của rule này, không phải phần trang trí. Thiếu nó thì tập render
94
+ một đường sát mép surface và card đọc lên như chưa hoàn thiện. Case 3 tồn tại vì trong lưới hai cột thì
95
+ hàng cuối là hai con cuối, nên chỉ dùng `last:` sẽ bỏ được một đường và bỏ sót đường bên cạnh.
96
+
97
+ ## BOUNDARY-3 — `divide-y divide-separator` / `--separator`
98
+
99
+ Một khai báo ở cha vẽ mọi đường bên trong tập. Các hàng không nói gì, nên không hàng nào bị bỏ sót và
100
+ không hàng nào render được một đường mà tập không định vẽ.
101
+
102
+ | Case | Dùng khi | Owner | Render |
103
+ | --- | --- | --- | --- |
104
+ | Case 1 | Một list mà các hàng đồng nhất và không cần ngoại lệ theo hàng | `—` | `<ul className="m-0 list-none p-0 divide-y divide-separator">` |
105
+ | Case 2 | Một lưới các số đo ngang hàng xếp chồng trên một trục | `—` | `<div className="grid min-w-0 grid-cols-1 divide-y divide-separator">` |
106
+ | Case 3 | Một list hay disclosure mà Common đã tách hàng sẵn | `StaticStateRow`, `SurfaceAccordionCard` | Ghép hàng, không viết class divide |
107
+
108
+ Không phải rule này: một tập mà từng hàng cần cạnh khác nhau thì dùng BOUNDARY-2.
109
+
110
+ Common vẽ Case 3 bằng luật anh em kề chứ không bằng khai báo ở cha. Hai cách cùng một nghĩa, một đường
111
+ giữa hai hàng liên tiếp và không đường nào ở hai mép ngoài, nên cả hai đều thoả rule này.
112
+
113
+ ## BOUNDARY-4 — `border-l` / `divide-x` / `--separator`
114
+
115
+ Một đường trên trục inline, giữa các cột của một lưới hoặc giữa hai nửa của một vùng chẻ đôi. Nó chỉ
116
+ xuất hiện ở bề rộng mà các cột thực sự tồn tại.
117
+
118
+ | Case | Dùng khi | Owner | Render |
119
+ | --- | --- | --- | --- |
120
+ | Case 1 | Một tập xếp chồng ở khổ hẹp và thành cột ở khổ rộng | `—` | `divide-y divide-separator lg:divide-y-0 lg:divide-x` trên cha |
121
+ | Case 2 | Lưới hai cột mà chỉ cột đầu mang đường ngăn cột | `—` | `sm:[&:nth-child(odd)]:border-r` trên class của hàng |
122
+ | Case 3 | Một panel trở thành vùng bên và cần một đường với cột chính | `—` | `lg:border-l lg:border-separator` trên panel |
123
+ | Case 4 | Một shell mà rail dẫn đầu được tách khỏi vùng chính bằng một đường kẻ | `WorkspaceShell` | Ghép shell, không viết class border |
124
+
125
+ Không phải rule này: các đường theo trục block của cùng tập đó. Chúng vẫn là BOUNDARY-2 hoặc
126
+ BOUNDARY-3, và mỗi trục phải gọi tên case của riêng nó.
127
+
128
+ Selector `nth-child` ở Case 2 chính là thứ giữ cho cột cuối không vẽ đường sát mép surface. Nó là dạng
129
+ trục inline của `last:border-b-0`.
130
+
131
+ ## BOUNDARY-5 — `border` / `--border`
132
+
133
+ Đường viền bao quanh một đối tượng, chứ không phải đường giữa hai thứ. Mọi case đều thuộc về một
134
+ Grammar component, vì những đối tượng cần đường viền đều là của Grammar.
135
+
136
+ | Case | Dùng khi | Owner | Render |
137
+ | --- | --- | --- | --- |
138
+ | Case 1 | Một card lồng bên trong một surface có ranh giới khác | `SurfaceCard` | `depth="nested"` đã vẽ sẵn đường viền |
139
+ | Case 2 | Một viewport media có khung | `MediaFrame` | Ghép frame, không viết class border |
140
+ | Case 3 | Một khối code hay khung bảng trong nội dung article | `FencedCodeBlock`, `MarkdownTableFrame` | Ghép khối, không viết class border |
141
+ | Case 4 | Một ranh giới có nhãn nêu ra lựa chọn thay thế giữa hai đường đi | `Divider` | `<Divider label="hoặc" />` |
142
+
143
+ Không phải rule này: đường giữa hai dải chạm nhau. Đó là đường mảnh trên `--separator`, nên dùng
144
+ BOUNDARY-1.
145
+
146
+ ## BOUNDARY-6 — không border / `--shadow-surface`
147
+
148
+ Một đối tượng được tách khỏi trang bằng độ nổi thay vì bằng đường kẻ. Đây là mặt mặc định của card cấp
149
+ cao nhất, và nó vẫn là một quyết định ranh giới dù không vẽ border nào.
150
+
151
+ | Case | Dùng khi | Owner | Render |
152
+ | --- | --- | --- | --- |
153
+ | Case 1 | Một card cấp cao nhất nằm thẳng trên canvas trang | `SurfaceCard` | `depth="top"` đã bỏ sẵn border và áp bóng đổ |
154
+ | Case 2 | Cũng card đó khi nó được lồng vào bên trong một surface khác | `SurfaceCard` | `depth="nested"` thay bóng đổ bằng BOUNDARY-5 |
155
+
156
+ Không phải rule này: thêm đường viền cho một card cấp cao nhất. Border và bóng đổ là hai lựa chọn thay
157
+ thế nhau, vẽ cả hai là `DOUBLE_OWNER`.
158
+
159
+ `--shadow-surface` là một điểm móc của theme chứ không phải giá trị cố định, và một theme có thể quy nó
160
+ về không bóng đổ. Khi đó card cấp cao nhất chỉ còn được tách bằng chính mặt của nó trên canvas trang,
161
+ và đó là quyết định surface, thuộc về [Surface](surface.md).
162
+
163
+ ## File này không quyết định
164
+
165
+ Mặt nào nằm ở hai bên một cạnh là việc của [Surface](surface.md). Khoảng cách giữa một cạnh và nội
166
+ dung của nó là [Padding](padding.md), và một ranh giới được vẽ bằng đường kẻ thay vì bằng khoảng trắng
167
+ chính là lý do cạnh giáp separator lấy inset nhỏ hơn cạnh mép ngoài. Khoảng cách giữa các phần tử ngang
168
+ hàng mà không cần đường kẻ là [Gap](gap.md), còn việc cắt để giữ một dải tràn viền nằm gọn trong card
169
+ là [Overflow](overflow.md).
@@ -0,0 +1,155 @@
1
+ # Font presentation
2
+
3
+ This file answers one question: given a line of copy the application has already ranked, which public
4
+ typography prop renders it?
5
+
6
+ Composition has already chosen the DOM tree and the Grammar objects. The application decides the
7
+ information rank. Grammar renders that rank. The application never writes a size, weight, line height,
8
+ or tracking class, and never overrides typography inside another Grammar component.
9
+
10
+ ## Scale
11
+
12
+ The type scale is closed and shared by `Text` and `Heading`. The rule ID is the ordinal position on
13
+ that scale, smallest first. It is not a Tailwind step and not a heading level.
14
+
15
+ | Rule | Rendered | `Text` | `Heading` |
16
+ | --- | --- | --- | --- |
17
+ | FONT-1 | `text-xs` / `leading-4` | `size="xs"` | `level={4}` |
18
+ | FONT-2 | `text-sm` / `leading-5` | `size="sm"` | `level={3}` |
19
+ | FONT-3 | `text-base` / `leading-6` | `size="md"`, the default | `level={2}` |
20
+ | FONT-4 | `text-xl` | none | `level={1}` |
21
+ | FONT-5 | `text-3xl` / `leading-9` | `size="metric-lead"` | none |
22
+ | FONT-6 | `text-4xl` / `leading-tight` | none | `scale="display"` |
23
+
24
+ `Text` and `Heading` are not interchangeable at the same size. A heading declares document structure;
25
+ a text line does not. Choosing `Heading` to obtain a size, or `Text` to avoid an outline entry, is a
26
+ structure error rather than a typography one.
27
+
28
+ Tracking is not an application decision. `Heading` applies `tracking-tight` at FONT-4 and FONT-6 only.
29
+
30
+ ## Owner
31
+
32
+ Typography belongs to Grammar. The owner cell names which component renders the rank.
33
+
34
+ | Owner | Meaning | Application writes |
35
+ | --- | --- | --- |
36
+ | A component name | `Text` or `Heading` renders this rank | The prop only |
37
+ | `—` | The rank has no public prop | Nothing. Report the gap |
38
+
39
+ There is no `App` owner in this file. An application typography class is `APP_OVERRIDE`, and a raw
40
+ `font-size` or `font-weight` that changes semantic rank is rejected even when the pixels match.
41
+
42
+ ## Font Common already owns
43
+
44
+ Generated from `@grammar/core` claims by `scripts/generate-presentation-owned.mjs`; edit the component, not this table.
45
+
46
+ | Component | Element or condition | Rule |
47
+ | --- | --- | --- |
48
+ | `ChatWorkspace` | rail trigger, hasRail, isCompactRail | FONT-2 |
49
+ | `Heading` | root, scale!="display", level=1 | FONT-4 |
50
+ | `Heading` | root, scale!="display", level=2 | FONT-3 |
51
+ | `Heading` | root, scale!="display", level=3 | FONT-2 |
52
+ | `Heading` | root, scale!="display", level=4 | FONT-1 |
53
+ | `Heading` | root, scale="display" | FONT-6 |
54
+ | `Input` | toggle label, not (!isSecret || toggleLabel === undefined), ToggleIcon=undefined | FONT-1 |
55
+ | `Label` | root, depth!="nested" | FONT-2 |
56
+ | `Label` | root, depth="nested" | FONT-1 |
57
+ | `Sidebar` | group label, group.label!=undefined, not collapsed | FONT-1 |
58
+ | `Sidebar` | item label, not collapsed | FONT-2 |
59
+ | `SurfaceListCard` | fact, not (label === undefined || labelHidden), fact!=undefined, depth!="nested" | FONT-2 |
60
+ | `SurfaceListCard` | fact, not (label === undefined || labelHidden), fact!=undefined, depth="nested" | FONT-1 |
61
+ | `Text` | root, size="md" | FONT-3 |
62
+ | `Text` | root, size="metric-lead" | FONT-5 |
63
+ | `Text` | root, size="sm" | FONT-2 |
64
+ | `Text` | root, size="xs" | FONT-1 |
65
+ | `TextAction` | root, size="md" | FONT-3 |
66
+ | `TextAction` | root, size="sm" | FONT-2 |
67
+ | `TextAction` | root, size="xs" | FONT-1 |
68
+ | `Tooltip` | content | FONT-1 |
69
+
70
+ ## FONT-1 — `text-xs` / `leading-4`
71
+
72
+ The smallest public size, for the lowest rank of supporting information.
73
+
74
+ | Case | When | Owner | Render |
75
+ | --- | --- | --- | --- |
76
+ | Case 1 | Brief metadata that stays understandable at the smallest size | `Text` | `<Text size="xs">Optional</Text>` |
77
+ | Case 2 | The label of a nested region inside an already-titled section | `Heading` | `<Heading level={4}>Card details</Heading>` |
78
+
79
+ `Text size="xs"` always resolves to muted and cannot be promoted to another tone. `Heading level={4}`
80
+ carries the same muted treatment.
81
+
82
+ Not this rule: ordinary sentences, or any fact the reader must not miss. Use FONT-2 or FONT-3.
83
+
84
+ ## FONT-2 — `text-sm` / `leading-5`
85
+
86
+ A compact reading size for supporting copy that still forms complete lines.
87
+
88
+ | Case | When | Owner | Render |
89
+ | --- | --- | --- | --- |
90
+ | Case 1 | A complete line ranked below normal body copy, such as a timestamp or short fact | `Text` | `<Text size="sm">Updated 2 minutes ago</Text>` |
91
+ | Case 2 | A third-level region heading inside a section | `Heading` | `<Heading level={3}>Payment method</Heading>` |
92
+
93
+ Not this rule: shrinking body copy so it fits a container that is too small. Fix the container.
94
+
95
+ ## FONT-3 — `text-base` / `leading-6`
96
+
97
+ The normal reading size, and the resolved default when no size is given.
98
+
99
+ | Case | When | Owner | Render |
100
+ | --- | --- | --- | --- |
101
+ | Case 1 | Ordinary explanatory copy with normal reading priority | `Text` | `<Text>Your subscription renews on 12 March.</Text>` |
102
+ | Case 2 | The heading of a section inside a page | `Heading` | `<Heading level={2}>Billing</Heading>` |
103
+
104
+ ## FONT-4 — `text-xl`
105
+
106
+ The page-level heading size, carrying tight tracking.
107
+
108
+ | Case | When | Owner | Render |
109
+ | --- | --- | --- | --- |
110
+ | Case 1 | The single heading that names the whole page or route | `Heading` | `<Heading level={1}>Account</Heading>` |
111
+
112
+ Not this rule: a second `level={1}` on the same page. One document, one top-level heading.
113
+
114
+ ## FONT-5 — `text-3xl` / `leading-9`
115
+
116
+ A large numeric treatment for one already-important value.
117
+
118
+ | Case | When | Owner | Render |
119
+ | --- | --- | --- | --- |
120
+ | Case 1 | The single leading metric or short value that is the main fact of its region | `Text` | `<Text size="metric-lead" weight="semibold">84%</Text>` |
121
+
122
+ Not this rule: sentences, decoration, or imitating a heading. It creates no heading semantics.
123
+
124
+ ## FONT-6 — `text-4xl` / `leading-tight`
125
+
126
+ Display emphasis applied to a heading that keeps its semantic level.
127
+
128
+ | Case | When | Owner | Render |
129
+ | --- | --- | --- | --- |
130
+ | Case 1 | A page-root heading that must carry marketing or landing weight | `Heading` | `<Heading level={1} scale="display">Learn without limits</Heading>` |
131
+
132
+ Not this rule: raising the visual size of a nested heading. `scale` changes the recipe, never the
133
+ outline position.
134
+
135
+ ## Weight
136
+
137
+ Weight is a second axis, not a position on the size scale. Its public set is closed.
138
+
139
+ | Prop | Rendered | Use for |
140
+ | --- | --- | --- |
141
+ | `weight="normal"` | `font-normal`, the default | Reading copy and ordinary facts |
142
+ | `weight="medium"` | `font-medium` | A compact label, or a title above its own description |
143
+ | `weight="semibold"` | `font-semibold` | A fact that must be found first within its region |
144
+
145
+ Weight refines a rank the application has already chosen. It never manufactures a new hierarchy
146
+ level, and it never substitutes for a heading. `Heading` applies its own weight per level and takes
147
+ no weight prop.
148
+
149
+ Bold beyond `semibold` has no public prop. Treat an intent that needs it as a gap rather than writing
150
+ a class.
151
+
152
+ ## What this file does not decide
153
+
154
+ Which colour expresses the rank is [Tone](tone.md). How the line wraps, aligns, or truncates is
155
+ [Text flow](text-flow.md). How much room the text region gets is [Measure](measure.md).
@@ -0,0 +1,156 @@
1
+ # Font presentation
2
+
3
+ File này trả lời đúng một câu hỏi: một dòng chữ mà ứng dụng đã xếp hạng xong thì render bằng prop
4
+ typography công khai nào.
5
+
6
+ Bước composition đã chọn xong cây DOM và các Grammar object. Ứng dụng quyết định hạng thông tin,
7
+ Grammar render hạng đó. Ứng dụng không bao giờ viết class cỡ chữ, độ đậm, line height hay tracking,
8
+ và không ghi đè typography bên trong một Grammar component khác.
9
+
10
+ ## Thang giá trị
11
+
12
+ Thang chữ là thang đóng, dùng chung cho `Text` và `Heading`. Số của rule là thứ tự trên thang đó,
13
+ nhỏ trước. Nó không phải bậc Tailwind và cũng không phải cấp heading.
14
+
15
+ | Rule | Render ra | `Text` | `Heading` |
16
+ | --- | --- | --- | --- |
17
+ | FONT-1 | `text-xs` / `leading-4` | `size="xs"` | `level={4}` |
18
+ | FONT-2 | `text-sm` / `leading-5` | `size="sm"` | `level={3}` |
19
+ | FONT-3 | `text-base` / `leading-6` | `size="md"`, mặc định | `level={2}` |
20
+ | FONT-4 | `text-xl` | không có | `level={1}` |
21
+ | FONT-5 | `text-3xl` / `leading-9` | `size="metric-lead"` | không có |
22
+ | FONT-6 | `text-4xl` / `leading-tight` | không có | `scale="display"` |
23
+
24
+ `Text` và `Heading` không thay thế nhau được dù cùng cỡ. Heading khai báo cấu trúc tài liệu, còn một
25
+ dòng text thì không. Chọn `Heading` để lấy cỡ chữ, hoặc chọn `Text` để né một mục trong dàn bài, là
26
+ lỗi cấu trúc chứ không phải lỗi typography.
27
+
28
+ Tracking không phải quyết định của ứng dụng. `Heading` chỉ áp `tracking-tight` ở FONT-4 và FONT-6.
29
+
30
+ ## Owner
31
+
32
+ Typography thuộc về Grammar. Ô owner gọi tên component nào render hạng đó.
33
+
34
+ | Owner | Nghĩa | Ứng dụng viết |
35
+ | --- | --- | --- |
36
+ | Tên component | `Text` hoặc `Heading` render hạng này | Chỉ truyền prop |
37
+ | `—` | Hạng này chưa có prop công khai | Không viết gì, báo là thiếu |
38
+
39
+ File này không có owner `App`. Một class typography do ứng dụng viết là `APP_OVERRIDE`, và một
40
+ `font-size` hay `font-weight` thô làm đổi hạng ngữ nghĩa thì bị từ chối kể cả khi pixel trùng khớp.
41
+
42
+ ## Font mà Common đã sở hữu
43
+
44
+ Sinh từ claim của `@grammar/core` bằng `scripts/generate-presentation-owned.mjs`; muốn đổi thì sửa component, đừng sửa bảng này.
45
+
46
+ | Component | Phần tử hoặc điều kiện | Rule |
47
+ | --- | --- | --- |
48
+ | `ChatWorkspace` | rail trigger, hasRail, isCompactRail | FONT-2 |
49
+ | `Heading` | root, scale!="display", level=1 | FONT-4 |
50
+ | `Heading` | root, scale!="display", level=2 | FONT-3 |
51
+ | `Heading` | root, scale!="display", level=3 | FONT-2 |
52
+ | `Heading` | root, scale!="display", level=4 | FONT-1 |
53
+ | `Heading` | root, scale="display" | FONT-6 |
54
+ | `Input` | toggle label, not (!isSecret || toggleLabel === undefined), ToggleIcon=undefined | FONT-1 |
55
+ | `Label` | root, depth!="nested" | FONT-2 |
56
+ | `Label` | root, depth="nested" | FONT-1 |
57
+ | `Sidebar` | group label, group.label!=undefined, not collapsed | FONT-1 |
58
+ | `Sidebar` | item label, not collapsed | FONT-2 |
59
+ | `SurfaceListCard` | fact, not (label === undefined || labelHidden), fact!=undefined, depth!="nested" | FONT-2 |
60
+ | `SurfaceListCard` | fact, not (label === undefined || labelHidden), fact!=undefined, depth="nested" | FONT-1 |
61
+ | `Text` | root, size="md" | FONT-3 |
62
+ | `Text` | root, size="metric-lead" | FONT-5 |
63
+ | `Text` | root, size="sm" | FONT-2 |
64
+ | `Text` | root, size="xs" | FONT-1 |
65
+ | `TextAction` | root, size="md" | FONT-3 |
66
+ | `TextAction` | root, size="sm" | FONT-2 |
67
+ | `TextAction` | root, size="xs" | FONT-1 |
68
+ | `Tooltip` | content | FONT-1 |
69
+
70
+ ## FONT-1 — `text-xs` / `leading-4`
71
+
72
+ Cỡ công khai nhỏ nhất, cho hạng thông tin phụ thấp nhất.
73
+
74
+ | Case | Dùng khi | Owner | Render |
75
+ | --- | --- | --- | --- |
76
+ | Case 1 | Metadata ngắn, vẫn hiểu được ở cỡ nhỏ nhất | `Text` | `<Text size="xs">Optional</Text>` |
77
+ | Case 2 | Nhãn của một vùng lồng bên trong một section đã có tiêu đề | `Heading` | `<Heading level={4}>Card details</Heading>` |
78
+
79
+ `Text size="xs"` luôn quy về muted và không nâng lên tone khác được. `Heading level={4}` mang đúng
80
+ cách xử lý muted đó.
81
+
82
+ Không phải rule này: câu văn thường, hoặc bất kỳ dữ kiện nào người đọc không được bỏ sót. Dùng
83
+ FONT-2 hoặc FONT-3.
84
+
85
+ ## FONT-2 — `text-sm` / `leading-5`
86
+
87
+ Cỡ đọc gọn cho phần copy phụ nhưng vẫn thành câu hoàn chỉnh.
88
+
89
+ | Case | Dùng khi | Owner | Render |
90
+ | --- | --- | --- | --- |
91
+ | Case 1 | Một dòng hoàn chỉnh xếp dưới body copy thường, kiểu mốc thời gian hay một dữ kiện ngắn | `Text` | `<Text size="sm">Updated 2 minutes ago</Text>` |
92
+ | Case 2 | Tiêu đề vùng cấp ba bên trong một section | `Heading` | `<Heading level={3}>Payment method</Heading>` |
93
+
94
+ Không phải rule này: thu nhỏ body copy cho vừa một container quá chật. Sửa cái container.
95
+
96
+ ## FONT-3 — `text-base` / `leading-6`
97
+
98
+ Cỡ đọc thường, và là giá trị mặc định khi không truyền size.
99
+
100
+ | Case | Dùng khi | Owner | Render |
101
+ | --- | --- | --- | --- |
102
+ | Case 1 | Copy giải thích thông thường, ưu tiên đọc ở mức bình thường | `Text` | `<Text>Your subscription renews on 12 March.</Text>` |
103
+ | Case 2 | Tiêu đề của một section bên trong trang | `Heading` | `<Heading level={2}>Billing</Heading>` |
104
+
105
+ ## FONT-4 — `text-xl`
106
+
107
+ Cỡ tiêu đề cấp trang, mang tracking chặt.
108
+
109
+ | Case | Dùng khi | Owner | Render |
110
+ | --- | --- | --- | --- |
111
+ | Case 1 | Tiêu đề duy nhất gọi tên cả trang hoặc cả route | `Heading` | `<Heading level={1}>Account</Heading>` |
112
+
113
+ Không phải rule này: một `level={1}` thứ hai trên cùng trang. Một tài liệu, một tiêu đề cấp cao nhất.
114
+
115
+ ## FONT-5 — `text-3xl` / `leading-9`
116
+
117
+ Cách trình bày số lớn cho một giá trị vốn đã quan trọng.
118
+
119
+ | Case | Dùng khi | Owner | Render |
120
+ | --- | --- | --- | --- |
121
+ | Case 1 | Chỉ số hoặc giá trị ngắn duy nhất, là dữ kiện chính của vùng đó | `Text` | `<Text size="metric-lead" weight="semibold">84%</Text>` |
122
+
123
+ Không phải rule này: câu văn, trang trí, hoặc giả làm tiêu đề. Nó không tạo ra ngữ nghĩa heading nào.
124
+
125
+ ## FONT-6 — `text-4xl` / `leading-tight`
126
+
127
+ Nhấn mạnh cỡ display áp lên một heading vẫn giữ nguyên cấp ngữ nghĩa của nó.
128
+
129
+ | Case | Dùng khi | Owner | Render |
130
+ | --- | --- | --- | --- |
131
+ | Case 1 | Tiêu đề gốc trang cần sức nặng kiểu landing hoặc marketing | `Heading` | `<Heading level={1} scale="display">Learn without limits</Heading>` |
132
+
133
+ Không phải rule này: phóng to một heading lồng bên trong. `scale` đổi công thức hiển thị chứ không
134
+ bao giờ đổi vị trí trong dàn bài.
135
+
136
+ ## Độ đậm
137
+
138
+ Độ đậm là trục thứ hai, không phải một vị trí trên thang cỡ chữ. Tập giá trị công khai của nó là
139
+ tập đóng.
140
+
141
+ | Prop | Render ra | Dùng cho |
142
+ | --- | --- | --- |
143
+ | `weight="normal"` | `font-normal`, mặc định | Copy để đọc và các dữ kiện thường |
144
+ | `weight="medium"` | `font-medium` | Một nhãn gọn, hoặc một tiêu đề nằm trên phần mô tả của chính nó |
145
+ | `weight="semibold"` | `font-semibold` | Dữ kiện phải tìm thấy đầu tiên trong vùng của nó |
146
+
147
+ Độ đậm chỉ tinh chỉnh một hạng mà ứng dụng đã chọn. Nó không đẻ ra một cấp phân cấp mới, và không
148
+ thay thế được một heading. `Heading` tự áp độ đậm theo từng cấp và không nhận prop weight.
149
+
150
+ Đậm hơn `semibold` chưa có prop công khai. Ý đồ nào cần tới nó thì coi là thiếu capability, đừng
151
+ viết class.
152
+
153
+ ## File này không quyết định
154
+
155
+ Màu nào diễn đạt hạng đó thuộc về [Tone](tone.md). Dòng chữ xuống dòng, canh lề hay cắt bớt ra sao
156
+ thuộc về [Text flow](text-flow.md). Vùng chữ được bao nhiêu chỗ thuộc về [Measure](measure.md).