@beehexa/design-rules 0.0.0-stage → 2611.3.3

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 (290) hide show
  1. package/README.md +56 -2
  2. package/dist/AGENTS.md +24 -0
  3. package/dist/catalog.json +1814 -0
  4. package/dist/docs/public/_redirects +7 -0
  5. package/dist/docs/public/apple-touch-icon.png +0 -0
  6. package/dist/docs/public/brand/logos/app/apple-touch-icon.png +0 -0
  7. package/dist/docs/public/brand/logos/app/avatar-800.png +0 -0
  8. package/dist/docs/public/brand/logos/app/icon-192.png +0 -0
  9. package/dist/docs/public/brand/logos/app/icon-512.png +0 -0
  10. package/dist/docs/public/brand/logos/app/icon-maskable-512.png +0 -0
  11. package/dist/docs/public/brand/logos/archive/d-550/beehexa-horizontal-1-light.svg +1 -0
  12. package/dist/docs/public/brand/logos/archive/d-550/beehexa-horizontal-2-dark.svg +1 -0
  13. package/dist/docs/public/brand/logos/archive/d-550/beehexa-horizontal-3-white.svg +1 -0
  14. package/dist/docs/public/brand/logos/archive/d-550/beehexa-horizontal-4-graphite.svg +1 -0
  15. package/dist/docs/public/brand/logos/archive/d-550/hexasync-horizontal-1-light.svg +1 -0
  16. package/dist/docs/public/brand/logos/archive/d-550/hexasync-horizontal-2-dark.svg +1 -0
  17. package/dist/docs/public/brand/logos/archive/d-550/hexasync-horizontal-3-white.svg +1 -0
  18. package/dist/docs/public/brand/logos/archive/d-550/hexasync-horizontal-4-graphite.svg +1 -0
  19. package/dist/docs/public/brand/logos/archive/d-550/ui/beehexa-d-550-dark.svg +1 -0
  20. package/dist/docs/public/brand/logos/archive/d-550/ui/beehexa-d-550-light.svg +1 -0
  21. package/dist/docs/public/brand/logos/archive/d-550/ui/beehexa-design-d-550-dark.svg +1 -0
  22. package/dist/docs/public/brand/logos/archive/d-550/ui/beehexa-design-d-550-light.svg +1 -0
  23. package/dist/docs/public/brand/logos/archive/d-550/ui/hexasync-d-550-dark.svg +1 -0
  24. package/dist/docs/public/brand/logos/archive/d-550/ui/hexasync-d-550-light.svg +1 -0
  25. package/dist/docs/public/brand/logos/archive/d-550/ui/png/beehexa-design-d-550-dark@3x.png +0 -0
  26. package/dist/docs/public/brand/logos/archive/d-550/ui/png/beehexa-design-d-550-light@3x.png +0 -0
  27. package/dist/docs/public/brand/logos/beehexa-logo.zip +0 -0
  28. package/dist/docs/public/brand/logos/fig/anatomy-en.png +0 -0
  29. package/dist/docs/public/brand/logos/fig/anatomy-vi.png +0 -0
  30. package/dist/docs/public/brand/logos/fig/beehexa-dark-12.png +0 -0
  31. package/dist/docs/public/brand/logos/fig/beehexa-dark-14.png +0 -0
  32. package/dist/docs/public/brand/logos/fig/beehexa-dark-28.png +0 -0
  33. package/dist/docs/public/brand/logos/fig/beehexa-dark-32.png +0 -0
  34. package/dist/docs/public/brand/logos/fig/beehexa-dark-56.png +0 -0
  35. package/dist/docs/public/brand/logos/fig/beehexa-graphite-28.png +0 -0
  36. package/dist/docs/public/brand/logos/fig/beehexa-graphite-32.png +0 -0
  37. package/dist/docs/public/brand/logos/fig/beehexa-light-14.png +0 -0
  38. package/dist/docs/public/brand/logos/fig/beehexa-light-21.png +0 -0
  39. package/dist/docs/public/brand/logos/fig/beehexa-light-22.png +0 -0
  40. package/dist/docs/public/brand/logos/fig/beehexa-light-24.png +0 -0
  41. package/dist/docs/public/brand/logos/fig/beehexa-light-28.png +0 -0
  42. package/dist/docs/public/brand/logos/fig/beehexa-light-32.png +0 -0
  43. package/dist/docs/public/brand/logos/fig/beehexa-light-36-7c3aed7c3aed.png +0 -0
  44. package/dist/docs/public/brand/logos/fig/beehexa-light-36-swap.png +0 -0
  45. package/dist/docs/public/brand/logos/fig/beehexa-light-36.png +0 -0
  46. package/dist/docs/public/brand/logos/fig/beehexa-light-56.png +0 -0
  47. package/dist/docs/public/brand/logos/fig/beehexa-white-20.png +0 -0
  48. package/dist/docs/public/brand/logos/fig/beehexa-white-32.png +0 -0
  49. package/dist/docs/public/brand/logos/fig/clearspace.png +0 -0
  50. package/dist/docs/public/brand/logos/fig/construction-en.png +0 -0
  51. package/dist/docs/public/brand/logos/fig/construction-vi.png +0 -0
  52. package/dist/docs/public/brand/logos/fig/container-en.png +0 -0
  53. package/dist/docs/public/brand/logos/fig/container-vi.png +0 -0
  54. package/dist/docs/public/brand/logos/fig/hexasync-dark-20.png +0 -0
  55. package/dist/docs/public/brand/logos/fig/hexasync-dark-28.png +0 -0
  56. package/dist/docs/public/brand/logos/fig/hexasync-dark-48.png +0 -0
  57. package/dist/docs/public/brand/logos/fig/hexasync-light-19.png +0 -0
  58. package/dist/docs/public/brand/logos/fig/hexasync-light-28.png +0 -0
  59. package/dist/docs/public/brand/logos/fig/hexasync-light-48.png +0 -0
  60. package/dist/docs/public/brand/logos/fig/icon-graphite-14.png +0 -0
  61. package/dist/docs/public/brand/logos/fig/icon-graphite-16.png +0 -0
  62. package/dist/docs/public/brand/logos/fig/icon-light-16.png +0 -0
  63. package/dist/docs/public/brand/logos/fig/icon-light-24.png +0 -0
  64. package/dist/docs/public/brand/logos/fig/icon-light-48.png +0 -0
  65. package/dist/docs/public/brand/logos/fig/icon-light-92.png +0 -0
  66. package/dist/docs/public/brand/logos/fig/meaning-bee-en.png +0 -0
  67. package/dist/docs/public/brand/logos/fig/meaning-bee-vi.png +0 -0
  68. package/dist/docs/public/brand/logos/fig/meaning-outline-en.png +0 -0
  69. package/dist/docs/public/brand/logos/fig/meaning-outline-vi.png +0 -0
  70. package/dist/docs/public/brand/logos/fig/meaning-stack-en.png +0 -0
  71. package/dist/docs/public/brand/logos/fig/meaning-stack-vi.png +0 -0
  72. package/dist/docs/public/brand/logos/fig/misuse-serif.png +0 -0
  73. package/dist/docs/public/brand/logos/icon/beehexa-icon-graphite.svg +1 -0
  74. package/dist/docs/public/brand/logos/icon/beehexa-icon-white.svg +1 -0
  75. package/dist/docs/public/brand/logos/icon/beehexa-icon-yellow.svg +1 -0
  76. package/dist/docs/public/brand/logos/lockups/beehexa-horizontal-1-light.svg +1 -0
  77. package/dist/docs/public/brand/logos/lockups/beehexa-horizontal-2-dark.svg +1 -0
  78. package/dist/docs/public/brand/logos/lockups/beehexa-horizontal-3-white.svg +1 -0
  79. package/dist/docs/public/brand/logos/lockups/beehexa-horizontal-4-graphite.svg +1 -0
  80. package/dist/docs/public/brand/logos/lockups/hexasync-horizontal-1-light.svg +1 -0
  81. package/dist/docs/public/brand/logos/lockups/hexasync-horizontal-2-dark.svg +1 -0
  82. package/dist/docs/public/brand/logos/lockups/hexasync-horizontal-3-white.svg +1 -0
  83. package/dist/docs/public/brand/logos/lockups/hexasync-horizontal-4-graphite.svg +1 -0
  84. package/dist/docs/public/brand/logos/ui/beehexa-dark.svg +1 -0
  85. package/dist/docs/public/brand/logos/ui/beehexa-design-dark.svg +1 -0
  86. package/dist/docs/public/brand/logos/ui/beehexa-design-light.svg +1 -0
  87. package/dist/docs/public/brand/logos/ui/beehexa-icon-yellow.svg +1 -0
  88. package/dist/docs/public/brand/logos/ui/beehexa-light.svg +1 -0
  89. package/dist/docs/public/brand/logos/ui/hexasync-dark.svg +1 -0
  90. package/dist/docs/public/brand/logos/ui/hexasync-light.svg +1 -0
  91. package/dist/docs/public/brand/logos/ui/png/beehexa-design-dark@3x.png +0 -0
  92. package/dist/docs/public/brand/logos/ui/png/beehexa-design-light@3x.png +0 -0
  93. package/dist/docs/public/favicon.ico +0 -0
  94. package/dist/docs/public/favicon.svg +1 -0
  95. package/dist/docs/public/fonts/LICENSE-Inter.txt +93 -0
  96. package/dist/docs/public/fonts/LICENSE-JetBrainsMono.txt +93 -0
  97. package/dist/docs/public/fonts/inter-latin-ext-opsz-wght-italic.woff2 +0 -0
  98. package/dist/docs/public/fonts/inter-latin-ext-opsz-wght-normal.woff2 +0 -0
  99. package/dist/docs/public/fonts/inter-latin-opsz-wght-italic.woff2 +0 -0
  100. package/dist/docs/public/fonts/inter-latin-opsz-wght-normal.woff2 +0 -0
  101. package/dist/docs/public/fonts/inter-vietnamese-opsz-wght-italic.woff2 +0 -0
  102. package/dist/docs/public/fonts/inter-vietnamese-opsz-wght-normal.woff2 +0 -0
  103. package/dist/docs/public/fonts/jetbrains-mono-latin-ext-wght-normal.woff2 +0 -0
  104. package/dist/docs/public/fonts/jetbrains-mono-latin-wght-normal.woff2 +0 -0
  105. package/dist/docs/public/fonts/jetbrains-mono-vietnamese-wght-normal.woff2 +0 -0
  106. package/dist/docs/public/icon-192.png +0 -0
  107. package/dist/docs/public/icon-512.png +0 -0
  108. package/dist/docs/public/icon-maskable-512.png +0 -0
  109. package/dist/docs/public/robots.txt +4 -0
  110. package/dist/docs/public/site.webmanifest +21 -0
  111. package/dist/docs/scripts/color-pairs.mjs +46 -0
  112. package/dist/docs/scripts/contrast-exceptions.mjs +6 -0
  113. package/dist/docs/scripts/token-utils.d.mts +26 -0
  114. package/dist/docs/scripts/token-utils.mjs +114 -0
  115. package/dist/docs/src/brand/Beehexa-brandguide-full-mar12.pdf +0 -0
  116. package/dist/docs/src/brand/color+typoDirections.pdf +0 -0
  117. package/dist/docs/src/brand/structure-proposal.md +227 -0
  118. package/dist/docs/src/components/ChildPages.astro +25 -0
  119. package/dist/docs/src/components/CodeExample.astro +18 -0
  120. package/dist/docs/src/components/ColorDemo.astro +794 -0
  121. package/dist/docs/src/components/ColorExample.astro +32 -0
  122. package/dist/docs/src/components/ColorSwatch.astro +20 -0
  123. package/dist/docs/src/components/ComponentTabs.astro +21 -0
  124. package/dist/docs/src/components/DocsFooter.astro +25 -0
  125. package/dist/docs/src/components/HelpOptions.astro +20 -0
  126. package/dist/docs/src/components/IconBrowser.astro +257 -0
  127. package/dist/docs/src/components/IconDemo.astro +185 -0
  128. package/dist/docs/src/components/InDevelopment.astro +29 -0
  129. package/dist/docs/src/components/LayoutDemo.astro +384 -0
  130. package/dist/docs/src/components/Logo.astro +25 -0
  131. package/dist/docs/src/components/PhaseTable.astro +22 -0
  132. package/dist/docs/src/components/RoleGuides.astro +48 -0
  133. package/dist/docs/src/components/ShapeDemo.astro +239 -0
  134. package/dist/docs/src/components/ShapePin.astro +22 -0
  135. package/dist/docs/src/components/Sidebar.astro +206 -0
  136. package/dist/docs/src/components/SiteHeader.astro +211 -0
  137. package/dist/docs/src/components/SpacingDemo.astro +172 -0
  138. package/dist/docs/src/components/StatusBadge.astro +22 -0
  139. package/dist/docs/src/components/SystemAreas.astro +29 -0
  140. package/dist/docs/src/components/TableOfContents.astro +47 -0
  141. package/dist/docs/src/components/TokenTable.astro +40 -0
  142. package/dist/docs/src/components/TypeDemo.astro +249 -0
  143. package/dist/docs/src/components/logos/Fig.astro +28 -0
  144. package/dist/docs/src/components/logos/LogoAnatomy.astro +101 -0
  145. package/dist/docs/src/components/logos/LogoClearSpace.astro +81 -0
  146. package/dist/docs/src/components/logos/LogoColourVersions.astro +45 -0
  147. package/dist/docs/src/components/logos/LogoConstruction.astro +84 -0
  148. package/dist/docs/src/components/logos/LogoContainer.astro +84 -0
  149. package/dist/docs/src/components/logos/LogoHero.astro +42 -0
  150. package/dist/docs/src/components/logos/LogoInUse.astro +197 -0
  151. package/dist/docs/src/components/logos/LogoMeanings.astro +75 -0
  152. package/dist/docs/src/components/logos/LogoMinSize.astro +55 -0
  153. package/dist/docs/src/components/logos/LogoMistakes.astro +109 -0
  154. package/dist/docs/src/components/logos/LogoMisuse.astro +96 -0
  155. package/dist/docs/src/components/logos/LogoPair.astro +26 -0
  156. package/dist/docs/src/components/logos/LogoSvg.astro +68 -0
  157. package/dist/docs/src/content/components/button/accessibility.mdx +18 -0
  158. package/dist/docs/src/content/components/button/changelog.mdx +6 -0
  159. package/dist/docs/src/content/components/button/code.mdx +27 -0
  160. package/dist/docs/src/content/components/button/examples.mdx +21 -0
  161. package/dist/docs/src/content/components/button/meta.json +5 -0
  162. package/dist/docs/src/content/components/button/usage.mdx +18 -0
  163. package/dist/docs/src/content/foundations/guidelines/accessibility.mdx +19 -0
  164. package/dist/docs/src/content/foundations/guidelines/content.mdx +25 -0
  165. package/dist/docs/src/content/foundations/index.mdx +9 -0
  166. package/dist/docs/src/content/foundations/styles/border.mdx +89 -0
  167. package/dist/docs/src/content/foundations/styles/color/accessibility.mdx +32 -0
  168. package/dist/docs/src/content/foundations/styles/color/dark-mode.mdx +22 -0
  169. package/dist/docs/src/content/foundations/styles/color/index.mdx +65 -0
  170. package/dist/docs/src/content/foundations/styles/color/palette.mdx +57 -0
  171. package/dist/docs/src/content/foundations/styles/color/tokens.mdx +55 -0
  172. package/dist/docs/src/content/foundations/styles/color/usage.mdx +111 -0
  173. package/dist/docs/src/content/foundations/styles/data-visualization.mdx +11 -0
  174. package/dist/docs/src/content/foundations/styles/elevation.mdx +12 -0
  175. package/dist/docs/src/content/foundations/styles/icons/accessibility.mdx +72 -0
  176. package/dist/docs/src/content/foundations/styles/icons/code.mdx +171 -0
  177. package/dist/docs/src/content/foundations/styles/icons/index.mdx +62 -0
  178. package/dist/docs/src/content/foundations/styles/icons/library.mdx +19 -0
  179. package/dist/docs/src/content/foundations/styles/icons/usage.mdx +100 -0
  180. package/dist/docs/src/content/foundations/styles/illustration.mdx +9 -0
  181. package/dist/docs/src/content/foundations/styles/interaction-states.mdx +49 -0
  182. package/dist/docs/src/content/foundations/styles/layout/app-frame.mdx +81 -0
  183. package/dist/docs/src/content/foundations/styles/layout/breakpoints.mdx +56 -0
  184. package/dist/docs/src/content/foundations/styles/layout/grid.mdx +87 -0
  185. package/dist/docs/src/content/foundations/styles/layout/index.mdx +24 -0
  186. package/dist/docs/src/content/foundations/styles/layout/overlays.mdx +45 -0
  187. package/dist/docs/src/content/foundations/styles/layout/page-widths.mdx +38 -0
  188. package/dist/docs/src/content/foundations/styles/logos/downloads-and-terms.mdx +65 -0
  189. package/dist/docs/src/content/foundations/styles/logos/index.mdx +64 -0
  190. package/dist/docs/src/content/foundations/styles/logos/placement-and-containers.mdx +96 -0
  191. package/dist/docs/src/content/foundations/styles/logos/product-logos.mdx +56 -0
  192. package/dist/docs/src/content/foundations/styles/logos/using-the-logo.mdx +70 -0
  193. package/dist/docs/src/content/foundations/styles/motion.mdx +11 -0
  194. package/dist/docs/src/content/foundations/styles/opacity.mdx +9 -0
  195. package/dist/docs/src/content/foundations/styles/radius.mdx +98 -0
  196. package/dist/docs/src/content/foundations/styles/size-and-density.mdx +41 -0
  197. package/dist/docs/src/content/foundations/styles/spacing.mdx +70 -0
  198. package/dist/docs/src/content/foundations/styles/typography/code.mdx +53 -0
  199. package/dist/docs/src/content/foundations/styles/typography/index.mdx +58 -0
  200. package/dist/docs/src/content/foundations/styles/typography/usage.mdx +144 -0
  201. package/dist/docs/src/content/foundations/styles/typography/vietnamese.mdx +46 -0
  202. package/dist/docs/src/content/foundations/styles/z-index.mdx +9 -0
  203. package/dist/docs/src/content/foundations/tokens/all-tokens.mdx +36 -0
  204. package/dist/docs/src/content/foundations/tokens/index.mdx +27 -0
  205. package/dist/docs/src/content/get-started/content.mdx +14 -0
  206. package/dist/docs/src/content/get-started/design.mdx +30 -0
  207. package/dist/docs/src/content/get-started/develop.mdx +59 -0
  208. package/dist/docs/src/content/get-started/get-help.mdx +19 -0
  209. package/dist/docs/src/content/get-started/index.mdx +50 -0
  210. package/dist/docs/src/content/news/2026-10-16-site-structure.md +15 -0
  211. package/dist/docs/src/content/news/2026-10-20-docs-site.md +13 -0
  212. package/dist/docs/src/content/release-phases/index.mdx +12 -0
  213. package/dist/docs/src/content/tools/ai-agents.mdx +49 -0
  214. package/dist/docs/src/content/tools/ant-design-vue-theme.mdx +138 -0
  215. package/dist/docs/src/content/tools/eslint.mdx +15 -0
  216. package/dist/docs/src/content/tools/index.mdx +7 -0
  217. package/dist/docs/src/content/tools/stylelint.mdx +19 -0
  218. package/dist/docs/src/content-vi/foundations/styles/border.mdx +89 -0
  219. package/dist/docs/src/content-vi/foundations/styles/color/accessibility.mdx +32 -0
  220. package/dist/docs/src/content-vi/foundations/styles/color/dark-mode.mdx +22 -0
  221. package/dist/docs/src/content-vi/foundations/styles/color/index.mdx +65 -0
  222. package/dist/docs/src/content-vi/foundations/styles/color/palette.mdx +57 -0
  223. package/dist/docs/src/content-vi/foundations/styles/color/tokens.mdx +55 -0
  224. package/dist/docs/src/content-vi/foundations/styles/color/usage.mdx +111 -0
  225. package/dist/docs/src/content-vi/foundations/styles/data-visualization.mdx +11 -0
  226. package/dist/docs/src/content-vi/foundations/styles/icons/accessibility.mdx +72 -0
  227. package/dist/docs/src/content-vi/foundations/styles/icons/code.mdx +170 -0
  228. package/dist/docs/src/content-vi/foundations/styles/icons/index.mdx +62 -0
  229. package/dist/docs/src/content-vi/foundations/styles/icons/library.mdx +19 -0
  230. package/dist/docs/src/content-vi/foundations/styles/icons/usage.mdx +100 -0
  231. package/dist/docs/src/content-vi/foundations/styles/illustration.mdx +9 -0
  232. package/dist/docs/src/content-vi/foundations/styles/interaction-states.mdx +49 -0
  233. package/dist/docs/src/content-vi/foundations/styles/layout/app-frame.mdx +77 -0
  234. package/dist/docs/src/content-vi/foundations/styles/layout/breakpoints.mdx +56 -0
  235. package/dist/docs/src/content-vi/foundations/styles/layout/grid.mdx +87 -0
  236. package/dist/docs/src/content-vi/foundations/styles/layout/index.mdx +24 -0
  237. package/dist/docs/src/content-vi/foundations/styles/layout/page-widths.mdx +34 -0
  238. package/dist/docs/src/content-vi/foundations/styles/logos/downloads-and-terms.mdx +65 -0
  239. package/dist/docs/src/content-vi/foundations/styles/logos/index.mdx +64 -0
  240. package/dist/docs/src/content-vi/foundations/styles/logos/placement-and-containers.mdx +96 -0
  241. package/dist/docs/src/content-vi/foundations/styles/logos/product-logos.mdx +56 -0
  242. package/dist/docs/src/content-vi/foundations/styles/logos/using-the-logo.mdx +70 -0
  243. package/dist/docs/src/content-vi/foundations/styles/opacity.mdx +9 -0
  244. package/dist/docs/src/content-vi/foundations/styles/radius.mdx +98 -0
  245. package/dist/docs/src/content-vi/foundations/styles/size-and-density.mdx +41 -0
  246. package/dist/docs/src/content-vi/foundations/styles/spacing.mdx +70 -0
  247. package/dist/docs/src/content-vi/foundations/styles/typography/code.mdx +53 -0
  248. package/dist/docs/src/content-vi/foundations/styles/typography/index.mdx +58 -0
  249. package/dist/docs/src/content-vi/foundations/styles/typography/usage.mdx +144 -0
  250. package/dist/docs/src/content-vi/foundations/styles/typography/vietnamese.mdx +46 -0
  251. package/dist/docs/src/content-vi/foundations/styles/z-index.mdx +9 -0
  252. package/dist/docs/src/content.config.ts +68 -0
  253. package/dist/docs/src/lib/brand.ts +57 -0
  254. package/dist/docs/src/lib/contrast.ts +34 -0
  255. package/dist/docs/src/lib/i18n.ts +152 -0
  256. package/dist/docs/src/lib/icons.ts +46 -0
  257. package/dist/docs/src/lib/logo-geometry.ts +30 -0
  258. package/dist/docs/src/lib/lucide-categories.json +1 -0
  259. package/dist/docs/src/lib/lucide-data.ts +40 -0
  260. package/dist/docs/src/lib/navigation.ts +222 -0
  261. package/dist/docs/src/lib/release-phases.ts +10 -0
  262. package/dist/docs/src/lib/routes.ts +40 -0
  263. package/dist/docs/src/lib/token-descriptions-vi.ts +40 -0
  264. package/dist/docs/src/lib/tokens.ts +67 -0
  265. package/dist/docs/src/lib/tri-grid.ts +28 -0
  266. package/dist/docs/src/styles/chrome.css +122 -0
  267. package/dist/docs/src/styles/color.css +270 -0
  268. package/dist/docs/src/styles/docs.css +323 -0
  269. package/dist/docs/src/styles/global.css +66 -0
  270. package/dist/docs/src/styles/icons.css +135 -0
  271. package/dist/docs/src/styles/layout.css +165 -0
  272. package/dist/docs/src/styles/logos.css +236 -0
  273. package/dist/docs/src/styles/shapes.css +139 -0
  274. package/dist/docs/src/styles/tokens.css +461 -0
  275. package/dist/docs/src/styles/tokens.js +425 -0
  276. package/dist/docs/src/styles/typography.css +91 -0
  277. package/dist/docs/tokens/border.json +26 -0
  278. package/dist/docs/tokens/breakpoints.json +8 -0
  279. package/dist/docs/tokens/color.json +1350 -0
  280. package/dist/docs/tokens/elevation.json +26 -0
  281. package/dist/docs/tokens/layout.json +29 -0
  282. package/dist/docs/tokens/motion.json +12 -0
  283. package/dist/docs/tokens/radius.json +44 -0
  284. package/dist/docs/tokens/size.json +13 -0
  285. package/dist/docs/tokens/spacing.json +18 -0
  286. package/dist/docs/tokens/states.json +12 -0
  287. package/dist/docs/tokens/typography.json +220 -0
  288. package/dist/index.d.ts +19 -0
  289. package/dist/index.js +1823 -0
  290. package/package.json +36 -4
@@ -0,0 +1,1814 @@
1
+ [
2
+ {
3
+ "id": "en/components/button/accessibility",
4
+ "path": "src/content/components/button/accessibility.mdx",
5
+ "documentPath": "docs/src/content/components/button/accessibility.mdx",
6
+ "locale": "en",
7
+ "kind": "guidance",
8
+ "title": "Button: accessibility",
9
+ "status": "active",
10
+ "releasePhase": null,
11
+ "planned": [],
12
+ "body": "\n## Keyboard\n\n| Key | Action |\n| --- | --- |\n| <kbd>Tab</kbd> | Moves focus to the button. |\n| <kbd>Enter</kbd> or <kbd>Space</kbd> | Activates the button. |\n\n## Requirements\n\n- Use a native `<button>` element. Ant Design Vue renders one.\n- Icon-only buttons need an `aria-label`.\n- Focus is shown with a 2 px ring in `color.border.focus`, 2 px away from the button (`border.width.focused`, `state.focus.offset`).\n- The target is at least 24 × 24px (WCAG 2.5.8).\n- Text and background meet 4.5:1 contrast in every state except disabled.\n- When `loading` is set, announce the result of the action when it finishes.\n",
13
+ "raw": "---\n---\n\n## Keyboard\n\n| Key | Action |\n| --- | --- |\n| <kbd>Tab</kbd> | Moves focus to the button. |\n| <kbd>Enter</kbd> or <kbd>Space</kbd> | Activates the button. |\n\n## Requirements\n\n- Use a native `<button>` element. Ant Design Vue renders one.\n- Icon-only buttons need an `aria-label`.\n- Focus is shown with a 2 px ring in `color.border.focus`, 2 px away from the button (`border.width.focused`, `state.focus.offset`).\n- The target is at least 24 × 24px (WCAG 2.5.8).\n- Text and background meet 4.5:1 contrast in every state except disabled.\n- When `loading` is set, announce the result of the action when it finishes.\n",
14
+ "frontmatter": {}
15
+ },
16
+ {
17
+ "id": "en/components/button/changelog",
18
+ "path": "src/content/components/button/changelog.mdx",
19
+ "documentPath": "docs/src/content/components/button/changelog.mdx",
20
+ "locale": "en",
21
+ "kind": "guidance",
22
+ "title": "Button: changelog",
23
+ "status": "active",
24
+ "releasePhase": null,
25
+ "planned": [],
26
+ "body": "\n## 0.1.0 – October 20, 2026\n\n- First documentation of Button. Early Access.\n",
27
+ "raw": "---\n---\n\n## 0.1.0 – October 20, 2026\n\n- First documentation of Button. Early Access.\n",
28
+ "frontmatter": {}
29
+ },
30
+ {
31
+ "id": "en/components/button/code",
32
+ "path": "src/content/components/button/code.mdx",
33
+ "documentPath": "docs/src/content/components/button/code.mdx",
34
+ "locale": "en",
35
+ "kind": "guidance",
36
+ "title": "Button: code",
37
+ "status": "active",
38
+ "releasePhase": null,
39
+ "planned": [],
40
+ "body": "import CodeExample from '../../../components/CodeExample.astro';\n\n## Installation\n\nButtons come from Ant Design Vue. Apply the [Beehexa theme](/tools/ant-design-vue-theme/) once at the root of the app.\n\n## Usage\n\n<CodeExample lang=\"vue\" code={`<template>\n <a-space>\n <a-button>Cancel</a-button>\n <a-button type=\"primary\" :loading=\"saving\" @click=\"save\">Save changes</a-button>\n <a-button danger>Delete integration</a-button>\n </a-space>\n</template>`} />\n\n## Props\n\n| Prop | Values | Notes |\n| --- | --- | --- |\n| `type` | `default`, `primary`, `link`, `text` | Use `primary` once per screen. |\n| `danger` | `boolean` | For destructive actions. |\n| `loading` | `boolean` | Shows a spinner and blocks repeat clicks. |\n| `disabled` | `boolean` | Prefer explaining why an action is unavailable. |\n",
41
+ "raw": "---\ndescription: Use the Ant Design Vue button with the Beehexa theme.\n---\nimport CodeExample from '../../../components/CodeExample.astro';\n\n## Installation\n\nButtons come from Ant Design Vue. Apply the [Beehexa theme](/tools/ant-design-vue-theme/) once at the root of the app.\n\n## Usage\n\n<CodeExample lang=\"vue\" code={`<template>\n <a-space>\n <a-button>Cancel</a-button>\n <a-button type=\"primary\" :loading=\"saving\" @click=\"save\">Save changes</a-button>\n <a-button danger>Delete integration</a-button>\n </a-space>\n</template>`} />\n\n## Props\n\n| Prop | Values | Notes |\n| --- | --- | --- |\n| `type` | `default`, `primary`, `link`, `text` | Use `primary` once per screen. |\n| `danger` | `boolean` | For destructive actions. |\n| `loading` | `boolean` | Shows a spinner and blocks repeat clicks. |\n| `disabled` | `boolean` | Prefer explaining why an action is unavailable. |\n",
42
+ "frontmatter": {
43
+ "description": "Use the Ant Design Vue button with the Beehexa theme."
44
+ }
45
+ },
46
+ {
47
+ "id": "en/components/button/examples",
48
+ "path": "src/content/components/button/examples.mdx",
49
+ "documentPath": "docs/src/content/components/button/examples.mdx",
50
+ "locale": "en",
51
+ "kind": "guidance",
52
+ "title": "Button: examples",
53
+ "status": "active",
54
+ "releasePhase": null,
55
+ "planned": [],
56
+ "body": "import CodeExample from '../../../components/CodeExample.astro';\n\n## Default\n\n<CodeExample code={`<button class=\"bh-button\" type=\"button\">Cancel</button>`} />\n\n## Primary\n\nUse one primary button for the main action on a screen.\n\n<CodeExample code={`<button class=\"bh-button bh-button-primary\" type=\"button\">Save changes</button>`} />\n\n## Danger\n\n<CodeExample code={`<button class=\"bh-button bh-button-danger\" type=\"button\">Delete integration</button>`} />\n\n## Disabled\n\n<CodeExample code={`<button class=\"bh-button bh-button-primary\" type=\"button\" disabled>Save changes</button>`} />\n",
57
+ "raw": "---\n---\nimport CodeExample from '../../../components/CodeExample.astro';\n\n## Default\n\n<CodeExample code={`<button class=\"bh-button\" type=\"button\">Cancel</button>`} />\n\n## Primary\n\nUse one primary button for the main action on a screen.\n\n<CodeExample code={`<button class=\"bh-button bh-button-primary\" type=\"button\">Save changes</button>`} />\n\n## Danger\n\n<CodeExample code={`<button class=\"bh-button bh-button-danger\" type=\"button\">Delete integration</button>`} />\n\n## Disabled\n\n<CodeExample code={`<button class=\"bh-button bh-button-primary\" type=\"button\" disabled>Save changes</button>`} />\n",
58
+ "frontmatter": {}
59
+ },
60
+ {
61
+ "id": "en/components/button/usage",
62
+ "path": "src/content/components/button/usage.mdx",
63
+ "documentPath": "docs/src/content/components/button/usage.mdx",
64
+ "locale": "en",
65
+ "kind": "guidance",
66
+ "title": "Button: usage",
67
+ "status": "active",
68
+ "releasePhase": null,
69
+ "planned": [],
70
+ "body": "\n## When to use\n\n- To trigger an action: save, submit, sync, delete.\n- To open a dialog or start a flow.\n\n## When not to use\n\n- To go to another page. Use a link.\n- For many actions in a row. Use a dropdown menu for the less common ones.\n\n## Best practices\n\n- Start the label with a verb and keep it short: \"Sync orders\".\n- Put the primary button last in a group, on the right.\n- Ask for confirmation before destructive actions.\n",
71
+ "raw": "---\n---\n\n## When to use\n\n- To trigger an action: save, submit, sync, delete.\n- To open a dialog or start a flow.\n\n## When not to use\n\n- To go to another page. Use a link.\n- For many actions in a row. Use a dropdown menu for the less common ones.\n\n## Best practices\n\n- Start the label with a verb and keep it short: \"Sync orders\".\n- Put the primary button last in a group, on the right.\n- Ask for confirmation before destructive actions.\n",
72
+ "frontmatter": {}
73
+ },
74
+ {
75
+ "id": "en/foundations/guidelines/accessibility",
76
+ "path": "src/content/foundations/guidelines/accessibility.mdx",
77
+ "documentPath": "docs/src/content/foundations/guidelines/accessibility.mdx",
78
+ "locale": "en",
79
+ "kind": "guidance",
80
+ "title": "Accessibility",
81
+ "status": "active",
82
+ "releasePhase": null,
83
+ "planned": [],
84
+ "body": "\n## Our commitment\n\nEvery Beehexa product meets [WCAG 2.2](https://www.w3.org/TR/WCAG22/) level AA. Every component page has an Accessibility tab that says how the component meets it and what product teams still need to do.\n\n## Checklist\n\n- **Contrast**: text has at least 4.5:1 contrast with its background, large text and UI parts at least 3:1.\n- **Keyboard**: everything that works with a mouse works with a keyboard, in a logical order.\n- **Focus**: keyboard focus is always visible. Use a 2 px ring in `color.border.focus`, 2 px away from the element (`border.width.focused`, `state.focus.offset`).\n- **Target size**: pointer targets are at least 24 × 24 CSS pixels.\n- **Labels**: every control has a visible label or an accessible name.\n- **Motion**: respect `prefers-reduced-motion`.\n- **Errors**: say what went wrong in text, not only with color.\n",
85
+ "raw": "---\ntitle: Accessibility\ndescription: Beehexa products meet WCAG 2.2 level AA.\norder: 1\n---\n\n## Our commitment\n\nEvery Beehexa product meets [WCAG 2.2](https://www.w3.org/TR/WCAG22/) level AA. Every component page has an Accessibility tab that says how the component meets it and what product teams still need to do.\n\n## Checklist\n\n- **Contrast**: text has at least 4.5:1 contrast with its background, large text and UI parts at least 3:1.\n- **Keyboard**: everything that works with a mouse works with a keyboard, in a logical order.\n- **Focus**: keyboard focus is always visible. Use a 2 px ring in `color.border.focus`, 2 px away from the element (`border.width.focused`, `state.focus.offset`).\n- **Target size**: pointer targets are at least 24 × 24 CSS pixels.\n- **Labels**: every control has a visible label or an accessible name.\n- **Motion**: respect `prefers-reduced-motion`.\n- **Errors**: say what went wrong in text, not only with color.\n",
86
+ "frontmatter": {
87
+ "title": "Accessibility",
88
+ "description": "Beehexa products meet WCAG 2.2 level AA.",
89
+ "order": 1
90
+ }
91
+ },
92
+ {
93
+ "id": "en/foundations/guidelines/content",
94
+ "path": "src/content/foundations/guidelines/content.mdx",
95
+ "documentPath": "docs/src/content/foundations/guidelines/content.mdx",
96
+ "locale": "en",
97
+ "kind": "guidance",
98
+ "title": "Content",
99
+ "status": "active",
100
+ "releasePhase": null,
101
+ "planned": [],
102
+ "body": "\n## Voice\n\nClear, direct and helpful. Write for busy people who manage data across many systems.\n\n## Rules\n\n- Use sentence case for labels, headings and buttons.\n- Start buttons with a verb: \"Save\", \"Sync orders\", \"Delete integration\".\n- Keep one name for one thing across the product.\n- Use numerals for numbers: \"3 orders failed\".\n- Avoid jargon unless your readers use it.\n\n## Messages\n\n| Type | Write |\n| --- | --- |\n| Error | What happened, why, and how to fix it. |\n| Empty state | What will appear here and how to add the first item. |\n| Confirmation | The action and its consequence: \"Delete 3 orders? This can't be undone.\" |\n",
103
+ "raw": "---\ntitle: Content\ndescription: How to write clear, concise and consistent product copy.\norder: 2\n---\n\n## Voice\n\nClear, direct and helpful. Write for busy people who manage data across many systems.\n\n## Rules\n\n- Use sentence case for labels, headings and buttons.\n- Start buttons with a verb: \"Save\", \"Sync orders\", \"Delete integration\".\n- Keep one name for one thing across the product.\n- Use numerals for numbers: \"3 orders failed\".\n- Avoid jargon unless your readers use it.\n\n## Messages\n\n| Type | Write |\n| --- | --- |\n| Error | What happened, why, and how to fix it. |\n| Empty state | What will appear here and how to add the first item. |\n| Confirmation | The action and its consequence: \"Delete 3 orders? This can't be undone.\" |\n",
104
+ "frontmatter": {
105
+ "title": "Content",
106
+ "description": "How to write clear, concise and consistent product copy.",
107
+ "order": 2
108
+ }
109
+ },
110
+ {
111
+ "id": "en/foundations/index",
112
+ "path": "src/content/foundations/index.mdx",
113
+ "documentPath": "docs/src/content/foundations/index.mdx",
114
+ "locale": "en",
115
+ "kind": "guidance",
116
+ "title": "Foundations",
117
+ "status": "active",
118
+ "releasePhase": null,
119
+ "planned": [],
120
+ "body": "\nFoundations are the decisions every Beehexa interface shares. They are grouped as design tokens, guidelines and styles.\n\n> Token values are provisional. They were taken from the current landing page while the team decides which system to base the values on.\n",
121
+ "raw": "---\ntitle: Foundations\ndescription: Foundations create consistent user experiences. They include our design tokens, guidelines and visual styles.\norder: 0\n---\n\nFoundations are the decisions every Beehexa interface shares. They are grouped as design tokens, guidelines and styles.\n\n> Token values are provisional. They were taken from the current landing page while the team decides which system to base the values on.\n",
122
+ "frontmatter": {
123
+ "title": "Foundations",
124
+ "description": "Foundations create consistent user experiences. They include our design tokens, guidelines and visual styles.",
125
+ "order": 0
126
+ }
127
+ },
128
+ {
129
+ "id": "en/foundations/styles/border",
130
+ "path": "src/content/foundations/styles/border.mdx",
131
+ "documentPath": "docs/src/content/foundations/styles/border.mdx",
132
+ "locale": "en",
133
+ "kind": "guidance",
134
+ "title": "Border",
135
+ "status": "active",
136
+ "releasePhase": null,
137
+ "planned": [],
138
+ "body": "import ShapeDemo from '../../../components/ShapeDemo.astro';\nimport TokenTable from '../../../components/TokenTable.astro';\n\n**Most borders are 1 px. Thicker lines mean something: selected, focused, or a status to notice.**\n\nBorder colours are colour tokens: `color.border` for dividers and cards, `color.border.bold` for the edges of inputs, checkboxes and selects. See [Tokens](/foundations/styles/color/tokens/#borders).\n\n## The widths\n\n<ShapeDemo kind=\"border-scale\" />\n\n## Examples\n\n### `border.width.default` · 1 px\n\nInputs, secondary buttons, cards, tables and dividers.\n\n<ShapeDemo kind=\"border-use\" item=\"default\" />\n\n### `border.width.selected` · 2 px\n\nThe bar under a selected tab, the bar beside a selected side navigation item, and the edge of a selected card. Always with `color.border.selected`.\n\n<ShapeDemo kind=\"border-use\" item=\"selected\" />\n\n### `border.width.focused` · 2 px\n\nThe focus ring, in `color.border.focus`, drawn 2 px outside the element (`state.focus.offset`). Draw it inside, at −2 px, when a box around the element would cut it off: menu items, table cells and tabs in a scroll area.\n\n<ShapeDemo kind=\"border-use\" item=\"focused\" />\n\n### `border.width.accent` · 4 px\n\nA status or emphasis bar on one edge: alerts and banners, a table row with an error, callouts and quotes. The box keeps its radius on all four corners and the bar follows the curve.\n\n<ShapeDemo kind=\"border-use\" item=\"accent\" />\n\n## Width and colour go together\n\n| Width | Colour | For |\n|---|---|---|\n| `border.width.default` | `color.border` or `color.border.bold` | Edges and dividers |\n| `border.width.selected` | `color.border.selected` | Selected tab, side navigation item or card |\n| `border.width.focused` | `color.border.focus` | Keyboard focus |\n| `border.width.accent` | `color.border.danger`, `.warning`, `.success`, `.info` or `.brand` | Status and emphasis bars |\n\nDon't show a state with colour alone. Selected and focused also change the width.\n\n## Do and don’t\n\n<ShapeDemo kind=\"dodont\" item=\"selected\" />\n<ShapeDemo kind=\"dodont\" item=\"accent\" />\n<ShapeDemo kind=\"dodont\" item=\"cards\" />\n\n## Code\n\n```css\n.alert {\n position: relative;\n overflow: hidden;\n border: var(--bh-border-width-default) solid var(--bh-color-border);\n border-radius: var(--bh-radius-100);\n}\n.alert::before {\n content: \"\";\n position: absolute;\n inset: 0 auto 0 0;\n width: var(--bh-border-width-accent);\n background: var(--bh-color-border-danger);\n}\n:focus-visible {\n outline: var(--bh-border-width-focused) solid var(--bh-color-border-focus);\n outline-offset: var(--bh-state-focus-offset);\n}\n```\n\n## Tokens\n\n<TokenTable prefix=\"border\" />\n\n## Related\n\n- [Radius](/foundations/styles/radius/): corner radius steps and the nesting rule.\n- [Interaction states](/foundations/styles/interaction-states/): hover, pressed, selected and disabled.\n",
139
+ "raw": "---\ntitle: Border\ndescription: Four border widths, the colour each one goes with, and how the focus ring is drawn.\norder: 7\n---\nimport ShapeDemo from '../../../components/ShapeDemo.astro';\nimport TokenTable from '../../../components/TokenTable.astro';\n\n**Most borders are 1 px. Thicker lines mean something: selected, focused, or a status to notice.**\n\nBorder colours are colour tokens: `color.border` for dividers and cards, `color.border.bold` for the edges of inputs, checkboxes and selects. See [Tokens](/foundations/styles/color/tokens/#borders).\n\n## The widths\n\n<ShapeDemo kind=\"border-scale\" />\n\n## Examples\n\n### `border.width.default` · 1 px\n\nInputs, secondary buttons, cards, tables and dividers.\n\n<ShapeDemo kind=\"border-use\" item=\"default\" />\n\n### `border.width.selected` · 2 px\n\nThe bar under a selected tab, the bar beside a selected side navigation item, and the edge of a selected card. Always with `color.border.selected`.\n\n<ShapeDemo kind=\"border-use\" item=\"selected\" />\n\n### `border.width.focused` · 2 px\n\nThe focus ring, in `color.border.focus`, drawn 2 px outside the element (`state.focus.offset`). Draw it inside, at −2 px, when a box around the element would cut it off: menu items, table cells and tabs in a scroll area.\n\n<ShapeDemo kind=\"border-use\" item=\"focused\" />\n\n### `border.width.accent` · 4 px\n\nA status or emphasis bar on one edge: alerts and banners, a table row with an error, callouts and quotes. The box keeps its radius on all four corners and the bar follows the curve.\n\n<ShapeDemo kind=\"border-use\" item=\"accent\" />\n\n## Width and colour go together\n\n| Width | Colour | For |\n|---|---|---|\n| `border.width.default` | `color.border` or `color.border.bold` | Edges and dividers |\n| `border.width.selected` | `color.border.selected` | Selected tab, side navigation item or card |\n| `border.width.focused` | `color.border.focus` | Keyboard focus |\n| `border.width.accent` | `color.border.danger`, `.warning`, `.success`, `.info` or `.brand` | Status and emphasis bars |\n\nDon't show a state with colour alone. Selected and focused also change the width.\n\n## Do and don’t\n\n<ShapeDemo kind=\"dodont\" item=\"selected\" />\n<ShapeDemo kind=\"dodont\" item=\"accent\" />\n<ShapeDemo kind=\"dodont\" item=\"cards\" />\n\n## Code\n\n```css\n.alert {\n position: relative;\n overflow: hidden;\n border: var(--bh-border-width-default) solid var(--bh-color-border);\n border-radius: var(--bh-radius-100);\n}\n.alert::before {\n content: \"\";\n position: absolute;\n inset: 0 auto 0 0;\n width: var(--bh-border-width-accent);\n background: var(--bh-color-border-danger);\n}\n:focus-visible {\n outline: var(--bh-border-width-focused) solid var(--bh-color-border-focus);\n outline-offset: var(--bh-state-focus-offset);\n}\n```\n\n## Tokens\n\n<TokenTable prefix=\"border\" />\n\n## Related\n\n- [Radius](/foundations/styles/radius/): corner radius steps and the nesting rule.\n- [Interaction states](/foundations/styles/interaction-states/): hover, pressed, selected and disabled.\n",
140
+ "frontmatter": {
141
+ "title": "Border",
142
+ "description": "Four border widths, the colour each one goes with, and how the focus ring is drawn.",
143
+ "order": 7
144
+ }
145
+ },
146
+ {
147
+ "id": "en/foundations/styles/color/accessibility",
148
+ "path": "src/content/foundations/styles/color/accessibility.mdx",
149
+ "documentPath": "docs/src/content/foundations/styles/color/accessibility.mdx",
150
+ "locale": "en",
151
+ "kind": "guidance",
152
+ "title": "Accessibility",
153
+ "status": "active",
154
+ "releasePhase": null,
155
+ "planned": [],
156
+ "body": "import ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Every text and icon token passes WCAG 2.2 AA on every background it is paired with, in light and in dark: all 386 pairs.**\n\n## Contrast\n\n| What | Minimum | WCAG 2.2 |\n|---|---|---|\n| Text | 4.5:1 | 1.4.3 |\n| Icons, control edges, focus ring | 3:1 | 1.4.11 |\n| Disabled controls, the yellow indicator bar, the logo | No minimum | 1.4.3 exception |\n\n<ColorDemo kind=\"contrast\" />\n\nColour is never the only signal (WCAG 1.4.1): statuses are written in words, selected items have a second cue.\n\n## Pairing\n\n**Text, icons and borders only go on the backgrounds listed with them.** Every pair here passes contrast in light and dark, and is checked on every build.\n\n<ColorDemo kind=\"pairing\" />\n\n<ColorDemo kind=\"dodont\" item=\"pairing\" />\n\n## Checked automatically\n\nEvery pair in [Pairing](#pairing) is checked automatically, in light and in dark. A text, icon or border token that falls below its minimum on any of its backgrounds is not released.\n",
157
+ "raw": "---\ntitle: Accessibility\ndescription: The contrast every colour pair meets, which text may sit on which background, and how it is checked.\norder: 6\n---\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Every text and icon token passes WCAG 2.2 AA on every background it is paired with, in light and in dark: all 386 pairs.**\n\n## Contrast\n\n| What | Minimum | WCAG 2.2 |\n|---|---|---|\n| Text | 4.5:1 | 1.4.3 |\n| Icons, control edges, focus ring | 3:1 | 1.4.11 |\n| Disabled controls, the yellow indicator bar, the logo | No minimum | 1.4.3 exception |\n\n<ColorDemo kind=\"contrast\" />\n\nColour is never the only signal (WCAG 1.4.1): statuses are written in words, selected items have a second cue.\n\n## Pairing\n\n**Text, icons and borders only go on the backgrounds listed with them.** Every pair here passes contrast in light and dark, and is checked on every build.\n\n<ColorDemo kind=\"pairing\" />\n\n<ColorDemo kind=\"dodont\" item=\"pairing\" />\n\n## Checked automatically\n\nEvery pair in [Pairing](#pairing) is checked automatically, in light and in dark. A text, icon or border token that falls below its minimum on any of its backgrounds is not released.\n",
158
+ "frontmatter": {
159
+ "title": "Accessibility",
160
+ "description": "The contrast every colour pair meets, which text may sit on which background, and how it is checked.",
161
+ "order": 6
162
+ }
163
+ },
164
+ {
165
+ "id": "en/foundations/styles/color/dark-mode",
166
+ "path": "src/content/foundations/styles/color/dark-mode.mdx",
167
+ "documentPath": "docs/src/content/foundations/styles/color/dark-mode.mdx",
168
+ "locale": "en",
169
+ "kind": "guidance",
170
+ "title": "Dark mode",
171
+ "status": "active",
172
+ "releasePhase": null,
173
+ "planned": [],
174
+ "body": "import ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Write each token once; the theme changes the value.**\n\n<ColorDemo kind=\"themes\" />\n\n## How it works\n\nEvery colour token has a light and a dark value under the same name. The theme picks the value; your code and designs name the token once. The dark values of every palette step are on [Palette](/foundations/styles/color/palette/), and every role token's are on [Tokens](/foundations/styles/color/tokens/).\n\n## Designing for dark\n\n- Never write a dark colour of your own or pick colours by theme in code.\n- Surfaces get lighter as they rise: page darkest, cards one step lighter.\n- The primary button turns light, and the solid status fills get brighter with dark text on them.\n- Check every screen in both themes before release.\n- Logos use their dark-background versions (see [Logos](/foundations/styles/logos/)).\n",
175
+ "raw": "---\ntitle: Dark mode\ndescription: How the dark theme works, what changes and what you never do in dark.\norder: 5\n---\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Write each token once; the theme changes the value.**\n\n<ColorDemo kind=\"themes\" />\n\n## How it works\n\nEvery colour token has a light and a dark value under the same name. The theme picks the value; your code and designs name the token once. The dark values of every palette step are on [Palette](/foundations/styles/color/palette/), and every role token's are on [Tokens](/foundations/styles/color/tokens/).\n\n## Designing for dark\n\n- Never write a dark colour of your own or pick colours by theme in code.\n- Surfaces get lighter as they rise: page darkest, cards one step lighter.\n- The primary button turns light, and the solid status fills get brighter with dark text on them.\n- Check every screen in both themes before release.\n- Logos use their dark-background versions (see [Logos](/foundations/styles/logos/)).\n",
176
+ "frontmatter": {
177
+ "title": "Dark mode",
178
+ "description": "How the dark theme works, what changes and what you never do in dark.",
179
+ "order": 5
180
+ }
181
+ },
182
+ {
183
+ "id": "en/foundations/styles/color/index",
184
+ "path": "src/content/foundations/styles/color/index.mdx",
185
+ "documentPath": "docs/src/content/foundations/styles/color/index.mdx",
186
+ "locale": "en",
187
+ "kind": "guidance",
188
+ "title": "Color",
189
+ "status": "active",
190
+ "releasePhase": null,
191
+ "planned": [],
192
+ "body": "import ColorDemo from '../../../../components/ColorDemo.astro';\n\nColour in Beehexa products is mostly graphite and white. Yellow marks the brand, and four functional colours mark status. You never pick a colour by its value: you pick a token by its job, such as `color.text` or `color.background.danger.bold`, and it is right in light and in dark.\n\n<ColorDemo kind=\"balance\" />\n\n## Brand colours\n\n<ColorDemo kind=\"brand\" />\n\n## Palette\n\nSix scales of twelve steps, in light and dark. The brand graphite is graphite 12 in light; the brand yellow is yellow 7 in light and yellow 11 in dark. See every value in [Palette](/foundations/styles/color/palette/).\n\n<ColorDemo kind=\"ramps\" />\n\n## How colour works\n\nColour comes in three tiers. You only ever use the middle one.\n\n| Tier | Example | Who uses it |\n|---|---|---|\n| Palette | `color.graphite.11` | Nobody directly. It feeds the role tokens. |\n| Role tokens | `color.text.subtle` | Every product and component. |\n| Component tokens | `color.code.background` | Only where no role fits. |\n\nRole tokens are listed in [Tokens](/foundations/styles/color/tokens/); how to pick one is in [Usage](/foundations/styles/color/usage/).\n\n## Principles\n\n### Graphite does the work, yellow is the accent\n\nText, icons, lines and the primary button are graphite. Yellow is only the logo, the current-page indicator, highlights and brand notes. It is never text and never a button: it is 1.85:1 on white.\n\n<ColorDemo kind=\"dodont\" item=\"yellow\" />\n\n### Colour means something\n\nRed, orange, green and blue mean danger, warning, success and info. Don't use them to decorate or to draw attention.\n\n<ColorDemo kind=\"dodont\" item=\"meaning\" />\n\n### Never colour alone\n\nWrite the status in words and add an icon. Mark a selected item with a second cue besides colour. Colour blind people and screen reader users don't get the colour.\n\n<ColorDemo kind=\"dodont\" item=\"alone\" />\n\n### Use the token for the job\n\nUse role tokens only. Never a hex value, and never a step of a scale such as `color.graphite.11`. If no token fits, ask for one.\n\n<ColorDemo kind=\"dodont\" item=\"tokens\" />\n\n### One primary button per view\n\nThe primary button is graphite. Every other button is a default button. There is no yellow button.\n\n<ColorDemo kind=\"dodont\" item=\"primary\" />\n",
193
+ "raw": "---\ntitle: Color\ndescription: Three brand colours and a set of colour tokens with one job each, for text, icons, surfaces, backgrounds, borders and status, in light and dark.\norder: 1\nsidebarLabel: Overview\n---\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\nColour in Beehexa products is mostly graphite and white. Yellow marks the brand, and four functional colours mark status. You never pick a colour by its value: you pick a token by its job, such as `color.text` or `color.background.danger.bold`, and it is right in light and in dark.\n\n<ColorDemo kind=\"balance\" />\n\n## Brand colours\n\n<ColorDemo kind=\"brand\" />\n\n## Palette\n\nSix scales of twelve steps, in light and dark. The brand graphite is graphite 12 in light; the brand yellow is yellow 7 in light and yellow 11 in dark. See every value in [Palette](/foundations/styles/color/palette/).\n\n<ColorDemo kind=\"ramps\" />\n\n## How colour works\n\nColour comes in three tiers. You only ever use the middle one.\n\n| Tier | Example | Who uses it |\n|---|---|---|\n| Palette | `color.graphite.11` | Nobody directly. It feeds the role tokens. |\n| Role tokens | `color.text.subtle` | Every product and component. |\n| Component tokens | `color.code.background` | Only where no role fits. |\n\nRole tokens are listed in [Tokens](/foundations/styles/color/tokens/); how to pick one is in [Usage](/foundations/styles/color/usage/).\n\n## Principles\n\n### Graphite does the work, yellow is the accent\n\nText, icons, lines and the primary button are graphite. Yellow is only the logo, the current-page indicator, highlights and brand notes. It is never text and never a button: it is 1.85:1 on white.\n\n<ColorDemo kind=\"dodont\" item=\"yellow\" />\n\n### Colour means something\n\nRed, orange, green and blue mean danger, warning, success and info. Don't use them to decorate or to draw attention.\n\n<ColorDemo kind=\"dodont\" item=\"meaning\" />\n\n### Never colour alone\n\nWrite the status in words and add an icon. Mark a selected item with a second cue besides colour. Colour blind people and screen reader users don't get the colour.\n\n<ColorDemo kind=\"dodont\" item=\"alone\" />\n\n### Use the token for the job\n\nUse role tokens only. Never a hex value, and never a step of a scale such as `color.graphite.11`. If no token fits, ask for one.\n\n<ColorDemo kind=\"dodont\" item=\"tokens\" />\n\n### One primary button per view\n\nThe primary button is graphite. Every other button is a default button. There is no yellow button.\n\n<ColorDemo kind=\"dodont\" item=\"primary\" />\n",
194
+ "frontmatter": {
195
+ "title": "Color",
196
+ "description": "Three brand colours and a set of colour tokens with one job each, for text, icons, surfaces, backgrounds, borders and status, in light and dark.",
197
+ "order": 1,
198
+ "sidebarLabel": "Overview"
199
+ }
200
+ },
201
+ {
202
+ "id": "en/foundations/styles/color/palette",
203
+ "path": "src/content/foundations/styles/color/palette.mdx",
204
+ "documentPath": "docs/src/content/foundations/styles/color/palette.mdx",
205
+ "locale": "en",
206
+ "kind": "guidance",
207
+ "title": "Palette",
208
+ "status": "active",
209
+ "releasePhase": null,
210
+ "planned": [],
211
+ "body": "import ColorDemo from '../../../../components/ColorDemo.astro';\n\n**The palette feeds the role tokens. Products use the role tokens, never a palette step directly.**\n\nSix scales of twelve steps. Hover a swatch to see its token name.\n\n<ColorDemo kind=\"palette\" />\n\n## What each scale is for\n\n| Scale | For | Never for |\n|---|---|---|\n| Graphite | Everything without a meaning: text, icons, lines, surfaces, the primary button | — |\n| Yellow | The brand: logo, current-page indicator, highlights, brand notes | Text, buttons, warnings |\n| Blue | Info, links, the focus ring | Decoration |\n| Green | Success | Anything else |\n| Orange | Warning | Anything else |\n| Red | Danger | Anything else |\n\nThere is no purple, pink or teal. Charts have no palette yet: ask before colouring a chart.\n\n## What each step is for\n\n**Every step has one job, the same in every scale.**\n\n<ColorDemo kind=\"steps\" />\n\n- **Steps 1–2:** page and surface backgrounds.\n- **Steps 3–5:** component backgrounds at rest, on hover and when pressed or selected.\n- **Steps 6–8:** borders and dividers, from subtle to strong.\n- **Steps 9–10:** solid fills, such as a button, and their hover.\n- **Steps 11–12:** text and icons. 11 is secondary, 12 is the default.\n\nGraphite carries the neutral text, so its dark end has three text levels instead of two: 12 default, 11 secondary, 10 tertiary. Step 9 is the edge of a control and step 8 is disabled text.\n\nYellow is the one exception: its brand fill is step 7, the brand yellow, with graphite text on top. Products don't use yellow for other fills or for text.\n\n## Light and dark\n\n**Every step has a light and a dark value under the same name.**\n\n`color.graphite.12` is the text colour in both themes. The role tokens switch on their own, so a screen never picks a dark colour by hand. In dark, the solid fills (steps 9 and 10) are lighter than in light, so the text on them is dark: use `text.on-bold`.\n\n## Contrast you can count on\n\nIn both themes:\n\n- In blue, green, orange and red, text on a solid fill (steps 9 and 10) reaches 4.5:1 with `text.on-bold`: white in light, dark in dark.\n- Step 11 text reaches 4.5:1 on every background it is paired with.\n- In graphite, steps 10, 11 and 12 all reach 4.5:1 as text; step 9 reaches 3:1 as the edge of a control.\n\nSee [Accessibility](/foundations/styles/color/accessibility/) for the pairs.\n",
212
+ "raw": "---\ntitle: Palette\ndescription: Every colour in the system, as six scales of twelve steps in light and dark, what each scale and each step is for, and the contrast each step guarantees.\norder: 3\n---\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**The palette feeds the role tokens. Products use the role tokens, never a palette step directly.**\n\nSix scales of twelve steps. Hover a swatch to see its token name.\n\n<ColorDemo kind=\"palette\" />\n\n## What each scale is for\n\n| Scale | For | Never for |\n|---|---|---|\n| Graphite | Everything without a meaning: text, icons, lines, surfaces, the primary button | — |\n| Yellow | The brand: logo, current-page indicator, highlights, brand notes | Text, buttons, warnings |\n| Blue | Info, links, the focus ring | Decoration |\n| Green | Success | Anything else |\n| Orange | Warning | Anything else |\n| Red | Danger | Anything else |\n\nThere is no purple, pink or teal. Charts have no palette yet: ask before colouring a chart.\n\n## What each step is for\n\n**Every step has one job, the same in every scale.**\n\n<ColorDemo kind=\"steps\" />\n\n- **Steps 1–2:** page and surface backgrounds.\n- **Steps 3–5:** component backgrounds at rest, on hover and when pressed or selected.\n- **Steps 6–8:** borders and dividers, from subtle to strong.\n- **Steps 9–10:** solid fills, such as a button, and their hover.\n- **Steps 11–12:** text and icons. 11 is secondary, 12 is the default.\n\nGraphite carries the neutral text, so its dark end has three text levels instead of two: 12 default, 11 secondary, 10 tertiary. Step 9 is the edge of a control and step 8 is disabled text.\n\nYellow is the one exception: its brand fill is step 7, the brand yellow, with graphite text on top. Products don't use yellow for other fills or for text.\n\n## Light and dark\n\n**Every step has a light and a dark value under the same name.**\n\n`color.graphite.12` is the text colour in both themes. The role tokens switch on their own, so a screen never picks a dark colour by hand. In dark, the solid fills (steps 9 and 10) are lighter than in light, so the text on them is dark: use `text.on-bold`.\n\n## Contrast you can count on\n\nIn both themes:\n\n- In blue, green, orange and red, text on a solid fill (steps 9 and 10) reaches 4.5:1 with `text.on-bold`: white in light, dark in dark.\n- Step 11 text reaches 4.5:1 on every background it is paired with.\n- In graphite, steps 10, 11 and 12 all reach 4.5:1 as text; step 9 reaches 3:1 as the edge of a control.\n\nSee [Accessibility](/foundations/styles/color/accessibility/) for the pairs.\n",
213
+ "frontmatter": {
214
+ "title": "Palette",
215
+ "description": "Every colour in the system, as six scales of twelve steps in light and dark, what each scale and each step is for, and the contrast each step guarantees.",
216
+ "order": 3
217
+ }
218
+ },
219
+ {
220
+ "id": "en/foundations/styles/color/tokens",
221
+ "path": "src/content/foundations/styles/color/tokens.mdx",
222
+ "documentPath": "docs/src/content/foundations/styles/color/tokens.mdx",
223
+ "locale": "en",
224
+ "kind": "guidance",
225
+ "title": "Tokens",
226
+ "status": "active",
227
+ "releasePhase": null,
228
+ "planned": [],
229
+ "body": "import ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Every colour token name says what is painted, what it means, how strong it is and what is happening.**\n\n## How names are built\n\n`color.{property}.{role}.{emphasis}.{state}`. A part is left out when it is the default.\n\n<ColorDemo kind=\"anatomy\" />\n\n| Part | Values |\n|---|---|\n| Property | `text`, `icon`, `link`, `surface`, `background`, `border`, `skeleton` |\n| Role | `neutral` (left out), `brand`, `danger`, `warning`, `success`, `info`, `inverse`, `disabled`; surfaces: `page`, `subtle`, `inverse`, `scrim` |\n| Emphasis | Text: default, `subtle`, `subtlest`. Fills: `subtle`, default, `bold`. Borders: default, `bold` |\n| State | `hover`, `pressed`, `selected`, `focus` |\n\n`color.background.danger.bold.hover` is the solid danger fill on hover. Two names name the fill under the text instead of a role: `text.on-bold` (on any solid status fill) and `text.on-brand` (on the brand yellow).\n\nIn CSS, write `--bh-` and the name with dots as hyphens: `color.text.subtle` is `var(--bh-color-text-subtle)`.\n\nUse role tokens. The [palette](/foundations/styles/color/palette/) feeds them and is never used directly (see [How colour works](/foundations/styles/color/#how-colour-works)).\n\n## Text and icons\n\n<ColorDemo kind=\"roles\" group=\"text\" />\n\n<ColorDemo kind=\"roles\" group=\"icon\" />\n\n## Surfaces\n\n<ColorDemo kind=\"roles\" group=\"surface\" />\n\n## Backgrounds\n\n<ColorDemo kind=\"roles\" group=\"background\" />\n\n## Borders\n\n<ColorDemo kind=\"roles\" group=\"border\" />\n\n## Missing a token\n\n1. Check [Find the token](/foundations/styles/color/usage/#find-the-token) and the list below.\n2. Ask the design system team. Say where you need it, and propose a name from the four parts that points at a step with the right job (fill at 3, border at 7, text at 11).\n3. The team checks its contrast in both themes and adds it. Use it only after it is released.\n\n## All colour tokens\n\n<ColorDemo kind=\"tokens\" />\n",
230
+ "raw": "---\ntitle: Tokens\ndescription: How colour token names are built, every role token with its light and dark value, how to use them in code, and how to ask for a new one.\norder: 4\n---\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Every colour token name says what is painted, what it means, how strong it is and what is happening.**\n\n## How names are built\n\n`color.{property}.{role}.{emphasis}.{state}`. A part is left out when it is the default.\n\n<ColorDemo kind=\"anatomy\" />\n\n| Part | Values |\n|---|---|\n| Property | `text`, `icon`, `link`, `surface`, `background`, `border`, `skeleton` |\n| Role | `neutral` (left out), `brand`, `danger`, `warning`, `success`, `info`, `inverse`, `disabled`; surfaces: `page`, `subtle`, `inverse`, `scrim` |\n| Emphasis | Text: default, `subtle`, `subtlest`. Fills: `subtle`, default, `bold`. Borders: default, `bold` |\n| State | `hover`, `pressed`, `selected`, `focus` |\n\n`color.background.danger.bold.hover` is the solid danger fill on hover. Two names name the fill under the text instead of a role: `text.on-bold` (on any solid status fill) and `text.on-brand` (on the brand yellow).\n\nIn CSS, write `--bh-` and the name with dots as hyphens: `color.text.subtle` is `var(--bh-color-text-subtle)`.\n\nUse role tokens. The [palette](/foundations/styles/color/palette/) feeds them and is never used directly (see [How colour works](/foundations/styles/color/#how-colour-works)).\n\n## Text and icons\n\n<ColorDemo kind=\"roles\" group=\"text\" />\n\n<ColorDemo kind=\"roles\" group=\"icon\" />\n\n## Surfaces\n\n<ColorDemo kind=\"roles\" group=\"surface\" />\n\n## Backgrounds\n\n<ColorDemo kind=\"roles\" group=\"background\" />\n\n## Borders\n\n<ColorDemo kind=\"roles\" group=\"border\" />\n\n## Missing a token\n\n1. Check [Find the token](/foundations/styles/color/usage/#find-the-token) and the list below.\n2. Ask the design system team. Say where you need it, and propose a name from the four parts that points at a step with the right job (fill at 3, border at 7, text at 11).\n3. The team checks its contrast in both themes and adds it. Use it only after it is released.\n\n## All colour tokens\n\n<ColorDemo kind=\"tokens\" />\n",
231
+ "frontmatter": {
232
+ "title": "Tokens",
233
+ "description": "How colour token names are built, every role token with its light and dark value, how to use them in code, and how to ask for a new one.",
234
+ "order": 4
235
+ }
236
+ },
237
+ {
238
+ "id": "en/foundations/styles/color/usage",
239
+ "path": "src/content/foundations/styles/color/usage.mdx",
240
+ "documentPath": "docs/src/content/foundations/styles/color/usage.mdx",
241
+ "locale": "en",
242
+ "kind": "guidance",
243
+ "title": "Usage",
244
+ "status": "active",
245
+ "releasePhase": null,
246
+ "planned": [],
247
+ "body": "import ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Pick a token by what you are painting and what it means, not by how it looks.**\n\n<ColorDemo kind=\"example\" />\n\n## Find the token\n\n| I need | Use |\n|---|---|\n| Page background | `surface.page` |\n| Card, panel, dialog | `surface`, edge `border` |\n| Sidebar, table header, quiet area | `surface.subtle` |\n| Body text, headings, labels | `text` |\n| Descriptions, secondary table columns, navigation | `text.subtle` |\n| Metadata, timestamps, helper text, breadcrumbs | `text.subtlest` |\n| Placeholder | `text.subtlest` |\n| Link | `link`; on hover `link.hover` |\n| Icon next to text | `icon`; less important `icon.subtle` |\n| Divider, card edge | `border` |\n| Edge of an input, checkbox or select | `border.bold` |\n| Keyboard focus ring | `border.focus`, 2 px, 2 px away |\n| Primary button | `background.neutral.bold`, `text.inverse` |\n| Default button | `surface`, `border`, `text`; on hover `background.neutral.subtle.hover` |\n| Destructive button | `background.danger.bold`, `text.on-bold` |\n| Row or menu item on hover | `background.neutral.subtle.hover` |\n| Selected row, tab or menu item | `background.selected` and a second cue |\n| Current page in the navigation | `border.selected` bar, `background.selected`, `aria-current=\"page\"` |\n| Error under a field | `text.danger`, `icon.danger` |\n| Banner for a status | `background.{role}.subtle`, `border.{role}.subtle`, `text`, `icon.{role}` |\n| Status in a table row | A [label](#labels) |\n| Tooltip, toast | `surface.inverse`, `text.inverse` |\n| Layer behind a dialog or drawer | `surface.scrim` |\n| Loading placeholder | `skeleton`, sheen `skeleton.subtle` |\n| Code block | `code.background`, `code.text` |\n| Brand note | `background.brand.subtle`, `border.brand.subtle` |\n| Disabled control | `background.disabled`, `text.disabled`, `border.disabled` |\n\nNot in the table? Build the name from its four parts (see [Tokens](/foundations/styles/color/tokens/)). If no token exists, ask for one; don't pick the nearest colour.\n\n## Surfaces and backgrounds\n\n**Surfaces are the layers of a screen; backgrounds fill the things on them.**\n\n<ColorDemo kind=\"surfaces\" />\n\n`surface.scrim` goes behind dialogs and drawers only, one layer, at its own opacity.\n\n## Emphasis\n\n<ColorDemo kind=\"emphasis\" />\n\n## Status\n\n**Every status is one of five roles. Pick by what the person needs to do, and always say it in words.**\n\n### Choosing a status\n\n| Role | Use when | HexaSync examples |\n|---|---|---|\n| Info | Something is happening or worth knowing; no action needed. | Syncing, queued, importing |\n| Success | It worked. | Synced, connected, completed |\n| Warning | It works now but needs attention soon. | Partial sync, token expires in 3 days, rate limited |\n| Danger | It failed or is blocked, or the action destroys something. | Failed, disconnected, delete |\n| Neutral | Nothing is happening and nothing is wrong. | Paused, draft, skipped, archived |\n\nWarning is orange, not yellow: yellow is the brand. There is no sixth level; say the difference in words (\"Failed 3 times\").\n\n### Status colours\n\n<ColorDemo kind=\"status\" />\n\n<ColorDemo kind=\"banners\" />\n\n<ColorDemo kind=\"dodont\" item=\"warning\" />\n\n### Labels\n\n<ColorDemo kind=\"labels\" />\n\n| | Label | State label |\n|---|---|---|\n| Looks | Outline in the role's `border`, text in its `text` | Fill in the role's `bold`, text and icon in `text.on-bold` |\n| Size | 20 px, padding 6 px; large 24 px, 8 px | 32 px, padding 12 px |\n| Use | Many per screen: table rows, tags | One per page: the status the page is about |\n\n## Interaction states\n\n**Add `.hover` or `.pressed` to the token at rest; never use opacity or an overlay.**\n\n<ColorDemo kind=\"states\" />\n\n| State | Use |\n|---|---|\n| Hover, pressed | The rest token plus `.hover` or `.pressed` |\n| Selected | `background.selected` and a second cue |\n| Focus | 2 px `border.focus` ring, 2 px away |\n| Disabled | `background.disabled`, `text.disabled`, `border.disabled` |\n\nOn a row or menu item each state sits one step further from the background: hover, then selected, then selected on hover. A hovered row is always lighter than a selected one, so it never looks selected.\n\nMore on [Interaction states](/foundations/styles/interaction-states/).\n\n## Buttons\n\n<ColorDemo kind=\"actions\" />\n",
248
+ "raw": "---\ntitle: Usage\ndescription: Which token to use for each part of a screen, how status, emphasis and states are coloured, and what not to do.\norder: 2\n---\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Pick a token by what you are painting and what it means, not by how it looks.**\n\n<ColorDemo kind=\"example\" />\n\n## Find the token\n\n| I need | Use |\n|---|---|\n| Page background | `surface.page` |\n| Card, panel, dialog | `surface`, edge `border` |\n| Sidebar, table header, quiet area | `surface.subtle` |\n| Body text, headings, labels | `text` |\n| Descriptions, secondary table columns, navigation | `text.subtle` |\n| Metadata, timestamps, helper text, breadcrumbs | `text.subtlest` |\n| Placeholder | `text.subtlest` |\n| Link | `link`; on hover `link.hover` |\n| Icon next to text | `icon`; less important `icon.subtle` |\n| Divider, card edge | `border` |\n| Edge of an input, checkbox or select | `border.bold` |\n| Keyboard focus ring | `border.focus`, 2 px, 2 px away |\n| Primary button | `background.neutral.bold`, `text.inverse` |\n| Default button | `surface`, `border`, `text`; on hover `background.neutral.subtle.hover` |\n| Destructive button | `background.danger.bold`, `text.on-bold` |\n| Row or menu item on hover | `background.neutral.subtle.hover` |\n| Selected row, tab or menu item | `background.selected` and a second cue |\n| Current page in the navigation | `border.selected` bar, `background.selected`, `aria-current=\"page\"` |\n| Error under a field | `text.danger`, `icon.danger` |\n| Banner for a status | `background.{role}.subtle`, `border.{role}.subtle`, `text`, `icon.{role}` |\n| Status in a table row | A [label](#labels) |\n| Tooltip, toast | `surface.inverse`, `text.inverse` |\n| Layer behind a dialog or drawer | `surface.scrim` |\n| Loading placeholder | `skeleton`, sheen `skeleton.subtle` |\n| Code block | `code.background`, `code.text` |\n| Brand note | `background.brand.subtle`, `border.brand.subtle` |\n| Disabled control | `background.disabled`, `text.disabled`, `border.disabled` |\n\nNot in the table? Build the name from its four parts (see [Tokens](/foundations/styles/color/tokens/)). If no token exists, ask for one; don't pick the nearest colour.\n\n## Surfaces and backgrounds\n\n**Surfaces are the layers of a screen; backgrounds fill the things on them.**\n\n<ColorDemo kind=\"surfaces\" />\n\n`surface.scrim` goes behind dialogs and drawers only, one layer, at its own opacity.\n\n## Emphasis\n\n<ColorDemo kind=\"emphasis\" />\n\n## Status\n\n**Every status is one of five roles. Pick by what the person needs to do, and always say it in words.**\n\n### Choosing a status\n\n| Role | Use when | HexaSync examples |\n|---|---|---|\n| Info | Something is happening or worth knowing; no action needed. | Syncing, queued, importing |\n| Success | It worked. | Synced, connected, completed |\n| Warning | It works now but needs attention soon. | Partial sync, token expires in 3 days, rate limited |\n| Danger | It failed or is blocked, or the action destroys something. | Failed, disconnected, delete |\n| Neutral | Nothing is happening and nothing is wrong. | Paused, draft, skipped, archived |\n\nWarning is orange, not yellow: yellow is the brand. There is no sixth level; say the difference in words (\"Failed 3 times\").\n\n### Status colours\n\n<ColorDemo kind=\"status\" />\n\n<ColorDemo kind=\"banners\" />\n\n<ColorDemo kind=\"dodont\" item=\"warning\" />\n\n### Labels\n\n<ColorDemo kind=\"labels\" />\n\n| | Label | State label |\n|---|---|---|\n| Looks | Outline in the role's `border`, text in its `text` | Fill in the role's `bold`, text and icon in `text.on-bold` |\n| Size | 20 px, padding 6 px; large 24 px, 8 px | 32 px, padding 12 px |\n| Use | Many per screen: table rows, tags | One per page: the status the page is about |\n\n## Interaction states\n\n**Add `.hover` or `.pressed` to the token at rest; never use opacity or an overlay.**\n\n<ColorDemo kind=\"states\" />\n\n| State | Use |\n|---|---|\n| Hover, pressed | The rest token plus `.hover` or `.pressed` |\n| Selected | `background.selected` and a second cue |\n| Focus | 2 px `border.focus` ring, 2 px away |\n| Disabled | `background.disabled`, `text.disabled`, `border.disabled` |\n\nOn a row or menu item each state sits one step further from the background: hover, then selected, then selected on hover. A hovered row is always lighter than a selected one, so it never looks selected.\n\nMore on [Interaction states](/foundations/styles/interaction-states/).\n\n## Buttons\n\n<ColorDemo kind=\"actions\" />\n",
249
+ "frontmatter": {
250
+ "title": "Usage",
251
+ "description": "Which token to use for each part of a screen, how status, emphasis and states are coloured, and what not to do.",
252
+ "order": 2
253
+ }
254
+ },
255
+ {
256
+ "id": "en/foundations/styles/data-visualization",
257
+ "path": "src/content/foundations/styles/data-visualization.mdx",
258
+ "documentPath": "docs/src/content/foundations/styles/data-visualization.mdx",
259
+ "locale": "en",
260
+ "kind": "guidance",
261
+ "title": "Data visualization",
262
+ "status": "planned",
263
+ "releasePhase": null,
264
+ "planned": [
265
+ "A chart palette for series, with contrast in light and dark",
266
+ "Status colours in charts",
267
+ "Chart types and when to use each",
268
+ "Axis, legend, tooltip and number formats",
269
+ "Accessible charts: not by colour alone, text alternatives"
270
+ ],
271
+ "body": "",
272
+ "raw": "---\ntitle: \"Data visualization\"\ndescription: \"Colours, type and rules for charts, KPI tiles and other data displays.\"\norder: 13\nplanned:\n - \"A chart palette for series, with contrast in light and dark\"\n - \"Status colours in charts\"\n - \"Chart types and when to use each\"\n - \"Axis, legend, tooltip and number formats\"\n - \"Accessible charts: not by colour alone, text alternatives\"\n---\n",
273
+ "frontmatter": {
274
+ "title": "Data visualization",
275
+ "description": "Colours, type and rules for charts, KPI tiles and other data displays.",
276
+ "order": 13,
277
+ "planned": [
278
+ "A chart palette for series, with contrast in light and dark",
279
+ "Status colours in charts",
280
+ "Chart types and when to use each",
281
+ "Axis, legend, tooltip and number formats",
282
+ "Accessible charts: not by colour alone, text alternatives"
283
+ ]
284
+ }
285
+ },
286
+ {
287
+ "id": "en/foundations/styles/elevation",
288
+ "path": "src/content/foundations/styles/elevation.mdx",
289
+ "documentPath": "docs/src/content/foundations/styles/elevation.mdx",
290
+ "locale": "en",
291
+ "kind": "guidance",
292
+ "title": "Elevation",
293
+ "status": "active",
294
+ "releasePhase": null,
295
+ "planned": [],
296
+ "body": "import TokenTable from '../../../components/TokenTable.astro';\n\n- `elevation.shadow.raised`: cards that sit on the page.\n- `elevation.shadow.overlay`: dropdowns, popovers and dialogs that float above content.\n\n## Tokens\n<TokenTable prefix=\"elevation\" />\n",
297
+ "raw": "---\ntitle: Elevation\ndescription: Shadows that show which surfaces sit above others.\norder: 8\n---\nimport TokenTable from '../../../components/TokenTable.astro';\n\n- `elevation.shadow.raised`: cards that sit on the page.\n- `elevation.shadow.overlay`: dropdowns, popovers and dialogs that float above content.\n\n## Tokens\n<TokenTable prefix=\"elevation\" />\n",
298
+ "frontmatter": {
299
+ "title": "Elevation",
300
+ "description": "Shadows that show which surfaces sit above others.",
301
+ "order": 8
302
+ }
303
+ },
304
+ {
305
+ "id": "en/foundations/styles/icons/accessibility",
306
+ "path": "src/content/foundations/styles/icons/accessibility.mdx",
307
+ "documentPath": "docs/src/content/foundations/styles/icons/accessibility.mdx",
308
+ "locale": "en",
309
+ "kind": "guidance",
310
+ "title": "Accessibility",
311
+ "status": "active",
312
+ "releasePhase": null,
313
+ "planned": [],
314
+ "body": "import IconDemo from '../../../../components/IconDemo.astro';\n\n**An icon is either decorative and hidden, or it has a name. A clickable icon is always inside a button or a link of at least 24 × 24.**\n\n| Check | Rule | WCAG 2.2 |\n|---|---|---|\n| Decorative icon | Hidden with `aria-hidden=\"true\"` | 1.1.1 |\n| Icon-only button or link | Has a name (`aria-label`) and a matching tooltip | 1.1.1, 2.5.3, 4.1.2 |\n| Icon that carries meaning | 3:1 contrast or more with its background | 1.4.11 |\n| Status | Written in words, never icon or colour alone | 1.4.1 |\n| Target | 24 × 24 or more; 32 × 32 icon buttons in products | 2.5.8 |\n\n## Decorative icons\n\n**When text sits next to the icon, the icon is decorative.** Hide it, so screen readers read the label once.\n\nLucide does this for you: an icon with no `aria-label`, `aria-labelledby`, `role` or `title` gets `aria-hidden=\"true\"`. Don’t add a label to an icon that already has text next to it.\n\n<IconDemo kind=\"dodont\" item=\"decorative\" />\n\n## Icon-only buttons\n\n**Name the button, not the icon.** Put the name on the `<button>` or `<a>` with `aria-label`. The icon inside stays hidden.\n\n- The name says what happens: “Delete store”, not “Trash” or “Icon”.\n- Add a tooltip with the same words, on hover and on keyboard focus. The tooltip must start with the button’s name, so speech input users can say what they see (WCAG 2.5.3).\n- Use an icon-only button only for well-known actions. See [Icon and label](/foundations/styles/icons/usage/#icon-and-label).\n\n```html\n<button type=\"button\" aria-label=\"Settings\">\n <svg aria-hidden=\"true\">…</svg>\n</button>\n```\n\n<IconDemo kind=\"dodont\" item=\"tooltip\" />\n\n## Meaningful icons on their own\n\nWhen an icon is the only sign of something, such as a status icon in a narrow table column, give the icon itself a name: `role=\"img\"` and `aria-label=\"Failed\"`. Prefer writing the status in words.\n\n## Contrast\n\n**Icons that carry meaning need 3:1 against their background** (WCAG 1.4.11). Every `color.icon.*` token meets 3:1 on the backgrounds it is paired with, in light and dark; the build checks it. Decorative icons and icons in disabled controls have no minimum.\n\nSee every pair in [Color › Accessibility](/foundations/styles/color/accessibility/).\n\n## Target size\n\n**Anything you can click is at least 24 × 24** (WCAG 2.5.8). In Beehexa products, icon buttons are 32 × 32 with a 16 px icon. The icon is never the only thing to click.\n\n<IconDemo kind=\"target\" />\n\n<IconDemo kind=\"dodont\" item=\"target\" />\n\n## Keyboard and focus\n\n- The button or link gets focus, never the icon. Don’t add `tabindex` to an `<svg>`.\n- The focus ring goes around the whole 32 × 32 button.\n- A tooltip opens on focus as well as hover, and closes with Escape.\n\n## Checklist\n\n- Every icon next to text is hidden from screen readers.\n- Every icon-only button has a name and a tooltip with the same words.\n- No status is shown by an icon or colour alone.\n- Meaningful icons reach 3:1; the token already does if you use the right one.\n- Every clickable icon sits in a target of 24 × 24 or more.\n",
315
+ "raw": "---\ntitle: Accessibility\ndescription: How icons get a name or stay silent, why icon-only buttons need a tooltip, and the contrast and target size icons must meet.\norder: 3\n---\nimport IconDemo from '../../../../components/IconDemo.astro';\n\n**An icon is either decorative and hidden, or it has a name. A clickable icon is always inside a button or a link of at least 24 × 24.**\n\n| Check | Rule | WCAG 2.2 |\n|---|---|---|\n| Decorative icon | Hidden with `aria-hidden=\"true\"` | 1.1.1 |\n| Icon-only button or link | Has a name (`aria-label`) and a matching tooltip | 1.1.1, 2.5.3, 4.1.2 |\n| Icon that carries meaning | 3:1 contrast or more with its background | 1.4.11 |\n| Status | Written in words, never icon or colour alone | 1.4.1 |\n| Target | 24 × 24 or more; 32 × 32 icon buttons in products | 2.5.8 |\n\n## Decorative icons\n\n**When text sits next to the icon, the icon is decorative.** Hide it, so screen readers read the label once.\n\nLucide does this for you: an icon with no `aria-label`, `aria-labelledby`, `role` or `title` gets `aria-hidden=\"true\"`. Don’t add a label to an icon that already has text next to it.\n\n<IconDemo kind=\"dodont\" item=\"decorative\" />\n\n## Icon-only buttons\n\n**Name the button, not the icon.** Put the name on the `<button>` or `<a>` with `aria-label`. The icon inside stays hidden.\n\n- The name says what happens: “Delete store”, not “Trash” or “Icon”.\n- Add a tooltip with the same words, on hover and on keyboard focus. The tooltip must start with the button’s name, so speech input users can say what they see (WCAG 2.5.3).\n- Use an icon-only button only for well-known actions. See [Icon and label](/foundations/styles/icons/usage/#icon-and-label).\n\n```html\n<button type=\"button\" aria-label=\"Settings\">\n <svg aria-hidden=\"true\">…</svg>\n</button>\n```\n\n<IconDemo kind=\"dodont\" item=\"tooltip\" />\n\n## Meaningful icons on their own\n\nWhen an icon is the only sign of something, such as a status icon in a narrow table column, give the icon itself a name: `role=\"img\"` and `aria-label=\"Failed\"`. Prefer writing the status in words.\n\n## Contrast\n\n**Icons that carry meaning need 3:1 against their background** (WCAG 1.4.11). Every `color.icon.*` token meets 3:1 on the backgrounds it is paired with, in light and dark; the build checks it. Decorative icons and icons in disabled controls have no minimum.\n\nSee every pair in [Color › Accessibility](/foundations/styles/color/accessibility/).\n\n## Target size\n\n**Anything you can click is at least 24 × 24** (WCAG 2.5.8). In Beehexa products, icon buttons are 32 × 32 with a 16 px icon. The icon is never the only thing to click.\n\n<IconDemo kind=\"target\" />\n\n<IconDemo kind=\"dodont\" item=\"target\" />\n\n## Keyboard and focus\n\n- The button or link gets focus, never the icon. Don’t add `tabindex` to an `<svg>`.\n- The focus ring goes around the whole 32 × 32 button.\n- A tooltip opens on focus as well as hover, and closes with Escape.\n\n## Checklist\n\n- Every icon next to text is hidden from screen readers.\n- Every icon-only button has a name and a tooltip with the same words.\n- No status is shown by an icon or colour alone.\n- Meaningful icons reach 3:1; the token already does if you use the right one.\n- Every clickable icon sits in a target of 24 × 24 or more.\n",
316
+ "frontmatter": {
317
+ "title": "Accessibility",
318
+ "description": "How icons get a name or stay silent, why icon-only buttons need a tooltip, and the contrast and target size icons must meet.",
319
+ "order": 3
320
+ }
321
+ },
322
+ {
323
+ "id": "en/foundations/styles/icons/code",
324
+ "path": "src/content/foundations/styles/icons/code.mdx",
325
+ "documentPath": "docs/src/content/foundations/styles/icons/code.mdx",
326
+ "locale": "en",
327
+ "kind": "guidance",
328
+ "title": "Code",
329
+ "status": "active",
330
+ "releasePhase": null,
331
+ "planned": [],
332
+ "body": "\n**Products use Lucide directly. Install the Lucide package for your framework, pin the version and import each icon by name.**\n\n## Packages\n\n| Framework | Package | Version |\n|---|---|---|\n| Vue, for Beehexa products | `@lucide/vue` | 1.62.0 |\n| React | `lucide-react` | 1.62.0 |\n\nEvery product uses the same Lucide version as this site, so the icons match the [Library](/foundations/styles/icons/library/). The icons are bundled into the app at build time. There is no request to a CDN.\n\n## Install\n\n```bash\nnpm install @lucide/vue@1.62.0 --save-exact\n```\n\nPin the exact version, with no `^` or `~`. A new Lucide version can change a shape or rename an icon, so raise the version on purpose. See [Updating Lucide](#updating-lucide).\n\n## Import\n\nImport each icon by name. Names are the Library names in PascalCase: `refresh-cw` becomes `RefreshCw`. Only the icons you import end up in the bundle.\n\n```vue\n<script setup lang=\"ts\">\nimport { RefreshCw } from '@lucide/vue';\n</script>\n\n<template>\n <button type=\"button\" class=\"bh-button\">\n <RefreshCw :size=\"16\" />\n Sync now\n </button>\n</template>\n```\n\nDon’t import the whole set with `import * as`. It puts every icon in the bundle.\n\n## Default size\n\nLucide draws icons at 24 px. Beehexa products use 16 px by default. Set it once in the root component:\n\n```vue\n<!-- App.vue -->\n<script setup lang=\"ts\">\nimport { setLucideProps } from '@lucide/vue';\n\nsetLucideProps({ size: 16 });\n</script>\n```\n\nThen set `size` only for a 20, 24 or 32 px icon.\n\n## Props\n\n| Prop | Lucide default | Beehexa rule |\n|---|---|---|\n| `size` | 24 | 16 by default. 20, 24 or 32 only where Usage says so. Nothing else. |\n| `color` | `currentColor` | Leave it. Set the colour on the parent with an icon colour token. |\n| `stroke-width` | 2 | Don’t change it. |\n| `non-scaling-stroke` | `false` | Don’t turn it on. Don’t use its older name, absolute-stroke-width, either. |\n| `aria-label` | none | Only for a meaningful icon on its own, together with the img role. |\n\n## Size\n\nUse the `size` prop, or set the size in CSS on the `svg`. Both keep the stroke in scale.\n\n```vue\n<RefreshCw :size=\"20\" />\n```\n\n## Colour\n\n```css\n.sync-status {\n color: var(--bh-color-icon-success);\n}\n```\n\n```vue\n<span class=\"sync-status\"><CircleCheck /> Synced</span>\n```\n\n## Spacing\n\nSet the gap on the control, from its size: 4 px (`space.050`) with a 16 px icon in small and default controls, 8 px (`space.100`) with a 20 or 24 px icon. See [Usage › Spacing](/foundations/styles/icons/usage/#spacing).\n\n```css\n.bh-button {\n display: inline-flex;\n align-items: center;\n gap: var(--bh-space-050);\n}\n.bh-button.is-large {\n gap: var(--bh-space-100);\n}\n```\n\n## Accessibility\n\nLucide hides an icon from screen readers with `aria-hidden=\"true\"`, unless you give it an `aria-*`, `role` or `title` prop. Name icon-only buttons on the button, and add a tooltip with the same text.\n\n```vue\n<a-tooltip title=\"Settings\">\n <button type=\"button\" class=\"icon-button\" aria-label=\"Settings\">\n <Settings />\n </button>\n</a-tooltip>\n```\n\nA meaningful icon on its own gets a role and a label, which also removes `aria-hidden`:\n\n```vue\n<CircleX role=\"img\" aria-label=\"Failed\" />\n```\n\n## Inside Ant Design Vue\n\nPut the icon in the `icon` slot and add the `anticon` class, so Ant Design Vue lines it up like its own icons.\n\n```vue\n<a-button>\n <template #icon><Plus class=\"anticon\" /></template>\n Add store\n</a-button>\n```\n\n## React\n\n`lucide-react` has the same icons and props, in camelCase. Set the default size once with `LucideProvider`.\n\n```tsx\nimport { LucideProvider, RefreshCw } from 'lucide-react';\n\n<LucideProvider size={16}>\n <button type=\"button\">\n <RefreshCw />\n Sync now\n </button>\n</LucideProvider>\n```\n\n## Astro\n\nbeehexa.design uses `@lucide/astro`. Import each icon from its own file, so the build stays fast:\n\n```astro\n---\nimport Search from '@lucide/astro/icons/search';\n---\n<button class=\"icon-button\" type=\"button\" aria-label=\"Search\">\n <Search size={20} />\n</button>\n```\n\n\n## Custom icons\n\nLucide covers what Beehexa needs today. If an icon is ever missing, draw it on Lucide’s 24 px grid with the same stroke and caps, name it in kebab-case with a `bh-` prefix, and add it to the library.\n\n## Updating Lucide\n\n1. Read the Lucide release notes for renamed or changed icons.\n2. Check that every icon in [Common actions](/foundations/styles/icons/usage/#common-actions) still exists.\n3. Raise the pinned version in the product, and ask the design system team to update the Library, so it shows the same icons.\n",
333
+ "raw": "---\ntitle: Code\ndescription: How Vue products install, import, size, colour and label Lucide icons, with short notes for React and Astro.\norder: 4\n---\n\n**Products use Lucide directly. Install the Lucide package for your framework, pin the version and import each icon by name.**\n\n## Packages\n\n| Framework | Package | Version |\n|---|---|---|\n| Vue, for Beehexa products | `@lucide/vue` | 1.62.0 |\n| React | `lucide-react` | 1.62.0 |\n\nEvery product uses the same Lucide version as this site, so the icons match the [Library](/foundations/styles/icons/library/). The icons are bundled into the app at build time. There is no request to a CDN.\n\n## Install\n\n```bash\nnpm install @lucide/vue@1.62.0 --save-exact\n```\n\nPin the exact version, with no `^` or `~`. A new Lucide version can change a shape or rename an icon, so raise the version on purpose. See [Updating Lucide](#updating-lucide).\n\n## Import\n\nImport each icon by name. Names are the Library names in PascalCase: `refresh-cw` becomes `RefreshCw`. Only the icons you import end up in the bundle.\n\n```vue\n<script setup lang=\"ts\">\nimport { RefreshCw } from '@lucide/vue';\n</script>\n\n<template>\n <button type=\"button\" class=\"bh-button\">\n <RefreshCw :size=\"16\" />\n Sync now\n </button>\n</template>\n```\n\nDon’t import the whole set with `import * as`. It puts every icon in the bundle.\n\n## Default size\n\nLucide draws icons at 24 px. Beehexa products use 16 px by default. Set it once in the root component:\n\n```vue\n<!-- App.vue -->\n<script setup lang=\"ts\">\nimport { setLucideProps } from '@lucide/vue';\n\nsetLucideProps({ size: 16 });\n</script>\n```\n\nThen set `size` only for a 20, 24 or 32 px icon.\n\n## Props\n\n| Prop | Lucide default | Beehexa rule |\n|---|---|---|\n| `size` | 24 | 16 by default. 20, 24 or 32 only where Usage says so. Nothing else. |\n| `color` | `currentColor` | Leave it. Set the colour on the parent with an icon colour token. |\n| `stroke-width` | 2 | Don’t change it. |\n| `non-scaling-stroke` | `false` | Don’t turn it on. Don’t use its older name, absolute-stroke-width, either. |\n| `aria-label` | none | Only for a meaningful icon on its own, together with the img role. |\n\n## Size\n\nUse the `size` prop, or set the size in CSS on the `svg`. Both keep the stroke in scale.\n\n```vue\n<RefreshCw :size=\"20\" />\n```\n\n## Colour\n\n```css\n.sync-status {\n color: var(--bh-color-icon-success);\n}\n```\n\n```vue\n<span class=\"sync-status\"><CircleCheck /> Synced</span>\n```\n\n## Spacing\n\nSet the gap on the control, from its size: 4 px (`space.050`) with a 16 px icon in small and default controls, 8 px (`space.100`) with a 20 or 24 px icon. See [Usage › Spacing](/foundations/styles/icons/usage/#spacing).\n\n```css\n.bh-button {\n display: inline-flex;\n align-items: center;\n gap: var(--bh-space-050);\n}\n.bh-button.is-large {\n gap: var(--bh-space-100);\n}\n```\n\n## Accessibility\n\nLucide hides an icon from screen readers with `aria-hidden=\"true\"`, unless you give it an `aria-*`, `role` or `title` prop. Name icon-only buttons on the button, and add a tooltip with the same text.\n\n```vue\n<a-tooltip title=\"Settings\">\n <button type=\"button\" class=\"icon-button\" aria-label=\"Settings\">\n <Settings />\n </button>\n</a-tooltip>\n```\n\nA meaningful icon on its own gets a role and a label, which also removes `aria-hidden`:\n\n```vue\n<CircleX role=\"img\" aria-label=\"Failed\" />\n```\n\n## Inside Ant Design Vue\n\nPut the icon in the `icon` slot and add the `anticon` class, so Ant Design Vue lines it up like its own icons.\n\n```vue\n<a-button>\n <template #icon><Plus class=\"anticon\" /></template>\n Add store\n</a-button>\n```\n\n## React\n\n`lucide-react` has the same icons and props, in camelCase. Set the default size once with `LucideProvider`.\n\n```tsx\nimport { LucideProvider, RefreshCw } from 'lucide-react';\n\n<LucideProvider size={16}>\n <button type=\"button\">\n <RefreshCw />\n Sync now\n </button>\n</LucideProvider>\n```\n\n## Astro\n\nbeehexa.design uses `@lucide/astro`. Import each icon from its own file, so the build stays fast:\n\n```astro\n---\nimport Search from '@lucide/astro/icons/search';\n---\n<button class=\"icon-button\" type=\"button\" aria-label=\"Search\">\n <Search size={20} />\n</button>\n```\n\n\n## Custom icons\n\nLucide covers what Beehexa needs today. If an icon is ever missing, draw it on Lucide’s 24 px grid with the same stroke and caps, name it in kebab-case with a `bh-` prefix, and add it to the library.\n\n## Updating Lucide\n\n1. Read the Lucide release notes for renamed or changed icons.\n2. Check that every icon in [Common actions](/foundations/styles/icons/usage/#common-actions) still exists.\n3. Raise the pinned version in the product, and ask the design system team to update the Library, so it shows the same icons.\n",
334
+ "frontmatter": {
335
+ "title": "Code",
336
+ "description": "How Vue products install, import, size, colour and label Lucide icons, with short notes for React and Astro.",
337
+ "order": 4
338
+ }
339
+ },
340
+ {
341
+ "id": "en/foundations/styles/icons/index",
342
+ "path": "src/content/foundations/styles/icons/index.mdx",
343
+ "documentPath": "docs/src/content/foundations/styles/icons/index.mdx",
344
+ "locale": "en",
345
+ "kind": "guidance",
346
+ "title": "Icons",
347
+ "status": "active",
348
+ "releasePhase": null,
349
+ "planned": [],
350
+ "body": "import IconDemo from '../../../../components/IconDemo.astro';\n\nIcons help people scan a screen and recognise an action. In Beehexa products they never replace words: a status is written, and most actions have a label.\n\nBeehexa uses **[Lucide](https://lucide.dev)**: about 1,900 outline icons on a 24 × 24 grid, under the ISC licence. Products import Lucide directly. There is no Beehexa icon package. We add usage rules on top.\n\n<IconDemo kind=\"sizes\" />\n\n## Principles\n\n### Words first\n\nAn icon supports a label. Use an icon on its own only for an action everyone knows, such as close, search or more, and give it a name and a tooltip.\n\n### One icon, one meaning\n\nThe same idea always has the same icon, in every product. Sync is `refresh-cw` everywhere. See the [common actions](/foundations/styles/icons/usage/#common-actions).\n\n### Outline only\n\nLucide has no filled icons. Show a selected item with the selected background and an indicator bar, not with a different icon.\n\n### Colour follows the text\n\nAn icon takes the colour of the text next to it. Use a status colour only when the icon shows that status.\n\n## The rules at a glance\n\n| Rule | Value |\n|---|---|\n| Icon set | Lucide, outline only |\n| Sizes | 16 (default), 20 (next to 16 px text, toolbars), 24 (icon on its own), 32 (empty states only) |\n| Stroke | Lucide’s default, scaled with the icon: 1.33 px at 16, 1.67 at 20, 2 at 24 |\n| Grid | 24 × 24, at least 1 unit of padding, round caps and joins |\n| Colour | `currentColor`, with the `color.icon.*` tokens |\n| Next to text | Centred on the first line. The gap follows the text size: 4 px next to 14 px text or smaller, 8 px next to 16 px text or larger |\n| Labels | Icon with a label by default; icon-only for well-known actions, with a name and a tooltip |\n| Decorative icons | Hidden from screen readers (`aria-hidden=\"true\"`) |\n| Contrast | 3:1 or more for icons that carry meaning (WCAG 1.4.11) |\n| Target | 24 × 24 or more (WCAG 2.5.8); icon buttons in products are 32 × 32 |\n| Names | One name per meaning, kebab-case, such as `circle-check` |\n| Package | Lucide for Vue 1.62.0, pinned, imported by name |\n| Right to left | Not needed: products are in Vietnamese and English |\n\n## In this section\n\n| Page | What is in it |\n|---|---|\n| [Library](/foundations/styles/icons/library/) | Every icon. Search, filter and copy a name. |\n| [Usage](/foundations/styles/icons/usage/) | Size, stroke, colour, text alignment, labels, and the icon for each common action. |\n| [Accessibility](/foundations/styles/icons/accessibility/) | Names, decorative icons, tooltips, contrast and target size. |\n| [Code](/foundations/styles/icons/code/) | Installing, importing, sizing and labelling Lucide icons in Vue, with notes for React and Astro. |\n\n## Licence\n\nLucide is © Lucide Contributors and released under the [ISC licence](https://lucide.dev/license). Parts of it come from Feather, © Cole Bemis, under the MIT licence. Both allow commercial use. Keep the licence notice when you ship the icons. The Lucide package keeps it for you.\n",
351
+ "raw": "---\ntitle: Icons\ndescription: Beehexa products use Lucide, an open-source set of outline icons, directly. A few rules cover size, colour, spacing, labels and accessibility.\norder: 11\nsidebarLabel: Overview\n---\nimport IconDemo from '../../../../components/IconDemo.astro';\n\nIcons help people scan a screen and recognise an action. In Beehexa products they never replace words: a status is written, and most actions have a label.\n\nBeehexa uses **[Lucide](https://lucide.dev)**: about 1,900 outline icons on a 24 × 24 grid, under the ISC licence. Products import Lucide directly. There is no Beehexa icon package. We add usage rules on top.\n\n<IconDemo kind=\"sizes\" />\n\n## Principles\n\n### Words first\n\nAn icon supports a label. Use an icon on its own only for an action everyone knows, such as close, search or more, and give it a name and a tooltip.\n\n### One icon, one meaning\n\nThe same idea always has the same icon, in every product. Sync is `refresh-cw` everywhere. See the [common actions](/foundations/styles/icons/usage/#common-actions).\n\n### Outline only\n\nLucide has no filled icons. Show a selected item with the selected background and an indicator bar, not with a different icon.\n\n### Colour follows the text\n\nAn icon takes the colour of the text next to it. Use a status colour only when the icon shows that status.\n\n## The rules at a glance\n\n| Rule | Value |\n|---|---|\n| Icon set | Lucide, outline only |\n| Sizes | 16 (default), 20 (next to 16 px text, toolbars), 24 (icon on its own), 32 (empty states only) |\n| Stroke | Lucide’s default, scaled with the icon: 1.33 px at 16, 1.67 at 20, 2 at 24 |\n| Grid | 24 × 24, at least 1 unit of padding, round caps and joins |\n| Colour | `currentColor`, with the `color.icon.*` tokens |\n| Next to text | Centred on the first line. The gap follows the text size: 4 px next to 14 px text or smaller, 8 px next to 16 px text or larger |\n| Labels | Icon with a label by default; icon-only for well-known actions, with a name and a tooltip |\n| Decorative icons | Hidden from screen readers (`aria-hidden=\"true\"`) |\n| Contrast | 3:1 or more for icons that carry meaning (WCAG 1.4.11) |\n| Target | 24 × 24 or more (WCAG 2.5.8); icon buttons in products are 32 × 32 |\n| Names | One name per meaning, kebab-case, such as `circle-check` |\n| Package | Lucide for Vue 1.62.0, pinned, imported by name |\n| Right to left | Not needed: products are in Vietnamese and English |\n\n## In this section\n\n| Page | What is in it |\n|---|---|\n| [Library](/foundations/styles/icons/library/) | Every icon. Search, filter and copy a name. |\n| [Usage](/foundations/styles/icons/usage/) | Size, stroke, colour, text alignment, labels, and the icon for each common action. |\n| [Accessibility](/foundations/styles/icons/accessibility/) | Names, decorative icons, tooltips, contrast and target size. |\n| [Code](/foundations/styles/icons/code/) | Installing, importing, sizing and labelling Lucide icons in Vue, with notes for React and Astro. |\n\n## Licence\n\nLucide is © Lucide Contributors and released under the [ISC licence](https://lucide.dev/license). Parts of it come from Feather, © Cole Bemis, under the MIT licence. Both allow commercial use. Keep the licence notice when you ship the icons. The Lucide package keeps it for you.\n",
352
+ "frontmatter": {
353
+ "title": "Icons",
354
+ "description": "Beehexa products use Lucide, an open-source set of outline icons, directly. A few rules cover size, colour, spacing, labels and accessibility.",
355
+ "order": 11,
356
+ "sidebarLabel": "Overview"
357
+ }
358
+ },
359
+ {
360
+ "id": "en/foundations/styles/icons/library",
361
+ "path": "src/content/foundations/styles/icons/library.mdx",
362
+ "documentPath": "docs/src/content/foundations/styles/icons/library.mdx",
363
+ "locale": "en",
364
+ "kind": "guidance",
365
+ "title": "Library",
366
+ "status": "active",
367
+ "releasePhase": null,
368
+ "planned": [],
369
+ "body": "import IconBrowser from '../../../../components/IconBrowser.astro';\n\n**Click an icon to copy its name.** Names are kebab-case, such as `circle-check`. In Vue the same icon is `CircleCheck`.\n\nBefore you pick an icon, check [Common actions](/foundations/styles/icons/usage/#common-actions): if the meaning is listed there, use that icon. The library opens on the category **Common actions**, which shows only those icons; a search looks through every icon, and **All** lists them all. They are Lucide icons chosen for common Beehexa actions. None is redrawn or renamed.\n\n<IconBrowser />\n\n## Using the library\n\n- Search matches icon names first, then the tags Lucide gives each icon. “Sync” finds `refresh-cw`.\n- The size switch shows 16, 20 and 24 px. Products use 16 px by default.\n- With the keyboard: Tab to the icons, move with the arrow keys, Home and End, and press Enter to copy.\n- Don’t see what you need? Search by meaning as well as by name. Two icons that each make sense alone rarely make a good third one. See [Custom icons](/foundations/styles/icons/code/#custom-icons).\n",
370
+ "raw": "---\ntitle: Library\ndescription: Every Lucide icon Beehexa can use. Search by name or tag, filter by category, switch the size and click an icon to copy its name.\norder: 1\n---\nimport IconBrowser from '../../../../components/IconBrowser.astro';\n\n**Click an icon to copy its name.** Names are kebab-case, such as `circle-check`. In Vue the same icon is `CircleCheck`.\n\nBefore you pick an icon, check [Common actions](/foundations/styles/icons/usage/#common-actions): if the meaning is listed there, use that icon. The library opens on the category **Common actions**, which shows only those icons; a search looks through every icon, and **All** lists them all. They are Lucide icons chosen for common Beehexa actions. None is redrawn or renamed.\n\n<IconBrowser />\n\n## Using the library\n\n- Search matches icon names first, then the tags Lucide gives each icon. “Sync” finds `refresh-cw`.\n- The size switch shows 16, 20 and 24 px. Products use 16 px by default.\n- With the keyboard: Tab to the icons, move with the arrow keys, Home and End, and press Enter to copy.\n- Don’t see what you need? Search by meaning as well as by name. Two icons that each make sense alone rarely make a good third one. See [Custom icons](/foundations/styles/icons/code/#custom-icons).\n",
371
+ "frontmatter": {
372
+ "title": "Library",
373
+ "description": "Every Lucide icon Beehexa can use. Search by name or tag, filter by category, switch the size and click an icon to copy its name.",
374
+ "order": 1
375
+ }
376
+ },
377
+ {
378
+ "id": "en/foundations/styles/icons/usage",
379
+ "path": "src/content/foundations/styles/icons/usage.mdx",
380
+ "documentPath": "docs/src/content/foundations/styles/icons/usage.mdx",
381
+ "locale": "en",
382
+ "kind": "guidance",
383
+ "title": "Usage",
384
+ "status": "active",
385
+ "releasePhase": null,
386
+ "planned": [],
387
+ "body": "import IconDemo from '../../../../components/IconDemo.astro';\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Use 16 px icons in the colour of the text, with a label, and the same icon for the same meaning everywhere.**\n\n## Sizes\n\n**Pick the size from the text next to the icon.**\n\n| Size | Use it for |\n|---|---|\n| 16 px | Default. Buttons, menus, tables, form fields, next to 14 px text. |\n| 20 px | Next to 16 px text, in toolbars and in the page header. |\n| 24 px | An icon on its own, such as a status in a card or a small empty state. |\n| 32 px | Empty states only. |\n\nDon’t use other sizes. Don’t scale an icon to fit a box: change the box.\n\n<IconDemo kind=\"dodont\" item=\"size\" />\n\n## Stroke\n\n**Keep Lucide’s stroke.** It is 2 units on the 24 grid and scales with the icon: 1.33 px at 16, 1.67 px at 20, 2 px at 24. Don’t set `stroke-width` or `absoluteStrokeWidth`. A fixed 2 px stroke fills in the small details of a 16 px icon.\n\n<IconDemo kind=\"dodont\" item=\"stroke\" />\n\n## Colour\n\n**An icon takes the colour of its text.** Icons draw with `currentColor`, so an icon in a button or a link is right without extra code. Set a colour only with a `color.icon.*` token:\n\n<ColorDemo kind=\"roles\" group=\"icon\" />\n\n- Status icons use the status token, such as `icon.danger`, and always sit next to the status in words.\n- Never give an icon a colour to decorate it, and never use the brand yellow for an icon.\n\n<IconDemo kind=\"dodont\" item=\"colour\" />\n\n## Alignment with text\n\n**Centre the icon on the line height of the text.** Use `display: flex; align-items: center`. Next to several lines, centre the icon on the first line.\n\n<IconDemo kind=\"align\" />\n\n<IconDemo kind=\"dodont\" item=\"align\" />\n\n## Spacing\n\n**The gap between an icon and its text follows the text size: 4 px next to 14 px text or smaller, 8 px next to 16 px text or larger.**\n\n| Text | Icon | Gap | Token | Where |\n|---|---|---|---|---|\n| 12 or 14 px | 16 px | 4 px | `space.050` | Small and default controls, menus, tabs, table cells |\n| 16 px or larger | 20 or 24 px | 8 px | `space.100` | Large controls, toolbars, the page header, a status in a card |\n\nSet the gap on the control with `gap`, not with a margin on the icon.\n\n<IconDemo kind=\"spacing\" />\n\n## Icon and label\n\n**Give an icon a label by default.** The label says what happens; the icon helps people find it again.\n\nUse an icon on its own only when all three are true:\n\n- The action is well known: close, search, add, edit, delete, copy, refresh, settings, filter, more, menu.\n- Space is tight, such as a table row or a toolbar.\n- The button has a name (`aria-label`) and a tooltip with the same words. See [Accessibility](/foundations/styles/icons/accessibility/).\n\n<IconDemo kind=\"dodont\" item=\"label\" />\n\n## Selected state\n\n**Lucide icons are outline only.** Show a selected item with `background.selected` and the indicator bar, not by filling the icon.\n\n<IconDemo kind=\"dodont\" item=\"selected\" />\n\n## Common actions\n\n**One icon per meaning.** Use this icon whenever you show one of these actions or objects, in every product. If a meaning is missing, ask before you choose one, so it is added here.\n\n<IconDemo kind=\"actions\" />\n\n<IconDemo kind=\"dodont\" item=\"meaning\" />\n\n## Do and don’t\n\n| Do | Don’t |\n|---|---|\n| Use 16, 20, 24 or 32 px. | Scale icons to other sizes. |\n| Keep the icon in the text colour. | Colour icons to decorate. |\n| Add a label to most icons. | Use an unfamiliar icon on its own. |\n| Use the same icon for the same meaning. | Use a different icon in each product. |\n| Use outline icons with a selected background. | Fill an icon to show it is selected. |\n| Write the status next to a status icon. | Let an icon or its colour carry the status alone. |\n| Use one icon per button. | Combine two icons into one action. |\n",
388
+ "raw": "---\ntitle: Usage\ndescription: Which size to use, how stroke, colour and alignment work next to text, when an icon needs a label, and the one icon for each common Beehexa action.\norder: 2\n---\nimport IconDemo from '../../../../components/IconDemo.astro';\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Use 16 px icons in the colour of the text, with a label, and the same icon for the same meaning everywhere.**\n\n## Sizes\n\n**Pick the size from the text next to the icon.**\n\n| Size | Use it for |\n|---|---|\n| 16 px | Default. Buttons, menus, tables, form fields, next to 14 px text. |\n| 20 px | Next to 16 px text, in toolbars and in the page header. |\n| 24 px | An icon on its own, such as a status in a card or a small empty state. |\n| 32 px | Empty states only. |\n\nDon’t use other sizes. Don’t scale an icon to fit a box: change the box.\n\n<IconDemo kind=\"dodont\" item=\"size\" />\n\n## Stroke\n\n**Keep Lucide’s stroke.** It is 2 units on the 24 grid and scales with the icon: 1.33 px at 16, 1.67 px at 20, 2 px at 24. Don’t set `stroke-width` or `absoluteStrokeWidth`. A fixed 2 px stroke fills in the small details of a 16 px icon.\n\n<IconDemo kind=\"dodont\" item=\"stroke\" />\n\n## Colour\n\n**An icon takes the colour of its text.** Icons draw with `currentColor`, so an icon in a button or a link is right without extra code. Set a colour only with a `color.icon.*` token:\n\n<ColorDemo kind=\"roles\" group=\"icon\" />\n\n- Status icons use the status token, such as `icon.danger`, and always sit next to the status in words.\n- Never give an icon a colour to decorate it, and never use the brand yellow for an icon.\n\n<IconDemo kind=\"dodont\" item=\"colour\" />\n\n## Alignment with text\n\n**Centre the icon on the line height of the text.** Use `display: flex; align-items: center`. Next to several lines, centre the icon on the first line.\n\n<IconDemo kind=\"align\" />\n\n<IconDemo kind=\"dodont\" item=\"align\" />\n\n## Spacing\n\n**The gap between an icon and its text follows the text size: 4 px next to 14 px text or smaller, 8 px next to 16 px text or larger.**\n\n| Text | Icon | Gap | Token | Where |\n|---|---|---|---|---|\n| 12 or 14 px | 16 px | 4 px | `space.050` | Small and default controls, menus, tabs, table cells |\n| 16 px or larger | 20 or 24 px | 8 px | `space.100` | Large controls, toolbars, the page header, a status in a card |\n\nSet the gap on the control with `gap`, not with a margin on the icon.\n\n<IconDemo kind=\"spacing\" />\n\n## Icon and label\n\n**Give an icon a label by default.** The label says what happens; the icon helps people find it again.\n\nUse an icon on its own only when all three are true:\n\n- The action is well known: close, search, add, edit, delete, copy, refresh, settings, filter, more, menu.\n- Space is tight, such as a table row or a toolbar.\n- The button has a name (`aria-label`) and a tooltip with the same words. See [Accessibility](/foundations/styles/icons/accessibility/).\n\n<IconDemo kind=\"dodont\" item=\"label\" />\n\n## Selected state\n\n**Lucide icons are outline only.** Show a selected item with `background.selected` and the indicator bar, not by filling the icon.\n\n<IconDemo kind=\"dodont\" item=\"selected\" />\n\n## Common actions\n\n**One icon per meaning.** Use this icon whenever you show one of these actions or objects, in every product. If a meaning is missing, ask before you choose one, so it is added here.\n\n<IconDemo kind=\"actions\" />\n\n<IconDemo kind=\"dodont\" item=\"meaning\" />\n\n## Do and don’t\n\n| Do | Don’t |\n|---|---|\n| Use 16, 20, 24 or 32 px. | Scale icons to other sizes. |\n| Keep the icon in the text colour. | Colour icons to decorate. |\n| Add a label to most icons. | Use an unfamiliar icon on its own. |\n| Use the same icon for the same meaning. | Use a different icon in each product. |\n| Use outline icons with a selected background. | Fill an icon to show it is selected. |\n| Write the status next to a status icon. | Let an icon or its colour carry the status alone. |\n| Use one icon per button. | Combine two icons into one action. |\n",
389
+ "frontmatter": {
390
+ "title": "Usage",
391
+ "description": "Which size to use, how stroke, colour and alignment work next to text, when an icon needs a label, and the one icon for each common Beehexa action.",
392
+ "order": 2
393
+ }
394
+ },
395
+ {
396
+ "id": "en/foundations/styles/illustration",
397
+ "path": "src/content/foundations/styles/illustration.mdx",
398
+ "documentPath": "docs/src/content/foundations/styles/illustration.mdx",
399
+ "locale": "en",
400
+ "kind": "guidance",
401
+ "title": "Illustration",
402
+ "status": "planned",
403
+ "releasePhase": null,
404
+ "planned": [
405
+ "When to use a diagram, an illustration or a screenshot",
406
+ "The diagram style from the brand guide: structured, built on the hexagon grid",
407
+ "Empty states and onboarding images"
408
+ ],
409
+ "body": "",
410
+ "raw": "---\ntitle: \"Illustration\"\ndescription: \"Diagrams, illustrations and images that explain Beehexa products.\"\norder: 14\nplanned:\n - \"When to use a diagram, an illustration or a screenshot\"\n - \"The diagram style from the brand guide: structured, built on the hexagon grid\"\n - \"Empty states and onboarding images\"\n---\n",
411
+ "frontmatter": {
412
+ "title": "Illustration",
413
+ "description": "Diagrams, illustrations and images that explain Beehexa products.",
414
+ "order": 14,
415
+ "planned": [
416
+ "When to use a diagram, an illustration or a screenshot",
417
+ "The diagram style from the brand guide: structured, built on the hexagon grid",
418
+ "Empty states and onboarding images"
419
+ ]
420
+ }
421
+ },
422
+ {
423
+ "id": "en/foundations/styles/interaction-states",
424
+ "path": "src/content/foundations/styles/interaction-states.mdx",
425
+ "documentPath": "docs/src/content/foundations/styles/interaction-states.mdx",
426
+ "locale": "en",
427
+ "kind": "guidance",
428
+ "title": "Interaction states",
429
+ "status": "active",
430
+ "releasePhase": null,
431
+ "planned": [],
432
+ "body": "import TokenTable from '../../../components/TokenTable.astro';\n\nEvery interactive element needs all of these states. Each state has its own colour token, so every component shows it the same way and it works in light and dark without extra code.\n\n## The rules\n\n1. Every state uses its own token. Find the token of the element at rest, then add the state: `color.background.neutral` at rest becomes `color.background.neutral.hover` on hover and `color.background.neutral.pressed` when pressed.\n2. Never draw a state with opacity, a transparent overlay, `filter: brightness()` or a mixed colour. The result changes with whatever is under the element, and its contrast can't be checked.\n3. Never invent a hover or pressed colour. If the token you need doesn't exist, ask for it to be added to the Color page first.\n4. Keyboard focus is always visible, on every element that can take focus. Hover is never the only way to show something.\n\n## Each state\n\n| State | When | Background | Text and icon | Border |\n| --- | --- | --- | --- | --- |\n| Rest | Nothing is happening. | The token for the element, such as `color.background.neutral` or `color.background.danger.bold` | The paired text token (see Color, Pairing) | `color.border` or `color.border.bold` |\n| Hover | A pointer is over the element. | The same token plus `.hover`: one step up the scale | Unchanged | Unchanged |\n| Pressed | The element is being clicked or tapped. | The same token plus `.pressed`: two steps up | Unchanged | Unchanged |\n\nThe primary button is the one exception. It rests on graphite 12, the last step, so it has no step above: on hover it moves one step back (graphite 11) and when pressed two steps back (graphite 10). Its tokens already do this.\n| Focus | The element has keyboard focus (`:focus-visible`). | Unchanged | Unchanged | Add a ring: `outline: var(--bh-border-width-focused) solid var(--bh-color-border-focus); outline-offset: var(--bh-state-focus-offset);` |\n| Selected | The element is chosen, like a table row, a tab or a menu item. | `color.background.selected`, and `color.background.selected.hover` on hover | Unchanged, and a second cue: a check, the yellow indicator bar (`color.border.selected`) or bold text in a menu | Unchanged |\n| Disabled | The element cannot be used now. | `color.background.disabled` | `color.text.disabled`, `color.icon.disabled` | `color.border.disabled` |\n\n## Rows, menu items and ghost buttons\n\nElements with no fill at rest use `color.background.neutral.subtle`, which is transparent. On hover they take `color.background.neutral.subtle.hover`; when pressed, `color.background.neutral.subtle.pressed`.\n\n## Disabled\n\n- Use the three disabled colour tokens above. Don't lower the opacity.\n- Remove the pointer and keyboard interaction (`disabled` on native controls, `aria-disabled=\"true\"` plus blocked events on others) and show `cursor: not-allowed`.\n- WCAG doesn't require contrast for disabled controls, so the disabled colours are light on purpose.\n- Prefer telling people why something can't be used, for example in helper text, over a silent disabled control.\n\n## Dark theme\n\nThe same tokens work in dark. In dark, fills get lighter on hover and when pressed instead of darker, and the primary button moves back from graphite 12 the same way; the tokens already do this, so the code doesn’t change.\n\n## Tokens\n\nThe colours are on the [Color](/foundations/styles/color/) page. The focus ring width, `border.width.focused`, is on the [Border](/foundations/styles/border/) page. This group holds the gap between a control and its ring.\n\n<TokenTable prefix=\"state\" />\n",
433
+ "raw": "---\ntitle: Interaction states\ndescription: How controls look when hovered, focused, pressed, selected or disabled.\norder: 10\n---\nimport TokenTable from '../../../components/TokenTable.astro';\n\nEvery interactive element needs all of these states. Each state has its own colour token, so every component shows it the same way and it works in light and dark without extra code.\n\n## The rules\n\n1. Every state uses its own token. Find the token of the element at rest, then add the state: `color.background.neutral` at rest becomes `color.background.neutral.hover` on hover and `color.background.neutral.pressed` when pressed.\n2. Never draw a state with opacity, a transparent overlay, `filter: brightness()` or a mixed colour. The result changes with whatever is under the element, and its contrast can't be checked.\n3. Never invent a hover or pressed colour. If the token you need doesn't exist, ask for it to be added to the Color page first.\n4. Keyboard focus is always visible, on every element that can take focus. Hover is never the only way to show something.\n\n## Each state\n\n| State | When | Background | Text and icon | Border |\n| --- | --- | --- | --- | --- |\n| Rest | Nothing is happening. | The token for the element, such as `color.background.neutral` or `color.background.danger.bold` | The paired text token (see Color, Pairing) | `color.border` or `color.border.bold` |\n| Hover | A pointer is over the element. | The same token plus `.hover`: one step up the scale | Unchanged | Unchanged |\n| Pressed | The element is being clicked or tapped. | The same token plus `.pressed`: two steps up | Unchanged | Unchanged |\n\nThe primary button is the one exception. It rests on graphite 12, the last step, so it has no step above: on hover it moves one step back (graphite 11) and when pressed two steps back (graphite 10). Its tokens already do this.\n| Focus | The element has keyboard focus (`:focus-visible`). | Unchanged | Unchanged | Add a ring: `outline: var(--bh-border-width-focused) solid var(--bh-color-border-focus); outline-offset: var(--bh-state-focus-offset);` |\n| Selected | The element is chosen, like a table row, a tab or a menu item. | `color.background.selected`, and `color.background.selected.hover` on hover | Unchanged, and a second cue: a check, the yellow indicator bar (`color.border.selected`) or bold text in a menu | Unchanged |\n| Disabled | The element cannot be used now. | `color.background.disabled` | `color.text.disabled`, `color.icon.disabled` | `color.border.disabled` |\n\n## Rows, menu items and ghost buttons\n\nElements with no fill at rest use `color.background.neutral.subtle`, which is transparent. On hover they take `color.background.neutral.subtle.hover`; when pressed, `color.background.neutral.subtle.pressed`.\n\n## Disabled\n\n- Use the three disabled colour tokens above. Don't lower the opacity.\n- Remove the pointer and keyboard interaction (`disabled` on native controls, `aria-disabled=\"true\"` plus blocked events on others) and show `cursor: not-allowed`.\n- WCAG doesn't require contrast for disabled controls, so the disabled colours are light on purpose.\n- Prefer telling people why something can't be used, for example in helper text, over a silent disabled control.\n\n## Dark theme\n\nThe same tokens work in dark. In dark, fills get lighter on hover and when pressed instead of darker, and the primary button moves back from graphite 12 the same way; the tokens already do this, so the code doesn’t change.\n\n## Tokens\n\nThe colours are on the [Color](/foundations/styles/color/) page. The focus ring width, `border.width.focused`, is on the [Border](/foundations/styles/border/) page. This group holds the gap between a control and its ring.\n\n<TokenTable prefix=\"state\" />\n",
434
+ "frontmatter": {
435
+ "title": "Interaction states",
436
+ "description": "How controls look when hovered, focused, pressed, selected or disabled.",
437
+ "order": 10
438
+ }
439
+ },
440
+ {
441
+ "id": "en/foundations/styles/layout/app-frame",
442
+ "path": "src/content/foundations/styles/layout/app-frame.mdx",
443
+ "documentPath": "docs/src/content/foundations/styles/layout/app-frame.mdx",
444
+ "locale": "en",
445
+ "kind": "guidance",
446
+ "title": "App frame",
447
+ "status": "active",
448
+ "releasePhase": null,
449
+ "planned": [],
450
+ "body": "import LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**The header, the side navigation and the page header repeat on every page, in the same place and at the same size.**\n\n## Header\n\n**48 px high, across the full width. It holds what belongs to the whole product.**\n\n| Part | Value |\n|---|---|\n| Height | 48 px: a 32 px control with 8 px above and below. The 1 px line under the header is not counted |\n| Holds | Menu button (below 1024 px), logo, global search, workspace switcher, notifications, account |\n| Does not hold | The breadcrumb and page actions. They change with the page, so they go in the page header |\n\nUse the package token `layout.header.height` (`--bh-layout-header-height`) for this dimension.\nThe sidebar widths below are `layout.sidebar.expanded` and `layout.sidebar.collapsed`.\nConvert source units at numeric framework API boundaries instead of copying their values.\n\n## Side navigation\n\n**280 px open, a 64 px rail when collapsed, a drawer below 1024 px. Every Beehexa product uses the same widths.**\n\n| Window | Side navigation |\n|---|---|\n| Below 1024 px | Hidden. The menu button in the header opens it as a drawer over the page. |\n| 1024 px and up | Open at 280 px. People can collapse it to the 64 px rail, and the choice is remembered. |\n\n- **280 px** fits a label of about 31 characters at 14 px, long Vietnamese labels included.\n- **The same width in every product**, so the page starts in the same place when people move between products.\n- **No resizing.** One width keeps products alike. A resizable panel would also need a way to resize it without dragging (WCAG 2.5.7).\n- **The rail** shows icons only. Each label appears in a tooltip.\n\n### Long labels\n\n<LayoutDemo kind=\"navlabels\" />\n\n1. Write a shorter label first.\n2. If it still does not fit, cut it with an ellipsis and show the full label in a tooltip, only when it is cut.\n3. Never widen the side navigation for one label. A product whose labels are long everywhere may set one width between 240 and 320 px for the whole product, and writes it down.\n\n## Page header\n\n**The top of every page: breadcrumb, title, status and page actions.**\n\n<LayoutDemo kind=\"pageheader\" />\n\n| Row | Holds | When |\n|---|---|---|\n| Breadcrumb | The pages above this one | Below the top level |\n| Title row | The page title (`heading.large`) and a status on the left; page actions on the right, the main action last | Always |\n| Description | One line about the page | Optional |\n| Tabs or filters | Views of the same page | Optional |\n\n- **The page header spans the whole content area at every page width.** Only the content below it follows [Full, Wide or Narrow](/foundations/styles/layout/page-widths/), so the title and the page actions stay in the same place on every page.\n- The breadcrumb belongs to the page, not to the header: it changes on every page, and the header stays the same.\n- Context for the whole product, such as the workspace, goes in the header.\n\n## Side panel\n\nA panel beside the main content, such as details of a selected row, takes grid columns: 4 of 12 from 1024 px and 3 of 12 from 1440 px. Below 1024 px it opens as a drawer over the page. See the spans on [Grid](/foundations/styles/layout/grid/#spans).\n\n## Spacing of the frame\n\n**Everything in the frame lines up on two edges: 20 px from the window on the left, and the page margin.**\n\n| Between | Space |\n|---|---|\n| The window edge and the logo; the window edge and the side navigation icons | 20 px, `space.250` |\n| The side navigation items and its edges | 8 px, `space.100` |\n| One side navigation item and the next (each 32 px high) | 4 px, `space.050` |\n| The content and the side navigation, the header or the window edge | The page margin: 16, 24 or 32 px ([Grid](/foundations/styles/layout/grid/)) |\n| The breadcrumb and the title | 8 px, `space.100` |\n| The title and the description | 4 px, `space.050` |\n| The page header and the content | 24 px, `space.300` |\n\nA 20 px edge for the logo comes from the side navigation: 8 px of inset plus the 12 px side padding of a 32 px control. The logo then sits right above the icons.\n",
451
+ "raw": "---\ntitle: App frame\ndescription: The header, side navigation and page header that repeat on every page, their sizes, and the spacing that lines them up.\norder: 1\n---\nimport LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**The header, the side navigation and the page header repeat on every page, in the same place and at the same size.**\n\n## Header\n\n**48 px high, across the full width. It holds what belongs to the whole product.**\n\n| Part | Value |\n|---|---|\n| Height | 48 px: a 32 px control with 8 px above and below. The 1 px line under the header is not counted |\n| Holds | Menu button (below 1024 px), logo, global search, workspace switcher, notifications, account |\n| Does not hold | The breadcrumb and page actions. They change with the page, so they go in the page header |\n\nUse the package token `layout.header.height` (`--bh-layout-header-height`) for this dimension.\nThe sidebar widths below are `layout.sidebar.expanded` and `layout.sidebar.collapsed`.\nConvert source units at numeric framework API boundaries instead of copying their values.\n\n## Side navigation\n\n**280 px open, a 64 px rail when collapsed, a drawer below 1024 px. Every Beehexa product uses the same widths.**\n\n| Window | Side navigation |\n|---|---|\n| Below 1024 px | Hidden. The menu button in the header opens it as a drawer over the page. |\n| 1024 px and up | Open at 280 px. People can collapse it to the 64 px rail, and the choice is remembered. |\n\n- **280 px** fits a label of about 31 characters at 14 px, long Vietnamese labels included.\n- **The same width in every product**, so the page starts in the same place when people move between products.\n- **No resizing.** One width keeps products alike. A resizable panel would also need a way to resize it without dragging (WCAG 2.5.7).\n- **The rail** shows icons only. Each label appears in a tooltip.\n\n### Long labels\n\n<LayoutDemo kind=\"navlabels\" />\n\n1. Write a shorter label first.\n2. If it still does not fit, cut it with an ellipsis and show the full label in a tooltip, only when it is cut.\n3. Never widen the side navigation for one label. A product whose labels are long everywhere may set one width between 240 and 320 px for the whole product, and writes it down.\n\n## Page header\n\n**The top of every page: breadcrumb, title, status and page actions.**\n\n<LayoutDemo kind=\"pageheader\" />\n\n| Row | Holds | When |\n|---|---|---|\n| Breadcrumb | The pages above this one | Below the top level |\n| Title row | The page title (`heading.large`) and a status on the left; page actions on the right, the main action last | Always |\n| Description | One line about the page | Optional |\n| Tabs or filters | Views of the same page | Optional |\n\n- **The page header spans the whole content area at every page width.** Only the content below it follows [Full, Wide or Narrow](/foundations/styles/layout/page-widths/), so the title and the page actions stay in the same place on every page.\n- The breadcrumb belongs to the page, not to the header: it changes on every page, and the header stays the same.\n- Context for the whole product, such as the workspace, goes in the header.\n\n## Side panel\n\nA panel beside the main content, such as details of a selected row, takes grid columns: 4 of 12 from 1024 px and 3 of 12 from 1440 px. Below 1024 px it opens as a drawer over the page. See the spans on [Grid](/foundations/styles/layout/grid/#spans).\n\n## Spacing of the frame\n\n**Everything in the frame lines up on two edges: 20 px from the window on the left, and the page margin.**\n\n| Between | Space |\n|---|---|\n| The window edge and the logo; the window edge and the side navigation icons | 20 px, `space.250` |\n| The side navigation items and its edges | 8 px, `space.100` |\n| One side navigation item and the next (each 32 px high) | 4 px, `space.050` |\n| The content and the side navigation, the header or the window edge | The page margin: 16, 24 or 32 px ([Grid](/foundations/styles/layout/grid/)) |\n| The breadcrumb and the title | 8 px, `space.100` |\n| The title and the description | 4 px, `space.050` |\n| The page header and the content | 24 px, `space.300` |\n\nA 20 px edge for the logo comes from the side navigation: 8 px of inset plus the 12 px side padding of a 32 px control. The logo then sits right above the icons.\n",
452
+ "frontmatter": {
453
+ "title": "App frame",
454
+ "description": "The header, side navigation and page header that repeat on every page, their sizes, and the spacing that lines them up.",
455
+ "order": 1
456
+ }
457
+ },
458
+ {
459
+ "id": "en/foundations/styles/layout/breakpoints",
460
+ "path": "src/content/foundations/styles/layout/breakpoints.mdx",
461
+ "documentPath": "docs/src/content/foundations/styles/layout/breakpoints.mdx",
462
+ "locale": "en",
463
+ "kind": "guidance",
464
+ "title": "Breakpoints",
465
+ "status": "active",
466
+ "releasePhase": null,
467
+ "planned": [],
468
+ "body": "import LayoutDemo from '../../../../components/LayoutDemo.astro';\nimport TokenTable from '../../../../components/TokenTable.astro';\n\n**The layout changes at three window widths: 768, 1024 and 1440 px. Every screen must also work at 320 px.**\n\n<LayoutDemo kind=\"breakpoints\" />\n\n## What changes\n\n| Breakpoint | From | Windows | What changes |\n|---|---|---|---|\n| `xs` | 0 | Phones and small windows | One fluid layout: 4 columns, gutter and page margin 16 px, content in one column. Side navigation in a drawer. |\n| `md` | 768 px | Tablets, narrow windows | 8 columns. Gutter and page margin 24 px. Side navigation still in a drawer. |\n| `lg` | 1024 px | Laptops, including 1280 and 1366 px screens | 12 columns. Side navigation open at 280 px, or collapsed to the 64 px rail. A side panel next to the main one. |\n| `xl` | 1440 px | Desktops, including 1536 and 1920 px screens | Page margin 32 px. Four cards a row. |\n\n- **Below 768 px is one layout.** Its columns stretch with the window, from 320 to 767 px. A card or a table inside it can still change with the width of its own container, using container queries.\n- **320 px is not a breakpoint.** It is the narrowest window every screen must work in, which is also a 1280 px window zoomed to 400% (WCAG 1.4.10).\n\n## Design order\n\n**Design for desktop first, then fit the screen to smaller windows. Write the CSS from the smallest window up.**\n\nBeehexa products are used mostly on desktop, so their main screens start at the width people use most.\n\n1. Design at 1440 px, and check it at 1280 px.\n2. Fit it to 1024 px, then to 768 px.\n3. Fit it to 360 px, and check it at 320 px.\n\nIn code, the base styles are for the smallest window, and each breakpoint adds to them with `min-width`. Fewer rules have to be undone that way.\n\n## Check every screen at\n\n| Window | Why |\n|---|---|\n| 1440 and 1280 px | The desktops and laptops people use most |\n| 1024 px | Just above the point where the side navigation becomes a drawer |\n| 768 px | Tablets, and the switch to 8 columns |\n| About 844 × 390 px | A phone held sideways: wide enough for the tablet layout, but short |\n| 360 and 320 px | Phones, and the narrowest window allowed |\n| 400% zoom | People who enlarge the page |\n\n## Tokens\n\n<TokenTable prefix=\"breakpoint\" />\n\n## Usage\n\n- Write media queries with `min-width`: `@media (min-width: 768px)`.\n- CSS custom properties cannot be used in media queries. Use the pixel values of these tokens.\n- Change the layout at breakpoints, never the spacing tokens or text sizes inside a component.\n",
469
+ "raw": "---\ntitle: Breakpoints\ndescription: The four window widths where Beehexa layouts change, what changes at each, and the order to design in.\norder: 4\n---\nimport LayoutDemo from '../../../../components/LayoutDemo.astro';\nimport TokenTable from '../../../../components/TokenTable.astro';\n\n**The layout changes at three window widths: 768, 1024 and 1440 px. Every screen must also work at 320 px.**\n\n<LayoutDemo kind=\"breakpoints\" />\n\n## What changes\n\n| Breakpoint | From | Windows | What changes |\n|---|---|---|---|\n| `xs` | 0 | Phones and small windows | One fluid layout: 4 columns, gutter and page margin 16 px, content in one column. Side navigation in a drawer. |\n| `md` | 768 px | Tablets, narrow windows | 8 columns. Gutter and page margin 24 px. Side navigation still in a drawer. |\n| `lg` | 1024 px | Laptops, including 1280 and 1366 px screens | 12 columns. Side navigation open at 280 px, or collapsed to the 64 px rail. A side panel next to the main one. |\n| `xl` | 1440 px | Desktops, including 1536 and 1920 px screens | Page margin 32 px. Four cards a row. |\n\n- **Below 768 px is one layout.** Its columns stretch with the window, from 320 to 767 px. A card or a table inside it can still change with the width of its own container, using container queries.\n- **320 px is not a breakpoint.** It is the narrowest window every screen must work in, which is also a 1280 px window zoomed to 400% (WCAG 1.4.10).\n\n## Design order\n\n**Design for desktop first, then fit the screen to smaller windows. Write the CSS from the smallest window up.**\n\nBeehexa products are used mostly on desktop, so their main screens start at the width people use most.\n\n1. Design at 1440 px, and check it at 1280 px.\n2. Fit it to 1024 px, then to 768 px.\n3. Fit it to 360 px, and check it at 320 px.\n\nIn code, the base styles are for the smallest window, and each breakpoint adds to them with `min-width`. Fewer rules have to be undone that way.\n\n## Check every screen at\n\n| Window | Why |\n|---|---|\n| 1440 and 1280 px | The desktops and laptops people use most |\n| 1024 px | Just above the point where the side navigation becomes a drawer |\n| 768 px | Tablets, and the switch to 8 columns |\n| About 844 × 390 px | A phone held sideways: wide enough for the tablet layout, but short |\n| 360 and 320 px | Phones, and the narrowest window allowed |\n| 400% zoom | People who enlarge the page |\n\n## Tokens\n\n<TokenTable prefix=\"breakpoint\" />\n\n## Usage\n\n- Write media queries with `min-width`: `@media (min-width: 768px)`.\n- CSS custom properties cannot be used in media queries. Use the pixel values of these tokens.\n- Change the layout at breakpoints, never the spacing tokens or text sizes inside a component.\n",
470
+ "frontmatter": {
471
+ "title": "Breakpoints",
472
+ "description": "The four window widths where Beehexa layouts change, what changes at each, and the order to design in.",
473
+ "order": 4
474
+ }
475
+ },
476
+ {
477
+ "id": "en/foundations/styles/layout/grid",
478
+ "path": "src/content/foundations/styles/layout/grid.mdx",
479
+ "documentPath": "docs/src/content/foundations/styles/layout/grid.mdx",
480
+ "locale": "en",
481
+ "kind": "guidance",
482
+ "title": "Grid",
483
+ "status": "active",
484
+ "releasePhase": null,
485
+ "planned": [],
486
+ "body": "import LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Lay out the main content area on 4 columns on phones, 8 on tablets and 12 from 1024 px.**\n\n<LayoutDemo kind=\"grid\" />\n\n## Columns, gutters and margins\n\n| Window | Columns | Gutter | Page margin |\n|---|---|---|---|\n| Below 768 px | 4 | 16 px | 16 px |\n| 768 to 1023 px | 8 | 24 px | 24 px |\n| 1024 to 1439 px | 12 | 24 px | 24 px |\n| 1440 px and up | 12 | 24 px | 32 px |\n\nThe values are spacing tokens: 16 px is `space.200`, 24 px is `space.300` and 32 px is `space.400`. The ranges start at the `md`, `lg` and `xl` breakpoints.\n\n- **12 columns** divide into halves, thirds, quarters and sixths.\n- **4 columns on phones** give two halves or four quarters. **8 on tablets** keep the same halves and quarters with more room.\n- **Gutters** are 16 px on phones and 24 px from 768 px, where there is room to separate cards more clearly.\n- **Page margins** start at 16 px and grow to 32 px on wide screens, so content does not touch the edge of a large window.\n- **Every value is a spacing token and a multiple of 8 px**, like the text line heights, so cards, text and controls line up.\n\nUse the same gutter between rows, so cards are as far apart down as across.\n\n## Fluid columns\n\n**Columns stretch with the window. Gutters and margins stay fixed within each range.**\n\nA wider window gives wider columns, not more empty space. At the next breakpoint the gutter, the margin or the number of columns changes.\n\n## Where the grid sits\n\n**The grid spans the main content area only.**\n\n- The header and the side navigation are not on the grid. The grid starts where the side navigation ends, so its columns always divide the content area.\n- The side navigation keeps a fixed width instead of taking columns. As columns, it would grow and shrink with the window, and collapsing it to the rail would break the column count.\n- Breakpoints still read the window width. Opening or collapsing the side navigation does not change the breakpoint.\n- Content inside a panel or a card can follow the width of its container instead, with container queries.\n- On a wide or narrow page, the grid fills the capped width. See [Page widths](/foundations/styles/layout/page-widths/).\n\n## Spans\n\nA span is the number of columns an item covers.\n\n| Layout | Below 768 px (of 4) | 768 px (of 8) | 1024 px (of 12) | 1440 px (of 12) |\n|---|---|---|---|---|\n| Cards, 1 to 4 a row | 4 | 4 | 4 | 3 |\n| Main panel and side panel | 4 | 8 | 8 + 4 | 9 + 3 |\n| Summary tiles | 2 | 2 | 3 | 2 |\n\nIn CSS, the grid is a few lines:\n\n```css\n.page-grid {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: var(--bh-space-200);\n padding-inline: var(--bh-space-200);\n}\n@media (min-width: 768px) {\n .page-grid {\n grid-template-columns: repeat(8, minmax(0, 1fr));\n gap: var(--bh-space-300);\n padding-inline: var(--bh-space-300);\n }\n}\n@media (min-width: 1024px) {\n .page-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }\n}\n@media (min-width: 1440px) {\n .page-grid { padding-inline: var(--bh-space-400); }\n}\n```\n\n## What goes on the grid\n\n- Page regions align to columns: cards, panels, form columns, tiles.\n- Controls inside a region do not. Inside a card, use spacing tokens.\n- A data table fills its region. Do not split table columns along the grid.\n\nSee [Breakpoints](/foundations/styles/layout/breakpoints/) for when the grid changes.\n",
487
+ "raw": "---\ntitle: Grid\ndescription: A fluid grid of 4, 8 or 12 columns in the main content area, with gutters and page margins from the spacing tokens.\norder: 3\n---\nimport LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Lay out the main content area on 4 columns on phones, 8 on tablets and 12 from 1024 px.**\n\n<LayoutDemo kind=\"grid\" />\n\n## Columns, gutters and margins\n\n| Window | Columns | Gutter | Page margin |\n|---|---|---|---|\n| Below 768 px | 4 | 16 px | 16 px |\n| 768 to 1023 px | 8 | 24 px | 24 px |\n| 1024 to 1439 px | 12 | 24 px | 24 px |\n| 1440 px and up | 12 | 24 px | 32 px |\n\nThe values are spacing tokens: 16 px is `space.200`, 24 px is `space.300` and 32 px is `space.400`. The ranges start at the `md`, `lg` and `xl` breakpoints.\n\n- **12 columns** divide into halves, thirds, quarters and sixths.\n- **4 columns on phones** give two halves or four quarters. **8 on tablets** keep the same halves and quarters with more room.\n- **Gutters** are 16 px on phones and 24 px from 768 px, where there is room to separate cards more clearly.\n- **Page margins** start at 16 px and grow to 32 px on wide screens, so content does not touch the edge of a large window.\n- **Every value is a spacing token and a multiple of 8 px**, like the text line heights, so cards, text and controls line up.\n\nUse the same gutter between rows, so cards are as far apart down as across.\n\n## Fluid columns\n\n**Columns stretch with the window. Gutters and margins stay fixed within each range.**\n\nA wider window gives wider columns, not more empty space. At the next breakpoint the gutter, the margin or the number of columns changes.\n\n## Where the grid sits\n\n**The grid spans the main content area only.**\n\n- The header and the side navigation are not on the grid. The grid starts where the side navigation ends, so its columns always divide the content area.\n- The side navigation keeps a fixed width instead of taking columns. As columns, it would grow and shrink with the window, and collapsing it to the rail would break the column count.\n- Breakpoints still read the window width. Opening or collapsing the side navigation does not change the breakpoint.\n- Content inside a panel or a card can follow the width of its container instead, with container queries.\n- On a wide or narrow page, the grid fills the capped width. See [Page widths](/foundations/styles/layout/page-widths/).\n\n## Spans\n\nA span is the number of columns an item covers.\n\n| Layout | Below 768 px (of 4) | 768 px (of 8) | 1024 px (of 12) | 1440 px (of 12) |\n|---|---|---|---|---|\n| Cards, 1 to 4 a row | 4 | 4 | 4 | 3 |\n| Main panel and side panel | 4 | 8 | 8 + 4 | 9 + 3 |\n| Summary tiles | 2 | 2 | 3 | 2 |\n\nIn CSS, the grid is a few lines:\n\n```css\n.page-grid {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: var(--bh-space-200);\n padding-inline: var(--bh-space-200);\n}\n@media (min-width: 768px) {\n .page-grid {\n grid-template-columns: repeat(8, minmax(0, 1fr));\n gap: var(--bh-space-300);\n padding-inline: var(--bh-space-300);\n }\n}\n@media (min-width: 1024px) {\n .page-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }\n}\n@media (min-width: 1440px) {\n .page-grid { padding-inline: var(--bh-space-400); }\n}\n```\n\n## What goes on the grid\n\n- Page regions align to columns: cards, panels, form columns, tiles.\n- Controls inside a region do not. Inside a card, use spacing tokens.\n- A data table fills its region. Do not split table columns along the grid.\n\nSee [Breakpoints](/foundations/styles/layout/breakpoints/) for when the grid changes.\n",
488
+ "frontmatter": {
489
+ "title": "Grid",
490
+ "description": "A fluid grid of 4, 8 or 12 columns in the main content area, with gutters and page margins from the spacing tokens.",
491
+ "order": 3
492
+ }
493
+ },
494
+ {
495
+ "id": "en/foundations/styles/layout/index",
496
+ "path": "src/content/foundations/styles/layout/index.mdx",
497
+ "documentPath": "docs/src/content/foundations/styles/layout/index.mdx",
498
+ "locale": "en",
499
+ "kind": "guidance",
500
+ "title": "Layout",
501
+ "status": "active",
502
+ "releasePhase": null,
503
+ "planned": [],
504
+ "body": "import LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Every Beehexa app uses one frame: a header across the top, side navigation on the left, and the page beside it.**\n\nPeople move between screens all day. When the menu, the search and the page actions stay in the same place, they find them without looking.\n\n<LayoutDemo kind=\"anatomy\" />\n\n## Where each part is set\n\n| Part | What it sets | Page |\n|---|---|---|\n| Header, side navigation, page header | The parts that repeat on every page, their sizes and the spacing between them | [App frame](/foundations/styles/layout/app-frame/) |\n| Content width | Full, wide or narrow, by what the page holds | [Page widths](/foundations/styles/layout/page-widths/) |\n| Columns | Columns, gutters and page margins inside the content area | [Grid](/foundations/styles/layout/grid/) |\n| Window widths | Where the layout changes, and the order to design in | [Breakpoints](/foundations/styles/layout/breakpoints/) |\n| Control heights | 24, 32 and 40 px, and density | [Size and density](/foundations/styles/size-and-density/) |\n| Space between things | The spacing steps | [Spacing](/foundations/styles/spacing/) |\n",
505
+ "raw": "---\ntitle: Layout\ndescription: The frame every Beehexa app shares (header, side navigation, page header and content) and the pages that set its sizes.\norder: 4\nsidebarLabel: Overview\n---\nimport LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Every Beehexa app uses one frame: a header across the top, side navigation on the left, and the page beside it.**\n\nPeople move between screens all day. When the menu, the search and the page actions stay in the same place, they find them without looking.\n\n<LayoutDemo kind=\"anatomy\" />\n\n## Where each part is set\n\n| Part | What it sets | Page |\n|---|---|---|\n| Header, side navigation, page header | The parts that repeat on every page, their sizes and the spacing between them | [App frame](/foundations/styles/layout/app-frame/) |\n| Content width | Full, wide or narrow, by what the page holds | [Page widths](/foundations/styles/layout/page-widths/) |\n| Columns | Columns, gutters and page margins inside the content area | [Grid](/foundations/styles/layout/grid/) |\n| Window widths | Where the layout changes, and the order to design in | [Breakpoints](/foundations/styles/layout/breakpoints/) |\n| Control heights | 24, 32 and 40 px, and density | [Size and density](/foundations/styles/size-and-density/) |\n| Space between things | The spacing steps | [Spacing](/foundations/styles/spacing/) |\n",
506
+ "frontmatter": {
507
+ "title": "Layout",
508
+ "description": "The frame every Beehexa app shares (header, side navigation, page header and content) and the pages that set its sizes.",
509
+ "order": 4,
510
+ "sidebarLabel": "Overview"
511
+ }
512
+ },
513
+ {
514
+ "id": "en/foundations/styles/layout/overlays",
515
+ "path": "src/content/foundations/styles/layout/overlays.mdx",
516
+ "documentPath": "docs/src/content/foundations/styles/layout/overlays.mdx",
517
+ "locale": "en",
518
+ "kind": "guidance",
519
+ "title": "Data-inspection overlays",
520
+ "status": "active",
521
+ "releasePhase": null,
522
+ "planned": [],
523
+ "body": "\n## Choose by task, not by existing component width\n\nUse a data-inspection overlay when people need record details, structured evidence or related\nconfiguration while retaining the page context. A short confirmation dialog is not a data-inspection\noverlay and does not inherit this width contract. Prefer the component's standard content sizing\nfor short confirmation/action prompts; do not enlarge it just because a data panel uses a wide role.\n\n## Width roles\n\n| Role | Token | When |\n| --- | --- | --- |\n| Default inspection | `layout.overlay.default` | From `breakpoint.lg`: `max(50vw, 900px)` |\n| Wide inspection | `layout.overlay.wide` | Explicit content-heavy variant from `breakpoint.lg`: `70vw` |\n| Mobile inspection | `layout.overlay.mobile` | Below `breakpoint.lg`: `100vw` |\n\nThe wide variant is chosen per content/task; it is not a global override for every drawer.\nAt the responsive boundary, switch to the mobile role rather than letting the desktop minimum\nforce outer-page overflow. Keep the title, close/back control, primary action, error/recovery\nfeedback and important content reachable. Long tables/code may scroll inside their own region;\nordinary text and form labels reflow. Width alone does not prove usable height, keyboard behavior,\nfocus containment/return, accessible naming or sticky-action visibility.\n\nStructured desktop descriptions may use `layout.description.minimum` as their nominal minimum\ncolumn width. When the available inline budget is smaller, stack label/value content; the minimum\nmust not force horizontal document overflow. This is a description layout role, not a general field,\nmodal or page-width token.\n\n## Apply through package exports\n\nUse `--bh-layout-overlay-*` CSS variables in styles, or resolved `tokens.light['layout.overlay.default']`\nwhen an overlay API expects a CSS length string. Numeric app-frame/page APIs convert source\n`rem` dimensions at their framework boundary. Do not copy these values into a consumer token file.\nThe explicit pixel CSS package variant preserves nominal sizes during root-unit migration, not\nan exception from font scaling or responsive behavior.\n\nHeader/sidebar and page-cap roles are also source tokens: `layout.header.height`,\n`layout.sidebar.expanded`, `layout.sidebar.collapsed`, `layout.page.narrow`, `layout.page.wide`\nand `layout.page.margin.*`. Their detailed semantics remain in [App frame](/foundations/styles/layout/app-frame/)\nand [Page widths](/foundations/styles/layout/page-widths/). Do not use a page cap as a viewport breakpoint.\n",
524
+ "raw": "---\ntitle: Data-inspection overlays\ndescription: Token-backed sizing and responsive behavior for structured data-inspection drawers and panels.\norder: 5\n---\n\n## Choose by task, not by existing component width\n\nUse a data-inspection overlay when people need record details, structured evidence or related\nconfiguration while retaining the page context. A short confirmation dialog is not a data-inspection\noverlay and does not inherit this width contract. Prefer the component's standard content sizing\nfor short confirmation/action prompts; do not enlarge it just because a data panel uses a wide role.\n\n## Width roles\n\n| Role | Token | When |\n| --- | --- | --- |\n| Default inspection | `layout.overlay.default` | From `breakpoint.lg`: `max(50vw, 900px)` |\n| Wide inspection | `layout.overlay.wide` | Explicit content-heavy variant from `breakpoint.lg`: `70vw` |\n| Mobile inspection | `layout.overlay.mobile` | Below `breakpoint.lg`: `100vw` |\n\nThe wide variant is chosen per content/task; it is not a global override for every drawer.\nAt the responsive boundary, switch to the mobile role rather than letting the desktop minimum\nforce outer-page overflow. Keep the title, close/back control, primary action, error/recovery\nfeedback and important content reachable. Long tables/code may scroll inside their own region;\nordinary text and form labels reflow. Width alone does not prove usable height, keyboard behavior,\nfocus containment/return, accessible naming or sticky-action visibility.\n\nStructured desktop descriptions may use `layout.description.minimum` as their nominal minimum\ncolumn width. When the available inline budget is smaller, stack label/value content; the minimum\nmust not force horizontal document overflow. This is a description layout role, not a general field,\nmodal or page-width token.\n\n## Apply through package exports\n\nUse `--bh-layout-overlay-*` CSS variables in styles, or resolved `tokens.light['layout.overlay.default']`\nwhen an overlay API expects a CSS length string. Numeric app-frame/page APIs convert source\n`rem` dimensions at their framework boundary. Do not copy these values into a consumer token file.\nThe explicit pixel CSS package variant preserves nominal sizes during root-unit migration, not\nan exception from font scaling or responsive behavior.\n\nHeader/sidebar and page-cap roles are also source tokens: `layout.header.height`,\n`layout.sidebar.expanded`, `layout.sidebar.collapsed`, `layout.page.narrow`, `layout.page.wide`\nand `layout.page.margin.*`. Their detailed semantics remain in [App frame](/foundations/styles/layout/app-frame/)\nand [Page widths](/foundations/styles/layout/page-widths/). Do not use a page cap as a viewport breakpoint.\n",
525
+ "frontmatter": {
526
+ "title": "Data-inspection overlays",
527
+ "description": "Token-backed sizing and responsive behavior for structured data-inspection drawers and panels.",
528
+ "order": 5
529
+ }
530
+ },
531
+ {
532
+ "id": "en/foundations/styles/layout/page-widths",
533
+ "path": "src/content/foundations/styles/layout/page-widths.mdx",
534
+ "documentPath": "docs/src/content/foundations/styles/layout/page-widths.mdx",
535
+ "locale": "en",
536
+ "kind": "guidance",
537
+ "title": "Page widths",
538
+ "status": "active",
539
+ "releasePhase": null,
540
+ "planned": [],
541
+ "body": "import LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Pick one of three widths for each page, by what the page holds.**\n\n<LayoutDemo kind=\"widths\" />\n\n| Width | Maximum | For |\n|---|---|---|\n| Full | None | Tables, lists, logs, builders and canvases |\n| Wide | 1280 px | Dashboards, detail pages, settings overviews, standard pages |\n| Narrow | 768 px | Forms, settings forms, wizard steps, help and documentation pages |\n\nWide and Narrow use package tokens `layout.page.wide` and `layout.page.narrow`.\nThe responsive margins use `layout.page.margin.small`, `.medium` and `.large`.\nFull has no maximum-width cap; do not replace it with an arbitrarily large numeric token.\n\n- **Full.** Tables and logs show more columns and rows when they use the whole window.\n- **Wide.** Cards and panels stay at a size people can scan on a large monitor.\n- **Narrow.** A form in one column is quick to fill in, and the eye does not travel far from label to field.\n- The maximum is the width of the content. The page margins are outside it.\n- The width applies to the content only. The [page header](/foundations/styles/layout/app-frame/#page-header) above it always spans the whole content area, so the title and the page actions do not move from page to page.\n\n## Alignment\n\n**Centre wide or narrow content in the area beside the side navigation. The page header stays across the full area.**\n\nWhen the side navigation opens or closes, the page moves to the new centre.\n\n## Running text\n\n**Text runs the full width of its column. To keep lines short enough to read, put long text on a Narrow page.**\n\nA Narrow column of 768 px holds about 100 characters a line of 16 px text. A help or documentation page is a Narrow page; a table of contents beside it is not part of the 768 px.\n",
542
+ "raw": "---\ntitle: Page widths\ndescription: Full, wide or narrow content, picked by what the page holds, and the length of a line of text.\norder: 2\n---\nimport LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Pick one of three widths for each page, by what the page holds.**\n\n<LayoutDemo kind=\"widths\" />\n\n| Width | Maximum | For |\n|---|---|---|\n| Full | None | Tables, lists, logs, builders and canvases |\n| Wide | 1280 px | Dashboards, detail pages, settings overviews, standard pages |\n| Narrow | 768 px | Forms, settings forms, wizard steps, help and documentation pages |\n\nWide and Narrow use package tokens `layout.page.wide` and `layout.page.narrow`.\nThe responsive margins use `layout.page.margin.small`, `.medium` and `.large`.\nFull has no maximum-width cap; do not replace it with an arbitrarily large numeric token.\n\n- **Full.** Tables and logs show more columns and rows when they use the whole window.\n- **Wide.** Cards and panels stay at a size people can scan on a large monitor.\n- **Narrow.** A form in one column is quick to fill in, and the eye does not travel far from label to field.\n- The maximum is the width of the content. The page margins are outside it.\n- The width applies to the content only. The [page header](/foundations/styles/layout/app-frame/#page-header) above it always spans the whole content area, so the title and the page actions do not move from page to page.\n\n## Alignment\n\n**Centre wide or narrow content in the area beside the side navigation. The page header stays across the full area.**\n\nWhen the side navigation opens or closes, the page moves to the new centre.\n\n## Running text\n\n**Text runs the full width of its column. To keep lines short enough to read, put long text on a Narrow page.**\n\nA Narrow column of 768 px holds about 100 characters a line of 16 px text. A help or documentation page is a Narrow page; a table of contents beside it is not part of the 768 px.\n",
543
+ "frontmatter": {
544
+ "title": "Page widths",
545
+ "description": "Full, wide or narrow content, picked by what the page holds, and the length of a line of text.",
546
+ "order": 2
547
+ }
548
+ },
549
+ {
550
+ "id": "en/foundations/styles/logos/downloads-and-terms",
551
+ "path": "src/content/foundations/styles/logos/downloads-and-terms.mdx",
552
+ "documentPath": "docs/src/content/foundations/styles/logos/downloads-and-terms.mdx",
553
+ "locale": "en",
554
+ "kind": "guidance",
555
+ "title": "Downloads and terms",
556
+ "status": "active",
557
+ "releasePhase": null,
558
+ "planned": [],
559
+ "body": "import LogoHero from '../../../../components/logos/LogoHero.astro';\n\n## The package\n\n<LogoHero />\n\n| Folder | Contents |\n|---|---|\n| `lockups/` | The beehexa and HexaSync lockups in four colour versions each, SVG, with the clear space in the artboard |\n| `icon/` | The icon in yellow, white and graphite, SVG, with clear space |\n| `favicon-web/` | favicon.svg, favicon.ico and PNG favicons at 16, 32 and 48 px, apple-touch-icon, web app icons 192 and 512 px, maskable icon, avatar 800 px, site.webmanifest |\n| `license/` | The SIL Open Font License for Inter |\n| `README.md` | The rules in short |\n\n## Which file to use\n\n| You need | Use |\n|---|---|\n| The logo on a website or in an app | A PNG exported at 3× from `lockups/beehexa-horizontal-1-light.svg` (light backgrounds) or `-2-dark.svg` (dark), shown at 1×. See [sharp on screen](/foundations/styles/logos/using-the-logo/#sharp-on-screen). |\n| The logo in a document, a slide or print | `lockups/beehexa-horizontal-1-light.svg` on light backgrounds, `-2-dark.svg` on dark |\n| The logo on a photo or a strong colour | `-3-white.svg` |\n| One-colour print, engraving, stamps | `-4-graphite.svg` |\n| A favicon | `favicon-web/favicon.svg` and `favicon.ico` |\n| An app icon or a social avatar | `favicon-web/apple-touch-icon.png`, `icon-192.png`, `icon-512.png`, `icon-maskable-512.png`, `avatar-800.png` |\n| The icon in your own layout | `icon/beehexa-icon-*.svg` |\n| A PNG or PDF | Export it from the SVG at the size you need. Never enlarge a small PNG. |\n\n## Colour codes\n\n| Colour | HEX | RGB | Print |\n|---|---|---|---|\n| Yellow | #FCB017 | 252 176 23 | Not set yet |\n| Graphite | #2B2A28 | 43 42 40 | Not set yet |\n| White | #FFFFFF | 255 255 255 | Paper |\n\nCMYK and Pantone values come after a print proof. The 2025 brand guide lists PMS 1235 C for the yellow; check it on paper before using it, because this yellow often prints dull in CMYK on uncoated stock.\n\n## Typeface\n\nThe wordmark is set in Inter Display and converted to outlines, so you don't need the font to use the logo. Inter is licensed under the SIL Open Font License 1.1, which allows its use in a logo. The licence is in the package.\n\n## Trademark\n\nThe Beehexa logo is registered as a trademark in Viet Nam, no. 4-0358730-000, in classes 9, 35 and 42. Registration of the logo as shown on this site is being confirmed with our industrial property representative.\n\n## Terms of use\n\n> Draft, pending legal review. Questions: [hello@beehexa.com](mailto:hello@beehexa.com?subject=Logo%20use).\n\nYou may use the Beehexa and HexaSync logos to refer to Beehexa, to show that your product integrates with HexaSync, or in news and reviews about us, as long as you:\n\n- use the files from the package without changing them, following [Using the logo](/foundations/styles/logos/using-the-logo/);\n- don't suggest that Beehexa sponsors, endorses or partners with you unless we have agreed to it in writing;\n- don't use the logo, the icon or a look-alike in your own product names, logos, domain names, app icons or social accounts;\n- don't make our logo the most prominent element of your material.\n\nWe may ask you to change or stop any use of the logos.\n",
560
+ "raw": "---\ntitle: Downloads and terms\ndescription: Every logo file, which one to use where, colour codes, the typeface licence and the terms for using the Beehexa trademark.\norder: 5\naudience: designers, developers, partners, press\nowner: Brand\nupdated: 2026-10-24\n---\nimport LogoHero from '../../../../components/logos/LogoHero.astro';\n\n## The package\n\n<LogoHero />\n\n| Folder | Contents |\n|---|---|\n| `lockups/` | The beehexa and HexaSync lockups in four colour versions each, SVG, with the clear space in the artboard |\n| `icon/` | The icon in yellow, white and graphite, SVG, with clear space |\n| `favicon-web/` | favicon.svg, favicon.ico and PNG favicons at 16, 32 and 48 px, apple-touch-icon, web app icons 192 and 512 px, maskable icon, avatar 800 px, site.webmanifest |\n| `license/` | The SIL Open Font License for Inter |\n| `README.md` | The rules in short |\n\n## Which file to use\n\n| You need | Use |\n|---|---|\n| The logo on a website or in an app | A PNG exported at 3× from `lockups/beehexa-horizontal-1-light.svg` (light backgrounds) or `-2-dark.svg` (dark), shown at 1×. See [sharp on screen](/foundations/styles/logos/using-the-logo/#sharp-on-screen). |\n| The logo in a document, a slide or print | `lockups/beehexa-horizontal-1-light.svg` on light backgrounds, `-2-dark.svg` on dark |\n| The logo on a photo or a strong colour | `-3-white.svg` |\n| One-colour print, engraving, stamps | `-4-graphite.svg` |\n| A favicon | `favicon-web/favicon.svg` and `favicon.ico` |\n| An app icon or a social avatar | `favicon-web/apple-touch-icon.png`, `icon-192.png`, `icon-512.png`, `icon-maskable-512.png`, `avatar-800.png` |\n| The icon in your own layout | `icon/beehexa-icon-*.svg` |\n| A PNG or PDF | Export it from the SVG at the size you need. Never enlarge a small PNG. |\n\n## Colour codes\n\n| Colour | HEX | RGB | Print |\n|---|---|---|---|\n| Yellow | #FCB017 | 252 176 23 | Not set yet |\n| Graphite | #2B2A28 | 43 42 40 | Not set yet |\n| White | #FFFFFF | 255 255 255 | Paper |\n\nCMYK and Pantone values come after a print proof. The 2025 brand guide lists PMS 1235 C for the yellow; check it on paper before using it, because this yellow often prints dull in CMYK on uncoated stock.\n\n## Typeface\n\nThe wordmark is set in Inter Display and converted to outlines, so you don't need the font to use the logo. Inter is licensed under the SIL Open Font License 1.1, which allows its use in a logo. The licence is in the package.\n\n## Trademark\n\nThe Beehexa logo is registered as a trademark in Viet Nam, no. 4-0358730-000, in classes 9, 35 and 42. Registration of the logo as shown on this site is being confirmed with our industrial property representative.\n\n## Terms of use\n\n> Draft, pending legal review. Questions: [hello@beehexa.com](mailto:hello@beehexa.com?subject=Logo%20use).\n\nYou may use the Beehexa and HexaSync logos to refer to Beehexa, to show that your product integrates with HexaSync, or in news and reviews about us, as long as you:\n\n- use the files from the package without changing them, following [Using the logo](/foundations/styles/logos/using-the-logo/);\n- don't suggest that Beehexa sponsors, endorses or partners with you unless we have agreed to it in writing;\n- don't use the logo, the icon or a look-alike in your own product names, logos, domain names, app icons or social accounts;\n- don't make our logo the most prominent element of your material.\n\nWe may ask you to change or stop any use of the logos.\n",
561
+ "frontmatter": {
562
+ "title": "Downloads and terms",
563
+ "description": "Every logo file, which one to use where, colour codes, the typeface licence and the terms for using the Beehexa trademark.",
564
+ "order": 5,
565
+ "audience": "designers, developers, partners, press",
566
+ "owner": "Brand",
567
+ "updated": "2026-10-24"
568
+ }
569
+ },
570
+ {
571
+ "id": "en/foundations/styles/logos/index",
572
+ "path": "src/content/foundations/styles/logos/index.mdx",
573
+ "documentPath": "docs/src/content/foundations/styles/logos/index.mdx",
574
+ "locale": "en",
575
+ "kind": "guidance",
576
+ "title": "Logos",
577
+ "status": "active",
578
+ "releasePhase": null,
579
+ "planned": [],
580
+ "body": "import LogoHero from '../../../../components/logos/LogoHero.astro';\nimport LogoAnatomy from '../../../../components/logos/LogoAnatomy.astro';\nimport LogoConstruction from '../../../../components/logos/LogoConstruction.astro';\nimport LogoMeanings from '../../../../components/logos/LogoMeanings.astro';\n\n## Download\n\n<LogoHero />\n\n## Anatomy\n\nThe lockup is the icon and the wordmark, side by side. Everything is measured in one unit: the side of the hexagon, which is also the x-height of the wordmark.\n\n<LogoAnatomy />\n\nThere are two forms only: this horizontal lockup and the [icon on its own](/foundations/styles/logos/using-the-logo/#the-icon-on-its-own). There is no stacked version.\n\n## Construction\n\nThe icon is drawn on a grid of equilateral triangles, so anyone can redraw it exactly: a regular hexagon with a pointy top, three layers and 30° edges.\n\n<LogoConstruction />\n\n## One icon, three meanings\n\n> As a bee builds its hive, Beehexa joins system after system into one solid block, then lifts the business up.\n\nThe three meanings sit inside each other: the yellow shows what Beehexa builds, the white shows what it brings.\n\n<LogoMeanings />\n\n## Rules at a glance\n\n| Rule | Value | Details |\n|---|---|---|\n| Forms | Horizontal lockup; icon on its own | [Anatomy](#anatomy) |\n| Colour versions | 4 versions, 3 colours: yellow #FCB017, graphite #2B2A28, white | [Colour versions](/foundations/styles/logos/using-the-logo/#colour-versions) |\n| Clear space | 1 x-height (one hexagon side) on every side | [Clear space](/foundations/styles/logos/using-the-logo/#clear-space) |\n| Minimum size | Lockup 100 px or 25 mm wide; icon 16 px or 6 mm tall | [Minimum size](/foundations/styles/logos/using-the-logo/#minimum-size) |\n| Icon on light backgrounds | Graphite, or yellow on a graphite tile | [The icon on its own](/foundations/styles/logos/using-the-logo/#the-icon-on-its-own) |\n| Spelling | The logo reads “beehexa”, lowercase. Product logos keep the product's spelling: “HexaSync”. In running text, write Beehexa. | [Product logos](/foundations/styles/logos/product-logos/) |\n\n## What changed from the 2018 logo\n\n| | 2018 logo | Refreshed logo |\n|---|---|---|\n| Typeface | Ubuntu, another company's typeface, without Vietnamese letters | Inter Display, Beehexa's typeface, outlined |\n| Wordmark colour | Yellow | Graphite on light backgrounds, white on dark |\n| Icon | No grid; stroke thinner than the gaps (0.8 : 1) | 28-band grid; stroke and gap equal (1 : 1), stroke 11% thicker |\n| Icon to text spacing | No rule | 10 bands, measured from the icon |\n| Clear space | One chevron layer, about 0.22 × the icon height | 1 x-height |\n| Minimum size | 120 px or 30 mm | 100 px or 25 mm |\n| Colour versions | All yellow | 4 versions |\n\nThe 2018 logo stays on existing material until the refreshed logo launches. Don't use it in new work.\n",
581
+ "raw": "---\ntitle: Logos\ndescription: The Beehexa logo and every product logo, with the rules and files to use them on web, print and inside our products.\norder: 12\nsidebarLabel: Overview\naudience: web, print, product UI\nowner: Brand\nupdated: 2026-10-23\n---\nimport LogoHero from '../../../../components/logos/LogoHero.astro';\nimport LogoAnatomy from '../../../../components/logos/LogoAnatomy.astro';\nimport LogoConstruction from '../../../../components/logos/LogoConstruction.astro';\nimport LogoMeanings from '../../../../components/logos/LogoMeanings.astro';\n\n## Download\n\n<LogoHero />\n\n## Anatomy\n\nThe lockup is the icon and the wordmark, side by side. Everything is measured in one unit: the side of the hexagon, which is also the x-height of the wordmark.\n\n<LogoAnatomy />\n\nThere are two forms only: this horizontal lockup and the [icon on its own](/foundations/styles/logos/using-the-logo/#the-icon-on-its-own). There is no stacked version.\n\n## Construction\n\nThe icon is drawn on a grid of equilateral triangles, so anyone can redraw it exactly: a regular hexagon with a pointy top, three layers and 30° edges.\n\n<LogoConstruction />\n\n## One icon, three meanings\n\n> As a bee builds its hive, Beehexa joins system after system into one solid block, then lifts the business up.\n\nThe three meanings sit inside each other: the yellow shows what Beehexa builds, the white shows what it brings.\n\n<LogoMeanings />\n\n## Rules at a glance\n\n| Rule | Value | Details |\n|---|---|---|\n| Forms | Horizontal lockup; icon on its own | [Anatomy](#anatomy) |\n| Colour versions | 4 versions, 3 colours: yellow #FCB017, graphite #2B2A28, white | [Colour versions](/foundations/styles/logos/using-the-logo/#colour-versions) |\n| Clear space | 1 x-height (one hexagon side) on every side | [Clear space](/foundations/styles/logos/using-the-logo/#clear-space) |\n| Minimum size | Lockup 100 px or 25 mm wide; icon 16 px or 6 mm tall | [Minimum size](/foundations/styles/logos/using-the-logo/#minimum-size) |\n| Icon on light backgrounds | Graphite, or yellow on a graphite tile | [The icon on its own](/foundations/styles/logos/using-the-logo/#the-icon-on-its-own) |\n| Spelling | The logo reads “beehexa”, lowercase. Product logos keep the product's spelling: “HexaSync”. In running text, write Beehexa. | [Product logos](/foundations/styles/logos/product-logos/) |\n\n## What changed from the 2018 logo\n\n| | 2018 logo | Refreshed logo |\n|---|---|---|\n| Typeface | Ubuntu, another company's typeface, without Vietnamese letters | Inter Display, Beehexa's typeface, outlined |\n| Wordmark colour | Yellow | Graphite on light backgrounds, white on dark |\n| Icon | No grid; stroke thinner than the gaps (0.8 : 1) | 28-band grid; stroke and gap equal (1 : 1), stroke 11% thicker |\n| Icon to text spacing | No rule | 10 bands, measured from the icon |\n| Clear space | One chevron layer, about 0.22 × the icon height | 1 x-height |\n| Minimum size | 120 px or 30 mm | 100 px or 25 mm |\n| Colour versions | All yellow | 4 versions |\n\nThe 2018 logo stays on existing material until the refreshed logo launches. Don't use it in new work.\n",
582
+ "frontmatter": {
583
+ "title": "Logos",
584
+ "description": "The Beehexa logo and every product logo, with the rules and files to use them on web, print and inside our products.",
585
+ "order": 12,
586
+ "sidebarLabel": "Overview",
587
+ "audience": "web, print, product UI",
588
+ "owner": "Brand",
589
+ "updated": "2026-10-23"
590
+ }
591
+ },
592
+ {
593
+ "id": "en/foundations/styles/logos/placement-and-containers",
594
+ "path": "src/content/foundations/styles/logos/placement-and-containers.mdx",
595
+ "documentPath": "docs/src/content/foundations/styles/logos/placement-and-containers.mdx",
596
+ "locale": "en",
597
+ "kind": "guidance",
598
+ "title": "Placement and containers",
599
+ "status": "active",
600
+ "releasePhase": null,
601
+ "planned": [],
602
+ "body": "import LogoInUse from '../../../../components/logos/LogoInUse.astro';\nimport LogoContainer from '../../../../components/logos/LogoContainer.astro';\nimport LogoMistakes from '../../../../components/logos/LogoMistakes.astro';\n\n## On a website\n\n- Put the lockup at the left of the header and link it to the home page.\n- Size: an icon of 24–32 px in a header 56–64 px tall. This site uses a 24 px icon in a 56 px header.\n- Keep the [clear space](/foundations/styles/logos/using-the-logo/#clear-space) and follow the [sharp on screen](/foundations/styles/logos/using-the-logo/#sharp-on-screen) rules.\n- Inside HexaSync, show the HexaSync logo instead. See [Product logos](/foundations/styles/logos/product-logos/).\n\n<LogoInUse only={['header', 'app']} />\n\n## In documents and slides\n\n- Place the lockup at the top left of the first page or the cover slide, with its clear space.\n- At least 25 mm wide in print.\n- Choose the colour version from the background: version 1 on paper and light slides, version 2 on dark slides.\n\n<LogoInUse only={['document', 'slide']} />\n\n## In email\n\n- Put the lockup under the sender's name, as a PNG exported at 2× and at least 100 px wide. Many email clients don't show SVG.\n- Use alt text “Beehexa”, so the signature still reads when images are blocked.\n\n<LogoInUse only={['email']} />\n\n## In print\n\n- Business cards: the lockup centred on the front, version 2 on graphite; name and details on the back, on white.\n- Keep the lockup at least 25 mm wide and the clear space free of folds, trims and holes.\n\n<LogoInUse only={['card']} />\n\n## On photos and brand colour\n\n- On a photo, use version 3 (white) on a calm area, usually a corner, with its clear space. Never put a box behind the logo to rescue a busy picture: choose another crop.\n- On brand yellow, use version 4 (graphite).\n\n<LogoInUse only={['photo', 'yellow']} />\n\n## Next to a partner logo\n\nWhen Beehexa appears with a partner, such as on an integration page, use the horizontal lockup. Give both logos the same visual weight, keep each one's clear space, and separate them with a thin vertical line.\n\n<LogoInUse only={['partner']} />\n\n## The icon in a tile: the 3-side rule\n\nApp icons and avatars put the icon inside a tile, and platforms crop that tile to a rounded square or a circle. The tile's edge is the boundary, so the icon uses its own rule, measured in hexagon sides:\n\n- The tile is 3 sides wide.\n- The icon is 2 sides tall, two thirds of the tile, centred.\n- That leaves half a side above and below.\n\n<LogoContainer />\n\n| File | Tile | Icon height | Background |\n|---|---|---|---|\n| apple-touch-icon.png | 180 px | 120 px | Graphite #2B2A28 |\n| icon-192.png, icon-512.png | 192 and 512 px | 128 and 341 px | Graphite #2B2A28 |\n| icon-maskable-512.png | 512 px | 341 px, inside the 80% safe circle | Graphite #2B2A28 |\n| avatar-800.png | 800 px | 533 px | Graphite #2B2A28 |\n\nThe icon is yellow on a graphite tile: it keeps the brand colour and reaches 7.76 : 1.\n\n## Favicons\n\nThe favicon is the icon alone, in yellow, on a transparent background, filling its square.\n\n| File | Sizes | Notes |\n|---|---|---|\n| favicon.svg | Any | Used by current browsers. Smooth edges, drawn from the master icon. |\n| favicon.ico | 16, 32 and 48 px | For older browsers and tools. Each size is drawn large and reduced, which keeps the edges smooth. |\n\n```html\n<link rel=\"icon\" href=\"/favicon.ico\" sizes=\"48x48\">\n<link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\">\n<link rel=\"apple-touch-icon\" href=\"/apple-touch-icon.png\">\n<link rel=\"manifest\" href=\"/site.webmanifest\">\n```\n\n<LogoInUse only={['tab', 'avatar']} />\n\n## Common mistakes\n\n<LogoMistakes />\n",
603
+ "raw": "---\ntitle: Placement and containers\ndescription: Where the logo sits on websites, in documents, email, print, on photos and next to partners; how the icon sits in app icons, avatars and favicons; and the mistakes to avoid.\norder: 2\naudience: web, product UI, documents\nowner: Brand\nupdated: 2026-10-23\n---\nimport LogoInUse from '../../../../components/logos/LogoInUse.astro';\nimport LogoContainer from '../../../../components/logos/LogoContainer.astro';\nimport LogoMistakes from '../../../../components/logos/LogoMistakes.astro';\n\n## On a website\n\n- Put the lockup at the left of the header and link it to the home page.\n- Size: an icon of 24–32 px in a header 56–64 px tall. This site uses a 24 px icon in a 56 px header.\n- Keep the [clear space](/foundations/styles/logos/using-the-logo/#clear-space) and follow the [sharp on screen](/foundations/styles/logos/using-the-logo/#sharp-on-screen) rules.\n- Inside HexaSync, show the HexaSync logo instead. See [Product logos](/foundations/styles/logos/product-logos/).\n\n<LogoInUse only={['header', 'app']} />\n\n## In documents and slides\n\n- Place the lockup at the top left of the first page or the cover slide, with its clear space.\n- At least 25 mm wide in print.\n- Choose the colour version from the background: version 1 on paper and light slides, version 2 on dark slides.\n\n<LogoInUse only={['document', 'slide']} />\n\n## In email\n\n- Put the lockup under the sender's name, as a PNG exported at 2× and at least 100 px wide. Many email clients don't show SVG.\n- Use alt text “Beehexa”, so the signature still reads when images are blocked.\n\n<LogoInUse only={['email']} />\n\n## In print\n\n- Business cards: the lockup centred on the front, version 2 on graphite; name and details on the back, on white.\n- Keep the lockup at least 25 mm wide and the clear space free of folds, trims and holes.\n\n<LogoInUse only={['card']} />\n\n## On photos and brand colour\n\n- On a photo, use version 3 (white) on a calm area, usually a corner, with its clear space. Never put a box behind the logo to rescue a busy picture: choose another crop.\n- On brand yellow, use version 4 (graphite).\n\n<LogoInUse only={['photo', 'yellow']} />\n\n## Next to a partner logo\n\nWhen Beehexa appears with a partner, such as on an integration page, use the horizontal lockup. Give both logos the same visual weight, keep each one's clear space, and separate them with a thin vertical line.\n\n<LogoInUse only={['partner']} />\n\n## The icon in a tile: the 3-side rule\n\nApp icons and avatars put the icon inside a tile, and platforms crop that tile to a rounded square or a circle. The tile's edge is the boundary, so the icon uses its own rule, measured in hexagon sides:\n\n- The tile is 3 sides wide.\n- The icon is 2 sides tall, two thirds of the tile, centred.\n- That leaves half a side above and below.\n\n<LogoContainer />\n\n| File | Tile | Icon height | Background |\n|---|---|---|---|\n| apple-touch-icon.png | 180 px | 120 px | Graphite #2B2A28 |\n| icon-192.png, icon-512.png | 192 and 512 px | 128 and 341 px | Graphite #2B2A28 |\n| icon-maskable-512.png | 512 px | 341 px, inside the 80% safe circle | Graphite #2B2A28 |\n| avatar-800.png | 800 px | 533 px | Graphite #2B2A28 |\n\nThe icon is yellow on a graphite tile: it keeps the brand colour and reaches 7.76 : 1.\n\n## Favicons\n\nThe favicon is the icon alone, in yellow, on a transparent background, filling its square.\n\n| File | Sizes | Notes |\n|---|---|---|\n| favicon.svg | Any | Used by current browsers. Smooth edges, drawn from the master icon. |\n| favicon.ico | 16, 32 and 48 px | For older browsers and tools. Each size is drawn large and reduced, which keeps the edges smooth. |\n\n```html\n<link rel=\"icon\" href=\"/favicon.ico\" sizes=\"48x48\">\n<link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\">\n<link rel=\"apple-touch-icon\" href=\"/apple-touch-icon.png\">\n<link rel=\"manifest\" href=\"/site.webmanifest\">\n```\n\n<LogoInUse only={['tab', 'avatar']} />\n\n## Common mistakes\n\n<LogoMistakes />\n",
604
+ "frontmatter": {
605
+ "title": "Placement and containers",
606
+ "description": "Where the logo sits on websites, in documents, email, print, on photos and next to partners; how the icon sits in app icons, avatars and favicons; and the mistakes to avoid.",
607
+ "order": 2,
608
+ "audience": "web, product UI, documents",
609
+ "owner": "Brand",
610
+ "updated": "2026-10-23"
611
+ }
612
+ },
613
+ {
614
+ "id": "en/foundations/styles/logos/product-logos",
615
+ "path": "src/content/foundations/styles/logos/product-logos.mdx",
616
+ "documentPath": "docs/src/content/foundations/styles/logos/product-logos.mdx",
617
+ "locale": "en",
618
+ "kind": "guidance",
619
+ "title": "Product logos",
620
+ "status": "active",
621
+ "releasePhase": null,
622
+ "planned": [],
623
+ "body": "import LogoPair from '../../../../components/logos/LogoPair.astro';\nimport LogoInUse from '../../../../components/logos/LogoInUse.astro';\n\n## HexaSync\n\n<LogoPair kind=\"hexasync\" name=\"HexaSync\" />\n\nThe HexaSync lockup is built exactly like the company lockup: the same icon, the product name in Inter Display at the same weight, 500, the same spacing and the same [clear space](/foundations/styles/logos/using-the-logo/#clear-space). The tail of the “y” hangs below the icon.\n\nAll the rules on [Using the logo](/foundations/styles/logos/using-the-logo/) apply: four colour versions, minimum size, misuse.\n\n## Which logo where\n\n| Where | Logo |\n|---|---|\n| Inside the HexaSync web app | HexaSync |\n| HexaSync product pages, connector listings and marketplaces | HexaSync |\n| Company website, contracts, invoices, recruiting, social media | beehexa |\n| Material about several products | beehexa |\n\nNever place the beehexa and HexaSync logos side by side: they share the icon, so the pair reads as a mistake. Pick one by context.\n\n## HexaSync in use\n\n- **App bar:** the dark version on a graphite bar, at the left, linking to the product home.\n- **Sign-in and empty screens:** the colour version, centred above the content.\n- **Marketplaces and connector listings:** the app icon tile with “HexaSync” written as text next to it. Listings crop to a square, so the lockup doesn't fit there.\n\n<LogoInUse only={['app', 'login', 'marketplace']} />\n\n## Icons and containers\n\nA product has no icon of its own. HexaSync uses the Beehexa icon files for its favicon, app icon and avatar, built with the [3-side rule](/foundations/styles/logos/placement-and-containers/#the-icon-in-a-tile-the-3-side-rule). The product name goes in the app name, the page title and the alt text, never inside the icon.\n\n## Spelling\n\n- The company logo is lowercase: “beehexa”.\n- A product logo keeps the product's own spelling: “HexaSync”, one word, capital H and S.\n\n## A new product logo\n\nEvery product lockup today uses the Beehexa icon with the product name next to it. To get one for a new product:\n\n1. Write to the Brand owner at [hello@beehexa.com](mailto:hello@beehexa.com?subject=New%20product%20logo) with the product name as it will be written.\n2. Brand builds the lockup from the masters: the icon, the name in Inter Display, outlined, at the chosen weight, with the same spacing.\n3. The files are added to the [package](/foundations/styles/logos/downloads-and-terms/).\n\nDon't draw a product logo yourself, and don't give a product an icon of its own.\n",
624
+ "raw": "---\ntitle: Product logos\ndescription: Logos for Beehexa products, starting with HexaSync, and when to use them instead of the company logo.\norder: 3\naudience: product, marketing\nowner: Brand\nupdated: 2026-10-23\n---\nimport LogoPair from '../../../../components/logos/LogoPair.astro';\nimport LogoInUse from '../../../../components/logos/LogoInUse.astro';\n\n## HexaSync\n\n<LogoPair kind=\"hexasync\" name=\"HexaSync\" />\n\nThe HexaSync lockup is built exactly like the company lockup: the same icon, the product name in Inter Display at the same weight, 500, the same spacing and the same [clear space](/foundations/styles/logos/using-the-logo/#clear-space). The tail of the “y” hangs below the icon.\n\nAll the rules on [Using the logo](/foundations/styles/logos/using-the-logo/) apply: four colour versions, minimum size, misuse.\n\n## Which logo where\n\n| Where | Logo |\n|---|---|\n| Inside the HexaSync web app | HexaSync |\n| HexaSync product pages, connector listings and marketplaces | HexaSync |\n| Company website, contracts, invoices, recruiting, social media | beehexa |\n| Material about several products | beehexa |\n\nNever place the beehexa and HexaSync logos side by side: they share the icon, so the pair reads as a mistake. Pick one by context.\n\n## HexaSync in use\n\n- **App bar:** the dark version on a graphite bar, at the left, linking to the product home.\n- **Sign-in and empty screens:** the colour version, centred above the content.\n- **Marketplaces and connector listings:** the app icon tile with “HexaSync” written as text next to it. Listings crop to a square, so the lockup doesn't fit there.\n\n<LogoInUse only={['app', 'login', 'marketplace']} />\n\n## Icons and containers\n\nA product has no icon of its own. HexaSync uses the Beehexa icon files for its favicon, app icon and avatar, built with the [3-side rule](/foundations/styles/logos/placement-and-containers/#the-icon-in-a-tile-the-3-side-rule). The product name goes in the app name, the page title and the alt text, never inside the icon.\n\n## Spelling\n\n- The company logo is lowercase: “beehexa”.\n- A product logo keeps the product's own spelling: “HexaSync”, one word, capital H and S.\n\n## A new product logo\n\nEvery product lockup today uses the Beehexa icon with the product name next to it. To get one for a new product:\n\n1. Write to the Brand owner at [hello@beehexa.com](mailto:hello@beehexa.com?subject=New%20product%20logo) with the product name as it will be written.\n2. Brand builds the lockup from the masters: the icon, the name in Inter Display, outlined, at the chosen weight, with the same spacing.\n3. The files are added to the [package](/foundations/styles/logos/downloads-and-terms/).\n\nDon't draw a product logo yourself, and don't give a product an icon of its own.\n",
625
+ "frontmatter": {
626
+ "title": "Product logos",
627
+ "description": "Logos for Beehexa products, starting with HexaSync, and when to use them instead of the company logo.",
628
+ "order": 3,
629
+ "audience": "product, marketing",
630
+ "owner": "Brand",
631
+ "updated": "2026-10-23"
632
+ }
633
+ },
634
+ {
635
+ "id": "en/foundations/styles/logos/using-the-logo",
636
+ "path": "src/content/foundations/styles/logos/using-the-logo.mdx",
637
+ "documentPath": "docs/src/content/foundations/styles/logos/using-the-logo.mdx",
638
+ "locale": "en",
639
+ "kind": "guidance",
640
+ "title": "Using the logo",
641
+ "status": "active",
642
+ "releasePhase": null,
643
+ "planned": [],
644
+ "body": "import LogoColourVersions from '../../../../components/logos/LogoColourVersions.astro';\nimport LogoClearSpace from '../../../../components/logos/LogoClearSpace.astro';\nimport LogoMinSize from '../../../../components/logos/LogoMinSize.astro';\nimport LogoMisuse from '../../../../components/logos/LogoMisuse.astro';\n\n## Colour versions\n\nFour versions made from three colours: yellow #FCB017, graphite #2B2A28 and white. Pick the one with the most contrast against your background.\n\n<LogoColourVersions />\n\nWCAG does not set a contrast minimum for logos (Understanding 1.4.3 and 1.4.11), but a logo nobody can see is not remembered. We place every version where it stands out, aiming for the 3 : 1 that WCAG sets for other graphics. That is why the yellow icon does not stand alone on a light background; the favicon is the one exception (see [the icon on its own](#the-icon-on-its-own)).\n\n## Clear space\n\nKeep an empty margin of **x** on all four sides: no text, images or page edges inside it. x is the x-height of the wordmark, the height of its lowercase letters, and it is exactly one side of the hexagon. Because x is part of the logo, the margin grows and shrinks with it.\n\n<LogoClearSpace />\n\nThe master files already include this margin in their artboard. Align the artboard, not the artwork, and the space comes for free.\n\n## Minimum size\n\n<LogoMinSize />\n\n| | Screen | Print |\n|---|---|---|\n| Lockup, width | 100 px | 25 mm |\n| Icon on its own, height | 16 px | 6 mm |\n\n## Sharp on screen\n\nThe icon's edges run at 30°, so on 100% (1×) screens they show stair steps when the logo lands between pixels.\n\n- Give the logo a whole-pixel height and a whole-pixel position.\n- On screen, show the logo as a PNG exported at 3× the size it is shown, not as an SVG. The browser shrinks the larger picture, which softens the edges a little and hides the steps. Every logo on this site, the header included, is drawn this way.\n- To make one, export the master SVG from Figma, Illustrator or Inkscape at 3× the size you need: for a logo 30 px tall, export it 90 px tall and show it at 30 px. A much larger file also works, but it costs more to download and each browser shrinks it a little differently.\n- Never redraw the icon to fit the pixel grid: it breaks the regular hexagon and the 30° angle.\n- In documents, slides and print, use the SVG.\n\n## The icon on its own\n\nUse the icon without the wordmark only where the name is already on screen, or where there is no room for the lockup: favicons, app icons, avatars and small product UI.\n\n| Background | Icon colour |\n|---|---|\n| Dark | Yellow |\n| Light | Graphite, or yellow on a graphite tile |\n| Photo or strong colour | White |\n\nYellow on white reaches only 1.85 : 1. Next to the wordmark that is fine, because the graphite text carries the logo; on its own the icon would almost disappear. The one exception is the favicon, which is yellow so the browser tab shows the brand colour.\n\n## Misuse\n\n<LogoMisuse />\n\n## Alt text and links\n\n- A logo on its own: alt text “Beehexa”, or the product name, such as “HexaSync”. Don't add the word “logo”.\n- A logo that links to the home page: “Beehexa – Home”, so people know where the link goes.\n- When the name is already written next to the logo, the logo is decorative: use an empty alt text.\n- A logo that is a link needs a visible focus ring, like any other link. The WCAG exemption covers the logo's colours, not the control around it.\n",
645
+ "raw": "---\ntitle: Using the logo\ndescription: Colour versions, backgrounds, clear space, minimum size, the icon on its own and what not to do.\norder: 1\naudience: everyone who places the logo\nowner: Brand\nupdated: 2026-10-23\n---\nimport LogoColourVersions from '../../../../components/logos/LogoColourVersions.astro';\nimport LogoClearSpace from '../../../../components/logos/LogoClearSpace.astro';\nimport LogoMinSize from '../../../../components/logos/LogoMinSize.astro';\nimport LogoMisuse from '../../../../components/logos/LogoMisuse.astro';\n\n## Colour versions\n\nFour versions made from three colours: yellow #FCB017, graphite #2B2A28 and white. Pick the one with the most contrast against your background.\n\n<LogoColourVersions />\n\nWCAG does not set a contrast minimum for logos (Understanding 1.4.3 and 1.4.11), but a logo nobody can see is not remembered. We place every version where it stands out, aiming for the 3 : 1 that WCAG sets for other graphics. That is why the yellow icon does not stand alone on a light background; the favicon is the one exception (see [the icon on its own](#the-icon-on-its-own)).\n\n## Clear space\n\nKeep an empty margin of **x** on all four sides: no text, images or page edges inside it. x is the x-height of the wordmark, the height of its lowercase letters, and it is exactly one side of the hexagon. Because x is part of the logo, the margin grows and shrinks with it.\n\n<LogoClearSpace />\n\nThe master files already include this margin in their artboard. Align the artboard, not the artwork, and the space comes for free.\n\n## Minimum size\n\n<LogoMinSize />\n\n| | Screen | Print |\n|---|---|---|\n| Lockup, width | 100 px | 25 mm |\n| Icon on its own, height | 16 px | 6 mm |\n\n## Sharp on screen\n\nThe icon's edges run at 30°, so on 100% (1×) screens they show stair steps when the logo lands between pixels.\n\n- Give the logo a whole-pixel height and a whole-pixel position.\n- On screen, show the logo as a PNG exported at 3× the size it is shown, not as an SVG. The browser shrinks the larger picture, which softens the edges a little and hides the steps. Every logo on this site, the header included, is drawn this way.\n- To make one, export the master SVG from Figma, Illustrator or Inkscape at 3× the size you need: for a logo 30 px tall, export it 90 px tall and show it at 30 px. A much larger file also works, but it costs more to download and each browser shrinks it a little differently.\n- Never redraw the icon to fit the pixel grid: it breaks the regular hexagon and the 30° angle.\n- In documents, slides and print, use the SVG.\n\n## The icon on its own\n\nUse the icon without the wordmark only where the name is already on screen, or where there is no room for the lockup: favicons, app icons, avatars and small product UI.\n\n| Background | Icon colour |\n|---|---|\n| Dark | Yellow |\n| Light | Graphite, or yellow on a graphite tile |\n| Photo or strong colour | White |\n\nYellow on white reaches only 1.85 : 1. Next to the wordmark that is fine, because the graphite text carries the logo; on its own the icon would almost disappear. The one exception is the favicon, which is yellow so the browser tab shows the brand colour.\n\n## Misuse\n\n<LogoMisuse />\n\n## Alt text and links\n\n- A logo on its own: alt text “Beehexa”, or the product name, such as “HexaSync”. Don't add the word “logo”.\n- A logo that links to the home page: “Beehexa – Home”, so people know where the link goes.\n- When the name is already written next to the logo, the logo is decorative: use an empty alt text.\n- A logo that is a link needs a visible focus ring, like any other link. The WCAG exemption covers the logo's colours, not the control around it.\n",
646
+ "frontmatter": {
647
+ "title": "Using the logo",
648
+ "description": "Colour versions, backgrounds, clear space, minimum size, the icon on its own and what not to do.",
649
+ "order": 1,
650
+ "audience": "everyone who places the logo",
651
+ "owner": "Brand",
652
+ "updated": "2026-10-23"
653
+ }
654
+ },
655
+ {
656
+ "id": "en/foundations/styles/motion",
657
+ "path": "src/content/foundations/styles/motion.mdx",
658
+ "documentPath": "docs/src/content/foundations/styles/motion.mdx",
659
+ "locale": "en",
660
+ "kind": "guidance",
661
+ "title": "Motion",
662
+ "status": "active",
663
+ "releasePhase": null,
664
+ "planned": [],
665
+ "body": "import TokenTable from '../../../components/TokenTable.astro';\n\nMotion should explain a change, not decorate it. Keep transitions short, and turn off non-essential motion when the user sets `prefers-reduced-motion`.\n\n## Tokens\n<TokenTable prefix=\"motion\" />\n",
666
+ "raw": "---\ntitle: Motion\ndescription: Durations and easing for transitions.\norder: 9\n---\nimport TokenTable from '../../../components/TokenTable.astro';\n\nMotion should explain a change, not decorate it. Keep transitions short, and turn off non-essential motion when the user sets `prefers-reduced-motion`.\n\n## Tokens\n<TokenTable prefix=\"motion\" />\n",
667
+ "frontmatter": {
668
+ "title": "Motion",
669
+ "description": "Durations and easing for transitions.",
670
+ "order": 9
671
+ }
672
+ },
673
+ {
674
+ "id": "en/foundations/styles/opacity",
675
+ "path": "src/content/foundations/styles/opacity.mdx",
676
+ "documentPath": "docs/src/content/foundations/styles/opacity.mdx",
677
+ "locale": "en",
678
+ "kind": "guidance",
679
+ "title": "Opacity",
680
+ "status": "planned",
681
+ "releasePhase": null,
682
+ "planned": [
683
+ "Where transparency is allowed: the scrim behind dialogs, image overlays",
684
+ "Why hover, pressed and disabled use colour steps, not opacity",
685
+ "Opacity tokens, if any are needed"
686
+ ],
687
+ "body": "",
688
+ "raw": "---\ntitle: \"Opacity\"\ndescription: \"When transparency is allowed, and why states and disabled controls use colour instead.\"\norder: 10.5\nplanned:\n - \"Where transparency is allowed: the scrim behind dialogs, image overlays\"\n - \"Why hover, pressed and disabled use colour steps, not opacity\"\n - \"Opacity tokens, if any are needed\"\n---\n",
689
+ "frontmatter": {
690
+ "title": "Opacity",
691
+ "description": "When transparency is allowed, and why states and disabled controls use colour instead.",
692
+ "order": 10.5,
693
+ "planned": [
694
+ "Where transparency is allowed: the scrim behind dialogs, image overlays",
695
+ "Why hover, pressed and disabled use colour steps, not opacity",
696
+ "Opacity tokens, if any are needed"
697
+ ]
698
+ }
699
+ },
700
+ {
701
+ "id": "en/foundations/styles/radius",
702
+ "path": "src/content/foundations/styles/radius.mdx",
703
+ "documentPath": "docs/src/content/foundations/styles/radius.mdx",
704
+ "locale": "en",
705
+ "kind": "guidance",
706
+ "title": "Radius",
707
+ "status": "active",
708
+ "releasePhase": null,
709
+ "planned": [],
710
+ "body": "import ShapeDemo from '../../../components/ShapeDemo.astro';\nimport TokenTable from '../../../components/TokenTable.astro';\n\n**Every corner is a radius token. Pick the step by what the element is, then check it against its container.**\n\n## The scale\n\nEight steps. The token number follows the spacing scale: `radius.100` is 8 px, like `space.100`.\n\n<ShapeDemo kind=\"radius-scale\" />\n\n## Examples\n\n### `radius.0` · square\n\nEdges that touch the screen: the page header, full-width tables and panels that run to the edge.\n\n<ShapeDemo kind=\"radius-use\" item=\"0\" />\n\n### `radius.050` · 4 px\n\nSmall things: checkboxes, tags, badges and the items inside a menu.\n\n<ShapeDemo kind=\"radius-use\" item=\"050\" />\n\n### `radius.100` · 8 px\n\nControls and the small surfaces that open from them: buttons, inputs, selects, menus, popovers, tooltips and alerts. Inputs and buttons always share this value.\n\n<ShapeDemo kind=\"radius-use\" item=\"100\" />\n\n### `radius.150` · 12 px\n\nCards, and a group of controls with 4 px padding, such as a segmented control.\n\n<ShapeDemo kind=\"radius-use\" item=\"150\" />\n\n### `radius.200` · 16 px\n\nDialogs and drawers, and a group of controls with 8 px padding.\n\n<ShapeDemo kind=\"radius-use\" item=\"200\" />\n\n### `radius.full` · pill\n\nAvatars, switches and pill-shaped status chips.\n\n<ShapeDemo kind=\"radius-use\" item=\"full\" />\n\n## Shapes inside shapes\n\n**Inner radius = outer radius − padding.** Use it when the padding is smaller than the outer radius. When the padding is larger, the inner element keeps its own radius, as long as it is not larger than the outer one.\n\n<ShapeDemo kind=\"nesting\" />\n\n`radius.025` and `radius.075` exist for these cases only. No component takes them by default.\n\nWith the spacing rules, the result is always a step on the scale: 2 px is never padding, and 6 px is padding only inside a component.\n\nWhen content sits flush inside a box with a 1 px border, clip it with `overflow: hidden`. Don't make a radius − 1 value.\n\n## Focus ring\n\nThe focus ring sits 2 px outside the element, and the browser rounds it to match: an 8 px button gets a 10 px ring. No radius token is needed. See [Border](/foundations/styles/border/) for the ring itself.\n\n<ShapeDemo kind=\"focus-radius\" />\n\n## Do and don’t\n\n<ShapeDemo kind=\"dodont\" item=\"nested\" />\n<ShapeDemo kind=\"dodont\" item=\"controls\" />\n<ShapeDemo kind=\"dodont\" item=\"corners\" />\n\n## Code\n\n```css\n.card {\n border-radius: var(--bh-radius-150);\n padding: var(--bh-space-050);\n}\n.card img {\n border-radius: var(--bh-radius-100); /* 12 − 4 = 8 */\n}\n```\n\n## Tokens\n\n<TokenTable prefix=\"radius\" />\n\n## Related\n\n- [Border](/foundations/styles/border/): border widths, the selected bar and the focus ring.\n- [Spacing](/foundations/styles/spacing/): the padding values used in the nesting rule.\n",
711
+ "raw": "---\ntitle: Radius\ndescription: Eight corner radius steps, which element takes which step, and how to round shapes inside other shapes.\norder: 6\n---\nimport ShapeDemo from '../../../components/ShapeDemo.astro';\nimport TokenTable from '../../../components/TokenTable.astro';\n\n**Every corner is a radius token. Pick the step by what the element is, then check it against its container.**\n\n## The scale\n\nEight steps. The token number follows the spacing scale: `radius.100` is 8 px, like `space.100`.\n\n<ShapeDemo kind=\"radius-scale\" />\n\n## Examples\n\n### `radius.0` · square\n\nEdges that touch the screen: the page header, full-width tables and panels that run to the edge.\n\n<ShapeDemo kind=\"radius-use\" item=\"0\" />\n\n### `radius.050` · 4 px\n\nSmall things: checkboxes, tags, badges and the items inside a menu.\n\n<ShapeDemo kind=\"radius-use\" item=\"050\" />\n\n### `radius.100` · 8 px\n\nControls and the small surfaces that open from them: buttons, inputs, selects, menus, popovers, tooltips and alerts. Inputs and buttons always share this value.\n\n<ShapeDemo kind=\"radius-use\" item=\"100\" />\n\n### `radius.150` · 12 px\n\nCards, and a group of controls with 4 px padding, such as a segmented control.\n\n<ShapeDemo kind=\"radius-use\" item=\"150\" />\n\n### `radius.200` · 16 px\n\nDialogs and drawers, and a group of controls with 8 px padding.\n\n<ShapeDemo kind=\"radius-use\" item=\"200\" />\n\n### `radius.full` · pill\n\nAvatars, switches and pill-shaped status chips.\n\n<ShapeDemo kind=\"radius-use\" item=\"full\" />\n\n## Shapes inside shapes\n\n**Inner radius = outer radius − padding.** Use it when the padding is smaller than the outer radius. When the padding is larger, the inner element keeps its own radius, as long as it is not larger than the outer one.\n\n<ShapeDemo kind=\"nesting\" />\n\n`radius.025` and `radius.075` exist for these cases only. No component takes them by default.\n\nWith the spacing rules, the result is always a step on the scale: 2 px is never padding, and 6 px is padding only inside a component.\n\nWhen content sits flush inside a box with a 1 px border, clip it with `overflow: hidden`. Don't make a radius − 1 value.\n\n## Focus ring\n\nThe focus ring sits 2 px outside the element, and the browser rounds it to match: an 8 px button gets a 10 px ring. No radius token is needed. See [Border](/foundations/styles/border/) for the ring itself.\n\n<ShapeDemo kind=\"focus-radius\" />\n\n## Do and don’t\n\n<ShapeDemo kind=\"dodont\" item=\"nested\" />\n<ShapeDemo kind=\"dodont\" item=\"controls\" />\n<ShapeDemo kind=\"dodont\" item=\"corners\" />\n\n## Code\n\n```css\n.card {\n border-radius: var(--bh-radius-150);\n padding: var(--bh-space-050);\n}\n.card img {\n border-radius: var(--bh-radius-100); /* 12 − 4 = 8 */\n}\n```\n\n## Tokens\n\n<TokenTable prefix=\"radius\" />\n\n## Related\n\n- [Border](/foundations/styles/border/): border widths, the selected bar and the focus ring.\n- [Spacing](/foundations/styles/spacing/): the padding values used in the nesting rule.\n",
712
+ "frontmatter": {
713
+ "title": "Radius",
714
+ "description": "Eight corner radius steps, which element takes which step, and how to round shapes inside other shapes.",
715
+ "order": 6
716
+ }
717
+ },
718
+ {
719
+ "id": "en/foundations/styles/size-and-density",
720
+ "path": "src/content/foundations/styles/size-and-density.mdx",
721
+ "documentPath": "docs/src/content/foundations/styles/size-and-density.mdx",
722
+ "locale": "en",
723
+ "kind": "guidance",
724
+ "title": "Size and density",
725
+ "status": "active",
726
+ "releasePhase": null,
727
+ "planned": [],
728
+ "body": "import LayoutDemo from '../../../components/LayoutDemo.astro';\nimport TokenTable from '../../../components/TokenTable.astro';\n\n**Every control comes in three heights: 24, 32 and 40 px. Controls in one row share one height.**\n\nControls are the things people click or type in: buttons, text fields, selects, segmented controls and tabs. A fixed height keeps a row of them lined up, whatever their text.\n\n<LayoutDemo kind=\"controls\" />\n\n| Size | Height | Where |\n|---|---|---|\n| Small | 24 px | Dense tables and their toolbars, filters, tags |\n| Default | 32 px | Forms, buttons, the header, toolbars, everything else |\n| Large | 40 px | Sign-in and onboarding pages. Optional for the main action on touch screens |\n\n- Keep controls of one height in one row. A 24 px button next to a 32 px field looks misaligned.\n- Set heights with the size tokens, not with padding. The text sits in the middle of the height.\n\n## Target size\n\n**Every control can be clicked in an area of at least 24 × 24 px, and tapped in 44 × 44 px on touch screens.**\n\n- 24 px is the minimum target size of WCAG 2.2 (SC 2.5.8). Every control height meets it.\n- On touch screens, keep the visible height and make the area that responds to a tap at least 44 × 44 px (`size.target.touch`).\n\n## Density\n\n**Beehexa has one density for now: default.**\n\nOne density means every screen is designed and checked at one size. A compact density may come later; it would lower control heights and spacing together, and screens that use the tokens will need no change.\n\nUntil then, make a dense table with small (24 px) controls and rows, not with smaller spacing tokens.\n\n## Tokens\n\n<TokenTable prefix=\"size\" />\n",
729
+ "raw": "---\ntitle: Size and density\ndescription: The three control heights, the size of a target people can click or tap, and how dense Beehexa screens are.\norder: 5\n---\nimport LayoutDemo from '../../../components/LayoutDemo.astro';\nimport TokenTable from '../../../components/TokenTable.astro';\n\n**Every control comes in three heights: 24, 32 and 40 px. Controls in one row share one height.**\n\nControls are the things people click or type in: buttons, text fields, selects, segmented controls and tabs. A fixed height keeps a row of them lined up, whatever their text.\n\n<LayoutDemo kind=\"controls\" />\n\n| Size | Height | Where |\n|---|---|---|\n| Small | 24 px | Dense tables and their toolbars, filters, tags |\n| Default | 32 px | Forms, buttons, the header, toolbars, everything else |\n| Large | 40 px | Sign-in and onboarding pages. Optional for the main action on touch screens |\n\n- Keep controls of one height in one row. A 24 px button next to a 32 px field looks misaligned.\n- Set heights with the size tokens, not with padding. The text sits in the middle of the height.\n\n## Target size\n\n**Every control can be clicked in an area of at least 24 × 24 px, and tapped in 44 × 44 px on touch screens.**\n\n- 24 px is the minimum target size of WCAG 2.2 (SC 2.5.8). Every control height meets it.\n- On touch screens, keep the visible height and make the area that responds to a tap at least 44 × 44 px (`size.target.touch`).\n\n## Density\n\n**Beehexa has one density for now: default.**\n\nOne density means every screen is designed and checked at one size. A compact density may come later; it would lower control heights and spacing together, and screens that use the tokens will need no change.\n\nUntil then, make a dense table with small (24 px) controls and rows, not with smaller spacing tokens.\n\n## Tokens\n\n<TokenTable prefix=\"size\" />\n",
730
+ "frontmatter": {
731
+ "title": "Size and density",
732
+ "description": "The three control heights, the size of a target people can click or tap, and how dense Beehexa screens are.",
733
+ "order": 5
734
+ }
735
+ },
736
+ {
737
+ "id": "en/foundations/styles/spacing",
738
+ "path": "src/content/foundations/styles/spacing.mdx",
739
+ "documentPath": "docs/src/content/foundations/styles/spacing.mdx",
740
+ "locale": "en",
741
+ "kind": "guidance",
742
+ "title": "Spacing",
743
+ "status": "active",
744
+ "releasePhase": null,
745
+ "planned": [],
746
+ "body": "import SpacingDemo from '../../../components/SpacingDemo.astro';\n\n**Every space is a spacing token. Pick the step by how closely two things belong together.**\n\nThings that belong together sit close. Separate groups sit further apart. Readers see the groups before they read a word.\n\n<SpacingDemo kind=\"anatomy\" />\n\n## The scale\n\n**14 steps on an 8 px base. Each step has its own job, shown beside it.**\n\nThe token number is a percentage of 8 px: `space.100` is 8 px, `space.200` is 16 px, and `space.075` is 6 px. The steps grow further apart as they get larger, because a 4 px change is clear between small gaps and invisible between large ones.\n\n<SpacingDemo kind=\"scale\" />\n\nWhen two things could take either of two steps, ask how much they belong together. More related means smaller.\n\n### Padding and gap\n\n<SpacingDemo kind=\"padding-gap\" />\n\n- Padding is the space inside an element. Set it on the element.\n- Gap is the space between elements. Set it on their parent with `gap`, in flex or grid layout.\n- Avoid margins between siblings. They add up where two meet and leave space after the last item; `gap` does neither.\n- Measure padding from the outer edge, border included. A 32 px input with a 1 px border has 11 px of padding inside the border, so its text sits 12 px from the edge.\n\n## The 8 px base\n\n**From 8 px up, every space is a multiple of 4 px. Below 8 px, the scale also has two 2 px steps: 2 and 6 px.**\n\n| Range | Steps | Use |\n|---|---|---|\n| Compact, below 8 px | 2, 4, 6 | Inside components only |\n| From 8 px | 8, 12, 16, 20, 24, 32, 40, 48, 64, 80 | Components, layout and page sections |\n\n- Text line heights are multiples of 4 px too (see [Typography](/foundations/styles/typography/)). Text, controls and spaces line up.\n- Use `space.025` (2 px) only to nudge a small thing into place: a badge on an icon, a status dot beside text. Never use it between controls or as padding.\n- Use `space.075` (6 px) only inside components, in two places: above and below the label of a 32 px control, where (32 − 20) ÷ 2 = 6, and the sides of a tooltip. Never use it for layout, sections or card padding, or between an icon and text: that gap is 4 px next to 14 px text and 8 px next to 16 px text and larger.\n- Borders and focus rings are not spacing. Keep them out of your sums except for padding, as above.\n\n### No negative space\n\nThere are no negative spacing tokens.\n\n- When two things overlap, such as a stack of avatars, the component sets the overlap.\n- Do not use a negative margin to pull an element into line. Fix the spacing around it.\n\n## Do and don’t\n\n<SpacingDemo kind=\"dodont\" item=\"grouping\" />\n<SpacingDemo kind=\"dodont\" item=\"scale\" />\n<SpacingDemo kind=\"dodont\" item=\"nudge\" />\n\n## Vietnamese text\n\nVietnamese text needs taller lines for its accents. The text styles add that height on their own (see [Typography](/foundations/styles/typography/)), so spacing does not change: use the same tokens in both languages.\n\nVietnamese labels are often longer than English ones. Let them wrap, or give the container room. Do not take space away to make a label fit.\n\n## Related\n\n- [App frame](/foundations/styles/layout/app-frame/): the spacing that lines up the header, side navigation and page header.\n- [Grid](/foundations/styles/layout/grid/): columns, gutters and page margins at each breakpoint.\n- [Size and density](/foundations/styles/size-and-density/): control heights.\n",
747
+ "raw": "---\ntitle: Spacing\ndescription: A spacing scale of 14 steps on an 8 px base for padding, gaps and margins, and how to choose a step.\norder: 3\n---\nimport SpacingDemo from '../../../components/SpacingDemo.astro';\n\n**Every space is a spacing token. Pick the step by how closely two things belong together.**\n\nThings that belong together sit close. Separate groups sit further apart. Readers see the groups before they read a word.\n\n<SpacingDemo kind=\"anatomy\" />\n\n## The scale\n\n**14 steps on an 8 px base. Each step has its own job, shown beside it.**\n\nThe token number is a percentage of 8 px: `space.100` is 8 px, `space.200` is 16 px, and `space.075` is 6 px. The steps grow further apart as they get larger, because a 4 px change is clear between small gaps and invisible between large ones.\n\n<SpacingDemo kind=\"scale\" />\n\nWhen two things could take either of two steps, ask how much they belong together. More related means smaller.\n\n### Padding and gap\n\n<SpacingDemo kind=\"padding-gap\" />\n\n- Padding is the space inside an element. Set it on the element.\n- Gap is the space between elements. Set it on their parent with `gap`, in flex or grid layout.\n- Avoid margins between siblings. They add up where two meet and leave space after the last item; `gap` does neither.\n- Measure padding from the outer edge, border included. A 32 px input with a 1 px border has 11 px of padding inside the border, so its text sits 12 px from the edge.\n\n## The 8 px base\n\n**From 8 px up, every space is a multiple of 4 px. Below 8 px, the scale also has two 2 px steps: 2 and 6 px.**\n\n| Range | Steps | Use |\n|---|---|---|\n| Compact, below 8 px | 2, 4, 6 | Inside components only |\n| From 8 px | 8, 12, 16, 20, 24, 32, 40, 48, 64, 80 | Components, layout and page sections |\n\n- Text line heights are multiples of 4 px too (see [Typography](/foundations/styles/typography/)). Text, controls and spaces line up.\n- Use `space.025` (2 px) only to nudge a small thing into place: a badge on an icon, a status dot beside text. Never use it between controls or as padding.\n- Use `space.075` (6 px) only inside components, in two places: above and below the label of a 32 px control, where (32 − 20) ÷ 2 = 6, and the sides of a tooltip. Never use it for layout, sections or card padding, or between an icon and text: that gap is 4 px next to 14 px text and 8 px next to 16 px text and larger.\n- Borders and focus rings are not spacing. Keep them out of your sums except for padding, as above.\n\n### No negative space\n\nThere are no negative spacing tokens.\n\n- When two things overlap, such as a stack of avatars, the component sets the overlap.\n- Do not use a negative margin to pull an element into line. Fix the spacing around it.\n\n## Do and don’t\n\n<SpacingDemo kind=\"dodont\" item=\"grouping\" />\n<SpacingDemo kind=\"dodont\" item=\"scale\" />\n<SpacingDemo kind=\"dodont\" item=\"nudge\" />\n\n## Vietnamese text\n\nVietnamese text needs taller lines for its accents. The text styles add that height on their own (see [Typography](/foundations/styles/typography/)), so spacing does not change: use the same tokens in both languages.\n\nVietnamese labels are often longer than English ones. Let them wrap, or give the container room. Do not take space away to make a label fit.\n\n## Related\n\n- [App frame](/foundations/styles/layout/app-frame/): the spacing that lines up the header, side navigation and page header.\n- [Grid](/foundations/styles/layout/grid/): columns, gutters and page margins at each breakpoint.\n- [Size and density](/foundations/styles/size-and-density/): control heights.\n",
748
+ "frontmatter": {
749
+ "title": "Spacing",
750
+ "description": "A spacing scale of 14 steps on an 8 px base for padding, gaps and margins, and how to choose a step.",
751
+ "order": 3
752
+ }
753
+ },
754
+ {
755
+ "id": "en/foundations/styles/typography/code",
756
+ "path": "src/content/foundations/styles/typography/code.mdx",
757
+ "documentPath": "docs/src/content/foundations/styles/typography/code.mdx",
758
+ "locale": "en",
759
+ "kind": "guidance",
760
+ "title": "Code",
761
+ "status": "active",
762
+ "releasePhase": null,
763
+ "planned": [],
764
+ "body": "import TokenTable from '../../../../components/TokenTable.astro';\nimport TypeDemo from '../../../../components/TypeDemo.astro';\n\n## Font stacks\n\nUse the tokens, not your own lists.\n\n```css\n/* font.family.sans */\nfont-family: Inter, \"Noto Sans\", system-ui, sans-serif;\n\n/* font.family.mono */\nfont-family: \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n```\n\nNoto Sans is the fallback because it covers Vietnamese and ₫ and is close to Inter in size (x-height 0.536 em against Inter's 0.546), so a page that falls back keeps its layout.\n\n## Getting the fonts\n\n- **On the web,** self-host the fonts. Use the Inter build from the Google Fonts repository (`github.com/google/fonts`, `ofl/inter`): it is hinted for small text on Windows and keeps every OpenType feature. Don't link the Google Fonts API: its files drop `cv05`, `cv08`, `ss02` and `zero`, and `cv05` and `cv08` are on by default (see [Numbers and codes](#numbers-and-codes)). This site serves those files, cut into Latin, Latin Extended and Vietnamese subsets.\n- **On your computer,** for Figma, slides and documents, install Inter from Google Fonts and JetBrains Mono from JetBrains. The Google Fonts build of Inter also avoids clipped accents in older Windows apps such as Office.\n- Both licences allow use in products, documents and logos.\n\n## Numbers and codes\n\n`cv05` and `cv08` are on for all Inter text. They give lowercase l a tail and uppercase I serifs, so l, I and 1 never look alike in names, IDs and keys. Turn the rest on where they help; leave body text as it is.\n\n- **Tables and changing values:** use tabular figures (`font-variant-numeric: tabular-nums`), so digits line up in columns and counters don't jitter.\n- **Codes people read or type,** such as order numbers, SKUs and API keys: add the slashed zero (`zero`) to Inter, or set them in JetBrains Mono (`code.default`). JetBrains Mono has no `cv05` or `cv08`, so code looks the same.\n\n<TypeDemo kind=\"numbers\" />\n\n<TypeDemo kind=\"features\" />\n\nEvery text style is applied with the `font` shorthand, and the shorthand resets `font-feature-settings`. So the features are set on every element from one variable, `--bh-font-features`; to add a feature, change the variable, not the property.\n\n```css\n/* Base: on every element */\n:root { --bh-font-features: \"cv05\", \"cv08\"; }\n*, ::before, ::after { font-feature-settings: var(--bh-font-features) !important; }\n\n/* Opt in where needed */\n.table-number { font-variant-numeric: tabular-nums; }\n.code-value { --bh-font-features: \"cv05\", \"cv08\", \"zero\"; }\n```\n\n## Tokens\n<TokenTable prefix=\"font\" />\n",
765
+ "raw": "---\ntitle: Code\ndescription: Font stacks, getting the fonts, OpenType features for numbers and codes, and the type tokens.\norder: 3\n---\nimport TokenTable from '../../../../components/TokenTable.astro';\nimport TypeDemo from '../../../../components/TypeDemo.astro';\n\n## Font stacks\n\nUse the tokens, not your own lists.\n\n```css\n/* font.family.sans */\nfont-family: Inter, \"Noto Sans\", system-ui, sans-serif;\n\n/* font.family.mono */\nfont-family: \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n```\n\nNoto Sans is the fallback because it covers Vietnamese and ₫ and is close to Inter in size (x-height 0.536 em against Inter's 0.546), so a page that falls back keeps its layout.\n\n## Getting the fonts\n\n- **On the web,** self-host the fonts. Use the Inter build from the Google Fonts repository (`github.com/google/fonts`, `ofl/inter`): it is hinted for small text on Windows and keeps every OpenType feature. Don't link the Google Fonts API: its files drop `cv05`, `cv08`, `ss02` and `zero`, and `cv05` and `cv08` are on by default (see [Numbers and codes](#numbers-and-codes)). This site serves those files, cut into Latin, Latin Extended and Vietnamese subsets.\n- **On your computer,** for Figma, slides and documents, install Inter from Google Fonts and JetBrains Mono from JetBrains. The Google Fonts build of Inter also avoids clipped accents in older Windows apps such as Office.\n- Both licences allow use in products, documents and logos.\n\n## Numbers and codes\n\n`cv05` and `cv08` are on for all Inter text. They give lowercase l a tail and uppercase I serifs, so l, I and 1 never look alike in names, IDs and keys. Turn the rest on where they help; leave body text as it is.\n\n- **Tables and changing values:** use tabular figures (`font-variant-numeric: tabular-nums`), so digits line up in columns and counters don't jitter.\n- **Codes people read or type,** such as order numbers, SKUs and API keys: add the slashed zero (`zero`) to Inter, or set them in JetBrains Mono (`code.default`). JetBrains Mono has no `cv05` or `cv08`, so code looks the same.\n\n<TypeDemo kind=\"numbers\" />\n\n<TypeDemo kind=\"features\" />\n\nEvery text style is applied with the `font` shorthand, and the shorthand resets `font-feature-settings`. So the features are set on every element from one variable, `--bh-font-features`; to add a feature, change the variable, not the property.\n\n```css\n/* Base: on every element */\n:root { --bh-font-features: \"cv05\", \"cv08\"; }\n*, ::before, ::after { font-feature-settings: var(--bh-font-features) !important; }\n\n/* Opt in where needed */\n.table-number { font-variant-numeric: tabular-nums; }\n.code-value { --bh-font-features: \"cv05\", \"cv08\", \"zero\"; }\n```\n\n## Tokens\n<TokenTable prefix=\"font\" />\n",
766
+ "frontmatter": {
767
+ "title": "Code",
768
+ "description": "Font stacks, getting the fonts, OpenType features for numbers and codes, and the type tokens.",
769
+ "order": 3
770
+ }
771
+ },
772
+ {
773
+ "id": "en/foundations/styles/typography/index",
774
+ "path": "src/content/foundations/styles/typography/index.mdx",
775
+ "documentPath": "docs/src/content/foundations/styles/typography/index.mdx",
776
+ "locale": "en",
777
+ "kind": "guidance",
778
+ "title": "Typography",
779
+ "status": "active",
780
+ "releasePhase": null,
781
+ "planned": [],
782
+ "body": "import TypeDemo from '../../../../components/TypeDemo.astro';\n\n## Typefaces\n\nTwo typefaces cover everything: Inter for interface and reading text, JetBrains Mono for code.\n\n<TypeDemo kind=\"faces\" />\n\nInter was chosen because:\n\n- Its tall x-height keeps small interface text legible.\n- It covers Vietnamese in full, the ₫ sign included.\n- It has OpenType features that tell look-alike characters apart, such as l, I and 1, which matters in a product full of order numbers and API keys.\n- It is open source under the SIL Open Font License, so it can be self-hosted and embedded.\n- It is the typeface of the Beehexa wordmark, so product text and logo belong to one family.\n\nInter has an optical size axis: from 32 px up it draws as Inter Display, with tighter spacing for headings. Browsers apply it on their own; leave `font-optical-sizing` at `auto`.\n\n## Text styles\n\nText is set with **text styles**, not loose sizes. Each style is one token that carries size, line height, weight and typeface together, named for its role. Fourteen styles in five groups cover every Beehexa product, document and page.\n\n<TypeDemo kind=\"styles\" />\n\n- **Display** is for marketing pages only. Product screens start at `heading.xlarge`.\n- **Heading** styles title pages, sections, cards and groups. Use one `heading.large` per page, as its title.\n- **Body** is for running text. `body.default` (14 px) is the default in product UI; `body.large` (16 px) is for text people read rather than scan.\n- **Label** is for text on or beside controls: buttons, form labels, tabs, menus, badges.\n- **Code** is for code, IDs and keys.\n\n## Weights\n\n| Weight | Token | Use |\n|---|---|---|\n| 400 | `font.weight.regular` | Body text |\n| 500 | `font.weight.medium` | Labels |\n| 600 | `font.weight.semibold` | Headings |\n| 700 | `font.weight.bold` | Display only |\n\nDon't go lighter than 400: thin strokes break up on small text. Bold body text is not a heading; for emphasis that matters to the meaning, use `<strong>` or `<em>`, so screen readers get it too.\n\n## Letter spacing\n\nLeave it at 0. Inter's optical size axis already tightens large text, so headings need no negative tracking, and small text stays at its default spacing.\n\n## Line height\n\nLine heights are part of each text style and sit on the 4 px grid: every one is a multiple of 4 px, so text lines up with spacing and components.\n\n- Body and label styles use 1.3–1.5 times the size (14/20, 12/16, 16/24), which leave room between lines of interface text without spreading a paragraph apart.\n- Headings tighten as they grow, to about 1.1–1.25 for display sizes, so large type stays one block.\n- Vietnamese text uses taller values; see [Vietnamese](/foundations/styles/typography/vietnamese/).\n",
783
+ "raw": "---\ntitle: Typography\ndescription: Two typefaces and fourteen text styles, with their weights, letter spacing and line heights.\norder: 2\nsidebarLabel: Overview\n---\nimport TypeDemo from '../../../../components/TypeDemo.astro';\n\n## Typefaces\n\nTwo typefaces cover everything: Inter for interface and reading text, JetBrains Mono for code.\n\n<TypeDemo kind=\"faces\" />\n\nInter was chosen because:\n\n- Its tall x-height keeps small interface text legible.\n- It covers Vietnamese in full, the ₫ sign included.\n- It has OpenType features that tell look-alike characters apart, such as l, I and 1, which matters in a product full of order numbers and API keys.\n- It is open source under the SIL Open Font License, so it can be self-hosted and embedded.\n- It is the typeface of the Beehexa wordmark, so product text and logo belong to one family.\n\nInter has an optical size axis: from 32 px up it draws as Inter Display, with tighter spacing for headings. Browsers apply it on their own; leave `font-optical-sizing` at `auto`.\n\n## Text styles\n\nText is set with **text styles**, not loose sizes. Each style is one token that carries size, line height, weight and typeface together, named for its role. Fourteen styles in five groups cover every Beehexa product, document and page.\n\n<TypeDemo kind=\"styles\" />\n\n- **Display** is for marketing pages only. Product screens start at `heading.xlarge`.\n- **Heading** styles title pages, sections, cards and groups. Use one `heading.large` per page, as its title.\n- **Body** is for running text. `body.default` (14 px) is the default in product UI; `body.large` (16 px) is for text people read rather than scan.\n- **Label** is for text on or beside controls: buttons, form labels, tabs, menus, badges.\n- **Code** is for code, IDs and keys.\n\n## Weights\n\n| Weight | Token | Use |\n|---|---|---|\n| 400 | `font.weight.regular` | Body text |\n| 500 | `font.weight.medium` | Labels |\n| 600 | `font.weight.semibold` | Headings |\n| 700 | `font.weight.bold` | Display only |\n\nDon't go lighter than 400: thin strokes break up on small text. Bold body text is not a heading; for emphasis that matters to the meaning, use `<strong>` or `<em>`, so screen readers get it too.\n\n## Letter spacing\n\nLeave it at 0. Inter's optical size axis already tightens large text, so headings need no negative tracking, and small text stays at its default spacing.\n\n## Line height\n\nLine heights are part of each text style and sit on the 4 px grid: every one is a multiple of 4 px, so text lines up with spacing and components.\n\n- Body and label styles use 1.3–1.5 times the size (14/20, 12/16, 16/24), which leave room between lines of interface text without spreading a paragraph apart.\n- Headings tighten as they grow, to about 1.1–1.25 for display sizes, so large type stays one block.\n- Vietnamese text uses taller values; see [Vietnamese](/foundations/styles/typography/vietnamese/).\n",
784
+ "frontmatter": {
785
+ "title": "Typography",
786
+ "description": "Two typefaces and fourteen text styles, with their weights, letter spacing and line heights.",
787
+ "order": 2,
788
+ "sidebarLabel": "Overview"
789
+ }
790
+ },
791
+ {
792
+ "id": "en/foundations/styles/typography/usage",
793
+ "path": "src/content/foundations/styles/typography/usage.mdx",
794
+ "documentPath": "docs/src/content/foundations/styles/typography/usage.mdx",
795
+ "locale": "en",
796
+ "kind": "guidance",
797
+ "title": "Usage",
798
+ "status": "active",
799
+ "releasePhase": null,
800
+ "planned": [],
801
+ "body": "import TypeDemo from '../../../../components/TypeDemo.astro';\n\n## Where each style goes\n\nProduct UI uses these styles; component pages name the style each part uses. When a part isn't listed, use the style of the nearest one with the same role.\n\n| Part | Style |\n|---|---|\n| **Page structure** | |\n| Page title | `heading.large` |\n| Section title | `heading.medium` |\n| Breadcrumb | `body.small` |\n| Large title on empty states and onboarding | `heading.xlarge` |\n| **Containers** | |\n| Card, panel and drawer title | `heading.small` |\n| Item title in a grid or list of many cards | `heading.xsmall` |\n| Card description | `body.default` |\n| Dialog title | `heading.medium` |\n| Dialog body | `body.default` |\n| Group title in a form, list or menu | `heading.xsmall` |\n| **Forms** | |\n| Field label | `label.default` |\n| Input text and placeholder | `body.default` |\n| Helper and error text | `body.small` |\n| Checkbox and radio text | `body.default` |\n| **Actions and navigation** | |\n| Button, link button | `label.default` |\n| Small button | `label.small` |\n| Tab, menu item, side navigation item | `label.default` |\n| Top navigation item | `label.default` |\n| **Data** | |\n| Table header | `label.small` |\n| Table cell | `body.default` |\n| Number in a table | `body.default` with tabular figures |\n| ID, SKU, key in a table | `code.default` |\n| Badge, tag, status | `label.small` |\n| Number in a card, such as a KPI | `heading.large` with tabular figures |\n| Label under a number | `body.small` |\n| **Feedback** | |\n| Banner and toast title | `heading.xsmall` |\n| Banner and toast message | `body.default` |\n| Tooltip | `body.small` |\n| Timestamp, meta | `body.small` |\n| **Reading** | |\n| Help article, document, email body | `body.large` |\n| Inline code | `code.default` family at the surrounding size |\n\n<TypeDemo kind=\"ui\" />\n\n## On websites and documentation\n\nWebsites and documentation, this site included, use the same styles. Two things differ from product UI: the page title is one step larger, and running text is `body.large`, because people read these pages rather than scan them.\n\n| Part | Style |\n|---|---|\n| **Site header** | |\n| Top navigation item | `label.default` |\n| Search field | `body.default` |\n| Keyboard shortcut hint | `label.small` |\n| Search result title | `label.default` |\n| Search result description | `body.small` |\n| **Sidebar** | |\n| Section | `heading.xsmall` |\n| Group label | `label.small` |\n| Page and sub-page | `label.default` |\n| **Table of contents** | |\n| Title (\"On this page\") | `heading.xsmall` |\n| Link | `label.default` |\n| **Page** | |\n| Breadcrumb | `body.small` |\n| Page title | `heading.xlarge` |\n| Lede under the title | `body.large` |\n| Section title (`h2`) | `heading.large` |\n| Subsection title (`h3`) | `heading.medium` |\n| Minor title (`h4`) | `heading.small` |\n| Running text and lists | `body.large` |\n| Table text | `body.default` |\n| Table header | `label.small` |\n| Code block | `code.default` |\n| Inline code | `code.default` family at the surrounding size |\n| Card title | `heading.small` |\n| Card text | `body.default` |\n| Status badge | `label.small` |\n| Tabs | `label.default` |\n| Previous and next links | `body.small` label, `heading.small` page name |\n| Footer and page meta | `body.small` |\n\n## Using the styles\n\nIn CSS, each style is one `font` declaration:\n\n```css\n.page-title { font: var(--bh-font-heading-large); }\n.card-title { font: var(--bh-font-heading-small); }\n.field-label { font: var(--bh-font-label-default); }\n.helper-text { font: var(--bh-font-body-small); }\n.kpi-value { font: var(--bh-font-heading-large); font-variant-numeric: tabular-nums; }\n```\n\n- Use a style as a whole. Don't take its size and set your own weight or line height: a near-miss style looks like a mistake next to the real one.\n- Don't make a new style for one screen. If a role is missing, add it here first.\n- Set colour separately, with `color.text.*` tokens.\n- Show the selected item, such as the current page or tab, with colour and an indicator bar, not with a heavier weight: a bolder word gets wider and shifts its neighbours.\n- Bold inside text (`<strong>`, `<b>`) is semibold, 600. Weight 700 stays with the display styles.\n- When one row mixes styles, such as an order ID in `code.default`, a badge and an amount in `body.default`, align the text on its baseline (`vertical-align: baseline`, or `align-items: baseline` in flex), not on the middle. Each style sits differently in its line height, so centring them puts the letters at different heights.\n\n\n## Sizes on small screens\n\n- Product styles keep their size on every screen. Text that changes size between breakpoints makes dense screens harder to learn.\n- Display styles step down below 768 px (`breakpoint.md`): `display.large` and `display.medium` become `display.small`, and `display.small` becomes `heading.xlarge`.\n- All sizes are in `rem`, so text follows the reader's browser setting and zoom.\n\n## Hierarchy\n\n- One page title (`h1`) per page. Go down the heading levels in order, without skipping one.\n- Mark up structure with headings, not with bold or larger paragraphs.\n- Show importance with size and weight first. Don't rely on color alone.\n\n## Readability\n\n- Keep lines to about 100 characters or fewer: put long text on a Narrow page (see [Page widths](/foundations/styles/layout/page-widths/)).\n- Align text to the left, ragged right. Don't justify it; center only short, standalone text.\n- Write in sentence case. Don't set text in all caps: it is slower to read, and in Vietnamese the marks crowd the line above.\n- Use italics sparingly, for titles and terms.\n\n## Long text\n\nOrder names, URLs and IDs have no length limit.\n\n- Truncate one-line text with an ellipsis, and always give another way to read the full value, such as a tooltip or a detail view.\n- Let long unbroken strings, such as URLs and keys, break anywhere rather than overflow.\n- Never truncate text people need to finish a task.\n\n## Accessibility\n\n- Text needs a contrast of at least 4.5 : 1 with its background; large text (24 px, or 18.66 px bold) at least 3 : 1. See [Color](/foundations/styles/color/).\n- Set sizes in `rem` and never block zoom, so text can grow to 200% (WCAG 1.4.4).\n- Don't put text in images. Real text scales, translates and reads aloud.\n",
802
+ "raw": "---\ntitle: Usage\ndescription: Which text style each part of a screen uses, and the rules for hierarchy, readability and long text.\norder: 1\n---\nimport TypeDemo from '../../../../components/TypeDemo.astro';\n\n## Where each style goes\n\nProduct UI uses these styles; component pages name the style each part uses. When a part isn't listed, use the style of the nearest one with the same role.\n\n| Part | Style |\n|---|---|\n| **Page structure** | |\n| Page title | `heading.large` |\n| Section title | `heading.medium` |\n| Breadcrumb | `body.small` |\n| Large title on empty states and onboarding | `heading.xlarge` |\n| **Containers** | |\n| Card, panel and drawer title | `heading.small` |\n| Item title in a grid or list of many cards | `heading.xsmall` |\n| Card description | `body.default` |\n| Dialog title | `heading.medium` |\n| Dialog body | `body.default` |\n| Group title in a form, list or menu | `heading.xsmall` |\n| **Forms** | |\n| Field label | `label.default` |\n| Input text and placeholder | `body.default` |\n| Helper and error text | `body.small` |\n| Checkbox and radio text | `body.default` |\n| **Actions and navigation** | |\n| Button, link button | `label.default` |\n| Small button | `label.small` |\n| Tab, menu item, side navigation item | `label.default` |\n| Top navigation item | `label.default` |\n| **Data** | |\n| Table header | `label.small` |\n| Table cell | `body.default` |\n| Number in a table | `body.default` with tabular figures |\n| ID, SKU, key in a table | `code.default` |\n| Badge, tag, status | `label.small` |\n| Number in a card, such as a KPI | `heading.large` with tabular figures |\n| Label under a number | `body.small` |\n| **Feedback** | |\n| Banner and toast title | `heading.xsmall` |\n| Banner and toast message | `body.default` |\n| Tooltip | `body.small` |\n| Timestamp, meta | `body.small` |\n| **Reading** | |\n| Help article, document, email body | `body.large` |\n| Inline code | `code.default` family at the surrounding size |\n\n<TypeDemo kind=\"ui\" />\n\n## On websites and documentation\n\nWebsites and documentation, this site included, use the same styles. Two things differ from product UI: the page title is one step larger, and running text is `body.large`, because people read these pages rather than scan them.\n\n| Part | Style |\n|---|---|\n| **Site header** | |\n| Top navigation item | `label.default` |\n| Search field | `body.default` |\n| Keyboard shortcut hint | `label.small` |\n| Search result title | `label.default` |\n| Search result description | `body.small` |\n| **Sidebar** | |\n| Section | `heading.xsmall` |\n| Group label | `label.small` |\n| Page and sub-page | `label.default` |\n| **Table of contents** | |\n| Title (\"On this page\") | `heading.xsmall` |\n| Link | `label.default` |\n| **Page** | |\n| Breadcrumb | `body.small` |\n| Page title | `heading.xlarge` |\n| Lede under the title | `body.large` |\n| Section title (`h2`) | `heading.large` |\n| Subsection title (`h3`) | `heading.medium` |\n| Minor title (`h4`) | `heading.small` |\n| Running text and lists | `body.large` |\n| Table text | `body.default` |\n| Table header | `label.small` |\n| Code block | `code.default` |\n| Inline code | `code.default` family at the surrounding size |\n| Card title | `heading.small` |\n| Card text | `body.default` |\n| Status badge | `label.small` |\n| Tabs | `label.default` |\n| Previous and next links | `body.small` label, `heading.small` page name |\n| Footer and page meta | `body.small` |\n\n## Using the styles\n\nIn CSS, each style is one `font` declaration:\n\n```css\n.page-title { font: var(--bh-font-heading-large); }\n.card-title { font: var(--bh-font-heading-small); }\n.field-label { font: var(--bh-font-label-default); }\n.helper-text { font: var(--bh-font-body-small); }\n.kpi-value { font: var(--bh-font-heading-large); font-variant-numeric: tabular-nums; }\n```\n\n- Use a style as a whole. Don't take its size and set your own weight or line height: a near-miss style looks like a mistake next to the real one.\n- Don't make a new style for one screen. If a role is missing, add it here first.\n- Set colour separately, with `color.text.*` tokens.\n- Show the selected item, such as the current page or tab, with colour and an indicator bar, not with a heavier weight: a bolder word gets wider and shifts its neighbours.\n- Bold inside text (`<strong>`, `<b>`) is semibold, 600. Weight 700 stays with the display styles.\n- When one row mixes styles, such as an order ID in `code.default`, a badge and an amount in `body.default`, align the text on its baseline (`vertical-align: baseline`, or `align-items: baseline` in flex), not on the middle. Each style sits differently in its line height, so centring them puts the letters at different heights.\n\n\n## Sizes on small screens\n\n- Product styles keep their size on every screen. Text that changes size between breakpoints makes dense screens harder to learn.\n- Display styles step down below 768 px (`breakpoint.md`): `display.large` and `display.medium` become `display.small`, and `display.small` becomes `heading.xlarge`.\n- All sizes are in `rem`, so text follows the reader's browser setting and zoom.\n\n## Hierarchy\n\n- One page title (`h1`) per page. Go down the heading levels in order, without skipping one.\n- Mark up structure with headings, not with bold or larger paragraphs.\n- Show importance with size and weight first. Don't rely on color alone.\n\n## Readability\n\n- Keep lines to about 100 characters or fewer: put long text on a Narrow page (see [Page widths](/foundations/styles/layout/page-widths/)).\n- Align text to the left, ragged right. Don't justify it; center only short, standalone text.\n- Write in sentence case. Don't set text in all caps: it is slower to read, and in Vietnamese the marks crowd the line above.\n- Use italics sparingly, for titles and terms.\n\n## Long text\n\nOrder names, URLs and IDs have no length limit.\n\n- Truncate one-line text with an ellipsis, and always give another way to read the full value, such as a tooltip or a detail view.\n- Let long unbroken strings, such as URLs and keys, break anywhere rather than overflow.\n- Never truncate text people need to finish a task.\n\n## Accessibility\n\n- Text needs a contrast of at least 4.5 : 1 with its background; large text (24 px, or 18.66 px bold) at least 3 : 1. See [Color](/foundations/styles/color/).\n- Set sizes in `rem` and never block zoom, so text can grow to 200% (WCAG 1.4.4).\n- Don't put text in images. Real text scales, translates and reads aloud.\n",
803
+ "frontmatter": {
804
+ "title": "Usage",
805
+ "description": "Which text style each part of a screen uses, and the rules for hierarchy, readability and long text.",
806
+ "order": 1
807
+ }
808
+ },
809
+ {
810
+ "id": "en/foundations/styles/typography/vietnamese",
811
+ "path": "src/content/foundations/styles/typography/vietnamese.mdx",
812
+ "documentPath": "docs/src/content/foundations/styles/typography/vietnamese.mdx",
813
+ "locale": "en",
814
+ "kind": "guidance",
815
+ "title": "Vietnamese",
816
+ "status": "active",
817
+ "releasePhase": null,
818
+ "planned": [],
819
+ "body": "import TypeDemo from '../../../../components/TypeDemo.astro';\n\n**Vietnamese text gets taller line heights, so its stacked marks never touch the line above or get cut off.**\n\nText marked `lang=\"vi\"` gets taller line heights. Vietnamese stacks two marks on some capitals, such as Ấ, Ổ and Ẫ, so they rise well above the other letters. At English line heights those marks touch the line above and are cut off in one-line elements that clip their overflow, such as truncated table cells and button labels.\n\nLine height is the space from one line to the next, so it shows on text of two lines or more. Each shaded band below is one line:\n\n<TypeDemo kind=\"leading\" />\n\nThe Vietnamese layer changes line height only; size, weight and typeface stay the same. Each value is the smallest multiple of 4 px that keeps every Vietnamese letter inside its own line box, so marks neither touch the line above nor get clipped.\n\n| Style | English | Vietnamese |\n|---|---|---|\n| `display.large` | <span class=\"type-num\">72/80</span> | <span class=\"type-num\">72/108</span> |\n| `display.medium` | <span class=\"type-num\">60/68</span> | <span class=\"type-num\">60/88</span> |\n| `display.small` | <span class=\"type-num\">48/56</span> | <span class=\"type-num\">48/72</span> |\n| `heading.xlarge` | <span class=\"type-num\">32/40</span> | <span class=\"type-num\">32/48</span> |\n| `heading.large` | <span class=\"type-num\">24/32</span> | <span class=\"type-num\">24/40</span> |\n| `heading.medium` | <span class=\"type-num\">20/28</span> | <span class=\"type-num\">20/32</span> |\n| `heading.small` | <span class=\"type-num\">16/24</span> | <span class=\"type-num\">16/24</span> (same) |\n| `heading.xsmall` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/24</span> |\n| `body.large` | <span class=\"type-num\">16/24</span> | <span class=\"type-num\">16/24</span> (same) |\n| `body.default` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/24</span> |\n| `body.small` | <span class=\"type-num\">12/16</span> | <span class=\"type-num\">12/20</span> |\n| `label.default` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/24</span> |\n| `label.small` | <span class=\"type-num\">12/16</span> | <span class=\"type-num\">12/20</span> |\n| `code.default` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/20</span> (same) |\n\nEach box below is one line that clips its overflow, with the line box outlined.\n\n<TypeDemo kind=\"vietnamese\" />\n\n- **Mark the language.** Set `lang=\"vi\"` on `<html>` for a Vietnamese page, or on the element that holds Vietnamese text. Text marked with another language inside it, such as `lang=\"en\"`, goes back to the English values.\n- **Use the tokens.** The text style tokens switch on their own under `lang=\"vi\"` (`:lang(vi)` in `tokens.css`). Code that can't read CSS variables, such as an Ant Design Vue theme, takes the `vi` values from `tokens.js`.\n- **Let components grow.** A control or row that sets a fixed height must fit the Vietnamese line height: a 14 px label needs 24 px of line, so set heights from padding plus line height, not as a fixed number.\n- **Don't clip text vertically.** Avoid `overflow: hidden` on a box with no vertical padding; when you must truncate, clip horizontally and let the line box hold the marks.\n- **Test with this string** in every component and state: **ỔN ĐỊNH · ẤN ĐỘ · ẪM · Ở ĐÂY CÓ ƯU ĐÃI**.\n\nJetBrains Mono draws Vietnamese marks inside its own line box, so `code.default` keeps 14/20. This site serves its Vietnamese subset too, so Vietnamese in code doesn't fall back to another typeface.\n\n",
820
+ "raw": "---\ntitle: Vietnamese\ndescription: Taller line heights for Vietnamese text, and how to keep its marks from being cut off.\norder: 2\n---\nimport TypeDemo from '../../../../components/TypeDemo.astro';\n\n**Vietnamese text gets taller line heights, so its stacked marks never touch the line above or get cut off.**\n\nText marked `lang=\"vi\"` gets taller line heights. Vietnamese stacks two marks on some capitals, such as Ấ, Ổ and Ẫ, so they rise well above the other letters. At English line heights those marks touch the line above and are cut off in one-line elements that clip their overflow, such as truncated table cells and button labels.\n\nLine height is the space from one line to the next, so it shows on text of two lines or more. Each shaded band below is one line:\n\n<TypeDemo kind=\"leading\" />\n\nThe Vietnamese layer changes line height only; size, weight and typeface stay the same. Each value is the smallest multiple of 4 px that keeps every Vietnamese letter inside its own line box, so marks neither touch the line above nor get clipped.\n\n| Style | English | Vietnamese |\n|---|---|---|\n| `display.large` | <span class=\"type-num\">72/80</span> | <span class=\"type-num\">72/108</span> |\n| `display.medium` | <span class=\"type-num\">60/68</span> | <span class=\"type-num\">60/88</span> |\n| `display.small` | <span class=\"type-num\">48/56</span> | <span class=\"type-num\">48/72</span> |\n| `heading.xlarge` | <span class=\"type-num\">32/40</span> | <span class=\"type-num\">32/48</span> |\n| `heading.large` | <span class=\"type-num\">24/32</span> | <span class=\"type-num\">24/40</span> |\n| `heading.medium` | <span class=\"type-num\">20/28</span> | <span class=\"type-num\">20/32</span> |\n| `heading.small` | <span class=\"type-num\">16/24</span> | <span class=\"type-num\">16/24</span> (same) |\n| `heading.xsmall` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/24</span> |\n| `body.large` | <span class=\"type-num\">16/24</span> | <span class=\"type-num\">16/24</span> (same) |\n| `body.default` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/24</span> |\n| `body.small` | <span class=\"type-num\">12/16</span> | <span class=\"type-num\">12/20</span> |\n| `label.default` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/24</span> |\n| `label.small` | <span class=\"type-num\">12/16</span> | <span class=\"type-num\">12/20</span> |\n| `code.default` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/20</span> (same) |\n\nEach box below is one line that clips its overflow, with the line box outlined.\n\n<TypeDemo kind=\"vietnamese\" />\n\n- **Mark the language.** Set `lang=\"vi\"` on `<html>` for a Vietnamese page, or on the element that holds Vietnamese text. Text marked with another language inside it, such as `lang=\"en\"`, goes back to the English values.\n- **Use the tokens.** The text style tokens switch on their own under `lang=\"vi\"` (`:lang(vi)` in `tokens.css`). Code that can't read CSS variables, such as an Ant Design Vue theme, takes the `vi` values from `tokens.js`.\n- **Let components grow.** A control or row that sets a fixed height must fit the Vietnamese line height: a 14 px label needs 24 px of line, so set heights from padding plus line height, not as a fixed number.\n- **Don't clip text vertically.** Avoid `overflow: hidden` on a box with no vertical padding; when you must truncate, clip horizontally and let the line box hold the marks.\n- **Test with this string** in every component and state: **ỔN ĐỊNH · ẤN ĐỘ · ẪM · Ở ĐÂY CÓ ƯU ĐÃI**.\n\nJetBrains Mono draws Vietnamese marks inside its own line box, so `code.default` keeps 14/20. This site serves its Vietnamese subset too, so Vietnamese in code doesn't fall back to another typeface.\n\n",
821
+ "frontmatter": {
822
+ "title": "Vietnamese",
823
+ "description": "Taller line heights for Vietnamese text, and how to keep its marks from being cut off.",
824
+ "order": 2
825
+ }
826
+ },
827
+ {
828
+ "id": "en/foundations/styles/z-index",
829
+ "path": "src/content/foundations/styles/z-index.mdx",
830
+ "documentPath": "docs/src/content/foundations/styles/z-index.mdx",
831
+ "locale": "en",
832
+ "kind": "guidance",
833
+ "title": "Z-index",
834
+ "status": "planned",
835
+ "releasePhase": null,
836
+ "planned": [
837
+ "Layer names and their order",
838
+ "Which layer each overlay uses: dropdown, popover, tooltip, dialog, drawer, toast",
839
+ "How layering pairs with elevation"
840
+ ],
841
+ "body": "",
842
+ "raw": "---\ntitle: \"Z-index\"\ndescription: \"The stacking order of layers: what sits above what, from sticky headers to dialogs and toasts.\"\norder: 8.5\nplanned:\n - \"Layer names and their order\"\n - \"Which layer each overlay uses: dropdown, popover, tooltip, dialog, drawer, toast\"\n - \"How layering pairs with elevation\"\n---\n",
843
+ "frontmatter": {
844
+ "title": "Z-index",
845
+ "description": "The stacking order of layers: what sits above what, from sticky headers to dialogs and toasts.",
846
+ "order": 8.5,
847
+ "planned": [
848
+ "Layer names and their order",
849
+ "Which layer each overlay uses: dropdown, popover, tooltip, dialog, drawer, toast",
850
+ "How layering pairs with elevation"
851
+ ]
852
+ }
853
+ },
854
+ {
855
+ "id": "en/foundations/tokens/all-tokens",
856
+ "path": "src/content/foundations/tokens/all-tokens.mdx",
857
+ "documentPath": "docs/src/content/foundations/tokens/all-tokens.mdx",
858
+ "locale": "en",
859
+ "kind": "guidance",
860
+ "title": "All design tokens",
861
+ "status": "active",
862
+ "releasePhase": null,
863
+ "planned": [],
864
+ "body": "import TokenTable from '../../../components/TokenTable.astro';\n\n## Color\n<TokenTable prefix=\"color\" />\n\n## Typography\n<TokenTable prefix=\"font\" />\n\n## Spacing\n<TokenTable prefix=\"space\" />\n\n## Size\n<TokenTable prefix=\"size\" />\n\n## Radius\n<TokenTable prefix=\"radius\" />\n\n## Border\n<TokenTable prefix=\"border\" />\n\n## Elevation\n<TokenTable prefix=\"elevation\" />\n\n## Motion\n<TokenTable prefix=\"motion\" />\n\n## Breakpoints\n<TokenTable prefix=\"breakpoint\" />\n\n## Interaction states\n<TokenTable prefix=\"state\" />\n",
865
+ "raw": "---\ntitle: All design tokens\ndescription: Every Beehexa design token, its value and when to use it.\norder: 2\n---\nimport TokenTable from '../../../components/TokenTable.astro';\n\n## Color\n<TokenTable prefix=\"color\" />\n\n## Typography\n<TokenTable prefix=\"font\" />\n\n## Spacing\n<TokenTable prefix=\"space\" />\n\n## Size\n<TokenTable prefix=\"size\" />\n\n## Radius\n<TokenTable prefix=\"radius\" />\n\n## Border\n<TokenTable prefix=\"border\" />\n\n## Elevation\n<TokenTable prefix=\"elevation\" />\n\n## Motion\n<TokenTable prefix=\"motion\" />\n\n## Breakpoints\n<TokenTable prefix=\"breakpoint\" />\n\n## Interaction states\n<TokenTable prefix=\"state\" />\n",
866
+ "frontmatter": {
867
+ "title": "All design tokens",
868
+ "description": "Every Beehexa design token, its value and when to use it.",
869
+ "order": 2
870
+ }
871
+ },
872
+ {
873
+ "id": "en/foundations/tokens/index",
874
+ "path": "src/content/foundations/tokens/index.mdx",
875
+ "documentPath": "docs/src/content/foundations/tokens/index.mdx",
876
+ "locale": "en",
877
+ "kind": "guidance",
878
+ "title": "Tokens overview",
879
+ "status": "active",
880
+ "releasePhase": null,
881
+ "planned": [],
882
+ "body": "\n## Why tokens\n\nA token gives a design decision a name. Design files and code both use the name, so a change to the value reaches every product at once and nothing drifts.\n\n## Naming\n\nTokens are named from general to specific, separated by dots in the source and by dashes in CSS:\n\n| Source name | CSS custom property |\n| --- | --- |\n| `color.text` | `--bh-color-text` |\n| `space.200` | `--bh-space-200` |\n| `color.border.focus` | `--bh-color-border-focus` |\n\n## Where tokens live\n\nEvery token has one value, kept in one place. The token tables on this site and the CSS variables in products come from that same source, so they never drift apart.\n\nA token can point at another token, for example `{color.graphite.12}`. Use the role token (`color.text`) in products rather than the raw palette token (`color.graphite.12`) when one exists.\n\nSee [All design tokens](/foundations/tokens/all-tokens/) for the full list.\n",
883
+ "raw": "---\ntitle: Tokens overview\ndescription: Design tokens are named design decisions, such as a color or a spacing step, shared by design and code.\norder: 1\n---\n\n## Why tokens\n\nA token gives a design decision a name. Design files and code both use the name, so a change to the value reaches every product at once and nothing drifts.\n\n## Naming\n\nTokens are named from general to specific, separated by dots in the source and by dashes in CSS:\n\n| Source name | CSS custom property |\n| --- | --- |\n| `color.text` | `--bh-color-text` |\n| `space.200` | `--bh-space-200` |\n| `color.border.focus` | `--bh-color-border-focus` |\n\n## Where tokens live\n\nEvery token has one value, kept in one place. The token tables on this site and the CSS variables in products come from that same source, so they never drift apart.\n\nA token can point at another token, for example `{color.graphite.12}`. Use the role token (`color.text`) in products rather than the raw palette token (`color.graphite.12`) when one exists.\n\nSee [All design tokens](/foundations/tokens/all-tokens/) for the full list.\n",
884
+ "frontmatter": {
885
+ "title": "Tokens overview",
886
+ "description": "Design tokens are named design decisions, such as a color or a spacing step, shared by design and code.",
887
+ "order": 1
888
+ }
889
+ },
890
+ {
891
+ "id": "en/get-started/content",
892
+ "path": "src/content/get-started/content.mdx",
893
+ "documentPath": "docs/src/content/get-started/content.mdx",
894
+ "locale": "en",
895
+ "kind": "guidance",
896
+ "title": "Content",
897
+ "status": "active",
898
+ "releasePhase": null,
899
+ "planned": [],
900
+ "body": "\nProduct copy is part of the interface. Read the [content guidelines](/foundations/guidelines/content/) before writing labels, messages or empty states.\n\n## Quick rules\n\n- Write in sentence case: \"Create order\", not \"Create Order\".\n- Lead with the action or the outcome.\n- Name things the same way everywhere.\n- Say what went wrong and how to fix it in error messages.\n",
901
+ "raw": "---\ntitle: Content\ndescription: How writers keep product copy clear, concise and consistent.\norder: 3\n---\n\nProduct copy is part of the interface. Read the [content guidelines](/foundations/guidelines/content/) before writing labels, messages or empty states.\n\n## Quick rules\n\n- Write in sentence case: \"Create order\", not \"Create Order\".\n- Lead with the action or the outcome.\n- Name things the same way everywhere.\n- Say what went wrong and how to fix it in error messages.\n",
902
+ "frontmatter": {
903
+ "title": "Content",
904
+ "description": "How writers keep product copy clear, concise and consistent.",
905
+ "order": 3
906
+ }
907
+ },
908
+ {
909
+ "id": "en/get-started/design",
910
+ "path": "src/content/get-started/design.mdx",
911
+ "documentPath": "docs/src/content/get-started/design.mdx",
912
+ "locale": "en",
913
+ "kind": "guidance",
914
+ "title": "Design",
915
+ "status": "active",
916
+ "releasePhase": null,
917
+ "planned": [],
918
+ "body": "\n## Start from tokens\n\nEvery color, size, radius and duration in a design should be a [design token](/foundations/tokens/). If a value you need is missing, ask for a new token rather than adding a one-off value.\n\n## Use existing components\n\nCheck [Components](/components/) before drawing a new control. Each component page has Usage guidance on when to use it and when to pick something else.\n\n## Design for every state\n\nSpecify hover, focus, pressed, selected and disabled for every interactive element. See [Interaction states](/foundations/styles/interaction-states/).\n\n## Check accessibility early\n\nBeehexa products meet WCAG 2.2 AA. Read the [accessibility guidelines](/foundations/guidelines/accessibility/) and the Accessibility tab of every component you use.\n\n## Check colour before handoff\n\n- Every colour is a role token; no hex values or scale steps.\n- Text and icons sit only on backgrounds they are [paired](/foundations/styles/color/accessibility/#pairing) with.\n- Yellow only for the logo, the current-page bar, highlights and brand notes.\n- One primary button per view.\n- Every status is written in words; every selected item has a second cue.\n- Checked in light and in dark.\n",
919
+ "raw": "---\ntitle: Design\ndescription: How designers use tokens, styles and components to build Beehexa interfaces.\norder: 1\n---\n\n## Start from tokens\n\nEvery color, size, radius and duration in a design should be a [design token](/foundations/tokens/). If a value you need is missing, ask for a new token rather than adding a one-off value.\n\n## Use existing components\n\nCheck [Components](/components/) before drawing a new control. Each component page has Usage guidance on when to use it and when to pick something else.\n\n## Design for every state\n\nSpecify hover, focus, pressed, selected and disabled for every interactive element. See [Interaction states](/foundations/styles/interaction-states/).\n\n## Check accessibility early\n\nBeehexa products meet WCAG 2.2 AA. Read the [accessibility guidelines](/foundations/guidelines/accessibility/) and the Accessibility tab of every component you use.\n\n## Check colour before handoff\n\n- Every colour is a role token; no hex values or scale steps.\n- Text and icons sit only on backgrounds they are [paired](/foundations/styles/color/accessibility/#pairing) with.\n- Yellow only for the logo, the current-page bar, highlights and brand notes.\n- One primary button per view.\n- Every status is written in words; every selected item has a second cue.\n- Checked in light and in dark.\n",
920
+ "frontmatter": {
921
+ "title": "Design",
922
+ "description": "How designers use tokens, styles and components to build Beehexa interfaces.",
923
+ "order": 1
924
+ }
925
+ },
926
+ {
927
+ "id": "en/get-started/develop",
928
+ "path": "src/content/get-started/develop.mdx",
929
+ "documentPath": "docs/src/content/get-started/develop.mdx",
930
+ "locale": "en",
931
+ "kind": "guidance",
932
+ "title": "Develop",
933
+ "status": "active",
934
+ "releasePhase": null,
935
+ "planned": [],
936
+ "body": "\n## Install local design packages\n\n`beehexa.design` owns `@beehexa/design-tokens` and `@beehexa/design-rules`.\nBuild them locally with `npm ci && npm run build:packages` in this repository.\nUntil managers authorize a real release, consumers use local package references, not guessed\nregistry versions. For a sibling Yarn consumer such as dashboard-v2:\n\n```json\n{\n \"dependencies\": {\n \"@beehexa/design-tokens\": \"portal:../beehexa.design/packages/design-tokens\",\n \"@beehexa/design-rules\": \"portal:../beehexa.design/packages/design-rules\"\n }\n}\n```\n\nInstall the consumer dependencies, then import `@beehexa/design-tokens/css` once in its entrypoint.\nUse the typed `tokens` and `tokenInfo` exports when an API needs resolved values instead of CSS.\nThe explicit `/css/pixels` variant supports nominal-size migration in apps with a nonstandard root;\nit does not satisfy user-default-font scaling. Do not copy generated files into consumers.\n\nNo release, deploy or CI execution is a prerequisite for local development. Publishing, release\ntags, deployment, release-CI dispatch and consumer version bumps require explicit manager approval.\nOnly an actual authorized published version may replace local references.\nCI is single-repository and uses real published dependency versions. Do not checkout/build sibling\nrepos or pass local references into CI. Until an authorized release exists, continue local work\nwithout running consumer CI or asking for a release to unblock local implementation.\n\n## Use the tokens\n\nTokens ship as CSS custom properties with the `--bh-` prefix:\n\n```css\n.panel {\n padding: var(--bh-space-300);\n border: var(--bh-border-width-default) solid var(--bh-color-border);\n border-radius: var(--bh-radius-150);\n}\n```\n\nDo not write raw hex colors, arbitrary sizes or durations. Choose installed tokens by semantic role and read their usage rules. The [Stylelint](/tools/stylelint/) and [ESLint](/tools/eslint/) integrations are planned; their documentation is not proof that enforcement is installed.\n\n## Theme Ant Design Vue\n\nBeehexa apps are built on Ant Design Vue. Apply the [Beehexa theme](/tools/ant-design-vue-theme/) so its components use the same tokens.\n\n## Working with AI agents\n\nStart with `@beehexa/design-rules/agent` (installed `dist/AGENTS.md`), then use the package's\n`listRules`, `readRule` and `searchRules` APIs to read the complete matching documents offline.\nPlanned stubs stay explicitly planned; they are not permission to invent component values.\nWebsite [`/llms.txt`](/llms.txt) is a supplementary browsing index, not a replacement for the\ninstalled rules. See [Docs for AI agents](/tools/ai-agents/).\n",
937
+ "raw": "---\ntitle: Develop\ndescription: How developers use the token CSS, the Ant Design Vue theme and the lint rules.\norder: 2\n---\n\n## Install local design packages\n\n`beehexa.design` owns `@beehexa/design-tokens` and `@beehexa/design-rules`.\nBuild them locally with `npm ci && npm run build:packages` in this repository.\nUntil managers authorize a real release, consumers use local package references, not guessed\nregistry versions. For a sibling Yarn consumer such as dashboard-v2:\n\n```json\n{\n \"dependencies\": {\n \"@beehexa/design-tokens\": \"portal:../beehexa.design/packages/design-tokens\",\n \"@beehexa/design-rules\": \"portal:../beehexa.design/packages/design-rules\"\n }\n}\n```\n\nInstall the consumer dependencies, then import `@beehexa/design-tokens/css` once in its entrypoint.\nUse the typed `tokens` and `tokenInfo` exports when an API needs resolved values instead of CSS.\nThe explicit `/css/pixels` variant supports nominal-size migration in apps with a nonstandard root;\nit does not satisfy user-default-font scaling. Do not copy generated files into consumers.\n\nNo release, deploy or CI execution is a prerequisite for local development. Publishing, release\ntags, deployment, release-CI dispatch and consumer version bumps require explicit manager approval.\nOnly an actual authorized published version may replace local references.\nCI is single-repository and uses real published dependency versions. Do not checkout/build sibling\nrepos or pass local references into CI. Until an authorized release exists, continue local work\nwithout running consumer CI or asking for a release to unblock local implementation.\n\n## Use the tokens\n\nTokens ship as CSS custom properties with the `--bh-` prefix:\n\n```css\n.panel {\n padding: var(--bh-space-300);\n border: var(--bh-border-width-default) solid var(--bh-color-border);\n border-radius: var(--bh-radius-150);\n}\n```\n\nDo not write raw hex colors, arbitrary sizes or durations. Choose installed tokens by semantic role and read their usage rules. The [Stylelint](/tools/stylelint/) and [ESLint](/tools/eslint/) integrations are planned; their documentation is not proof that enforcement is installed.\n\n## Theme Ant Design Vue\n\nBeehexa apps are built on Ant Design Vue. Apply the [Beehexa theme](/tools/ant-design-vue-theme/) so its components use the same tokens.\n\n## Working with AI agents\n\nStart with `@beehexa/design-rules/agent` (installed `dist/AGENTS.md`), then use the package's\n`listRules`, `readRule` and `searchRules` APIs to read the complete matching documents offline.\nPlanned stubs stay explicitly planned; they are not permission to invent component values.\nWebsite [`/llms.txt`](/llms.txt) is a supplementary browsing index, not a replacement for the\ninstalled rules. See [Docs for AI agents](/tools/ai-agents/).\n",
938
+ "frontmatter": {
939
+ "title": "Develop",
940
+ "description": "How developers use the token CSS, the Ant Design Vue theme and the lint rules.",
941
+ "order": 2
942
+ }
943
+ },
944
+ {
945
+ "id": "en/get-started/get-help",
946
+ "path": "src/content/get-started/get-help.mdx",
947
+ "documentPath": "docs/src/content/get-started/get-help.mdx",
948
+ "locale": "en",
949
+ "kind": "guidance",
950
+ "title": "Get help",
951
+ "status": "active",
952
+ "releasePhase": null,
953
+ "planned": [],
954
+ "body": "import HelpOptions from '../../components/HelpOptions.astro';\n\nThe design system team looks after this site, the tokens and the component guidance.\n\n## Ways to reach us\n\n<HelpOptions />\n\n## What to include\n\n- The page or component, with a link.\n- What you were trying to do.\n- A screenshot if something looks wrong.\n",
955
+ "raw": "---\ntitle: Get help\ndescription: Ask a question, report a problem or propose a change to the design system.\norder: 3\nsidebarGroup: Reference\n---\nimport HelpOptions from '../../components/HelpOptions.astro';\n\nThe design system team looks after this site, the tokens and the component guidance.\n\n## Ways to reach us\n\n<HelpOptions />\n\n## What to include\n\n- The page or component, with a link.\n- What you were trying to do.\n- A screenshot if something looks wrong.\n",
956
+ "frontmatter": {
957
+ "title": "Get help",
958
+ "description": "Ask a question, report a problem or propose a change to the design system.",
959
+ "order": 3,
960
+ "sidebarGroup": "Reference"
961
+ }
962
+ },
963
+ {
964
+ "id": "en/get-started/index",
965
+ "path": "src/content/get-started/index.mdx",
966
+ "documentPath": "docs/src/content/get-started/index.mdx",
967
+ "locale": "en",
968
+ "kind": "guidance",
969
+ "title": "Get started",
970
+ "status": "active",
971
+ "releasePhase": null,
972
+ "planned": [],
973
+ "body": "import RoleGuides from '../../components/RoleGuides.astro';\nimport SystemAreas from '../../components/SystemAreas.astro';\nimport PhaseTable from '../../components/PhaseTable.astro';\nimport HelpOptions from '../../components/HelpOptions.astro';\n\n<div class=\"callout\">\n <p class=\"callout-title\">Working proposal</p>\n <p>Token values and the component catalog are not final. Check the [release phase](/release-phases/) of anything before you rely on it.</p>\n</div>\n\nThe Beehexa Design System is the shared language for every Beehexa web product. It holds the design tokens, guidelines and components that keep interfaces consistent as the team ships about twice a week.\n\n## Pick your guide\n\n<RoleGuides />\n\n## What is in the system\n\n<SystemAreas />\n\n## Your first change\n\nUse tokens instead of raw values. Tokens ship as CSS custom properties with the `--bh-` prefix:\n\n```css\n.panel {\n padding: var(--bh-space-300);\n border: var(--bh-border-width-default) solid var(--bh-color-border);\n border-radius: var(--bh-radius-150);\n}\n```\n\nThe [Stylelint](/tools/stylelint/) and [ESLint](/tools/eslint/) rules flag raw hex colors, pixel sizes and durations.\n\n## Release phases\n\nEvery page and component shows how stable it is.\n\n<PhaseTable />\n\n## Get help\n\n<HelpOptions />\n",
974
+ "raw": "---\ntitle: Get started\ndescription: Start designing, building and writing Beehexa products with shared foundations, components and standards.\norder: 0\nsidebarLabel: Overview\naudience: Designers, developers, writers\n---\nimport RoleGuides from '../../components/RoleGuides.astro';\nimport SystemAreas from '../../components/SystemAreas.astro';\nimport PhaseTable from '../../components/PhaseTable.astro';\nimport HelpOptions from '../../components/HelpOptions.astro';\n\n<div class=\"callout\">\n <p class=\"callout-title\">Working proposal</p>\n <p>Token values and the component catalog are not final. Check the [release phase](/release-phases/) of anything before you rely on it.</p>\n</div>\n\nThe Beehexa Design System is the shared language for every Beehexa web product. It holds the design tokens, guidelines and components that keep interfaces consistent as the team ships about twice a week.\n\n## Pick your guide\n\n<RoleGuides />\n\n## What is in the system\n\n<SystemAreas />\n\n## Your first change\n\nUse tokens instead of raw values. Tokens ship as CSS custom properties with the `--bh-` prefix:\n\n```css\n.panel {\n padding: var(--bh-space-300);\n border: var(--bh-border-width-default) solid var(--bh-color-border);\n border-radius: var(--bh-radius-150);\n}\n```\n\nThe [Stylelint](/tools/stylelint/) and [ESLint](/tools/eslint/) rules flag raw hex colors, pixel sizes and durations.\n\n## Release phases\n\nEvery page and component shows how stable it is.\n\n<PhaseTable />\n\n## Get help\n\n<HelpOptions />\n",
975
+ "frontmatter": {
976
+ "title": "Get started",
977
+ "description": "Start designing, building and writing Beehexa products with shared foundations, components and standards.",
978
+ "order": 0,
979
+ "sidebarLabel": "Overview",
980
+ "audience": "Designers, developers, writers"
981
+ }
982
+ },
983
+ {
984
+ "id": "en/news/2026-10-16-site-structure",
985
+ "path": "src/content/news/2026-10-16-site-structure.md",
986
+ "documentPath": "docs/src/content/news/2026-10-16-site-structure.md",
987
+ "locale": "en",
988
+ "kind": "news",
989
+ "title": "Site structure proposal published",
990
+ "status": "active",
991
+ "releasePhase": null,
992
+ "planned": [],
993
+ "body": "\nThe site is organised as Get started, Foundations, Components, Tools, Release phases and News.\n\nThree parts get their own place:\n\n- an Accessibility tab on every component page,\n- a dedicated [Interaction states](/foundations/styles/interaction-states/) page,\n- a dedicated [Breakpoints](/foundations/styles/layout/breakpoints/) page.\n\nToken values are a separate decision and are still open.\n",
994
+ "raw": "---\ntitle: Site structure proposal published\ndescription: The design system site is organised as Get started, Foundations, Components, Tools, Release phases and News.\ndate: 2026-10-16\n---\n\nThe site is organised as Get started, Foundations, Components, Tools, Release phases and News.\n\nThree parts get their own place:\n\n- an Accessibility tab on every component page,\n- a dedicated [Interaction states](/foundations/styles/interaction-states/) page,\n- a dedicated [Breakpoints](/foundations/styles/layout/breakpoints/) page.\n\nToken values are a separate decision and are still open.\n",
995
+ "frontmatter": {
996
+ "title": "Site structure proposal published",
997
+ "description": "The design system site is organised as Get started, Foundations, Components, Tools, Release phases and News.",
998
+ "date": "2026-10-16"
999
+ }
1000
+ },
1001
+ {
1002
+ "id": "en/news/2026-10-20-docs-site",
1003
+ "path": "src/content/news/2026-10-20-docs-site.md",
1004
+ "documentPath": "docs/src/content/news/2026-10-20-docs-site.md",
1005
+ "locale": "en",
1006
+ "kind": "news",
1007
+ "title": "Docs site structure is live",
1008
+ "status": "active",
1009
+ "releasePhase": null,
1010
+ "planned": [],
1011
+ "body": "\nThe documentation site now follows the proposed structure. Design tokens live in one place, `tokens/`, and feed both the CSS and the token tables on this site.\n\nWhat is new:\n\n- [Foundations](/foundations/) with provisional tokens.\n- [Button](/components/button/), the first component page, with all five tabs.\n- [`/llms.txt`](/llms.txt) for AI coding agents.\n",
1012
+ "raw": "---\ntitle: Docs site structure is live\ndescription: Foundations, Button and Tools pages are published as Early Access.\ndate: 2026-10-20\n---\n\nThe documentation site now follows the proposed structure. Design tokens live in one place, `tokens/`, and feed both the CSS and the token tables on this site.\n\nWhat is new:\n\n- [Foundations](/foundations/) with provisional tokens.\n- [Button](/components/button/), the first component page, with all five tabs.\n- [`/llms.txt`](/llms.txt) for AI coding agents.\n",
1013
+ "frontmatter": {
1014
+ "title": "Docs site structure is live",
1015
+ "description": "Foundations, Button and Tools pages are published as Early Access.",
1016
+ "date": "2026-10-20"
1017
+ }
1018
+ },
1019
+ {
1020
+ "id": "en/reference/structure-proposal",
1021
+ "path": "src/brand/structure-proposal.md",
1022
+ "documentPath": "docs/src/brand/structure-proposal.md",
1023
+ "locale": "en",
1024
+ "kind": "reference",
1025
+ "title": "structure-proposal",
1026
+ "status": "active",
1027
+ "releasePhase": null,
1028
+ "planned": [],
1029
+ "body": "Beehexa Design System\nWebsite Structure Proposal\n\nBeehexa should build its design system website on the site structure of the Atlassian Design System, and borrow three parts from Material Design 3.\n1. Purpose and Scope\nPurpose: choose the structure (sections, URL paths, scope of each section) of the Beehexa design system website.\nScope: site structure only. This document does not decide which system Beehexa takes design token values from (color, radius, spacing…). That question is still open.\nMethod: public pages of Material Design 3 and the Atlassian Design System were read on October 16, 2026. Material was read in a browser; Atlassian with WebFetch and Atlassian's llms.txt. Quotes are verbatim from the linked pages.\nStatus: proposal, not yet a decision.\n2. Proposed Site Structure\nSection\nPages\nTaken from\nGet started\nDesign, Develop, Content\nAtlassian (split by role)\nFoundations - Design tokens\nTokens overview, full token list\nAtlassian\nFoundations - Guidelines\nAccessibility, Content\nBoth\nFoundations - Styles\nColor, Typography, Spacing, Grid, Radius, Border, Elevation, Motion, Iconography\nAtlassian\nFoundations - Styles\nBreakpoints\nMaterial\nFoundations - Styles\nInteraction states\nMaterial\nComponents\nOne page per component, tabs: Examples, Code, Usage, Accessibility, Changelog\nAtlassian tabs + Material Accessibility tab\nTools\nStylelint and ESLint rules, Ant Design Vue theme, docs for AI agents\nAtlassian\nRelease phases\nEarly Access, Beta, General Availability, Deprecated\nAtlassian\nNews\nUpdates and changelog\nBoth\n\n\nURL pattern: /section/topic/subtopic, and /components/name/tab for component pages, following Atlassian.\n\nNot included: Rovo UI and AMP Patterns (Atlassian's AI products), Devices and the per-platform Develop section (Material), illustrations and logos (covered by the Beehexa brand guide).\n3. Why This Structure\n3.1 Why Atlassian as the Base\nWeb-only, B2B, data-heavy: Beehexa's product is closer to Atlassian's products. Material serves many platforms (Android, Flutter, watches, XR).\nSmall team, design tokens first: Atlassian puts everything foundational in one Foundations section that starts with Tokens, with fewer top-level sections to maintain.\nGoal is to prevent drift: the Tools section with ESLint and Stylelint plugins matches the first-round guardrails.\nCode is often written by AI agents: Atlassian publishes llms.txt and guides for AI tooling.\nFrequent releases, about two per week: Changelog tabs and Release phases tell the team what changed and what is still in trial.\nDevelopers are the main readers: Examples and Code tabs serve them directly.\nEven URL pattern: new pages are easy to name and find.\n3.2 What to Borrow from Material\nAccessibility tab on component pages: Beehexa commits to WCAG 2.2 AA; Atlassian has no such tab.\nDedicated Interaction states page: disabled, hover and focus are design token groups Beehexa is missing.\nDedicated Breakpoints page: breakpoints are missing in both the brand guide and the code.\n4. Reference Comparison\n4.1 Material Design 3 Sections\nSection\nPath\nDefinition (verbatim)\nGet started\n/get-started\n\"Get to know Material 3 – from UX guidance and tools to reusable components and open-source code\"\nDevelop\n/develop\n\"Implement Material Design with code and developer documentation for Jetpack Compose, Android Views, Flutter, and the web\"\nFoundations\n/foundations\n\"Foundations inform the basis of any great user interface, from accessibility standards to essential patterns for layout and interaction.\"\nStyles\n/styles\n\"Styles are the visual aspects of a UI that give it a distinct look and feel. They can be customized by changing your Material theme.\"\nComponents\n/components\n\"Components are interactive building blocks for creating a user interface.\"\nBlog\n/blog\n\"Read the latest and greatest about Material Design\"\n\n\nFoundations: Accessibility, Building for all, Content design, Customizing Material, Devices, Design tokens, Interaction (incl. States), Layout (incl. Breakpoints, Grids & spacing), Usability, Material A-Z glossary.\nStyles: Color, Elevation, Icons, Motion, Shape, Spacing, Typography.\nComponents: about 35, grouped by component family. Tabs: Overview, Specs, Guidelines, Accessibility.\n4.2 Atlassian Design System Sections\nSection\nPath\nDefinition (verbatim)\nGet started\n/get-started\n\"Start designing and developing beautiful interfaces with Atlassian Design System foundations, components, and standards.\"\nFoundations\n/foundations\n\"Foundations create engaging user experiences. These include our tokens, guidelines, and visual styles: color, spacing, typography, and more.\"\nComponents\n/components\n\"Components are reusable building blocks that meet specific interaction needs.\"\nRovo UI\n/rovo-ui\n\"The AI voice of the Atlassian Design Language which defines how Rovo looks, moves, and behaves across Atlassian surfaces.\"\nTools\n/tools\n\"The essential tooling for Atlassian Design System: design resources, development tools, and AI tooling.\"\nAMP Patterns\n/amp\n\"Atlassian's powerful collection of design patterns to enhance how humans and agents collaborate.\"\nRelease phases\n/release-phases\n\"Our components and foundations have different release phases and availability.\"\nContact us\n/contact-us\n\"How to get help from the Atlassian Design System team and contribute to the system.\"\nNews\n/news\n\"Keep up to date with our insightful design blog posts and leadership talks\"\n\n\nGet started: split by role: Design, Develop, Content design, About.\nFoundations: 14 pages in 3 groups: Design tokens (Tokens); Guidelines (Accessibility, Content); Styles (Spacing, Grid, Color, Typography, Motion, Iconography, Illustrations, Logos, Elevation, Border, Radius).\nComponents: about 90, grouped by function, plus Primitives, Libraries, Tooling and Deprecated. Tabs: Examples, Code, Usage, Changelog.\n4.3 Similarities\nTopic\nMaterial Design 3\nAtlassian\nGet started section\nYes\nYes\nFoundations section\nYes\nYes\nFoundations cover accessibility, content, design tokens, layout\nYes\nYes\nCore styles: color, type, spacing, radius, elevation, motion, icons\nYes, under Styles\nYes, under Foundations\nComponents as a top-level section, path /components/name\nYes\nYes\nComponent pages with 4 tabs\nYes\nYes\nDedicated design tokens page\nYes\nYes\nNo dedicated dark mode page\nYes\nYes\nNews section\nBlog\nNews\n\n\nBoth share the same core: Get started → Foundations → Components, plus a news section.\n4.4 Differences\nTopic\nMaterial Design 3\nAtlassian\nWhere visual styles live\nSeparate Styles section\nInside Foundations, grouped as Design tokens, Guidelines, Styles\nRadius and border\nRadius under Styles > Shape; no border page\nSeparate Radius and Border pages\nInteraction states\nDedicated page\nPart of the Color page\nLayout and breakpoints\nSeveral pages, incl. a dedicated Breakpoints page\nOne Grid page with a breakpoint table\nToken list\nToken tab on each style page\nOne All design tokens page\nIllustrations, logos\nNot covered\nDedicated pages\nDeveloper docs\nDevelop section per platform\nCode tab on each component + Tools section\nComponent tabs\nOverview, Specs, Guidelines, Accessibility\nExamples, Code, Usage, Changelog\nComponent grouping\nBy component family\nBy function, plus Primitives, Libraries, Tooling, Deprecated\nGuardrail tooling\nNot on the site\nESLint, Stylelint plugins, Storybook addon\nDocs for AI agents\nNot found on the site\nllms.txt, MCP server, Develop with AI guide\nLifecycle and support\nNot covered\nRelease phases, Contact us\nGet started\nOne general page\nSplit by role\nProduct-specific sections\nDevices (watches, XR)\nRovo UI, AMP Patterns\nGlossary\nYes\nNo\nURL pattern\nUneven across sections\nEven: /section/topic/subtopic\n\n5. Limits\nOnly two systems were compared. Ant Design, the library app.hexasync.com uses, has not been compared yet.\nChoosing Atlassian's site structure does not mean taking design token values from Atlassian. These are separate decisions.\nNot verified: tabs of about 33 Material component pages (assumed the same as the 3 pages opened); Atlassian's old /patterns page (empty response).\n6. Sources\nMaterial Design 3\nMaterial Design 3 Design tokens\nMaterial Design 3 Interaction states\nMaterial Design 3 Breakpoints\nAtlassian Design System\nAtlassian Foundations\nAtlassian Tokens\nAtlassian Grid\nAtlassian Button component, Examples tab\nAtlassian llms.txt\n",
1030
+ "raw": "Beehexa Design System\nWebsite Structure Proposal\n\nBeehexa should build its design system website on the site structure of the Atlassian Design System, and borrow three parts from Material Design 3.\n1. Purpose and Scope\nPurpose: choose the structure (sections, URL paths, scope of each section) of the Beehexa design system website.\nScope: site structure only. This document does not decide which system Beehexa takes design token values from (color, radius, spacing…). That question is still open.\nMethod: public pages of Material Design 3 and the Atlassian Design System were read on October 16, 2026. Material was read in a browser; Atlassian with WebFetch and Atlassian's llms.txt. Quotes are verbatim from the linked pages.\nStatus: proposal, not yet a decision.\n2. Proposed Site Structure\nSection\nPages\nTaken from\nGet started\nDesign, Develop, Content\nAtlassian (split by role)\nFoundations - Design tokens\nTokens overview, full token list\nAtlassian\nFoundations - Guidelines\nAccessibility, Content\nBoth\nFoundations - Styles\nColor, Typography, Spacing, Grid, Radius, Border, Elevation, Motion, Iconography\nAtlassian\nFoundations - Styles\nBreakpoints\nMaterial\nFoundations - Styles\nInteraction states\nMaterial\nComponents\nOne page per component, tabs: Examples, Code, Usage, Accessibility, Changelog\nAtlassian tabs + Material Accessibility tab\nTools\nStylelint and ESLint rules, Ant Design Vue theme, docs for AI agents\nAtlassian\nRelease phases\nEarly Access, Beta, General Availability, Deprecated\nAtlassian\nNews\nUpdates and changelog\nBoth\n\n\nURL pattern: /section/topic/subtopic, and /components/name/tab for component pages, following Atlassian.\n\nNot included: Rovo UI and AMP Patterns (Atlassian's AI products), Devices and the per-platform Develop section (Material), illustrations and logos (covered by the Beehexa brand guide).\n3. Why This Structure\n3.1 Why Atlassian as the Base\nWeb-only, B2B, data-heavy: Beehexa's product is closer to Atlassian's products. Material serves many platforms (Android, Flutter, watches, XR).\nSmall team, design tokens first: Atlassian puts everything foundational in one Foundations section that starts with Tokens, with fewer top-level sections to maintain.\nGoal is to prevent drift: the Tools section with ESLint and Stylelint plugins matches the first-round guardrails.\nCode is often written by AI agents: Atlassian publishes llms.txt and guides for AI tooling.\nFrequent releases, about two per week: Changelog tabs and Release phases tell the team what changed and what is still in trial.\nDevelopers are the main readers: Examples and Code tabs serve them directly.\nEven URL pattern: new pages are easy to name and find.\n3.2 What to Borrow from Material\nAccessibility tab on component pages: Beehexa commits to WCAG 2.2 AA; Atlassian has no such tab.\nDedicated Interaction states page: disabled, hover and focus are design token groups Beehexa is missing.\nDedicated Breakpoints page: breakpoints are missing in both the brand guide and the code.\n4. Reference Comparison\n4.1 Material Design 3 Sections\nSection\nPath\nDefinition (verbatim)\nGet started\n/get-started\n\"Get to know Material 3 – from UX guidance and tools to reusable components and open-source code\"\nDevelop\n/develop\n\"Implement Material Design with code and developer documentation for Jetpack Compose, Android Views, Flutter, and the web\"\nFoundations\n/foundations\n\"Foundations inform the basis of any great user interface, from accessibility standards to essential patterns for layout and interaction.\"\nStyles\n/styles\n\"Styles are the visual aspects of a UI that give it a distinct look and feel. They can be customized by changing your Material theme.\"\nComponents\n/components\n\"Components are interactive building blocks for creating a user interface.\"\nBlog\n/blog\n\"Read the latest and greatest about Material Design\"\n\n\nFoundations: Accessibility, Building for all, Content design, Customizing Material, Devices, Design tokens, Interaction (incl. States), Layout (incl. Breakpoints, Grids & spacing), Usability, Material A-Z glossary.\nStyles: Color, Elevation, Icons, Motion, Shape, Spacing, Typography.\nComponents: about 35, grouped by component family. Tabs: Overview, Specs, Guidelines, Accessibility.\n4.2 Atlassian Design System Sections\nSection\nPath\nDefinition (verbatim)\nGet started\n/get-started\n\"Start designing and developing beautiful interfaces with Atlassian Design System foundations, components, and standards.\"\nFoundations\n/foundations\n\"Foundations create engaging user experiences. These include our tokens, guidelines, and visual styles: color, spacing, typography, and more.\"\nComponents\n/components\n\"Components are reusable building blocks that meet specific interaction needs.\"\nRovo UI\n/rovo-ui\n\"The AI voice of the Atlassian Design Language which defines how Rovo looks, moves, and behaves across Atlassian surfaces.\"\nTools\n/tools\n\"The essential tooling for Atlassian Design System: design resources, development tools, and AI tooling.\"\nAMP Patterns\n/amp\n\"Atlassian's powerful collection of design patterns to enhance how humans and agents collaborate.\"\nRelease phases\n/release-phases\n\"Our components and foundations have different release phases and availability.\"\nContact us\n/contact-us\n\"How to get help from the Atlassian Design System team and contribute to the system.\"\nNews\n/news\n\"Keep up to date with our insightful design blog posts and leadership talks\"\n\n\nGet started: split by role: Design, Develop, Content design, About.\nFoundations: 14 pages in 3 groups: Design tokens (Tokens); Guidelines (Accessibility, Content); Styles (Spacing, Grid, Color, Typography, Motion, Iconography, Illustrations, Logos, Elevation, Border, Radius).\nComponents: about 90, grouped by function, plus Primitives, Libraries, Tooling and Deprecated. Tabs: Examples, Code, Usage, Changelog.\n4.3 Similarities\nTopic\nMaterial Design 3\nAtlassian\nGet started section\nYes\nYes\nFoundations section\nYes\nYes\nFoundations cover accessibility, content, design tokens, layout\nYes\nYes\nCore styles: color, type, spacing, radius, elevation, motion, icons\nYes, under Styles\nYes, under Foundations\nComponents as a top-level section, path /components/name\nYes\nYes\nComponent pages with 4 tabs\nYes\nYes\nDedicated design tokens page\nYes\nYes\nNo dedicated dark mode page\nYes\nYes\nNews section\nBlog\nNews\n\n\nBoth share the same core: Get started → Foundations → Components, plus a news section.\n4.4 Differences\nTopic\nMaterial Design 3\nAtlassian\nWhere visual styles live\nSeparate Styles section\nInside Foundations, grouped as Design tokens, Guidelines, Styles\nRadius and border\nRadius under Styles > Shape; no border page\nSeparate Radius and Border pages\nInteraction states\nDedicated page\nPart of the Color page\nLayout and breakpoints\nSeveral pages, incl. a dedicated Breakpoints page\nOne Grid page with a breakpoint table\nToken list\nToken tab on each style page\nOne All design tokens page\nIllustrations, logos\nNot covered\nDedicated pages\nDeveloper docs\nDevelop section per platform\nCode tab on each component + Tools section\nComponent tabs\nOverview, Specs, Guidelines, Accessibility\nExamples, Code, Usage, Changelog\nComponent grouping\nBy component family\nBy function, plus Primitives, Libraries, Tooling, Deprecated\nGuardrail tooling\nNot on the site\nESLint, Stylelint plugins, Storybook addon\nDocs for AI agents\nNot found on the site\nllms.txt, MCP server, Develop with AI guide\nLifecycle and support\nNot covered\nRelease phases, Contact us\nGet started\nOne general page\nSplit by role\nProduct-specific sections\nDevices (watches, XR)\nRovo UI, AMP Patterns\nGlossary\nYes\nNo\nURL pattern\nUneven across sections\nEven: /section/topic/subtopic\n\n5. Limits\nOnly two systems were compared. Ant Design, the library app.hexasync.com uses, has not been compared yet.\nChoosing Atlassian's site structure does not mean taking design token values from Atlassian. These are separate decisions.\nNot verified: tabs of about 33 Material component pages (assumed the same as the 3 pages opened); Atlassian's old /patterns page (empty response).\n6. Sources\nMaterial Design 3\nMaterial Design 3 Design tokens\nMaterial Design 3 Interaction states\nMaterial Design 3 Breakpoints\nAtlassian Design System\nAtlassian Foundations\nAtlassian Tokens\nAtlassian Grid\nAtlassian Button component, Examples tab\nAtlassian llms.txt\n",
1031
+ "frontmatter": {}
1032
+ },
1033
+ {
1034
+ "id": "en/release-phases/index",
1035
+ "path": "src/content/release-phases/index.mdx",
1036
+ "documentPath": "docs/src/content/release-phases/index.mdx",
1037
+ "locale": "en",
1038
+ "kind": "guidance",
1039
+ "title": "Release phases",
1040
+ "status": "active",
1041
+ "releasePhase": null,
1042
+ "planned": [],
1043
+ "body": "import PhaseTable from '../../components/PhaseTable.astro';\n\n\n<PhaseTable />\n\nEvery page and component shows its phase in a chip. When every page in a section shares one phase, the sidebar says so once instead. Changes are recorded in each component's Changelog tab and in [News](/news/).\n",
1044
+ "raw": "---\ntitle: Release phases\ndescription: Components and foundations go through release phases that tell you how stable they are.\norder: 1\nsidebarGroup: Reference\n---\nimport PhaseTable from '../../components/PhaseTable.astro';\n\n\n<PhaseTable />\n\nEvery page and component shows its phase in a chip. When every page in a section shares one phase, the sidebar says so once instead. Changes are recorded in each component's Changelog tab and in [News](/news/).\n",
1045
+ "frontmatter": {
1046
+ "title": "Release phases",
1047
+ "description": "Components and foundations go through release phases that tell you how stable they are.",
1048
+ "order": 1,
1049
+ "sidebarGroup": "Reference"
1050
+ }
1051
+ },
1052
+ {
1053
+ "id": "en/tools/ai-agents",
1054
+ "path": "src/content/tools/ai-agents.mdx",
1055
+ "documentPath": "docs/src/content/tools/ai-agents.mdx",
1056
+ "locale": "en",
1057
+ "kind": "guidance",
1058
+ "title": "Docs for AI agents",
1059
+ "status": "active",
1060
+ "releasePhase": null,
1061
+ "planned": [],
1062
+ "body": "\nCoding agents must read the same installed tokens and complete usage rules as people.\n\n## Package entrypoint and rule discovery\n\n`@beehexa/design-rules/agent` resolves to the installed package's `dist/AGENTS.md`.\nThe package includes complete source documents plus a typed catalog with stable IDs, source paths,\nlocale, titles, raw/body content and explicit active/planned status.\n\n```js\nimport { listRules, readRule, searchRules } from '@beehexa/design-rules';\n\nconst matching = searchRules('typography');\nfor (const rule of matching) console.log(rule.id, rule.status, rule.title);\n// Read a complete document selected by its stable catalog ID.\nconst document = matching[0] && readRule(matching[0].id);\n```\n\nActive means authored guidance is present, not a final release or compliance certification.\nA planned stub is not a defined rule. Read full usage/accessibility/state/layout documents for the\nactual task; a matching token value or a short search result is not sufficient.\n\n## Consumer hard rules\n\nKeep these requirements in the consumer's canonical `AGENTS.md`; `CODEX.md` and `CLAUDE.md`\nreference that entrypoint rather than creating competing policies:\n\n- Install local references to `@beehexa/design-tokens` and `@beehexa/design-rules` until\n managers explicitly authorize a release. Do not copy JSON/CSS/TS/rule bodies or generators.\n- No release, deployment or CI execution is required for local development. Publishing,\n release tags, deployment, release-CI dispatch and consumer version bumps require manager approval.\n Replace local references only with a real authorized published version.\n- CI is single-repository and consumer dependencies must be actual published versions.\n Never add sibling checkouts/builds or local references to CI. Unreleased local work stays local.\n- Before every UI change, read the installed agent entrypoint and complete matching package rules.\n Use semantic tokens, not nearest values. Missing reusable roles/rules must be authored in the\n producer package first.\n- There are no exceptions for business colours, canvas geometry, charts, editors, SVG/Mermaid\n or exports. Package availability does not prove actual consumer adoption or accessibility.\n\n## Website browsing index\n\n[`/llms.txt`](/llms.txt) lists website pages for browsing. The installed package is the offline\nrules contract; do not require website availability or another source checkout to read it.\n",
1063
+ "raw": "---\ntitle: Docs for AI agents\ndescription: How AI coding agents read the Beehexa Design System.\norder: 4\n---\n\nCoding agents must read the same installed tokens and complete usage rules as people.\n\n## Package entrypoint and rule discovery\n\n`@beehexa/design-rules/agent` resolves to the installed package's `dist/AGENTS.md`.\nThe package includes complete source documents plus a typed catalog with stable IDs, source paths,\nlocale, titles, raw/body content and explicit active/planned status.\n\n```js\nimport { listRules, readRule, searchRules } from '@beehexa/design-rules';\n\nconst matching = searchRules('typography');\nfor (const rule of matching) console.log(rule.id, rule.status, rule.title);\n// Read a complete document selected by its stable catalog ID.\nconst document = matching[0] && readRule(matching[0].id);\n```\n\nActive means authored guidance is present, not a final release or compliance certification.\nA planned stub is not a defined rule. Read full usage/accessibility/state/layout documents for the\nactual task; a matching token value or a short search result is not sufficient.\n\n## Consumer hard rules\n\nKeep these requirements in the consumer's canonical `AGENTS.md`; `CODEX.md` and `CLAUDE.md`\nreference that entrypoint rather than creating competing policies:\n\n- Install local references to `@beehexa/design-tokens` and `@beehexa/design-rules` until\n managers explicitly authorize a release. Do not copy JSON/CSS/TS/rule bodies or generators.\n- No release, deployment or CI execution is required for local development. Publishing,\n release tags, deployment, release-CI dispatch and consumer version bumps require manager approval.\n Replace local references only with a real authorized published version.\n- CI is single-repository and consumer dependencies must be actual published versions.\n Never add sibling checkouts/builds or local references to CI. Unreleased local work stays local.\n- Before every UI change, read the installed agent entrypoint and complete matching package rules.\n Use semantic tokens, not nearest values. Missing reusable roles/rules must be authored in the\n producer package first.\n- There are no exceptions for business colours, canvas geometry, charts, editors, SVG/Mermaid\n or exports. Package availability does not prove actual consumer adoption or accessibility.\n\n## Website browsing index\n\n[`/llms.txt`](/llms.txt) lists website pages for browsing. The installed package is the offline\nrules contract; do not require website availability or another source checkout to read it.\n",
1064
+ "frontmatter": {
1065
+ "title": "Docs for AI agents",
1066
+ "description": "How AI coding agents read the Beehexa Design System.",
1067
+ "order": 4
1068
+ }
1069
+ },
1070
+ {
1071
+ "id": "en/tools/ant-design-vue-theme",
1072
+ "path": "src/content/tools/ant-design-vue-theme.mdx",
1073
+ "documentPath": "docs/src/content/tools/ant-design-vue-theme.mdx",
1074
+ "locale": "en",
1075
+ "kind": "guidance",
1076
+ "title": "Ant Design Vue theme",
1077
+ "status": "active",
1078
+ "releasePhase": null,
1079
+ "planned": [],
1080
+ "body": "\nTokens and full rules are available as local `@beehexa/design-tokens` and `@beehexa/design-rules` packages. They are not released to npm yet. There is no exported `/antdv` theme subpath: keep a framework adapter in your application and derive its values from the installed token package.\n\n**Beehexa tokens are the source of truth. Ant Design Vue only reads them.**\n\nThis page is the only place where the Beehexa foundations meet Ant Design Vue. The foundation pages stay the same whatever the product is built with.\n\n## Usage\n\n```vue\n<script setup>\nimport { tokens } from '@beehexa/design-tokens';\nimport '@beehexa/design-tokens/css';\n\n// The framework adapter selects semantic roles, not a new application palette.\nconst theme = {\n token: {\n colorPrimary: tokens.light['color.background.neutral.bold'],\n colorText: tokens.light['color.text'],\n colorBorder: tokens.light['color.border'],\n fontFamily: tokens.light['font.family.sans'],\n },\n};\n</script>\n\n<template>\n <a-config-provider :theme=\"theme\">\n <App />\n </a-config-provider>\n</template>\n```\n\nThis light-mode colour/font example is not the complete theme recipe. Apply the mappings below\nin your adapter, resolve `rem` to pixels at numeric API boundaries, and recompute from\n`{ ...tokens.light, ...tokens.dark }` for dark mode and the `tokens.vi` typography alternatives\nfor Vietnamese. Read the installed rule documents before implementing states or components.\n\n## Token mapping\n\n| Ant Design token | Beehexa token |\n| --- | --- |\n| `colorPrimary` | `color.background.neutral.bold` |\n| `colorText` | `color.text` |\n| `colorBorder` | `color.border` |\n| `borderRadius` | `radius.100` |\n| `fontFamily` | `font.family.sans` |\n\n## Spacing\n\nAnt Design Vue sizes come from `sizeUnit` and `sizeStep`. Keep both at 4, so `size` is 16 px. The theme then sets each size from a [spacing](/foundations/styles/spacing/) token.\n\n| Beehexa token | Value | Ant Design Vue tokens |\n|---|---|---|\n| `space.050` | 4 px | `sizeXXS, paddingXXS, marginXXS` |\n| `space.100` | 8 px | `sizeXS, paddingXS, marginXS` |\n| `space.150` | 12 px | `sizeSM, paddingSM, marginSM` |\n| `space.200` | 16 px | `size, sizeMS, padding, margin` |\n| `space.250` | 20 px | `sizeMD, paddingMD, marginMD` |\n| `space.300` | 24 px | `sizeLG, paddingLG, marginLG` |\n| `space.400` | 32 px | `sizeXL, paddingXL, marginXL` |\n| `space.600` | 48 px | `sizeXXL, marginXXL` |\n\n`space.0`, `space.025`, `space.075`, `space.500`, `space.800` and `space.1000` have no Ant Design Vue token. Use their CSS variables in your own styles.\n\nProps that take a number, such as `size` on `a-space` and `gutter` on `a-row`, take pixels. Use a value from the scale: `<a-space :size=\"8\">`.\n\n## Control height\n\n| Beehexa token | Height | Ant Design Vue token | Component prop |\n|---|---|---|---|\n| `size.control.small` | 24 px | `controlHeightSM` | `size=\"small\"` |\n| `size.control.default` | 32 px | `controlHeight` | None |\n| `size.control.large` | 40 px | `controlHeightLG` | `size=\"large\"` |\n\nThese are Ant Design Vue’s own heights. The theme still sets each one from its size token, so a change to the token reaches the components. See [Size and density](/foundations/styles/size-and-density/).\n\n## Breakpoints\n\n**Override the `screen*` tokens with the Beehexa [breakpoints](/foundations/styles/layout/breakpoints/).** The default Ant Design Vue values are different (576, 992, 1200 and 1600 px).\n\nThe `Min` and `Max` tokens are computed from the defaults, not from your overrides. Set them too: each `Max` is the next breakpoint minus 1.\n\n| Beehexa | Value | Ant Design Vue tokens |\n|---|---|---|\n| `breakpoint.xs` | 0 | `screenXSMax: 767` |\n| `breakpoint.md` | 768 px | `screenSM`, `screenSMMin`, `screenMD`, `screenMDMin`: 768; `screenSMMax`, `screenMDMax`: 1023 |\n| `breakpoint.lg` | 1024 px | `screenLG`, `screenLGMin`: 1024; `screenLGMax`: 1439 |\n| `breakpoint.xl` | 1440 px | `screenXL`, `screenXLMin`, `screenXXL`, `screenXXLMin`: 1440 |\n\nAnt Design Vue has six breakpoints and Beehexa has four, so `sm` switches with `md`, and `xxl` with `xl`. Use the `xs`, `md`, `lg` and `xl` props of `a-col`.\n\nThe props of `a-col` and the responsive `gutter` of `a-row` then switch at the Beehexa widths. Do not use `xxxl`: its media query is malformed in Ant Design Vue 4.2.6 and never matches.\n\n## Grid\n\nAnt Design Vue divides a row into 24 parts. The Beehexa [grid](/foundations/styles/layout/grid/) has 4, 8 or 12 columns, and each one fits 24 exactly.\n\n| Beehexa grid | Window | `a-col` span |\n|---|---|---|\n| 4 columns | Below 768 px | Beehexa span × 6 |\n| 8 columns | 768 to 1023 px | Beehexa span × 3 |\n| 12 columns | 1024 px and up | Beehexa span × 2 |\n\n| Layout | Beehexa spans (4 / 8 / 12 / 12) | Props of each `a-col` |\n|---|---|---|\n| Cards, 1 to 4 a row | 4 / 4 / 4 / 3 | `:xs=\"24\" :md=\"12\" :lg=\"8\" :xl=\"6\"` |\n| Main panel | 4 / 8 / 8 / 9 | `:xs=\"24\" :lg=\"16\" :xl=\"18\"` |\n| Side panel | 4 / 8 / 4 / 3 | `:xs=\"24\" :lg=\"8\" :xl=\"6\"` |\n| Summary tile | 2 / 2 / 3 / 2 | `:xs=\"12\" :md=\"6\" :xl=\"4\"` |\n\nAnt Design Vue rows have no gutter by default. Set it from the spacing tokens, and set the page margin on the content area.\n\n```vue\n<a-row :gutter=\"[{ xs: 16, md: 24 }, { xs: 16, md: 24 }]\">\n <a-col :xs=\"24\" :md=\"12\" :lg=\"8\" :xl=\"6\">\n <OrderSummary />\n </a-col>\n</a-row>\n```\n\n## App frame\n\n| Region | Beehexa | Ant Design Vue |\n|---|---|---|\n| Header | 48 px | `<a-layout-header style=\"height: 48px; line-height: 48px\">` |\n| Side navigation, open | 280 px | `<a-layout-sider :width=\"280\">` |\n| Side navigation, collapsed | 64 px | `<a-layout-sider :collapsed-width=\"64\">` |\n\nThe header is 64 px by default and has no token for its height, so set it in the header’s style.\n\nThe `breakpoint` prop of `a-layout-sider` uses fixed widths that ignore the `screen*` tokens. Do not use it. Set `collapsed` from your own media query and the user’s choice: open from 1024 px, collapsed to the rail when the user asks, and the choice remembered. Below 1024 px, hide the sider and show the menu in `a-drawer`.\n\nSee [Layout](/foundations/styles/layout/) for the frame.\n",
1081
+ "raw": "---\ntitle: Ant Design Vue theme\ndescription: Make Ant Design Vue components use Beehexa design tokens, breakpoints, grid, control heights and app frame.\norder: 3\n---\n\nTokens and full rules are available as local `@beehexa/design-tokens` and `@beehexa/design-rules` packages. They are not released to npm yet. There is no exported `/antdv` theme subpath: keep a framework adapter in your application and derive its values from the installed token package.\n\n**Beehexa tokens are the source of truth. Ant Design Vue only reads them.**\n\nThis page is the only place where the Beehexa foundations meet Ant Design Vue. The foundation pages stay the same whatever the product is built with.\n\n## Usage\n\n```vue\n<script setup>\nimport { tokens } from '@beehexa/design-tokens';\nimport '@beehexa/design-tokens/css';\n\n// The framework adapter selects semantic roles, not a new application palette.\nconst theme = {\n token: {\n colorPrimary: tokens.light['color.background.neutral.bold'],\n colorText: tokens.light['color.text'],\n colorBorder: tokens.light['color.border'],\n fontFamily: tokens.light['font.family.sans'],\n },\n};\n</script>\n\n<template>\n <a-config-provider :theme=\"theme\">\n <App />\n </a-config-provider>\n</template>\n```\n\nThis light-mode colour/font example is not the complete theme recipe. Apply the mappings below\nin your adapter, resolve `rem` to pixels at numeric API boundaries, and recompute from\n`{ ...tokens.light, ...tokens.dark }` for dark mode and the `tokens.vi` typography alternatives\nfor Vietnamese. Read the installed rule documents before implementing states or components.\n\n## Token mapping\n\n| Ant Design token | Beehexa token |\n| --- | --- |\n| `colorPrimary` | `color.background.neutral.bold` |\n| `colorText` | `color.text` |\n| `colorBorder` | `color.border` |\n| `borderRadius` | `radius.100` |\n| `fontFamily` | `font.family.sans` |\n\n## Spacing\n\nAnt Design Vue sizes come from `sizeUnit` and `sizeStep`. Keep both at 4, so `size` is 16 px. The theme then sets each size from a [spacing](/foundations/styles/spacing/) token.\n\n| Beehexa token | Value | Ant Design Vue tokens |\n|---|---|---|\n| `space.050` | 4 px | `sizeXXS, paddingXXS, marginXXS` |\n| `space.100` | 8 px | `sizeXS, paddingXS, marginXS` |\n| `space.150` | 12 px | `sizeSM, paddingSM, marginSM` |\n| `space.200` | 16 px | `size, sizeMS, padding, margin` |\n| `space.250` | 20 px | `sizeMD, paddingMD, marginMD` |\n| `space.300` | 24 px | `sizeLG, paddingLG, marginLG` |\n| `space.400` | 32 px | `sizeXL, paddingXL, marginXL` |\n| `space.600` | 48 px | `sizeXXL, marginXXL` |\n\n`space.0`, `space.025`, `space.075`, `space.500`, `space.800` and `space.1000` have no Ant Design Vue token. Use their CSS variables in your own styles.\n\nProps that take a number, such as `size` on `a-space` and `gutter` on `a-row`, take pixels. Use a value from the scale: `<a-space :size=\"8\">`.\n\n## Control height\n\n| Beehexa token | Height | Ant Design Vue token | Component prop |\n|---|---|---|---|\n| `size.control.small` | 24 px | `controlHeightSM` | `size=\"small\"` |\n| `size.control.default` | 32 px | `controlHeight` | None |\n| `size.control.large` | 40 px | `controlHeightLG` | `size=\"large\"` |\n\nThese are Ant Design Vue’s own heights. The theme still sets each one from its size token, so a change to the token reaches the components. See [Size and density](/foundations/styles/size-and-density/).\n\n## Breakpoints\n\n**Override the `screen*` tokens with the Beehexa [breakpoints](/foundations/styles/layout/breakpoints/).** The default Ant Design Vue values are different (576, 992, 1200 and 1600 px).\n\nThe `Min` and `Max` tokens are computed from the defaults, not from your overrides. Set them too: each `Max` is the next breakpoint minus 1.\n\n| Beehexa | Value | Ant Design Vue tokens |\n|---|---|---|\n| `breakpoint.xs` | 0 | `screenXSMax: 767` |\n| `breakpoint.md` | 768 px | `screenSM`, `screenSMMin`, `screenMD`, `screenMDMin`: 768; `screenSMMax`, `screenMDMax`: 1023 |\n| `breakpoint.lg` | 1024 px | `screenLG`, `screenLGMin`: 1024; `screenLGMax`: 1439 |\n| `breakpoint.xl` | 1440 px | `screenXL`, `screenXLMin`, `screenXXL`, `screenXXLMin`: 1440 |\n\nAnt Design Vue has six breakpoints and Beehexa has four, so `sm` switches with `md`, and `xxl` with `xl`. Use the `xs`, `md`, `lg` and `xl` props of `a-col`.\n\nThe props of `a-col` and the responsive `gutter` of `a-row` then switch at the Beehexa widths. Do not use `xxxl`: its media query is malformed in Ant Design Vue 4.2.6 and never matches.\n\n## Grid\n\nAnt Design Vue divides a row into 24 parts. The Beehexa [grid](/foundations/styles/layout/grid/) has 4, 8 or 12 columns, and each one fits 24 exactly.\n\n| Beehexa grid | Window | `a-col` span |\n|---|---|---|\n| 4 columns | Below 768 px | Beehexa span × 6 |\n| 8 columns | 768 to 1023 px | Beehexa span × 3 |\n| 12 columns | 1024 px and up | Beehexa span × 2 |\n\n| Layout | Beehexa spans (4 / 8 / 12 / 12) | Props of each `a-col` |\n|---|---|---|\n| Cards, 1 to 4 a row | 4 / 4 / 4 / 3 | `:xs=\"24\" :md=\"12\" :lg=\"8\" :xl=\"6\"` |\n| Main panel | 4 / 8 / 8 / 9 | `:xs=\"24\" :lg=\"16\" :xl=\"18\"` |\n| Side panel | 4 / 8 / 4 / 3 | `:xs=\"24\" :lg=\"8\" :xl=\"6\"` |\n| Summary tile | 2 / 2 / 3 / 2 | `:xs=\"12\" :md=\"6\" :xl=\"4\"` |\n\nAnt Design Vue rows have no gutter by default. Set it from the spacing tokens, and set the page margin on the content area.\n\n```vue\n<a-row :gutter=\"[{ xs: 16, md: 24 }, { xs: 16, md: 24 }]\">\n <a-col :xs=\"24\" :md=\"12\" :lg=\"8\" :xl=\"6\">\n <OrderSummary />\n </a-col>\n</a-row>\n```\n\n## App frame\n\n| Region | Beehexa | Ant Design Vue |\n|---|---|---|\n| Header | 48 px | `<a-layout-header style=\"height: 48px; line-height: 48px\">` |\n| Side navigation, open | 280 px | `<a-layout-sider :width=\"280\">` |\n| Side navigation, collapsed | 64 px | `<a-layout-sider :collapsed-width=\"64\">` |\n\nThe header is 64 px by default and has no token for its height, so set it in the header’s style.\n\nThe `breakpoint` prop of `a-layout-sider` uses fixed widths that ignore the `screen*` tokens. Do not use it. Set `collapsed` from your own media query and the user’s choice: open from 1024 px, collapsed to the rail when the user asks, and the choice remembered. Below 1024 px, hide the sider and show the menu in `a-drawer`.\n\nSee [Layout](/foundations/styles/layout/) for the frame.\n",
1082
+ "frontmatter": {
1083
+ "title": "Ant Design Vue theme",
1084
+ "description": "Make Ant Design Vue components use Beehexa design tokens, breakpoints, grid, control heights and app frame.",
1085
+ "order": 3
1086
+ }
1087
+ },
1088
+ {
1089
+ "id": "en/tools/eslint",
1090
+ "path": "src/content/tools/eslint.mdx",
1091
+ "documentPath": "docs/src/content/tools/eslint.mdx",
1092
+ "locale": "en",
1093
+ "kind": "guidance",
1094
+ "title": "ESLint rules",
1095
+ "status": "active",
1096
+ "releasePhase": null,
1097
+ "planned": [],
1098
+ "body": "\n> Planned. The plugin is not published yet; this page describes the rules it will ship.\n\n## Rules\n\n| Rule | Flags |\n| --- | --- |\n| `beehexa/no-inline-style-values` | Raw colors and sizes in `style` bindings. |\n| `beehexa/no-deprecated-components` | Components in the Deprecated release phase. |\n| `beehexa/icon-button-label` | Icon-only `a-button` without `aria-label`. |\n",
1099
+ "raw": "---\ntitle: ESLint rules\ndescription: ESLint rules for Vue templates and scripts that use the design system.\norder: 2\n---\n\n> Planned. The plugin is not published yet; this page describes the rules it will ship.\n\n## Rules\n\n| Rule | Flags |\n| --- | --- |\n| `beehexa/no-inline-style-values` | Raw colors and sizes in `style` bindings. |\n| `beehexa/no-deprecated-components` | Components in the Deprecated release phase. |\n| `beehexa/icon-button-label` | Icon-only `a-button` without `aria-label`. |\n",
1100
+ "frontmatter": {
1101
+ "title": "ESLint rules",
1102
+ "description": "ESLint rules for Vue templates and scripts that use the design system.",
1103
+ "order": 2
1104
+ }
1105
+ },
1106
+ {
1107
+ "id": "en/tools/index",
1108
+ "path": "src/content/tools/index.mdx",
1109
+ "documentPath": "docs/src/content/tools/index.mdx",
1110
+ "locale": "en",
1111
+ "kind": "guidance",
1112
+ "title": "Tools",
1113
+ "status": "active",
1114
+ "releasePhase": null,
1115
+ "planned": [],
1116
+ "body": "\nThese tools stop products drifting away from the design system: lint rules catch raw values, the theme makes Ant Design Vue use our tokens, and AI agents get docs they can read.\n",
1117
+ "raw": "---\ntitle: Tools\ndescription: Lint rules, the Ant Design Vue theme and docs for AI agents that keep products on the system.\norder: 0\n---\n\nThese tools stop products drifting away from the design system: lint rules catch raw values, the theme makes Ant Design Vue use our tokens, and AI agents get docs they can read.\n",
1118
+ "frontmatter": {
1119
+ "title": "Tools",
1120
+ "description": "Lint rules, the Ant Design Vue theme and docs for AI agents that keep products on the system.",
1121
+ "order": 0
1122
+ }
1123
+ },
1124
+ {
1125
+ "id": "en/tools/stylelint",
1126
+ "path": "src/content/tools/stylelint.mdx",
1127
+ "documentPath": "docs/src/content/tools/stylelint.mdx",
1128
+ "locale": "en",
1129
+ "kind": "guidance",
1130
+ "title": "Stylelint rules",
1131
+ "status": "active",
1132
+ "releasePhase": null,
1133
+ "planned": [],
1134
+ "body": "\n> Planned. The plugin is not published yet; this page describes the rules it will ship.\n\n## Rules\n\n| Rule | Flags |\n| --- | --- |\n| `beehexa/no-raw-color` | Hex, `rgb()` and named colors. Use a `--bh-color-*` token. |\n| `beehexa/no-color-scale` | Scale, brand and static colour tokens (`--bh-color-graphite-9`, `--bh-color-brand-yellow`). Use a role token. |\n| `beehexa/no-state-opacity` | `opacity`, `filter` or a transparent overlay on `:hover`, `:active` or `:disabled`. Use the state's colour token. |\n| `beehexa/no-raw-spacing` | Pixel and rem values in `margin`, `padding` and `gap`. Use `--bh-space-*`. |\n| `beehexa/no-raw-radius` | Raw values in `border-radius`. Use `--bh-radius-*`. |\n| `beehexa/known-tokens` | `--bh-*` properties that do not exist. |\n\n",
1135
+ "raw": "---\ntitle: Stylelint rules\ndescription: Stylelint rules that flag raw values where a design token exists.\norder: 1\n---\n\n> Planned. The plugin is not published yet; this page describes the rules it will ship.\n\n## Rules\n\n| Rule | Flags |\n| --- | --- |\n| `beehexa/no-raw-color` | Hex, `rgb()` and named colors. Use a `--bh-color-*` token. |\n| `beehexa/no-color-scale` | Scale, brand and static colour tokens (`--bh-color-graphite-9`, `--bh-color-brand-yellow`). Use a role token. |\n| `beehexa/no-state-opacity` | `opacity`, `filter` or a transparent overlay on `:hover`, `:active` or `:disabled`. Use the state's colour token. |\n| `beehexa/no-raw-spacing` | Pixel and rem values in `margin`, `padding` and `gap`. Use `--bh-space-*`. |\n| `beehexa/no-raw-radius` | Raw values in `border-radius`. Use `--bh-radius-*`. |\n| `beehexa/known-tokens` | `--bh-*` properties that do not exist. |\n\n",
1136
+ "frontmatter": {
1137
+ "title": "Stylelint rules",
1138
+ "description": "Stylelint rules that flag raw values where a design token exists.",
1139
+ "order": 1
1140
+ }
1141
+ },
1142
+ {
1143
+ "id": "vi/foundations/styles/border",
1144
+ "path": "src/content-vi/foundations/styles/border.mdx",
1145
+ "documentPath": "docs/src/content-vi/foundations/styles/border.mdx",
1146
+ "locale": "vi",
1147
+ "kind": "guidance",
1148
+ "title": "Viền",
1149
+ "status": "active",
1150
+ "releasePhase": null,
1151
+ "planned": [],
1152
+ "body": "import ShapeDemo from '../../../components/ShapeDemo.astro';\nimport TokenTable from '../../../components/TokenTable.astro';\n\n**Phần lớn viền là 1 px. Viền dày hơn mang ý nghĩa: đang chọn, đang focus, hoặc một trạng thái cần chú ý.**\n\nMàu viền là token màu: `color.border` cho đường phân cách và card, `color.border.bold` cho mép ô nhập, checkbox và select. Xem [Token](/vi/foundations/styles/color/tokens/#borders).\n\n## Các độ dày\n\n<ShapeDemo kind=\"border-scale\" />\n\n## Ví dụ\n\n### `border.width.default` · 1 px\n\nÔ nhập, button phụ, card, bảng và đường phân cách.\n\n<ShapeDemo kind=\"border-use\" item=\"default\" />\n\n### `border.width.selected` · 2 px\n\nThanh dưới tab đang chọn, thanh cạnh mục side nav đang chọn, và viền card đang chọn. Luôn đi cùng `color.border.selected`.\n\n<ShapeDemo kind=\"border-use\" item=\"selected\" />\n\n### `border.width.focused` · 2 px\n\nFocus ring, màu `color.border.focus`, vẽ cách phần tử 2 px về phía ngoài (`state.focus.offset`). Vẽ vào trong, ở −2 px, khi khung bao quanh sẽ cắt mất ring: mục menu, ô bảng và tab trong vùng cuộn.\n\n<ShapeDemo kind=\"border-use\" item=\"focused\" />\n\n### `border.width.accent` · 4 px\n\nThanh trạng thái hoặc nhấn mạnh ở một cạnh: alert và banner, dòng bảng bị lỗi, callout và trích dẫn. Hộp vẫn bo đủ bốn góc và thanh chạy theo đường cong.\n\n<ShapeDemo kind=\"border-use\" item=\"accent\" />\n\n## Độ dày đi cùng màu\n\n| Độ dày | Màu | Dùng cho |\n|---|---|---|\n| `border.width.default` | `color.border` hoặc `color.border.bold` | Mép và đường phân cách |\n| `border.width.selected` | `color.border.selected` | Tab, mục side nav hoặc card đang chọn |\n| `border.width.focused` | `color.border.focus` | Focus bằng bàn phím |\n| `border.width.accent` | `color.border.danger`, `.warning`, `.success`, `.info` hoặc `.brand` | Thanh trạng thái và nhấn mạnh |\n\nKhông báo trạng thái chỉ bằng màu. Đang chọn và đang focus còn đổi cả độ dày.\n\n## Nên và không nên\n\n<ShapeDemo kind=\"dodont\" item=\"selected\" />\n<ShapeDemo kind=\"dodont\" item=\"accent\" />\n<ShapeDemo kind=\"dodont\" item=\"cards\" />\n\n## Code\n\n```css\n.alert {\n position: relative;\n overflow: hidden;\n border: var(--bh-border-width-default) solid var(--bh-color-border);\n border-radius: var(--bh-radius-100);\n}\n.alert::before {\n content: \"\";\n position: absolute;\n inset: 0 auto 0 0;\n width: var(--bh-border-width-accent);\n background: var(--bh-color-border-danger);\n}\n:focus-visible {\n outline: var(--bh-border-width-focused) solid var(--bh-color-border-focus);\n outline-offset: var(--bh-state-focus-offset);\n}\n```\n\n## Token\n\n<TokenTable prefix=\"border\" />\n\n## Liên quan\n\n- [Bo góc](/vi/foundations/styles/radius/): các bậc bo góc và quy tắc lồng nhau.\n- [Trạng thái tương tác](/vi/foundations/styles/interaction-states/): hover, nhấn, đang chọn và vô hiệu.\n",
1153
+ "raw": "---\ntitle: Viền\ndescription: Bốn độ dày viền, màu đi cùng mỗi độ dày, và cách vẽ focus ring.\norder: 7\n---\nimport ShapeDemo from '../../../components/ShapeDemo.astro';\nimport TokenTable from '../../../components/TokenTable.astro';\n\n**Phần lớn viền là 1 px. Viền dày hơn mang ý nghĩa: đang chọn, đang focus, hoặc một trạng thái cần chú ý.**\n\nMàu viền là token màu: `color.border` cho đường phân cách và card, `color.border.bold` cho mép ô nhập, checkbox và select. Xem [Token](/vi/foundations/styles/color/tokens/#borders).\n\n## Các độ dày\n\n<ShapeDemo kind=\"border-scale\" />\n\n## Ví dụ\n\n### `border.width.default` · 1 px\n\nÔ nhập, button phụ, card, bảng và đường phân cách.\n\n<ShapeDemo kind=\"border-use\" item=\"default\" />\n\n### `border.width.selected` · 2 px\n\nThanh dưới tab đang chọn, thanh cạnh mục side nav đang chọn, và viền card đang chọn. Luôn đi cùng `color.border.selected`.\n\n<ShapeDemo kind=\"border-use\" item=\"selected\" />\n\n### `border.width.focused` · 2 px\n\nFocus ring, màu `color.border.focus`, vẽ cách phần tử 2 px về phía ngoài (`state.focus.offset`). Vẽ vào trong, ở −2 px, khi khung bao quanh sẽ cắt mất ring: mục menu, ô bảng và tab trong vùng cuộn.\n\n<ShapeDemo kind=\"border-use\" item=\"focused\" />\n\n### `border.width.accent` · 4 px\n\nThanh trạng thái hoặc nhấn mạnh ở một cạnh: alert và banner, dòng bảng bị lỗi, callout và trích dẫn. Hộp vẫn bo đủ bốn góc và thanh chạy theo đường cong.\n\n<ShapeDemo kind=\"border-use\" item=\"accent\" />\n\n## Độ dày đi cùng màu\n\n| Độ dày | Màu | Dùng cho |\n|---|---|---|\n| `border.width.default` | `color.border` hoặc `color.border.bold` | Mép và đường phân cách |\n| `border.width.selected` | `color.border.selected` | Tab, mục side nav hoặc card đang chọn |\n| `border.width.focused` | `color.border.focus` | Focus bằng bàn phím |\n| `border.width.accent` | `color.border.danger`, `.warning`, `.success`, `.info` hoặc `.brand` | Thanh trạng thái và nhấn mạnh |\n\nKhông báo trạng thái chỉ bằng màu. Đang chọn và đang focus còn đổi cả độ dày.\n\n## Nên và không nên\n\n<ShapeDemo kind=\"dodont\" item=\"selected\" />\n<ShapeDemo kind=\"dodont\" item=\"accent\" />\n<ShapeDemo kind=\"dodont\" item=\"cards\" />\n\n## Code\n\n```css\n.alert {\n position: relative;\n overflow: hidden;\n border: var(--bh-border-width-default) solid var(--bh-color-border);\n border-radius: var(--bh-radius-100);\n}\n.alert::before {\n content: \"\";\n position: absolute;\n inset: 0 auto 0 0;\n width: var(--bh-border-width-accent);\n background: var(--bh-color-border-danger);\n}\n:focus-visible {\n outline: var(--bh-border-width-focused) solid var(--bh-color-border-focus);\n outline-offset: var(--bh-state-focus-offset);\n}\n```\n\n## Token\n\n<TokenTable prefix=\"border\" />\n\n## Liên quan\n\n- [Bo góc](/vi/foundations/styles/radius/): các bậc bo góc và quy tắc lồng nhau.\n- [Trạng thái tương tác](/vi/foundations/styles/interaction-states/): hover, nhấn, đang chọn và vô hiệu.\n",
1154
+ "frontmatter": {
1155
+ "title": "Viền",
1156
+ "description": "Bốn độ dày viền, màu đi cùng mỗi độ dày, và cách vẽ focus ring.",
1157
+ "order": 7
1158
+ }
1159
+ },
1160
+ {
1161
+ "id": "vi/foundations/styles/color/accessibility",
1162
+ "path": "src/content-vi/foundations/styles/color/accessibility.mdx",
1163
+ "documentPath": "docs/src/content-vi/foundations/styles/color/accessibility.mdx",
1164
+ "locale": "vi",
1165
+ "kind": "guidance",
1166
+ "title": "Khả năng tiếp cận",
1167
+ "status": "active",
1168
+ "releasePhase": null,
1169
+ "planned": [],
1170
+ "body": "import ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Mọi token chữ và icon đều đạt WCAG 2.2 AA trên mọi nền đi cùng nó, ở cả giao diện sáng và tối: đủ cả 386 cặp.**\n\n## Độ tương phản\n\n| Thành phần | Tối thiểu | WCAG 2.2 |\n|---|---|---|\n| Chữ | 4.5:1 | 1.4.3 |\n| Icon, viền control, viền focus | 3:1 | 1.4.11 |\n| Control bị vô hiệu, vạch chỉ báo màu vàng, logo | Không có mức tối thiểu | Ngoại lệ của 1.4.3 |\n\n<ColorDemo kind=\"contrast\" />\n\nMàu không bao giờ là tín hiệu duy nhất (WCAG 1.4.1): trạng thái được ghi bằng chữ, mục được chọn có thêm dấu hiệu thứ hai.\n\n## Ghép cặp\n\n**Chữ, icon và viền chỉ được đặt trên các nền ghi cùng với chúng.** Mọi cặp ở đây đều đạt độ tương phản ở giao diện sáng và tối, và được kiểm tra ở mỗi lần build.\n\n<ColorDemo kind=\"pairing\" />\n\n<ColorDemo kind=\"dodont\" item=\"pairing\" />\n\n## Được kiểm tra tự động\n\nMọi cặp trong phần [Ghép cặp](#ghép-cặp) được kiểm tra tự động, ở giao diện sáng và tối. Token chữ, icon hoặc viền nào thấp hơn mức tối thiểu trên bất kỳ nền nào của nó sẽ không được phát hành.\n",
1171
+ "raw": "---\ntitle: Khả năng tiếp cận\ndescription: Độ tương phản mà mọi cặp màu đạt được, chữ nào được đặt trên nền nào, và cách kiểm tra.\norder: 6\n---\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Mọi token chữ và icon đều đạt WCAG 2.2 AA trên mọi nền đi cùng nó, ở cả giao diện sáng và tối: đủ cả 386 cặp.**\n\n## Độ tương phản\n\n| Thành phần | Tối thiểu | WCAG 2.2 |\n|---|---|---|\n| Chữ | 4.5:1 | 1.4.3 |\n| Icon, viền control, viền focus | 3:1 | 1.4.11 |\n| Control bị vô hiệu, vạch chỉ báo màu vàng, logo | Không có mức tối thiểu | Ngoại lệ của 1.4.3 |\n\n<ColorDemo kind=\"contrast\" />\n\nMàu không bao giờ là tín hiệu duy nhất (WCAG 1.4.1): trạng thái được ghi bằng chữ, mục được chọn có thêm dấu hiệu thứ hai.\n\n## Ghép cặp\n\n**Chữ, icon và viền chỉ được đặt trên các nền ghi cùng với chúng.** Mọi cặp ở đây đều đạt độ tương phản ở giao diện sáng và tối, và được kiểm tra ở mỗi lần build.\n\n<ColorDemo kind=\"pairing\" />\n\n<ColorDemo kind=\"dodont\" item=\"pairing\" />\n\n## Được kiểm tra tự động\n\nMọi cặp trong phần [Ghép cặp](#ghép-cặp) được kiểm tra tự động, ở giao diện sáng và tối. Token chữ, icon hoặc viền nào thấp hơn mức tối thiểu trên bất kỳ nền nào của nó sẽ không được phát hành.\n",
1172
+ "frontmatter": {
1173
+ "title": "Khả năng tiếp cận",
1174
+ "description": "Độ tương phản mà mọi cặp màu đạt được, chữ nào được đặt trên nền nào, và cách kiểm tra.",
1175
+ "order": 6
1176
+ }
1177
+ },
1178
+ {
1179
+ "id": "vi/foundations/styles/color/dark-mode",
1180
+ "path": "src/content-vi/foundations/styles/color/dark-mode.mdx",
1181
+ "documentPath": "docs/src/content-vi/foundations/styles/color/dark-mode.mdx",
1182
+ "locale": "vi",
1183
+ "kind": "guidance",
1184
+ "title": "Giao diện tối",
1185
+ "status": "active",
1186
+ "releasePhase": null,
1187
+ "planned": [],
1188
+ "body": "import ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Viết mỗi token một lần; giao diện sẽ đổi giá trị.**\n\n<ColorDemo kind=\"themes\" />\n\n## Cách hoạt động\n\nMỗi token màu có một giá trị sáng và một giá trị tối dưới cùng tên. Giao diện chọn giá trị; code và thiết kế của bạn chỉ gọi tên token một lần. Giá trị tối của mọi bậc trong bảng màu có ở trang [Bảng màu](/vi/foundations/styles/color/palette/), của mọi role token có ở trang [Token](/vi/foundations/styles/color/tokens/).\n\n## Thiết kế cho giao diện tối\n\n- Không tự đặt màu tối riêng, không chọn màu theo giao diện trong code.\n- Bề mặt càng nổi lên càng sáng: nền trang tối nhất, card sáng hơn một bậc.\n- Nút chính chuyển sang màu sáng, và các nền đặc của trạng thái sáng lên với chữ tối bên trên.\n- Kiểm tra mọi màn hình ở cả hai giao diện trước khi phát hành.\n- Logo dùng bản dành cho nền tối (xem [Logo](/vi/foundations/styles/logos/)).\n",
1189
+ "raw": "---\ntitle: Giao diện tối\ndescription: Giao diện tối hoạt động thế nào, những gì thay đổi và những điều không bao giờ làm ở giao diện tối.\norder: 5\n---\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Viết mỗi token một lần; giao diện sẽ đổi giá trị.**\n\n<ColorDemo kind=\"themes\" />\n\n## Cách hoạt động\n\nMỗi token màu có một giá trị sáng và một giá trị tối dưới cùng tên. Giao diện chọn giá trị; code và thiết kế của bạn chỉ gọi tên token một lần. Giá trị tối của mọi bậc trong bảng màu có ở trang [Bảng màu](/vi/foundations/styles/color/palette/), của mọi role token có ở trang [Token](/vi/foundations/styles/color/tokens/).\n\n## Thiết kế cho giao diện tối\n\n- Không tự đặt màu tối riêng, không chọn màu theo giao diện trong code.\n- Bề mặt càng nổi lên càng sáng: nền trang tối nhất, card sáng hơn một bậc.\n- Nút chính chuyển sang màu sáng, và các nền đặc của trạng thái sáng lên với chữ tối bên trên.\n- Kiểm tra mọi màn hình ở cả hai giao diện trước khi phát hành.\n- Logo dùng bản dành cho nền tối (xem [Logo](/vi/foundations/styles/logos/)).\n",
1190
+ "frontmatter": {
1191
+ "title": "Giao diện tối",
1192
+ "description": "Giao diện tối hoạt động thế nào, những gì thay đổi và những điều không bao giờ làm ở giao diện tối.",
1193
+ "order": 5
1194
+ }
1195
+ },
1196
+ {
1197
+ "id": "vi/foundations/styles/color/index",
1198
+ "path": "src/content-vi/foundations/styles/color/index.mdx",
1199
+ "documentPath": "docs/src/content-vi/foundations/styles/color/index.mdx",
1200
+ "locale": "vi",
1201
+ "kind": "guidance",
1202
+ "title": "Màu sắc",
1203
+ "status": "active",
1204
+ "releasePhase": null,
1205
+ "planned": [],
1206
+ "body": "import ColorDemo from '../../../../components/ColorDemo.astro';\n\nMàu trong sản phẩm Beehexa chủ yếu là xám ghi và trắng. Màu vàng đánh dấu thương hiệu, bốn màu chức năng đánh dấu trạng thái. Bạn không bao giờ chọn màu theo mã màu. Bạn chọn token theo việc nó làm, như `color.text` hay `color.background.danger.bold`, và token đó đúng ở cả giao diện sáng lẫn tối.\n\n<ColorDemo kind=\"balance\" />\n\n## Màu thương hiệu\n\n<ColorDemo kind=\"brand\" />\n\n## Bảng màu\n\nSáu thang màu, mỗi thang mười hai bậc, cho giao diện sáng và tối. Màu xám ghi thương hiệu là bậc graphite 12 ở giao diện sáng. Màu vàng thương hiệu là bậc yellow 7 ở giao diện sáng và yellow 11 ở giao diện tối. Xem mọi giá trị ở trang [Bảng màu](/vi/foundations/styles/color/palette/).\n\n<ColorDemo kind=\"ramps\" />\n\n## Màu hoạt động thế nào\n\nMàu chia làm ba tầng. Bạn chỉ dùng tầng giữa.\n\n| Tầng | Ví dụ | Ai dùng |\n|---|---|---|\n| Bảng màu | `color.graphite.11` | Không ai dùng trực tiếp. Tầng này cấp giá trị cho role token. |\n| Role token | `color.text.subtle` | Mọi sản phẩm và component. |\n| Component token | `color.code.background` | Chỉ khi không có role token nào phù hợp. |\n\nRole token là token đặt tên theo vai trò của màu. Danh sách role token ở trang [Token](/vi/foundations/styles/color/tokens/). Cách chọn token ở trang [Cách dùng](/vi/foundations/styles/color/usage/).\n\n## Nguyên tắc\n\n### Xám ghi làm phần việc chính, vàng là điểm nhấn\n\nChữ, icon, đường kẻ và nút chính đều màu xám ghi. Màu vàng chỉ dùng cho logo, vạch chỉ trang hiện tại, phần tô nổi bật và ghi chú thương hiệu. Màu vàng không bao giờ dùng cho chữ hay nút: trên nền trắng nó chỉ đạt 1.85:1.\n\n<ColorDemo kind=\"dodont\" item=\"yellow\" />\n\n### Màu phải có nghĩa\n\nĐỏ, cam, xanh lá và xanh dương nghĩa là nguy hiểm, cảnh báo, thành công và thông tin. Không dùng chúng để trang trí hay để gây chú ý.\n\n<ColorDemo kind=\"dodont\" item=\"meaning\" />\n\n### Không chỉ dựa vào màu\n\nGhi trạng thái bằng chữ và thêm icon. Đánh dấu mục được chọn bằng một dấu hiệu thứ hai ngoài màu. Người mù màu và người dùng trình đọc màn hình không nhận được thông tin từ màu.\n\n<ColorDemo kind=\"dodont\" item=\"alone\" />\n\n### Dùng đúng token cho đúng việc\n\nChỉ dùng role token. Không dùng mã hex, không dùng một bậc của thang màu như `color.graphite.11`. Nếu không có token phù hợp, hãy đề nghị thêm token mới.\n\n<ColorDemo kind=\"dodont\" item=\"tokens\" />\n\n### Mỗi màn hình một nút chính\n\nNút chính màu xám ghi. Mọi nút khác là nút mặc định. Không có nút màu vàng.\n\n<ColorDemo kind=\"dodont\" item=\"primary\" />\n",
1207
+ "raw": "---\ntitle: Màu sắc\ndescription: Ba màu thương hiệu và một bộ token màu, mỗi token một việc, cho chữ, icon, bề mặt, nền, viền và trạng thái, ở cả giao diện sáng và tối.\norder: 1\nsidebarLabel: Tổng quan\n---\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\nMàu trong sản phẩm Beehexa chủ yếu là xám ghi và trắng. Màu vàng đánh dấu thương hiệu, bốn màu chức năng đánh dấu trạng thái. Bạn không bao giờ chọn màu theo mã màu. Bạn chọn token theo việc nó làm, như `color.text` hay `color.background.danger.bold`, và token đó đúng ở cả giao diện sáng lẫn tối.\n\n<ColorDemo kind=\"balance\" />\n\n## Màu thương hiệu\n\n<ColorDemo kind=\"brand\" />\n\n## Bảng màu\n\nSáu thang màu, mỗi thang mười hai bậc, cho giao diện sáng và tối. Màu xám ghi thương hiệu là bậc graphite 12 ở giao diện sáng. Màu vàng thương hiệu là bậc yellow 7 ở giao diện sáng và yellow 11 ở giao diện tối. Xem mọi giá trị ở trang [Bảng màu](/vi/foundations/styles/color/palette/).\n\n<ColorDemo kind=\"ramps\" />\n\n## Màu hoạt động thế nào\n\nMàu chia làm ba tầng. Bạn chỉ dùng tầng giữa.\n\n| Tầng | Ví dụ | Ai dùng |\n|---|---|---|\n| Bảng màu | `color.graphite.11` | Không ai dùng trực tiếp. Tầng này cấp giá trị cho role token. |\n| Role token | `color.text.subtle` | Mọi sản phẩm và component. |\n| Component token | `color.code.background` | Chỉ khi không có role token nào phù hợp. |\n\nRole token là token đặt tên theo vai trò của màu. Danh sách role token ở trang [Token](/vi/foundations/styles/color/tokens/). Cách chọn token ở trang [Cách dùng](/vi/foundations/styles/color/usage/).\n\n## Nguyên tắc\n\n### Xám ghi làm phần việc chính, vàng là điểm nhấn\n\nChữ, icon, đường kẻ và nút chính đều màu xám ghi. Màu vàng chỉ dùng cho logo, vạch chỉ trang hiện tại, phần tô nổi bật và ghi chú thương hiệu. Màu vàng không bao giờ dùng cho chữ hay nút: trên nền trắng nó chỉ đạt 1.85:1.\n\n<ColorDemo kind=\"dodont\" item=\"yellow\" />\n\n### Màu phải có nghĩa\n\nĐỏ, cam, xanh lá và xanh dương nghĩa là nguy hiểm, cảnh báo, thành công và thông tin. Không dùng chúng để trang trí hay để gây chú ý.\n\n<ColorDemo kind=\"dodont\" item=\"meaning\" />\n\n### Không chỉ dựa vào màu\n\nGhi trạng thái bằng chữ và thêm icon. Đánh dấu mục được chọn bằng một dấu hiệu thứ hai ngoài màu. Người mù màu và người dùng trình đọc màn hình không nhận được thông tin từ màu.\n\n<ColorDemo kind=\"dodont\" item=\"alone\" />\n\n### Dùng đúng token cho đúng việc\n\nChỉ dùng role token. Không dùng mã hex, không dùng một bậc của thang màu như `color.graphite.11`. Nếu không có token phù hợp, hãy đề nghị thêm token mới.\n\n<ColorDemo kind=\"dodont\" item=\"tokens\" />\n\n### Mỗi màn hình một nút chính\n\nNút chính màu xám ghi. Mọi nút khác là nút mặc định. Không có nút màu vàng.\n\n<ColorDemo kind=\"dodont\" item=\"primary\" />\n",
1208
+ "frontmatter": {
1209
+ "title": "Màu sắc",
1210
+ "description": "Ba màu thương hiệu và một bộ token màu, mỗi token một việc, cho chữ, icon, bề mặt, nền, viền và trạng thái, ở cả giao diện sáng và tối.",
1211
+ "order": 1,
1212
+ "sidebarLabel": "Tổng quan"
1213
+ }
1214
+ },
1215
+ {
1216
+ "id": "vi/foundations/styles/color/palette",
1217
+ "path": "src/content-vi/foundations/styles/color/palette.mdx",
1218
+ "documentPath": "docs/src/content-vi/foundations/styles/color/palette.mdx",
1219
+ "locale": "vi",
1220
+ "kind": "guidance",
1221
+ "title": "Bảng màu",
1222
+ "status": "active",
1223
+ "releasePhase": null,
1224
+ "planned": [],
1225
+ "body": "import ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Bảng màu cấp giá trị cho role token. Sản phẩm dùng role token, không bao giờ dùng trực tiếp một bậc của bảng màu.**\n\nSáu thang màu, mỗi thang mười hai bậc. Rê chuột lên một ô màu để xem tên token.\n\n<ColorDemo kind=\"palette\" />\n\n## Công dụng của từng thang\n\n| Thang | Dùng cho | Không dùng cho |\n|---|---|---|\n| Graphite | Mọi thứ không mang nghĩa riêng: chữ, icon, đường kẻ, bề mặt, nút chính | — |\n| Yellow | Thương hiệu: logo, vạch chỉ trang hiện tại, phần tô nổi bật, ghi chú thương hiệu | Chữ, nút, cảnh báo |\n| Blue | Thông tin, link, viền focus | Trang trí |\n| Green | Thành công | Mọi việc khác |\n| Orange | Cảnh báo | Mọi việc khác |\n| Red | Nguy hiểm | Mọi việc khác |\n\nKhông có tím, hồng hay xanh ngọc. Biểu đồ chưa có bảng màu riêng: hãy hỏi trước khi tô màu cho biểu đồ.\n\n## Công dụng của từng bậc\n\n**Mỗi bậc có một việc, giống nhau ở mọi thang.**\n\n<ColorDemo kind=\"steps\" />\n\n- **Bậc 1–2:** nền trang và nền bề mặt.\n- **Bậc 3–5:** nền component khi nghỉ, khi hover và khi nhấn hoặc được chọn.\n- **Bậc 6–8:** viền và đường phân cách, từ nhạt tới đậm.\n- **Bậc 9–10:** nền đặc, như nền của nút, và màu hover của chúng.\n- **Bậc 11–12:** chữ và icon. 11 là chữ phụ, 12 là chữ mặc định.\n\nGraphite là màu của chữ trung tính, nên đầu tối của thang có ba mức chữ thay vì hai: 12 mặc định, 11 chữ phụ, 10 chữ mức ba. Bậc 9 là viền của control và bậc 8 là chữ bị vô hiệu hoá.\n\nYellow là ngoại lệ duy nhất: nền thương hiệu của nó là bậc 7, chính là màu vàng thương hiệu, với chữ graphite bên trên. Sản phẩm không dùng màu vàng cho nền khác hay cho chữ.\n\n## Sáng và tối\n\n**Mỗi bậc có một giá trị sáng và một giá trị tối dưới cùng một tên.**\n\n`color.graphite.12` là màu chữ ở cả hai giao diện. Role token tự đổi theo giao diện, nên màn hình không bao giờ phải tự chọn màu tối. Ở giao diện tối, nền đặc (bậc 9 và 10) sáng hơn ở giao diện sáng, nên chữ trên đó là chữ tối: dùng `text.on-bold`.\n\n## Độ tương phản được bảo đảm\n\nỞ cả hai giao diện:\n\n- Ở blue, green, orange và red, chữ trên nền đặc (bậc 9 và 10) đạt 4.5:1 với `text.on-bold`: trắng ở giao diện sáng, tối ở giao diện tối.\n- Chữ bậc 11 đạt 4.5:1 trên mọi nền nó được ghép cặp.\n- Ở graphite, bậc 10, 11 và 12 đều đạt 4.5:1 khi làm chữ; bậc 9 đạt 3:1 khi làm viền của control.\n\nXem các cặp màu ở trang [Khả năng tiếp cận](/foundations/styles/color/accessibility/).\n",
1226
+ "raw": "---\ntitle: Bảng màu\ndescription: Mọi màu trong hệ thống, gồm sáu thang màu mười hai bậc ở giao diện sáng và tối, công dụng của từng thang, từng bậc và độ tương phản mỗi bậc bảo đảm.\norder: 3\n---\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Bảng màu cấp giá trị cho role token. Sản phẩm dùng role token, không bao giờ dùng trực tiếp một bậc của bảng màu.**\n\nSáu thang màu, mỗi thang mười hai bậc. Rê chuột lên một ô màu để xem tên token.\n\n<ColorDemo kind=\"palette\" />\n\n## Công dụng của từng thang\n\n| Thang | Dùng cho | Không dùng cho |\n|---|---|---|\n| Graphite | Mọi thứ không mang nghĩa riêng: chữ, icon, đường kẻ, bề mặt, nút chính | — |\n| Yellow | Thương hiệu: logo, vạch chỉ trang hiện tại, phần tô nổi bật, ghi chú thương hiệu | Chữ, nút, cảnh báo |\n| Blue | Thông tin, link, viền focus | Trang trí |\n| Green | Thành công | Mọi việc khác |\n| Orange | Cảnh báo | Mọi việc khác |\n| Red | Nguy hiểm | Mọi việc khác |\n\nKhông có tím, hồng hay xanh ngọc. Biểu đồ chưa có bảng màu riêng: hãy hỏi trước khi tô màu cho biểu đồ.\n\n## Công dụng của từng bậc\n\n**Mỗi bậc có một việc, giống nhau ở mọi thang.**\n\n<ColorDemo kind=\"steps\" />\n\n- **Bậc 1–2:** nền trang và nền bề mặt.\n- **Bậc 3–5:** nền component khi nghỉ, khi hover và khi nhấn hoặc được chọn.\n- **Bậc 6–8:** viền và đường phân cách, từ nhạt tới đậm.\n- **Bậc 9–10:** nền đặc, như nền của nút, và màu hover của chúng.\n- **Bậc 11–12:** chữ và icon. 11 là chữ phụ, 12 là chữ mặc định.\n\nGraphite là màu của chữ trung tính, nên đầu tối của thang có ba mức chữ thay vì hai: 12 mặc định, 11 chữ phụ, 10 chữ mức ba. Bậc 9 là viền của control và bậc 8 là chữ bị vô hiệu hoá.\n\nYellow là ngoại lệ duy nhất: nền thương hiệu của nó là bậc 7, chính là màu vàng thương hiệu, với chữ graphite bên trên. Sản phẩm không dùng màu vàng cho nền khác hay cho chữ.\n\n## Sáng và tối\n\n**Mỗi bậc có một giá trị sáng và một giá trị tối dưới cùng một tên.**\n\n`color.graphite.12` là màu chữ ở cả hai giao diện. Role token tự đổi theo giao diện, nên màn hình không bao giờ phải tự chọn màu tối. Ở giao diện tối, nền đặc (bậc 9 và 10) sáng hơn ở giao diện sáng, nên chữ trên đó là chữ tối: dùng `text.on-bold`.\n\n## Độ tương phản được bảo đảm\n\nỞ cả hai giao diện:\n\n- Ở blue, green, orange và red, chữ trên nền đặc (bậc 9 và 10) đạt 4.5:1 với `text.on-bold`: trắng ở giao diện sáng, tối ở giao diện tối.\n- Chữ bậc 11 đạt 4.5:1 trên mọi nền nó được ghép cặp.\n- Ở graphite, bậc 10, 11 và 12 đều đạt 4.5:1 khi làm chữ; bậc 9 đạt 3:1 khi làm viền của control.\n\nXem các cặp màu ở trang [Khả năng tiếp cận](/foundations/styles/color/accessibility/).\n",
1227
+ "frontmatter": {
1228
+ "title": "Bảng màu",
1229
+ "description": "Mọi màu trong hệ thống, gồm sáu thang màu mười hai bậc ở giao diện sáng và tối, công dụng của từng thang, từng bậc và độ tương phản mỗi bậc bảo đảm.",
1230
+ "order": 3
1231
+ }
1232
+ },
1233
+ {
1234
+ "id": "vi/foundations/styles/color/tokens",
1235
+ "path": "src/content-vi/foundations/styles/color/tokens.mdx",
1236
+ "documentPath": "docs/src/content-vi/foundations/styles/color/tokens.mdx",
1237
+ "locale": "vi",
1238
+ "kind": "guidance",
1239
+ "title": "Token",
1240
+ "status": "active",
1241
+ "releasePhase": null,
1242
+ "planned": [],
1243
+ "body": "import ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Tên mỗi token màu cho biết nó tô cái gì, mang nghĩa gì, đậm nhạt ra sao và đang ở trạng thái nào.**\n\n## Cách đặt tên\n\n`color.{property}.{role}.{emphasis}.{state}`. Phần nào là mặc định thì bỏ đi.\n\n<ColorDemo kind=\"anatomy\" />\n\n| Phần | Giá trị |\n|---|---|\n| Property (thứ được tô) | `text`, `icon`, `link`, `surface`, `background`, `border`, `skeleton` |\n| Role (vai trò) | `neutral` (bỏ đi), `brand`, `danger`, `warning`, `success`, `info`, `inverse`, `disabled`; với surface: `page`, `subtle`, `inverse`, `scrim` |\n| Emphasis (mức nhấn) | Chữ: mặc định, `subtle`, `subtlest`. Nền: `subtle`, mặc định, `bold`. Viền: mặc định, `bold` |\n| State (trạng thái) | `hover`, `pressed`, `selected`, `focus` |\n\n`color.background.danger.bold.hover` là nền đặc màu nguy hiểm khi hover. Có hai tên gọi theo nền nằm dưới chữ thay vì theo vai trò: `text.on-bold` (trên mọi nền đặc của trạng thái) và `text.on-brand` (trên màu vàng thương hiệu).\n\nTrong CSS, viết `--bh-` rồi đến tên token, thay dấu chấm bằng dấu gạch ngang: `color.text.subtle` là `var(--bh-color-text-subtle)`.\n\nHãy dùng role token. [Bảng màu](/vi/foundations/styles/color/palette/) cấp giá trị cho role token và không bao giờ được dùng trực tiếp (xem [Màu hoạt động thế nào](/vi/foundations/styles/color/#màu-hoạt-động-thế-nào)).\n\n## Chữ và icon\n\n<ColorDemo kind=\"roles\" group=\"text\" />\n\n<ColorDemo kind=\"roles\" group=\"icon\" />\n\n## Bề mặt\n\n<ColorDemo kind=\"roles\" group=\"surface\" />\n\n## Nền\n\n<ColorDemo kind=\"roles\" group=\"background\" />\n\n## Viền\n\n<ColorDemo kind=\"roles\" group=\"border\" />\n\n## Thiếu token\n\n1. Xem bảng [Tìm token](/vi/foundations/styles/color/usage/#tìm-token) và danh sách bên dưới.\n2. Hỏi đội design system. Cho biết bạn cần token ở đâu, và đề xuất một tên ghép từ bốn phần, trỏ tới một bậc có đúng công dụng (nền ở bậc 3, viền ở bậc 7, chữ ở bậc 11).\n3. Đội sẽ kiểm tra độ tương phản ở cả hai giao diện rồi thêm token. Chỉ dùng token sau khi nó được phát hành.\n\n## Mọi token màu\n\n<ColorDemo kind=\"tokens\" />\n",
1244
+ "raw": "---\ntitle: Token\ndescription: Cách đặt tên token màu, mọi role token với giá trị ở giao diện sáng và tối, cách dùng trong code và cách đề nghị thêm token mới.\norder: 4\n---\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Tên mỗi token màu cho biết nó tô cái gì, mang nghĩa gì, đậm nhạt ra sao và đang ở trạng thái nào.**\n\n## Cách đặt tên\n\n`color.{property}.{role}.{emphasis}.{state}`. Phần nào là mặc định thì bỏ đi.\n\n<ColorDemo kind=\"anatomy\" />\n\n| Phần | Giá trị |\n|---|---|\n| Property (thứ được tô) | `text`, `icon`, `link`, `surface`, `background`, `border`, `skeleton` |\n| Role (vai trò) | `neutral` (bỏ đi), `brand`, `danger`, `warning`, `success`, `info`, `inverse`, `disabled`; với surface: `page`, `subtle`, `inverse`, `scrim` |\n| Emphasis (mức nhấn) | Chữ: mặc định, `subtle`, `subtlest`. Nền: `subtle`, mặc định, `bold`. Viền: mặc định, `bold` |\n| State (trạng thái) | `hover`, `pressed`, `selected`, `focus` |\n\n`color.background.danger.bold.hover` là nền đặc màu nguy hiểm khi hover. Có hai tên gọi theo nền nằm dưới chữ thay vì theo vai trò: `text.on-bold` (trên mọi nền đặc của trạng thái) và `text.on-brand` (trên màu vàng thương hiệu).\n\nTrong CSS, viết `--bh-` rồi đến tên token, thay dấu chấm bằng dấu gạch ngang: `color.text.subtle` là `var(--bh-color-text-subtle)`.\n\nHãy dùng role token. [Bảng màu](/vi/foundations/styles/color/palette/) cấp giá trị cho role token và không bao giờ được dùng trực tiếp (xem [Màu hoạt động thế nào](/vi/foundations/styles/color/#màu-hoạt-động-thế-nào)).\n\n## Chữ và icon\n\n<ColorDemo kind=\"roles\" group=\"text\" />\n\n<ColorDemo kind=\"roles\" group=\"icon\" />\n\n## Bề mặt\n\n<ColorDemo kind=\"roles\" group=\"surface\" />\n\n## Nền\n\n<ColorDemo kind=\"roles\" group=\"background\" />\n\n## Viền\n\n<ColorDemo kind=\"roles\" group=\"border\" />\n\n## Thiếu token\n\n1. Xem bảng [Tìm token](/vi/foundations/styles/color/usage/#tìm-token) và danh sách bên dưới.\n2. Hỏi đội design system. Cho biết bạn cần token ở đâu, và đề xuất một tên ghép từ bốn phần, trỏ tới một bậc có đúng công dụng (nền ở bậc 3, viền ở bậc 7, chữ ở bậc 11).\n3. Đội sẽ kiểm tra độ tương phản ở cả hai giao diện rồi thêm token. Chỉ dùng token sau khi nó được phát hành.\n\n## Mọi token màu\n\n<ColorDemo kind=\"tokens\" />\n",
1245
+ "frontmatter": {
1246
+ "title": "Token",
1247
+ "description": "Cách đặt tên token màu, mọi role token với giá trị ở giao diện sáng và tối, cách dùng trong code và cách đề nghị thêm token mới.",
1248
+ "order": 4
1249
+ }
1250
+ },
1251
+ {
1252
+ "id": "vi/foundations/styles/color/usage",
1253
+ "path": "src/content-vi/foundations/styles/color/usage.mdx",
1254
+ "documentPath": "docs/src/content-vi/foundations/styles/color/usage.mdx",
1255
+ "locale": "vi",
1256
+ "kind": "guidance",
1257
+ "title": "Cách dùng",
1258
+ "status": "active",
1259
+ "releasePhase": null,
1260
+ "planned": [],
1261
+ "body": "import ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Chọn token theo thứ bạn đang tô và ý nghĩa của nó, không chọn theo vẻ ngoài.**\n\n<ColorDemo kind=\"example\" />\n\n## Tìm token\n\n| Tôi cần | Dùng |\n|---|---|\n| Nền trang | `surface.page` |\n| Card, panel, dialog | `surface`, viền `border` |\n| Sidebar, header của bảng, vùng nền nhạt | `surface.subtle` |\n| Chữ nội dung, tiêu đề, nhãn | `text` |\n| Mô tả, cột phụ của bảng, điều hướng | `text.subtle` |\n| Metadata, mốc thời gian, chữ hướng dẫn, breadcrumb | `text.subtlest` |\n| Placeholder | `text.subtlest` |\n| Link | `link`; khi hover `link.hover` |\n| Icon cạnh chữ | `icon`; icon ít quan trọng hơn `icon.subtle` |\n| Đường phân cách, viền card | `border` |\n| Viền của ô nhập, checkbox hoặc select | `border.bold` |\n| Viền focus khi dùng bàn phím | `border.focus`, dày 2 px, cách 2 px |\n| Nút chính | `background.neutral.bold`, `text.inverse` |\n| Nút mặc định | `surface`, `border`, `text`; khi hover `background.neutral.subtle.hover` |\n| Nút cho hành động xoá, huỷ | `background.danger.bold`, `text.on-bold` |\n| Dòng hoặc mục menu khi hover | `background.neutral.subtle.hover` |\n| Dòng, tab hoặc mục menu được chọn | `background.selected` và một dấu hiệu thứ hai |\n| Trang hiện tại trong thanh điều hướng | Vạch `border.selected`, `background.selected`, `aria-current=\"page\"` |\n| Lỗi dưới một trường nhập | `text.danger`, `icon.danger` |\n| Banner báo trạng thái | `background.{role}.subtle`, `border.{role}.subtle`, `text`, `icon.{role}` |\n| Trạng thái trong một dòng của bảng | Một [nhãn](#nhãn) |\n| Tooltip, toast | `surface.inverse`, `text.inverse` |\n| Lớp phủ sau dialog hoặc drawer | `surface.scrim` |\n| Khung chờ khi đang tải | `skeleton`, vệt sáng `skeleton.subtle` |\n| Khối code | `code.background`, `code.text` |\n| Ghi chú thương hiệu | `background.brand.subtle`, `border.brand.subtle` |\n| Control bị vô hiệu | `background.disabled`, `text.disabled`, `border.disabled` |\n\nKhông có trong bảng? Ghép tên từ bốn phần của nó (xem [Token](/vi/foundations/styles/color/tokens/)). Nếu chưa có token, hãy đề nghị thêm. Không chọn màu gần giống.\n\n## Bề mặt và nền\n\n**Bề mặt (surface) là các lớp của màn hình. Nền (background) tô cho những thứ nằm trên đó.**\n\n<ColorDemo kind=\"surfaces\" />\n\n`surface.scrim` chỉ nằm sau dialog và drawer, một lớp duy nhất, với độ mờ riêng của nó.\n\n## Mức nhấn\n\n<ColorDemo kind=\"emphasis\" />\n\n## Trạng thái\n\n**Mỗi trạng thái thuộc một trong năm vai trò. Chọn theo việc người dùng cần làm, và luôn nói rõ bằng chữ.**\n\n### Chọn trạng thái\n\n| Vai trò | Dùng khi | Ví dụ trong HexaSync |\n|---|---|---|\n| Thông tin (info) | Có việc đang diễn ra hoặc đáng biết; không cần làm gì. | Đang đồng bộ, đang chờ, đang nhập |\n| Thành công (success) | Đã chạy tốt. | Đã đồng bộ, đã kết nối, đã xong |\n| Cảnh báo (warning) | Đang chạy nhưng sắp cần xử lý. | Đồng bộ một phần, token hết hạn sau 3 ngày, bị giới hạn tần suất |\n| Nguy hiểm (danger) | Bị lỗi hoặc bị chặn, hoặc hành động sẽ xoá mất dữ liệu. | Lỗi, mất kết nối, xoá |\n| Trung tính (neutral) | Không có gì đang chạy và không có gì sai. | Tạm dừng, nháp, bỏ qua, lưu trữ |\n\nCảnh báo dùng màu cam, không dùng màu vàng, vì màu vàng là màu thương hiệu. Không có mức thứ sáu; hãy nói rõ khác biệt bằng chữ (\"Lỗi 3 lần\").\n\n### Màu trạng thái\n\n<ColorDemo kind=\"status\" />\n\n<ColorDemo kind=\"banners\" />\n\n<ColorDemo kind=\"dodont\" item=\"warning\" />\n\n### Nhãn\n\n<ColorDemo kind=\"labels\" />\n\n| | Nhãn | Nhãn trạng thái |\n|---|---|---|\n| Hình thức | Viền theo `border` của vai trò, chữ theo `text` của vai trò | Nền theo `bold` của vai trò, chữ và icon theo `text.on-bold` |\n| Kích thước | Cao 20 px, padding 6 px; cỡ lớn 24 px, 8 px | Cao 32 px, padding 12 px |\n| Dùng | Nhiều nhãn trên một màn hình: dòng trong bảng, tag | Một nhãn trên mỗi trang: trạng thái chính của trang đó |\n\n## Trạng thái tương tác\n\n**Thêm `.hover` hoặc `.pressed` vào token ở trạng thái nghỉ. Không dùng độ mờ (opacity) hay lớp phủ.**\n\n<ColorDemo kind=\"states\" />\n\n| Trạng thái | Dùng |\n|---|---|\n| Hover, nhấn | Token ở trạng thái nghỉ, thêm `.hover` hoặc `.pressed` |\n| Được chọn | `background.selected` và một dấu hiệu thứ hai |\n| Focus | Viền `border.focus` dày 2 px, cách 2 px |\n| Vô hiệu | `background.disabled`, `text.disabled`, `border.disabled` |\n\nVới dòng hoặc mục menu, mỗi trạng thái cách nền thêm một bậc: hover, rồi được chọn, rồi được chọn khi hover. Dòng đang hover luôn nhạt hơn dòng được chọn, nên không bao giờ trông như đang được chọn.\n\nXem thêm ở trang [Trạng thái tương tác](/vi/foundations/styles/interaction-states/).\n\n## Nút\n\n<ColorDemo kind=\"actions\" />\n",
1262
+ "raw": "---\ntitle: Cách dùng\ndescription: Dùng token nào cho từng phần của màn hình, cách tô màu trạng thái, mức nhấn và trạng thái tương tác, và những điều không được làm.\norder: 2\n---\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Chọn token theo thứ bạn đang tô và ý nghĩa của nó, không chọn theo vẻ ngoài.**\n\n<ColorDemo kind=\"example\" />\n\n## Tìm token\n\n| Tôi cần | Dùng |\n|---|---|\n| Nền trang | `surface.page` |\n| Card, panel, dialog | `surface`, viền `border` |\n| Sidebar, header của bảng, vùng nền nhạt | `surface.subtle` |\n| Chữ nội dung, tiêu đề, nhãn | `text` |\n| Mô tả, cột phụ của bảng, điều hướng | `text.subtle` |\n| Metadata, mốc thời gian, chữ hướng dẫn, breadcrumb | `text.subtlest` |\n| Placeholder | `text.subtlest` |\n| Link | `link`; khi hover `link.hover` |\n| Icon cạnh chữ | `icon`; icon ít quan trọng hơn `icon.subtle` |\n| Đường phân cách, viền card | `border` |\n| Viền của ô nhập, checkbox hoặc select | `border.bold` |\n| Viền focus khi dùng bàn phím | `border.focus`, dày 2 px, cách 2 px |\n| Nút chính | `background.neutral.bold`, `text.inverse` |\n| Nút mặc định | `surface`, `border`, `text`; khi hover `background.neutral.subtle.hover` |\n| Nút cho hành động xoá, huỷ | `background.danger.bold`, `text.on-bold` |\n| Dòng hoặc mục menu khi hover | `background.neutral.subtle.hover` |\n| Dòng, tab hoặc mục menu được chọn | `background.selected` và một dấu hiệu thứ hai |\n| Trang hiện tại trong thanh điều hướng | Vạch `border.selected`, `background.selected`, `aria-current=\"page\"` |\n| Lỗi dưới một trường nhập | `text.danger`, `icon.danger` |\n| Banner báo trạng thái | `background.{role}.subtle`, `border.{role}.subtle`, `text`, `icon.{role}` |\n| Trạng thái trong một dòng của bảng | Một [nhãn](#nhãn) |\n| Tooltip, toast | `surface.inverse`, `text.inverse` |\n| Lớp phủ sau dialog hoặc drawer | `surface.scrim` |\n| Khung chờ khi đang tải | `skeleton`, vệt sáng `skeleton.subtle` |\n| Khối code | `code.background`, `code.text` |\n| Ghi chú thương hiệu | `background.brand.subtle`, `border.brand.subtle` |\n| Control bị vô hiệu | `background.disabled`, `text.disabled`, `border.disabled` |\n\nKhông có trong bảng? Ghép tên từ bốn phần của nó (xem [Token](/vi/foundations/styles/color/tokens/)). Nếu chưa có token, hãy đề nghị thêm. Không chọn màu gần giống.\n\n## Bề mặt và nền\n\n**Bề mặt (surface) là các lớp của màn hình. Nền (background) tô cho những thứ nằm trên đó.**\n\n<ColorDemo kind=\"surfaces\" />\n\n`surface.scrim` chỉ nằm sau dialog và drawer, một lớp duy nhất, với độ mờ riêng của nó.\n\n## Mức nhấn\n\n<ColorDemo kind=\"emphasis\" />\n\n## Trạng thái\n\n**Mỗi trạng thái thuộc một trong năm vai trò. Chọn theo việc người dùng cần làm, và luôn nói rõ bằng chữ.**\n\n### Chọn trạng thái\n\n| Vai trò | Dùng khi | Ví dụ trong HexaSync |\n|---|---|---|\n| Thông tin (info) | Có việc đang diễn ra hoặc đáng biết; không cần làm gì. | Đang đồng bộ, đang chờ, đang nhập |\n| Thành công (success) | Đã chạy tốt. | Đã đồng bộ, đã kết nối, đã xong |\n| Cảnh báo (warning) | Đang chạy nhưng sắp cần xử lý. | Đồng bộ một phần, token hết hạn sau 3 ngày, bị giới hạn tần suất |\n| Nguy hiểm (danger) | Bị lỗi hoặc bị chặn, hoặc hành động sẽ xoá mất dữ liệu. | Lỗi, mất kết nối, xoá |\n| Trung tính (neutral) | Không có gì đang chạy và không có gì sai. | Tạm dừng, nháp, bỏ qua, lưu trữ |\n\nCảnh báo dùng màu cam, không dùng màu vàng, vì màu vàng là màu thương hiệu. Không có mức thứ sáu; hãy nói rõ khác biệt bằng chữ (\"Lỗi 3 lần\").\n\n### Màu trạng thái\n\n<ColorDemo kind=\"status\" />\n\n<ColorDemo kind=\"banners\" />\n\n<ColorDemo kind=\"dodont\" item=\"warning\" />\n\n### Nhãn\n\n<ColorDemo kind=\"labels\" />\n\n| | Nhãn | Nhãn trạng thái |\n|---|---|---|\n| Hình thức | Viền theo `border` của vai trò, chữ theo `text` của vai trò | Nền theo `bold` của vai trò, chữ và icon theo `text.on-bold` |\n| Kích thước | Cao 20 px, padding 6 px; cỡ lớn 24 px, 8 px | Cao 32 px, padding 12 px |\n| Dùng | Nhiều nhãn trên một màn hình: dòng trong bảng, tag | Một nhãn trên mỗi trang: trạng thái chính của trang đó |\n\n## Trạng thái tương tác\n\n**Thêm `.hover` hoặc `.pressed` vào token ở trạng thái nghỉ. Không dùng độ mờ (opacity) hay lớp phủ.**\n\n<ColorDemo kind=\"states\" />\n\n| Trạng thái | Dùng |\n|---|---|\n| Hover, nhấn | Token ở trạng thái nghỉ, thêm `.hover` hoặc `.pressed` |\n| Được chọn | `background.selected` và một dấu hiệu thứ hai |\n| Focus | Viền `border.focus` dày 2 px, cách 2 px |\n| Vô hiệu | `background.disabled`, `text.disabled`, `border.disabled` |\n\nVới dòng hoặc mục menu, mỗi trạng thái cách nền thêm một bậc: hover, rồi được chọn, rồi được chọn khi hover. Dòng đang hover luôn nhạt hơn dòng được chọn, nên không bao giờ trông như đang được chọn.\n\nXem thêm ở trang [Trạng thái tương tác](/vi/foundations/styles/interaction-states/).\n\n## Nút\n\n<ColorDemo kind=\"actions\" />\n",
1263
+ "frontmatter": {
1264
+ "title": "Cách dùng",
1265
+ "description": "Dùng token nào cho từng phần của màn hình, cách tô màu trạng thái, mức nhấn và trạng thái tương tác, và những điều không được làm.",
1266
+ "order": 2
1267
+ }
1268
+ },
1269
+ {
1270
+ "id": "vi/foundations/styles/data-visualization",
1271
+ "path": "src/content-vi/foundations/styles/data-visualization.mdx",
1272
+ "documentPath": "docs/src/content-vi/foundations/styles/data-visualization.mdx",
1273
+ "locale": "vi",
1274
+ "kind": "guidance",
1275
+ "title": "Biểu đồ dữ liệu",
1276
+ "status": "planned",
1277
+ "releasePhase": null,
1278
+ "planned": [
1279
+ "Bảng màu cho các chuỗi dữ liệu, đủ tương phản ở light và dark",
1280
+ "Màu trạng thái trong biểu đồ",
1281
+ "Các loại biểu đồ và khi nào dùng",
1282
+ "Trục, chú giải, tooltip và định dạng số",
1283
+ "Biểu đồ dễ tiếp cận: không chỉ dựa vào màu, có phần mô tả bằng chữ"
1284
+ ],
1285
+ "body": "",
1286
+ "raw": "---\ntitle: \"Biểu đồ dữ liệu\"\ndescription: \"Màu, chữ và quy tắc cho biểu đồ, ô KPI và các cách hiển thị dữ liệu khác.\"\norder: 13\nplanned:\n - \"Bảng màu cho các chuỗi dữ liệu, đủ tương phản ở light và dark\"\n - \"Màu trạng thái trong biểu đồ\"\n - \"Các loại biểu đồ và khi nào dùng\"\n - \"Trục, chú giải, tooltip và định dạng số\"\n - \"Biểu đồ dễ tiếp cận: không chỉ dựa vào màu, có phần mô tả bằng chữ\"\n---\n",
1287
+ "frontmatter": {
1288
+ "title": "Biểu đồ dữ liệu",
1289
+ "description": "Màu, chữ và quy tắc cho biểu đồ, ô KPI và các cách hiển thị dữ liệu khác.",
1290
+ "order": 13,
1291
+ "planned": [
1292
+ "Bảng màu cho các chuỗi dữ liệu, đủ tương phản ở light và dark",
1293
+ "Màu trạng thái trong biểu đồ",
1294
+ "Các loại biểu đồ và khi nào dùng",
1295
+ "Trục, chú giải, tooltip và định dạng số",
1296
+ "Biểu đồ dễ tiếp cận: không chỉ dựa vào màu, có phần mô tả bằng chữ"
1297
+ ]
1298
+ }
1299
+ },
1300
+ {
1301
+ "id": "vi/foundations/styles/icons/accessibility",
1302
+ "path": "src/content-vi/foundations/styles/icons/accessibility.mdx",
1303
+ "documentPath": "docs/src/content-vi/foundations/styles/icons/accessibility.mdx",
1304
+ "locale": "vi",
1305
+ "kind": "guidance",
1306
+ "title": "Khả năng tiếp cận",
1307
+ "status": "active",
1308
+ "releasePhase": null,
1309
+ "planned": [],
1310
+ "body": "import IconDemo from '../../../../components/IconDemo.astro';\n\n**Icon hoặc là trang trí và bị ẩn, hoặc có tên. Icon bấm được luôn nằm trong một nút hoặc link cỡ ít nhất 24 × 24.**\n\n| Kiểm tra | Quy tắc | WCAG 2.2 |\n|---|---|---|\n| Icon trang trí | Ẩn bằng `aria-hidden=\"true\"` | 1.1.1 |\n| Nút hoặc link chỉ có icon | Có tên (`aria-label`) và tooltip cùng nội dung | 1.1.1, 2.5.3, 4.1.2 |\n| Icon mang nghĩa | Tương phản từ 3:1 trở lên với nền | 1.4.11 |\n| Trạng thái | Viết bằng chữ, không bao giờ chỉ dùng icon hay màu | 1.4.1 |\n| Vùng bấm | Từ 24 × 24 trở lên; nút icon trong sản phẩm là 32 × 32 | 2.5.8 |\n\n## Icon trang trí\n\n**Khi có chữ đứng cạnh, icon chỉ là trang trí.** Ẩn nó đi để trình đọc màn hình chỉ đọc nhãn một lần.\n\nLucide làm sẵn việc này: icon không có `aria-label`, `aria-labelledby`, `role` hay `title` sẽ được gắn `aria-hidden=\"true\"`. Không thêm nhãn cho icon đã có chữ bên cạnh.\n\n<IconDemo kind=\"dodont\" item=\"decorative\" />\n\n## Nút chỉ có icon\n\n**Đặt tên cho nút, không đặt cho icon.** Gắn tên lên `<button>` hoặc `<a>` bằng `aria-label`. Icon bên trong vẫn ẩn.\n\n- Tên nói điều gì sẽ xảy ra: \"Xoá cửa hàng\", không phải \"Thùng rác\" hay \"Icon\".\n- Thêm tooltip cùng nội dung, hiện khi rê chuột và khi focus bằng bàn phím. Tooltip phải bắt đầu bằng tên của nút, để người dùng điều khiển bằng giọng nói đọc đúng những gì họ thấy (WCAG 2.5.3).\n- Chỉ dùng nút chỉ có icon cho thao tác quen thuộc. Xem [Icon và nhãn](/vi/foundations/styles/icons/usage/#icon-và-nhãn).\n\n```html\n<button type=\"button\" aria-label=\"Cài đặt\">\n <svg aria-hidden=\"true\">…</svg>\n</button>\n```\n\n<IconDemo kind=\"dodont\" item=\"tooltip\" />\n\n## Icon mang nghĩa đứng riêng\n\nKhi icon là dấu hiệu duy nhất của một điều gì đó, như icon trạng thái trong cột bảng hẹp, hãy đặt tên cho chính icon: `role=\"img\"` và `aria-label=\"Thất bại\"`. Nên ưu tiên viết trạng thái bằng chữ.\n\n## Độ tương phản\n\n**Icon mang nghĩa cần tương phản 3:1 với nền** (WCAG 1.4.11). Mọi token `color.icon.*` đều đạt 3:1 trên các nền đi kèm, ở cả giao diện sáng và tối. Icon trang trí và icon trong control bị vô hiệu không có mức tối thiểu.\n\nXem mọi cặp màu ở [Màu sắc › Khả năng tiếp cận](/vi/foundations/styles/color/accessibility/).\n\n## Vùng bấm\n\n**Mọi thứ bấm được có cỡ ít nhất 24 × 24** (WCAG 2.5.8). Trong sản phẩm Beehexa, nút icon cỡ 32 × 32 với icon 16 px. Icon không bao giờ là thứ duy nhất để bấm.\n\n<IconDemo kind=\"target\" />\n\n<IconDemo kind=\"dodont\" item=\"target\" />\n\n## Bàn phím và focus\n\n- Nút hoặc link nhận focus, không phải icon. Không thêm `tabindex` cho `<svg>`.\n- Vòng focus bao quanh toàn bộ nút 32 × 32.\n- Tooltip mở khi focus cũng như khi rê chuột, và đóng bằng phím Escape.\n\n## Danh sách kiểm tra\n\n- Mọi icon cạnh chữ đều ẩn khỏi trình đọc màn hình.\n- Mọi nút chỉ có icon đều có tên và tooltip cùng nội dung.\n- Không trạng thái nào chỉ được thể hiện bằng icon hay màu.\n- Icon mang nghĩa đạt 3:1; dùng đúng token là đã đạt.\n- Mọi icon bấm được nằm trong vùng bấm từ 24 × 24 trở lên.\n",
1311
+ "raw": "---\ntitle: Khả năng tiếp cận\ndescription: Icon được đặt tên hoặc giữ im lặng thế nào, vì sao nút chỉ có icon cần tooltip, và mức tương phản cùng vùng bấm icon phải đạt.\norder: 3\n---\nimport IconDemo from '../../../../components/IconDemo.astro';\n\n**Icon hoặc là trang trí và bị ẩn, hoặc có tên. Icon bấm được luôn nằm trong một nút hoặc link cỡ ít nhất 24 × 24.**\n\n| Kiểm tra | Quy tắc | WCAG 2.2 |\n|---|---|---|\n| Icon trang trí | Ẩn bằng `aria-hidden=\"true\"` | 1.1.1 |\n| Nút hoặc link chỉ có icon | Có tên (`aria-label`) và tooltip cùng nội dung | 1.1.1, 2.5.3, 4.1.2 |\n| Icon mang nghĩa | Tương phản từ 3:1 trở lên với nền | 1.4.11 |\n| Trạng thái | Viết bằng chữ, không bao giờ chỉ dùng icon hay màu | 1.4.1 |\n| Vùng bấm | Từ 24 × 24 trở lên; nút icon trong sản phẩm là 32 × 32 | 2.5.8 |\n\n## Icon trang trí\n\n**Khi có chữ đứng cạnh, icon chỉ là trang trí.** Ẩn nó đi để trình đọc màn hình chỉ đọc nhãn một lần.\n\nLucide làm sẵn việc này: icon không có `aria-label`, `aria-labelledby`, `role` hay `title` sẽ được gắn `aria-hidden=\"true\"`. Không thêm nhãn cho icon đã có chữ bên cạnh.\n\n<IconDemo kind=\"dodont\" item=\"decorative\" />\n\n## Nút chỉ có icon\n\n**Đặt tên cho nút, không đặt cho icon.** Gắn tên lên `<button>` hoặc `<a>` bằng `aria-label`. Icon bên trong vẫn ẩn.\n\n- Tên nói điều gì sẽ xảy ra: \"Xoá cửa hàng\", không phải \"Thùng rác\" hay \"Icon\".\n- Thêm tooltip cùng nội dung, hiện khi rê chuột và khi focus bằng bàn phím. Tooltip phải bắt đầu bằng tên của nút, để người dùng điều khiển bằng giọng nói đọc đúng những gì họ thấy (WCAG 2.5.3).\n- Chỉ dùng nút chỉ có icon cho thao tác quen thuộc. Xem [Icon và nhãn](/vi/foundations/styles/icons/usage/#icon-và-nhãn).\n\n```html\n<button type=\"button\" aria-label=\"Cài đặt\">\n <svg aria-hidden=\"true\">…</svg>\n</button>\n```\n\n<IconDemo kind=\"dodont\" item=\"tooltip\" />\n\n## Icon mang nghĩa đứng riêng\n\nKhi icon là dấu hiệu duy nhất của một điều gì đó, như icon trạng thái trong cột bảng hẹp, hãy đặt tên cho chính icon: `role=\"img\"` và `aria-label=\"Thất bại\"`. Nên ưu tiên viết trạng thái bằng chữ.\n\n## Độ tương phản\n\n**Icon mang nghĩa cần tương phản 3:1 với nền** (WCAG 1.4.11). Mọi token `color.icon.*` đều đạt 3:1 trên các nền đi kèm, ở cả giao diện sáng và tối. Icon trang trí và icon trong control bị vô hiệu không có mức tối thiểu.\n\nXem mọi cặp màu ở [Màu sắc › Khả năng tiếp cận](/vi/foundations/styles/color/accessibility/).\n\n## Vùng bấm\n\n**Mọi thứ bấm được có cỡ ít nhất 24 × 24** (WCAG 2.5.8). Trong sản phẩm Beehexa, nút icon cỡ 32 × 32 với icon 16 px. Icon không bao giờ là thứ duy nhất để bấm.\n\n<IconDemo kind=\"target\" />\n\n<IconDemo kind=\"dodont\" item=\"target\" />\n\n## Bàn phím và focus\n\n- Nút hoặc link nhận focus, không phải icon. Không thêm `tabindex` cho `<svg>`.\n- Vòng focus bao quanh toàn bộ nút 32 × 32.\n- Tooltip mở khi focus cũng như khi rê chuột, và đóng bằng phím Escape.\n\n## Danh sách kiểm tra\n\n- Mọi icon cạnh chữ đều ẩn khỏi trình đọc màn hình.\n- Mọi nút chỉ có icon đều có tên và tooltip cùng nội dung.\n- Không trạng thái nào chỉ được thể hiện bằng icon hay màu.\n- Icon mang nghĩa đạt 3:1; dùng đúng token là đã đạt.\n- Mọi icon bấm được nằm trong vùng bấm từ 24 × 24 trở lên.\n",
1312
+ "frontmatter": {
1313
+ "title": "Khả năng tiếp cận",
1314
+ "description": "Icon được đặt tên hoặc giữ im lặng thế nào, vì sao nút chỉ có icon cần tooltip, và mức tương phản cùng vùng bấm icon phải đạt.",
1315
+ "order": 3
1316
+ }
1317
+ },
1318
+ {
1319
+ "id": "vi/foundations/styles/icons/code",
1320
+ "path": "src/content-vi/foundations/styles/icons/code.mdx",
1321
+ "documentPath": "docs/src/content-vi/foundations/styles/icons/code.mdx",
1322
+ "locale": "vi",
1323
+ "kind": "guidance",
1324
+ "title": "Code",
1325
+ "status": "active",
1326
+ "releasePhase": null,
1327
+ "planned": [],
1328
+ "body": "\n**Sản phẩm dùng Lucide trực tiếp. Cài gói Lucide cho framework của bạn, cố định phiên bản và import từng icon theo tên.**\n\n## Gói\n\n| Framework | Gói | Phiên bản |\n|---|---|---|\n| Vue, cho sản phẩm Beehexa | `@lucide/vue` | 1.62.0 |\n| React | `lucide-react` | 1.62.0 |\n\nMọi sản phẩm dùng cùng phiên bản Lucide với trang này, nên icon khớp với [Thư viện](/vi/foundations/styles/icons/library/). Icon được đóng gói vào ứng dụng lúc build. Không có request nào tới CDN.\n\n## Cài đặt\n\n```bash\nnpm install @lucide/vue@1.62.0 --save-exact\n```\n\nCố định đúng phiên bản, không dùng `^` hay `~`. Phiên bản Lucide mới có thể đổi hình hoặc đổi tên icon, nên chỉ nâng phiên bản khi có chủ đích. Xem [Cập nhật Lucide](#cập-nhật-lucide).\n\n## Import\n\nImport từng icon theo tên. Tên là tên trong Thư viện viết kiểu PascalCase: `refresh-cw` thành `RefreshCw`. Chỉ những icon bạn import mới nằm trong bundle.\n\n```vue\n<script setup lang=\"ts\">\nimport { RefreshCw } from '@lucide/vue';\n</script>\n\n<template>\n <button type=\"button\" class=\"bh-button\">\n <RefreshCw :size=\"16\" />\n Đồng bộ ngay\n </button>\n</template>\n```\n\nKhông import cả bộ bằng `import * as`. Cách đó đưa mọi icon vào bundle.\n\n## Cỡ mặc định\n\nLucide vẽ icon ở cỡ 24 px. Sản phẩm Beehexa mặc định dùng 16 px. Đặt một lần ở component gốc:\n\n```vue\n<!-- App.vue -->\n<script setup lang=\"ts\">\nimport { setLucideProps } from '@lucide/vue';\n\nsetLucideProps({ size: 16 });\n</script>\n```\n\nSau đó chỉ đặt `size` cho icon 20, 24 hoặc 32 px.\n\n## Props\n\n| Prop | Mặc định của Lucide | Quy tắc Beehexa |\n|---|---|---|\n| `size` | 24 | Mặc định 16. Chỉ dùng 20, 24 hoặc 32 ở chỗ trang Cách dùng cho phép. Không dùng cỡ khác. |\n| `color` | `currentColor` | Để nguyên. Đặt màu ở phần tử cha bằng token màu icon. |\n| `stroke-width` | 2 | Không đổi. |\n| `non-scaling-stroke` | `false` | Không bật. Cũng không dùng tên cũ của nó là absolute-stroke-width. |\n| `aria-label` | không có | Chỉ cho icon mang nghĩa đứng riêng, đi cùng role img. |\n\n## Cỡ\n\nDùng prop `size`, hoặc đặt cỡ bằng CSS trên `svg`. Cả hai cách đều giữ nét đúng tỉ lệ.\n\n```vue\n<RefreshCw :size=\"20\" />\n```\n\n## Màu\n\n```css\n.sync-status {\n color: var(--bh-color-icon-success);\n}\n```\n\n```vue\n<span class=\"sync-status\"><CircleCheck /> Đã đồng bộ</span>\n```\n\n## Khoảng cách\n\nĐặt khoảng cách trên control, theo cỡ của nó: 4 px (`space.050`) với icon 16 px trong control cỡ nhỏ và mặc định, 8 px (`space.100`) với icon 20 hoặc 24 px. Xem [Cách dùng › Khoảng cách](/vi/foundations/styles/icons/usage/#khoảng-cách).\n\n```css\n.bh-button {\n display: inline-flex;\n align-items: center;\n gap: var(--bh-space-050);\n}\n.bh-button.is-large {\n gap: var(--bh-space-100);\n}\n```\n\n## Khả năng tiếp cận\n\nLucide ẩn icon khỏi trình đọc màn hình bằng `aria-hidden=\"true\"`, trừ khi bạn truyền prop `aria-*`, `role` hoặc `title`. Đặt tên cho nút chỉ có icon trên chính nút đó, và thêm tooltip cùng nội dung.\n\n```vue\n<a-tooltip title=\"Cài đặt\">\n <button type=\"button\" class=\"icon-button\" aria-label=\"Cài đặt\">\n <Settings />\n </button>\n</a-tooltip>\n```\n\nIcon mang nghĩa đứng riêng được gắn role và nhãn, việc này cũng bỏ `aria-hidden`:\n\n```vue\n<CircleX role=\"img\" aria-label=\"Thất bại\" />\n```\n\n## Trong Ant Design Vue\n\nĐặt icon vào slot `icon` và thêm class `anticon`, để Ant Design Vue căn nó như icon của chính nó.\n\n```vue\n<a-button>\n <template #icon><Plus class=\"anticon\" /></template>\n Thêm cửa hàng\n</a-button>\n```\n\n## React\n\n`lucide-react` có cùng icon và props, viết kiểu camelCase. Đặt cỡ mặc định một lần bằng `LucideProvider`.\n\n```tsx\nimport { LucideProvider, RefreshCw } from 'lucide-react';\n\n<LucideProvider size={16}>\n <button type=\"button\">\n <RefreshCw />\n Đồng bộ ngay\n </button>\n</LucideProvider>\n```\n\n## Astro\n\nbeehexa.design dùng `@lucide/astro`. Import từng icon từ file riêng của nó để build luôn nhanh:\n\n```astro\n---\nimport Search from '@lucide/astro/icons/search';\n---\n<button class=\"icon-button\" type=\"button\" aria-label=\"Tìm kiếm\">\n <Search size={20} />\n</button>\n```\n\n## Icon tự vẽ\n\nLucide đáp ứng đủ những gì Beehexa cần hiện nay. Nếu có lúc thiếu icon, hãy vẽ trên lưới 24 px của Lucide với cùng nét và đầu nét, đặt tên kiểu kebab-case với tiền tố `bh-`, và thêm vào thư viện.\n\n## Cập nhật Lucide\n\n1. Đọc ghi chú phát hành của Lucide để biết icon nào bị đổi tên hoặc đổi hình.\n2. Kiểm tra mọi icon trong [Thao tác thường gặp](/vi/foundations/styles/icons/usage/#thao-tác-thường-gặp) vẫn còn.\n3. Nâng phiên bản đã cố định trong sản phẩm, và báo nhóm design system cập nhật Thư viện để hiện đúng các icon đó.\n",
1329
+ "raw": "---\ntitle: Code\ndescription: Sản phẩm Vue cài đặt, import, đặt cỡ, tô màu và đặt tên icon Lucide thế nào, kèm ghi chú ngắn cho React và Astro.\norder: 4\n---\n\n**Sản phẩm dùng Lucide trực tiếp. Cài gói Lucide cho framework của bạn, cố định phiên bản và import từng icon theo tên.**\n\n## Gói\n\n| Framework | Gói | Phiên bản |\n|---|---|---|\n| Vue, cho sản phẩm Beehexa | `@lucide/vue` | 1.62.0 |\n| React | `lucide-react` | 1.62.0 |\n\nMọi sản phẩm dùng cùng phiên bản Lucide với trang này, nên icon khớp với [Thư viện](/vi/foundations/styles/icons/library/). Icon được đóng gói vào ứng dụng lúc build. Không có request nào tới CDN.\n\n## Cài đặt\n\n```bash\nnpm install @lucide/vue@1.62.0 --save-exact\n```\n\nCố định đúng phiên bản, không dùng `^` hay `~`. Phiên bản Lucide mới có thể đổi hình hoặc đổi tên icon, nên chỉ nâng phiên bản khi có chủ đích. Xem [Cập nhật Lucide](#cập-nhật-lucide).\n\n## Import\n\nImport từng icon theo tên. Tên là tên trong Thư viện viết kiểu PascalCase: `refresh-cw` thành `RefreshCw`. Chỉ những icon bạn import mới nằm trong bundle.\n\n```vue\n<script setup lang=\"ts\">\nimport { RefreshCw } from '@lucide/vue';\n</script>\n\n<template>\n <button type=\"button\" class=\"bh-button\">\n <RefreshCw :size=\"16\" />\n Đồng bộ ngay\n </button>\n</template>\n```\n\nKhông import cả bộ bằng `import * as`. Cách đó đưa mọi icon vào bundle.\n\n## Cỡ mặc định\n\nLucide vẽ icon ở cỡ 24 px. Sản phẩm Beehexa mặc định dùng 16 px. Đặt một lần ở component gốc:\n\n```vue\n<!-- App.vue -->\n<script setup lang=\"ts\">\nimport { setLucideProps } from '@lucide/vue';\n\nsetLucideProps({ size: 16 });\n</script>\n```\n\nSau đó chỉ đặt `size` cho icon 20, 24 hoặc 32 px.\n\n## Props\n\n| Prop | Mặc định của Lucide | Quy tắc Beehexa |\n|---|---|---|\n| `size` | 24 | Mặc định 16. Chỉ dùng 20, 24 hoặc 32 ở chỗ trang Cách dùng cho phép. Không dùng cỡ khác. |\n| `color` | `currentColor` | Để nguyên. Đặt màu ở phần tử cha bằng token màu icon. |\n| `stroke-width` | 2 | Không đổi. |\n| `non-scaling-stroke` | `false` | Không bật. Cũng không dùng tên cũ của nó là absolute-stroke-width. |\n| `aria-label` | không có | Chỉ cho icon mang nghĩa đứng riêng, đi cùng role img. |\n\n## Cỡ\n\nDùng prop `size`, hoặc đặt cỡ bằng CSS trên `svg`. Cả hai cách đều giữ nét đúng tỉ lệ.\n\n```vue\n<RefreshCw :size=\"20\" />\n```\n\n## Màu\n\n```css\n.sync-status {\n color: var(--bh-color-icon-success);\n}\n```\n\n```vue\n<span class=\"sync-status\"><CircleCheck /> Đã đồng bộ</span>\n```\n\n## Khoảng cách\n\nĐặt khoảng cách trên control, theo cỡ của nó: 4 px (`space.050`) với icon 16 px trong control cỡ nhỏ và mặc định, 8 px (`space.100`) với icon 20 hoặc 24 px. Xem [Cách dùng › Khoảng cách](/vi/foundations/styles/icons/usage/#khoảng-cách).\n\n```css\n.bh-button {\n display: inline-flex;\n align-items: center;\n gap: var(--bh-space-050);\n}\n.bh-button.is-large {\n gap: var(--bh-space-100);\n}\n```\n\n## Khả năng tiếp cận\n\nLucide ẩn icon khỏi trình đọc màn hình bằng `aria-hidden=\"true\"`, trừ khi bạn truyền prop `aria-*`, `role` hoặc `title`. Đặt tên cho nút chỉ có icon trên chính nút đó, và thêm tooltip cùng nội dung.\n\n```vue\n<a-tooltip title=\"Cài đặt\">\n <button type=\"button\" class=\"icon-button\" aria-label=\"Cài đặt\">\n <Settings />\n </button>\n</a-tooltip>\n```\n\nIcon mang nghĩa đứng riêng được gắn role và nhãn, việc này cũng bỏ `aria-hidden`:\n\n```vue\n<CircleX role=\"img\" aria-label=\"Thất bại\" />\n```\n\n## Trong Ant Design Vue\n\nĐặt icon vào slot `icon` và thêm class `anticon`, để Ant Design Vue căn nó như icon của chính nó.\n\n```vue\n<a-button>\n <template #icon><Plus class=\"anticon\" /></template>\n Thêm cửa hàng\n</a-button>\n```\n\n## React\n\n`lucide-react` có cùng icon và props, viết kiểu camelCase. Đặt cỡ mặc định một lần bằng `LucideProvider`.\n\n```tsx\nimport { LucideProvider, RefreshCw } from 'lucide-react';\n\n<LucideProvider size={16}>\n <button type=\"button\">\n <RefreshCw />\n Đồng bộ ngay\n </button>\n</LucideProvider>\n```\n\n## Astro\n\nbeehexa.design dùng `@lucide/astro`. Import từng icon từ file riêng của nó để build luôn nhanh:\n\n```astro\n---\nimport Search from '@lucide/astro/icons/search';\n---\n<button class=\"icon-button\" type=\"button\" aria-label=\"Tìm kiếm\">\n <Search size={20} />\n</button>\n```\n\n## Icon tự vẽ\n\nLucide đáp ứng đủ những gì Beehexa cần hiện nay. Nếu có lúc thiếu icon, hãy vẽ trên lưới 24 px của Lucide với cùng nét và đầu nét, đặt tên kiểu kebab-case với tiền tố `bh-`, và thêm vào thư viện.\n\n## Cập nhật Lucide\n\n1. Đọc ghi chú phát hành của Lucide để biết icon nào bị đổi tên hoặc đổi hình.\n2. Kiểm tra mọi icon trong [Thao tác thường gặp](/vi/foundations/styles/icons/usage/#thao-tác-thường-gặp) vẫn còn.\n3. Nâng phiên bản đã cố định trong sản phẩm, và báo nhóm design system cập nhật Thư viện để hiện đúng các icon đó.\n",
1330
+ "frontmatter": {
1331
+ "title": "Code",
1332
+ "description": "Sản phẩm Vue cài đặt, import, đặt cỡ, tô màu và đặt tên icon Lucide thế nào, kèm ghi chú ngắn cho React và Astro.",
1333
+ "order": 4
1334
+ }
1335
+ },
1336
+ {
1337
+ "id": "vi/foundations/styles/icons/index",
1338
+ "path": "src/content-vi/foundations/styles/icons/index.mdx",
1339
+ "documentPath": "docs/src/content-vi/foundations/styles/icons/index.mdx",
1340
+ "locale": "vi",
1341
+ "kind": "guidance",
1342
+ "title": "Icon",
1343
+ "status": "active",
1344
+ "releasePhase": null,
1345
+ "planned": [],
1346
+ "body": "import IconDemo from '../../../../components/IconDemo.astro';\n\nIcon giúp người dùng lướt nhanh màn hình và nhận ra một thao tác. Trong sản phẩm Beehexa, icon không bao giờ thay cho chữ: trạng thái được viết ra, và hầu hết thao tác đều có nhãn.\n\nBeehexa dùng **[Lucide](https://lucide.dev)**: khoảng 1.900 icon nét trên lưới 24 × 24, theo giấy phép ISC. Sản phẩm import Lucide trực tiếp. Không có gói icon riêng của Beehexa. Chúng tôi chỉ thêm quy tắc sử dụng.\n\n<IconDemo kind=\"sizes\" />\n\n## Nguyên tắc\n\n### Chữ trước\n\nIcon hỗ trợ cho nhãn. Chỉ dùng icon đứng riêng cho thao tác ai cũng biết, như đóng, tìm kiếm hoặc thêm, và luôn đặt tên cùng tooltip cho nó.\n\n### Một icon, một nghĩa\n\nCùng một ý luôn dùng cùng một icon, trong mọi sản phẩm. Đồng bộ luôn là `refresh-cw`. Xem [thao tác thường gặp](/vi/foundations/styles/icons/usage/#thao-tác-thường-gặp).\n\n### Chỉ dùng icon nét\n\nLucide không có icon tô đặc. Thể hiện mục đang chọn bằng nền \"đã chọn\" và thanh chỉ báo, không đổi sang icon khác.\n\n### Màu theo chữ\n\nIcon lấy màu của chữ bên cạnh. Chỉ dùng màu trạng thái khi chính icon đó thể hiện trạng thái.\n\n## Tóm tắt quy tắc\n\n| Quy tắc | Giá trị |\n|---|---|\n| Bộ icon | Lucide, chỉ icon nét |\n| Cỡ | 16 (mặc định), 20 (cạnh chữ 16 px, thanh công cụ), 24 (icon đứng riêng), 32 (chỉ cho trạng thái trống) |\n| Nét | Mặc định của Lucide, co giãn theo icon: 1,33 px ở cỡ 16, 1,67 ở cỡ 20, 2 ở cỡ 24 |\n| Lưới | 24 × 24, chừa ít nhất 1 đơn vị, đầu nét và góc nối bo tròn |\n| Màu | `currentColor`, với các token `color.icon.*` |\n| Cạnh chữ | Căn giữa theo dòng đầu tiên. Khoảng cách theo cỡ chữ: 4 px cạnh chữ 14 px trở xuống, 8 px cạnh chữ 16 px trở lên |\n| Nhãn | Mặc định icon đi kèm nhãn; chỉ dùng icon đứng riêng cho thao tác quen thuộc, có tên và tooltip |\n| Icon trang trí | Ẩn khỏi trình đọc màn hình (`aria-hidden=\"true\"`) |\n| Độ tương phản | Từ 3:1 trở lên với icon mang nghĩa (WCAG 1.4.11) |\n| Vùng bấm | Từ 24 × 24 trở lên (WCAG 2.5.8); nút icon trong sản phẩm là 32 × 32 |\n| Tên | Mỗi nghĩa một tên, kebab-case, như `circle-check` |\n| Gói | Lucide cho Vue 1.62.0, cố định phiên bản, import theo tên |\n| Viết từ phải sang trái | Không cần: sản phẩm dùng tiếng Việt và tiếng Anh |\n\n## Trong mục này\n\n| Trang | Nội dung |\n|---|---|\n| [Thư viện](/vi/foundations/styles/icons/library/) | Mọi icon. Tìm, lọc và sao chép tên. |\n| [Cách dùng](/vi/foundations/styles/icons/usage/) | Cỡ, nét, màu, căn với chữ, nhãn, và icon cho từng thao tác thường gặp. |\n| [Khả năng tiếp cận](/vi/foundations/styles/icons/accessibility/) | Tên, icon trang trí, tooltip, độ tương phản và vùng bấm. |\n| [Code](/vi/foundations/styles/icons/code/) | Cài đặt, import, đặt cỡ và đặt tên icon Lucide trong Vue, kèm ghi chú cho React và Astro. |\n\n## Giấy phép\n\nLucide thuộc © Lucide Contributors và phát hành theo [giấy phép ISC](https://lucide.dev/license). Một phần lấy từ Feather, © Cole Bemis, theo giấy phép MIT. Cả hai đều cho phép dùng thương mại. Giữ lại thông báo giấy phép khi phát hành icon. Gói Lucide đã giữ sẵn cho bạn.\n",
1347
+ "raw": "---\ntitle: Icon\ndescription: Sản phẩm Beehexa dùng trực tiếp Lucide, một bộ icon nét mở nguồn. Vài quy tắc về cỡ, màu, khoảng cách, nhãn và khả năng tiếp cận.\norder: 11\nsidebarLabel: Tổng quan\n---\nimport IconDemo from '../../../../components/IconDemo.astro';\n\nIcon giúp người dùng lướt nhanh màn hình và nhận ra một thao tác. Trong sản phẩm Beehexa, icon không bao giờ thay cho chữ: trạng thái được viết ra, và hầu hết thao tác đều có nhãn.\n\nBeehexa dùng **[Lucide](https://lucide.dev)**: khoảng 1.900 icon nét trên lưới 24 × 24, theo giấy phép ISC. Sản phẩm import Lucide trực tiếp. Không có gói icon riêng của Beehexa. Chúng tôi chỉ thêm quy tắc sử dụng.\n\n<IconDemo kind=\"sizes\" />\n\n## Nguyên tắc\n\n### Chữ trước\n\nIcon hỗ trợ cho nhãn. Chỉ dùng icon đứng riêng cho thao tác ai cũng biết, như đóng, tìm kiếm hoặc thêm, và luôn đặt tên cùng tooltip cho nó.\n\n### Một icon, một nghĩa\n\nCùng một ý luôn dùng cùng một icon, trong mọi sản phẩm. Đồng bộ luôn là `refresh-cw`. Xem [thao tác thường gặp](/vi/foundations/styles/icons/usage/#thao-tác-thường-gặp).\n\n### Chỉ dùng icon nét\n\nLucide không có icon tô đặc. Thể hiện mục đang chọn bằng nền \"đã chọn\" và thanh chỉ báo, không đổi sang icon khác.\n\n### Màu theo chữ\n\nIcon lấy màu của chữ bên cạnh. Chỉ dùng màu trạng thái khi chính icon đó thể hiện trạng thái.\n\n## Tóm tắt quy tắc\n\n| Quy tắc | Giá trị |\n|---|---|\n| Bộ icon | Lucide, chỉ icon nét |\n| Cỡ | 16 (mặc định), 20 (cạnh chữ 16 px, thanh công cụ), 24 (icon đứng riêng), 32 (chỉ cho trạng thái trống) |\n| Nét | Mặc định của Lucide, co giãn theo icon: 1,33 px ở cỡ 16, 1,67 ở cỡ 20, 2 ở cỡ 24 |\n| Lưới | 24 × 24, chừa ít nhất 1 đơn vị, đầu nét và góc nối bo tròn |\n| Màu | `currentColor`, với các token `color.icon.*` |\n| Cạnh chữ | Căn giữa theo dòng đầu tiên. Khoảng cách theo cỡ chữ: 4 px cạnh chữ 14 px trở xuống, 8 px cạnh chữ 16 px trở lên |\n| Nhãn | Mặc định icon đi kèm nhãn; chỉ dùng icon đứng riêng cho thao tác quen thuộc, có tên và tooltip |\n| Icon trang trí | Ẩn khỏi trình đọc màn hình (`aria-hidden=\"true\"`) |\n| Độ tương phản | Từ 3:1 trở lên với icon mang nghĩa (WCAG 1.4.11) |\n| Vùng bấm | Từ 24 × 24 trở lên (WCAG 2.5.8); nút icon trong sản phẩm là 32 × 32 |\n| Tên | Mỗi nghĩa một tên, kebab-case, như `circle-check` |\n| Gói | Lucide cho Vue 1.62.0, cố định phiên bản, import theo tên |\n| Viết từ phải sang trái | Không cần: sản phẩm dùng tiếng Việt và tiếng Anh |\n\n## Trong mục này\n\n| Trang | Nội dung |\n|---|---|\n| [Thư viện](/vi/foundations/styles/icons/library/) | Mọi icon. Tìm, lọc và sao chép tên. |\n| [Cách dùng](/vi/foundations/styles/icons/usage/) | Cỡ, nét, màu, căn với chữ, nhãn, và icon cho từng thao tác thường gặp. |\n| [Khả năng tiếp cận](/vi/foundations/styles/icons/accessibility/) | Tên, icon trang trí, tooltip, độ tương phản và vùng bấm. |\n| [Code](/vi/foundations/styles/icons/code/) | Cài đặt, import, đặt cỡ và đặt tên icon Lucide trong Vue, kèm ghi chú cho React và Astro. |\n\n## Giấy phép\n\nLucide thuộc © Lucide Contributors và phát hành theo [giấy phép ISC](https://lucide.dev/license). Một phần lấy từ Feather, © Cole Bemis, theo giấy phép MIT. Cả hai đều cho phép dùng thương mại. Giữ lại thông báo giấy phép khi phát hành icon. Gói Lucide đã giữ sẵn cho bạn.\n",
1348
+ "frontmatter": {
1349
+ "title": "Icon",
1350
+ "description": "Sản phẩm Beehexa dùng trực tiếp Lucide, một bộ icon nét mở nguồn. Vài quy tắc về cỡ, màu, khoảng cách, nhãn và khả năng tiếp cận.",
1351
+ "order": 11,
1352
+ "sidebarLabel": "Tổng quan"
1353
+ }
1354
+ },
1355
+ {
1356
+ "id": "vi/foundations/styles/icons/library",
1357
+ "path": "src/content-vi/foundations/styles/icons/library.mdx",
1358
+ "documentPath": "docs/src/content-vi/foundations/styles/icons/library.mdx",
1359
+ "locale": "vi",
1360
+ "kind": "guidance",
1361
+ "title": "Thư viện",
1362
+ "status": "active",
1363
+ "releasePhase": null,
1364
+ "planned": [],
1365
+ "body": "import IconBrowser from '../../../../components/IconBrowser.astro';\n\n**Bấm vào icon để sao chép tên.** Tên viết kiểu kebab-case, như `circle-check`. Trong Vue, icon đó là `CircleCheck`.\n\nTrước khi chọn icon, xem [Thao tác thường gặp](/vi/foundations/styles/icons/usage/#thao-tác-thường-gặp): nếu nghĩa bạn cần đã có ở đó, dùng đúng icon đó. Thư viện mở sẵn nhóm **Thao tác thường gặp**, chỉ hiện các icon này; ô tìm kiếm tìm trong toàn bộ icon, chọn **Tất cả** để xem hết. Đó là icon Lucide được chọn cho các thao tác thường gặp ở Beehexa, không cái nào bị vẽ lại hay đổi tên.\n\n<IconBrowser />\n\n## Dùng thư viện\n\n- Ô tìm kiếm khớp tên icon trước, sau đó tới các thẻ Lucide gắn cho từng icon. Gõ \"sync\" sẽ ra `refresh-cw`.\n- Nút đổi cỡ hiện 16, 20 và 24 px. Sản phẩm mặc định dùng 16 px.\n- Dùng bàn phím: nhấn Tab để vào lưới icon, di chuyển bằng phím mũi tên, Home và End, nhấn Enter để sao chép.\n- Không thấy icon cần tìm? Tìm theo nghĩa, không chỉ theo tên. Ghép hai icon có nghĩa riêng hiếm khi thành một icon thứ ba tốt. Xem [Icon tự vẽ](/vi/foundations/styles/icons/code/#icon-tự-vẽ).\n",
1366
+ "raw": "---\ntitle: Thư viện\ndescription: Mọi icon Lucide Beehexa được dùng. Tìm theo tên hoặc thẻ, lọc theo nhóm, đổi cỡ và bấm vào icon để sao chép tên.\norder: 1\n---\nimport IconBrowser from '../../../../components/IconBrowser.astro';\n\n**Bấm vào icon để sao chép tên.** Tên viết kiểu kebab-case, như `circle-check`. Trong Vue, icon đó là `CircleCheck`.\n\nTrước khi chọn icon, xem [Thao tác thường gặp](/vi/foundations/styles/icons/usage/#thao-tác-thường-gặp): nếu nghĩa bạn cần đã có ở đó, dùng đúng icon đó. Thư viện mở sẵn nhóm **Thao tác thường gặp**, chỉ hiện các icon này; ô tìm kiếm tìm trong toàn bộ icon, chọn **Tất cả** để xem hết. Đó là icon Lucide được chọn cho các thao tác thường gặp ở Beehexa, không cái nào bị vẽ lại hay đổi tên.\n\n<IconBrowser />\n\n## Dùng thư viện\n\n- Ô tìm kiếm khớp tên icon trước, sau đó tới các thẻ Lucide gắn cho từng icon. Gõ \"sync\" sẽ ra `refresh-cw`.\n- Nút đổi cỡ hiện 16, 20 và 24 px. Sản phẩm mặc định dùng 16 px.\n- Dùng bàn phím: nhấn Tab để vào lưới icon, di chuyển bằng phím mũi tên, Home và End, nhấn Enter để sao chép.\n- Không thấy icon cần tìm? Tìm theo nghĩa, không chỉ theo tên. Ghép hai icon có nghĩa riêng hiếm khi thành một icon thứ ba tốt. Xem [Icon tự vẽ](/vi/foundations/styles/icons/code/#icon-tự-vẽ).\n",
1367
+ "frontmatter": {
1368
+ "title": "Thư viện",
1369
+ "description": "Mọi icon Lucide Beehexa được dùng. Tìm theo tên hoặc thẻ, lọc theo nhóm, đổi cỡ và bấm vào icon để sao chép tên.",
1370
+ "order": 1
1371
+ }
1372
+ },
1373
+ {
1374
+ "id": "vi/foundations/styles/icons/usage",
1375
+ "path": "src/content-vi/foundations/styles/icons/usage.mdx",
1376
+ "documentPath": "docs/src/content-vi/foundations/styles/icons/usage.mdx",
1377
+ "locale": "vi",
1378
+ "kind": "guidance",
1379
+ "title": "Cách dùng",
1380
+ "status": "active",
1381
+ "releasePhase": null,
1382
+ "planned": [],
1383
+ "body": "import IconDemo from '../../../../components/IconDemo.astro';\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Dùng icon 16 px, cùng màu với chữ, có nhãn, và cùng một icon cho cùng một nghĩa ở mọi nơi.**\n\n## Cỡ\n\n**Chọn cỡ theo chữ đứng cạnh icon.**\n\n| Cỡ | Dùng cho |\n|---|---|\n| 16 px | Mặc định. Nút, menu, bảng, ô nhập, cạnh chữ 14 px. |\n| 20 px | Cạnh chữ 16 px, trong thanh công cụ và page header. |\n| 24 px | Icon đứng riêng, như trạng thái trong card hoặc trạng thái trống nhỏ. |\n| 32 px | Chỉ cho trạng thái trống. |\n\nKhông dùng cỡ khác. Không phóng to thu nhỏ icon cho vừa khung: hãy đổi khung.\n\n<IconDemo kind=\"dodont\" item=\"size\" />\n\n## Nét\n\n**Giữ nguyên nét của Lucide.** Nét dày 2 đơn vị trên lưới 24 và co giãn theo icon: 1,33 px ở cỡ 16, 1,67 px ở cỡ 20, 2 px ở cỡ 24. Không đặt `stroke-width` hay `absoluteStrokeWidth`. Nét cố định 2 px sẽ lấp mất chi tiết nhỏ của icon 16 px.\n\n<IconDemo kind=\"dodont\" item=\"stroke\" />\n\n## Màu\n\n**Icon lấy màu của chữ.** Icon vẽ bằng `currentColor`, nên icon trong nút hay link tự đúng màu mà không cần thêm code. Chỉ đặt màu bằng token `color.icon.*`:\n\n<ColorDemo kind=\"roles\" group=\"icon\" />\n\n- Icon trạng thái dùng token trạng thái, như `icon.danger`, và luôn đi kèm trạng thái viết bằng chữ.\n- Không tô màu icon để trang trí, và không bao giờ dùng màu vàng thương hiệu cho icon.\n\n<IconDemo kind=\"dodont\" item=\"colour\" />\n\n## Căn với chữ\n\n**Căn icon vào giữa line height của chữ.** Dùng `display: flex; align-items: center`. Khi chữ có nhiều dòng, căn icon vào giữa dòng đầu tiên.\n\n<IconDemo kind=\"align\" />\n\n<IconDemo kind=\"dodont\" item=\"align\" />\n\n## Khoảng cách\n\n**Khoảng cách giữa icon và chữ theo cỡ chữ: 4 px cạnh chữ 14 px trở xuống, 8 px cạnh chữ 16 px trở lên.**\n\n| Chữ | Icon | Khoảng cách | Token | Ở đâu |\n|---|---|---|---|---|\n| 12 hoặc 14 px | 16 px | 4 px | `space.050` | Control cỡ nhỏ và mặc định, menu, tab, ô trong bảng |\n| Từ 16 px trở lên | 20 hoặc 24 px | 8 px | `space.100` | Control cỡ lớn, thanh công cụ, page header, trạng thái trong card |\n\nĐặt khoảng cách trên control bằng `gap`, không dùng margin trên icon.\n\n<IconDemo kind=\"spacing\" />\n\n## Icon và nhãn\n\n**Mặc định icon có nhãn đi kèm.** Nhãn nói điều gì sẽ xảy ra; icon giúp người dùng tìm lại nhanh.\n\nChỉ dùng icon đứng riêng khi cả ba điều sau đều đúng:\n\n- Thao tác ai cũng biết: đóng, tìm kiếm, thêm, sửa, xoá, sao chép, làm mới, cài đặt, lọc, thêm tuỳ chọn, menu.\n- Chỗ hẹp, như một dòng trong bảng hay thanh công cụ.\n- Nút có tên (`aria-label`) và tooltip cùng nội dung. Xem [Khả năng tiếp cận](/vi/foundations/styles/icons/accessibility/).\n\n<IconDemo kind=\"dodont\" item=\"label\" />\n\n## Trạng thái đã chọn\n\n**Icon Lucide chỉ có dạng nét.** Thể hiện mục đã chọn bằng `background.selected` và thanh chỉ báo, không tô đặc icon.\n\n<IconDemo kind=\"dodont\" item=\"selected\" />\n\n## Thao tác thường gặp\n\n**Mỗi nghĩa một icon.** Dùng đúng icon này mỗi khi hiển thị một trong các thao tác hay đối tượng dưới đây, ở mọi sản phẩm. Nếu chưa có nghĩa bạn cần, hãy hỏi trước khi chọn, để nó được bổ sung vào đây.\n\n<IconDemo kind=\"actions\" />\n\n<IconDemo kind=\"dodont\" item=\"meaning\" />\n\n## Nên và không nên\n\n| Nên | Không nên |\n|---|---|\n| Dùng cỡ 16, 20, 24 hoặc 32 px. | Phóng to thu nhỏ icon sang cỡ khác. |\n| Giữ icon cùng màu chữ. | Tô màu icon để trang trí. |\n| Thêm nhãn cho hầu hết icon. | Dùng một icon lạ đứng riêng. |\n| Dùng cùng icon cho cùng nghĩa. | Mỗi sản phẩm dùng một icon khác nhau. |\n| Dùng icon nét với nền \"đã chọn\". | Tô đặc icon để báo đã chọn. |\n| Viết trạng thái bên cạnh icon trạng thái. | Để icon hoặc màu của nó tự báo trạng thái. |\n| Mỗi nút một icon. | Ghép hai icon thành một thao tác. |\n",
1384
+ "raw": "---\ntitle: Cách dùng\ndescription: Dùng cỡ nào, nét, màu và căn chỉnh cạnh chữ hoạt động thế nào, khi nào icon cần nhãn, và icon duy nhất cho từng thao tác thường gặp ở Beehexa.\norder: 2\n---\nimport IconDemo from '../../../../components/IconDemo.astro';\nimport ColorDemo from '../../../../components/ColorDemo.astro';\n\n**Dùng icon 16 px, cùng màu với chữ, có nhãn, và cùng một icon cho cùng một nghĩa ở mọi nơi.**\n\n## Cỡ\n\n**Chọn cỡ theo chữ đứng cạnh icon.**\n\n| Cỡ | Dùng cho |\n|---|---|\n| 16 px | Mặc định. Nút, menu, bảng, ô nhập, cạnh chữ 14 px. |\n| 20 px | Cạnh chữ 16 px, trong thanh công cụ và page header. |\n| 24 px | Icon đứng riêng, như trạng thái trong card hoặc trạng thái trống nhỏ. |\n| 32 px | Chỉ cho trạng thái trống. |\n\nKhông dùng cỡ khác. Không phóng to thu nhỏ icon cho vừa khung: hãy đổi khung.\n\n<IconDemo kind=\"dodont\" item=\"size\" />\n\n## Nét\n\n**Giữ nguyên nét của Lucide.** Nét dày 2 đơn vị trên lưới 24 và co giãn theo icon: 1,33 px ở cỡ 16, 1,67 px ở cỡ 20, 2 px ở cỡ 24. Không đặt `stroke-width` hay `absoluteStrokeWidth`. Nét cố định 2 px sẽ lấp mất chi tiết nhỏ của icon 16 px.\n\n<IconDemo kind=\"dodont\" item=\"stroke\" />\n\n## Màu\n\n**Icon lấy màu của chữ.** Icon vẽ bằng `currentColor`, nên icon trong nút hay link tự đúng màu mà không cần thêm code. Chỉ đặt màu bằng token `color.icon.*`:\n\n<ColorDemo kind=\"roles\" group=\"icon\" />\n\n- Icon trạng thái dùng token trạng thái, như `icon.danger`, và luôn đi kèm trạng thái viết bằng chữ.\n- Không tô màu icon để trang trí, và không bao giờ dùng màu vàng thương hiệu cho icon.\n\n<IconDemo kind=\"dodont\" item=\"colour\" />\n\n## Căn với chữ\n\n**Căn icon vào giữa line height của chữ.** Dùng `display: flex; align-items: center`. Khi chữ có nhiều dòng, căn icon vào giữa dòng đầu tiên.\n\n<IconDemo kind=\"align\" />\n\n<IconDemo kind=\"dodont\" item=\"align\" />\n\n## Khoảng cách\n\n**Khoảng cách giữa icon và chữ theo cỡ chữ: 4 px cạnh chữ 14 px trở xuống, 8 px cạnh chữ 16 px trở lên.**\n\n| Chữ | Icon | Khoảng cách | Token | Ở đâu |\n|---|---|---|---|---|\n| 12 hoặc 14 px | 16 px | 4 px | `space.050` | Control cỡ nhỏ và mặc định, menu, tab, ô trong bảng |\n| Từ 16 px trở lên | 20 hoặc 24 px | 8 px | `space.100` | Control cỡ lớn, thanh công cụ, page header, trạng thái trong card |\n\nĐặt khoảng cách trên control bằng `gap`, không dùng margin trên icon.\n\n<IconDemo kind=\"spacing\" />\n\n## Icon và nhãn\n\n**Mặc định icon có nhãn đi kèm.** Nhãn nói điều gì sẽ xảy ra; icon giúp người dùng tìm lại nhanh.\n\nChỉ dùng icon đứng riêng khi cả ba điều sau đều đúng:\n\n- Thao tác ai cũng biết: đóng, tìm kiếm, thêm, sửa, xoá, sao chép, làm mới, cài đặt, lọc, thêm tuỳ chọn, menu.\n- Chỗ hẹp, như một dòng trong bảng hay thanh công cụ.\n- Nút có tên (`aria-label`) và tooltip cùng nội dung. Xem [Khả năng tiếp cận](/vi/foundations/styles/icons/accessibility/).\n\n<IconDemo kind=\"dodont\" item=\"label\" />\n\n## Trạng thái đã chọn\n\n**Icon Lucide chỉ có dạng nét.** Thể hiện mục đã chọn bằng `background.selected` và thanh chỉ báo, không tô đặc icon.\n\n<IconDemo kind=\"dodont\" item=\"selected\" />\n\n## Thao tác thường gặp\n\n**Mỗi nghĩa một icon.** Dùng đúng icon này mỗi khi hiển thị một trong các thao tác hay đối tượng dưới đây, ở mọi sản phẩm. Nếu chưa có nghĩa bạn cần, hãy hỏi trước khi chọn, để nó được bổ sung vào đây.\n\n<IconDemo kind=\"actions\" />\n\n<IconDemo kind=\"dodont\" item=\"meaning\" />\n\n## Nên và không nên\n\n| Nên | Không nên |\n|---|---|\n| Dùng cỡ 16, 20, 24 hoặc 32 px. | Phóng to thu nhỏ icon sang cỡ khác. |\n| Giữ icon cùng màu chữ. | Tô màu icon để trang trí. |\n| Thêm nhãn cho hầu hết icon. | Dùng một icon lạ đứng riêng. |\n| Dùng cùng icon cho cùng nghĩa. | Mỗi sản phẩm dùng một icon khác nhau. |\n| Dùng icon nét với nền \"đã chọn\". | Tô đặc icon để báo đã chọn. |\n| Viết trạng thái bên cạnh icon trạng thái. | Để icon hoặc màu của nó tự báo trạng thái. |\n| Mỗi nút một icon. | Ghép hai icon thành một thao tác. |\n",
1385
+ "frontmatter": {
1386
+ "title": "Cách dùng",
1387
+ "description": "Dùng cỡ nào, nét, màu và căn chỉnh cạnh chữ hoạt động thế nào, khi nào icon cần nhãn, và icon duy nhất cho từng thao tác thường gặp ở Beehexa.",
1388
+ "order": 2
1389
+ }
1390
+ },
1391
+ {
1392
+ "id": "vi/foundations/styles/illustration",
1393
+ "path": "src/content-vi/foundations/styles/illustration.mdx",
1394
+ "documentPath": "docs/src/content-vi/foundations/styles/illustration.mdx",
1395
+ "locale": "vi",
1396
+ "kind": "guidance",
1397
+ "title": "Hình minh hoạ",
1398
+ "status": "planned",
1399
+ "releasePhase": null,
1400
+ "planned": [
1401
+ "Khi nào dùng sơ đồ, hình minh hoạ hay ảnh chụp màn hình",
1402
+ "Phong cách sơ đồ theo brand guide: có cấu trúc, dựng trên lưới lục giác",
1403
+ "Hình cho trạng thái trống và onboarding"
1404
+ ],
1405
+ "body": "",
1406
+ "raw": "---\ntitle: \"Hình minh hoạ\"\ndescription: \"Sơ đồ, hình minh hoạ và hình ảnh giải thích sản phẩm Beehexa.\"\norder: 14\nplanned:\n - \"Khi nào dùng sơ đồ, hình minh hoạ hay ảnh chụp màn hình\"\n - \"Phong cách sơ đồ theo brand guide: có cấu trúc, dựng trên lưới lục giác\"\n - \"Hình cho trạng thái trống và onboarding\"\n---\n",
1407
+ "frontmatter": {
1408
+ "title": "Hình minh hoạ",
1409
+ "description": "Sơ đồ, hình minh hoạ và hình ảnh giải thích sản phẩm Beehexa.",
1410
+ "order": 14,
1411
+ "planned": [
1412
+ "Khi nào dùng sơ đồ, hình minh hoạ hay ảnh chụp màn hình",
1413
+ "Phong cách sơ đồ theo brand guide: có cấu trúc, dựng trên lưới lục giác",
1414
+ "Hình cho trạng thái trống và onboarding"
1415
+ ]
1416
+ }
1417
+ },
1418
+ {
1419
+ "id": "vi/foundations/styles/interaction-states",
1420
+ "path": "src/content-vi/foundations/styles/interaction-states.mdx",
1421
+ "documentPath": "docs/src/content-vi/foundations/styles/interaction-states.mdx",
1422
+ "locale": "vi",
1423
+ "kind": "guidance",
1424
+ "title": "Trạng thái tương tác",
1425
+ "status": "active",
1426
+ "releasePhase": null,
1427
+ "planned": [],
1428
+ "body": "import TokenTable from '../../../components/TokenTable.astro';\n\nMọi thành phần tương tác đều cần đủ các trạng thái này. Mỗi trạng thái có token màu riêng, nên mọi component hiển thị nó giống nhau và chạy đúng ở giao diện sáng lẫn tối mà không cần thêm code.\n\n## Quy tắc\n\n1. Mỗi trạng thái dùng token riêng. Tìm token của thành phần ở trạng thái nghỉ, rồi thêm trạng thái: `color.background.neutral` ở trạng thái nghỉ thành `color.background.neutral.hover` khi hover và `color.background.neutral.pressed` khi nhấn.\n2. Không bao giờ vẽ trạng thái bằng độ mờ, lớp phủ trong suốt, `filter: brightness()` hay màu pha trộn. Kết quả sẽ thay đổi theo thứ nằm bên dưới, và không kiểm tra được độ tương phản.\n3. Không tự nghĩ ra màu hover hay màu nhấn. Nếu chưa có token bạn cần, hãy đề nghị thêm nó vào trang Màu sắc trước.\n4. Focus bằng bàn phím luôn nhìn thấy được, trên mọi thành phần nhận được focus. Hover không bao giờ là cách duy nhất để hiện một thứ gì đó.\n\n## Từng trạng thái\n\n| Trạng thái | Khi nào | Nền | Chữ và icon | Viền |\n| --- | --- | --- | --- | --- |\n| Nghỉ (rest) | Không có gì xảy ra. | Token của thành phần, như `color.background.neutral` hoặc `color.background.danger.bold` | Token chữ đi cặp với nền (xem Màu sắc, phần Ghép cặp) | `color.border` hoặc `color.border.bold` |\n| Hover | Con trỏ đang nằm trên thành phần. | Cùng token, thêm `.hover`: lên một bậc trên thang màu | Không đổi | Không đổi |\n| Nhấn (pressed) | Thành phần đang được click hoặc chạm. | Cùng token, thêm `.pressed`: lên hai bậc | Không đổi | Không đổi |\n\nNút chính là ngoại lệ duy nhất. Nút này nằm ở graphite 12, bậc cuối của thang, nên không còn bậc nào phía trên: khi hover nó lùi một bậc (graphite 11), khi nhấn lùi hai bậc (graphite 10). Token của nút đã làm sẵn việc này.\n| Focus | Thành phần đang có focus từ bàn phím (`:focus-visible`). | Không đổi | Không đổi | Thêm viền: `outline: var(--bh-border-width-focused) solid var(--bh-color-border-focus); outline-offset: var(--bh-state-focus-offset);` |\n| Được chọn (selected) | Thành phần đã được chọn, như một dòng trong bảng, một tab hay một mục menu. | `color.background.selected`, và `color.background.selected.hover` khi hover | Không đổi, kèm một dấu hiệu thứ hai: dấu tích, vạch chỉ báo màu vàng (`color.border.selected`) hoặc chữ đậm trong menu | Không đổi |\n| Vô hiệu (disabled) | Thành phần tạm thời không dùng được. | `color.background.disabled` | `color.text.disabled`, `color.icon.disabled` | `color.border.disabled` |\n\n## Dòng, mục menu và nút ghost\n\nThành phần không có nền ở trạng thái nghỉ dùng `color.background.neutral.subtle`, là màu trong suốt. Khi hover, chúng dùng `color.background.neutral.subtle.hover`; khi nhấn, dùng `color.background.neutral.subtle.pressed`.\n\n## Vô hiệu\n\n- Dùng ba token màu vô hiệu ở trên. Không giảm độ mờ.\n- Bỏ tương tác bằng chuột và bàn phím (`disabled` với control gốc của HTML, `aria-disabled=\"true\"` kèm chặn sự kiện với các thành phần khác) và hiện `cursor: not-allowed`.\n- WCAG không yêu cầu độ tương phản cho control bị vô hiệu, nên các màu vô hiệu được cố ý làm nhạt.\n- Nên cho người dùng biết vì sao không dùng được, ví dụ bằng helper text, thay vì để control bị vô hiệu mà không giải thích.\n\n## Giao diện tối\n\nCác token này dùng được ở giao diện tối. Ở giao diện tối, nền sáng lên khi hover và khi nhấn thay vì tối đi, còn nút chính lùi khỏi graphite 12 theo cùng cách; token đã làm sẵn việc này, nên code không đổi.\n\n## Token\n\nCác màu nằm ở trang [Màu sắc](/vi/foundations/styles/color/). Độ dày focus ring, `border.width.focused`, nằm ở trang [Viền](/vi/foundations/styles/border/). Nhóm này chứa khoảng cách giữa control và ring.\n\n<TokenTable prefix=\"state\" />\n",
1429
+ "raw": "---\ntitle: Trạng thái tương tác\ndescription: Control trông thế nào khi được hover, focus, nhấn, chọn hoặc bị vô hiệu.\norder: 10\n---\nimport TokenTable from '../../../components/TokenTable.astro';\n\nMọi thành phần tương tác đều cần đủ các trạng thái này. Mỗi trạng thái có token màu riêng, nên mọi component hiển thị nó giống nhau và chạy đúng ở giao diện sáng lẫn tối mà không cần thêm code.\n\n## Quy tắc\n\n1. Mỗi trạng thái dùng token riêng. Tìm token của thành phần ở trạng thái nghỉ, rồi thêm trạng thái: `color.background.neutral` ở trạng thái nghỉ thành `color.background.neutral.hover` khi hover và `color.background.neutral.pressed` khi nhấn.\n2. Không bao giờ vẽ trạng thái bằng độ mờ, lớp phủ trong suốt, `filter: brightness()` hay màu pha trộn. Kết quả sẽ thay đổi theo thứ nằm bên dưới, và không kiểm tra được độ tương phản.\n3. Không tự nghĩ ra màu hover hay màu nhấn. Nếu chưa có token bạn cần, hãy đề nghị thêm nó vào trang Màu sắc trước.\n4. Focus bằng bàn phím luôn nhìn thấy được, trên mọi thành phần nhận được focus. Hover không bao giờ là cách duy nhất để hiện một thứ gì đó.\n\n## Từng trạng thái\n\n| Trạng thái | Khi nào | Nền | Chữ và icon | Viền |\n| --- | --- | --- | --- | --- |\n| Nghỉ (rest) | Không có gì xảy ra. | Token của thành phần, như `color.background.neutral` hoặc `color.background.danger.bold` | Token chữ đi cặp với nền (xem Màu sắc, phần Ghép cặp) | `color.border` hoặc `color.border.bold` |\n| Hover | Con trỏ đang nằm trên thành phần. | Cùng token, thêm `.hover`: lên một bậc trên thang màu | Không đổi | Không đổi |\n| Nhấn (pressed) | Thành phần đang được click hoặc chạm. | Cùng token, thêm `.pressed`: lên hai bậc | Không đổi | Không đổi |\n\nNút chính là ngoại lệ duy nhất. Nút này nằm ở graphite 12, bậc cuối của thang, nên không còn bậc nào phía trên: khi hover nó lùi một bậc (graphite 11), khi nhấn lùi hai bậc (graphite 10). Token của nút đã làm sẵn việc này.\n| Focus | Thành phần đang có focus từ bàn phím (`:focus-visible`). | Không đổi | Không đổi | Thêm viền: `outline: var(--bh-border-width-focused) solid var(--bh-color-border-focus); outline-offset: var(--bh-state-focus-offset);` |\n| Được chọn (selected) | Thành phần đã được chọn, như một dòng trong bảng, một tab hay một mục menu. | `color.background.selected`, và `color.background.selected.hover` khi hover | Không đổi, kèm một dấu hiệu thứ hai: dấu tích, vạch chỉ báo màu vàng (`color.border.selected`) hoặc chữ đậm trong menu | Không đổi |\n| Vô hiệu (disabled) | Thành phần tạm thời không dùng được. | `color.background.disabled` | `color.text.disabled`, `color.icon.disabled` | `color.border.disabled` |\n\n## Dòng, mục menu và nút ghost\n\nThành phần không có nền ở trạng thái nghỉ dùng `color.background.neutral.subtle`, là màu trong suốt. Khi hover, chúng dùng `color.background.neutral.subtle.hover`; khi nhấn, dùng `color.background.neutral.subtle.pressed`.\n\n## Vô hiệu\n\n- Dùng ba token màu vô hiệu ở trên. Không giảm độ mờ.\n- Bỏ tương tác bằng chuột và bàn phím (`disabled` với control gốc của HTML, `aria-disabled=\"true\"` kèm chặn sự kiện với các thành phần khác) và hiện `cursor: not-allowed`.\n- WCAG không yêu cầu độ tương phản cho control bị vô hiệu, nên các màu vô hiệu được cố ý làm nhạt.\n- Nên cho người dùng biết vì sao không dùng được, ví dụ bằng helper text, thay vì để control bị vô hiệu mà không giải thích.\n\n## Giao diện tối\n\nCác token này dùng được ở giao diện tối. Ở giao diện tối, nền sáng lên khi hover và khi nhấn thay vì tối đi, còn nút chính lùi khỏi graphite 12 theo cùng cách; token đã làm sẵn việc này, nên code không đổi.\n\n## Token\n\nCác màu nằm ở trang [Màu sắc](/vi/foundations/styles/color/). Độ dày focus ring, `border.width.focused`, nằm ở trang [Viền](/vi/foundations/styles/border/). Nhóm này chứa khoảng cách giữa control và ring.\n\n<TokenTable prefix=\"state\" />\n",
1430
+ "frontmatter": {
1431
+ "title": "Trạng thái tương tác",
1432
+ "description": "Control trông thế nào khi được hover, focus, nhấn, chọn hoặc bị vô hiệu.",
1433
+ "order": 10
1434
+ }
1435
+ },
1436
+ {
1437
+ "id": "vi/foundations/styles/layout/app-frame",
1438
+ "path": "src/content-vi/foundations/styles/layout/app-frame.mdx",
1439
+ "documentPath": "docs/src/content-vi/foundations/styles/layout/app-frame.mdx",
1440
+ "locale": "vi",
1441
+ "kind": "guidance",
1442
+ "title": "Khung ứng dụng",
1443
+ "status": "active",
1444
+ "releasePhase": null,
1445
+ "planned": [],
1446
+ "body": "import LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Header, menu bên và page header lặp lại trên mọi trang, ở cùng vị trí và cùng kích thước.**\n\n## Header\n\n**Cao 48 px, trải hết chiều ngang. Chứa những gì thuộc về cả sản phẩm.**\n\n| Phần | Giá trị |\n|---|---|\n| Chiều cao | 48 px: một control 32 px, cách 8 px phía trên và phía dưới. Đường kẻ 1 px dưới header không tính vào |\n| Chứa | Nút menu (dưới 1024 px), logo, tìm kiếm toàn cục, chuyển workspace, thông báo, tài khoản |\n| Không chứa | Breadcrumb và nút hành động của trang. Chúng đổi theo từng trang, nên nằm trong page header |\n\n## Menu bên\n\n**Rộng 280 px khi mở, thu thành rail 64 px khi gọn, thành drawer khi dưới 1024 px. Mọi sản phẩm Beehexa dùng cùng các độ rộng này.**\n\n| Cửa sổ | Menu bên |\n|---|---|\n| Dưới 1024 px | Ẩn. Nút menu trên header mở nó thành drawer phủ lên trang. |\n| Từ 1024 px trở lên | Mở ở 280 px. Người dùng có thể thu gọn thành rail 64 px, và lựa chọn này được ghi nhớ. |\n\n- **280 px** chứa vừa nhãn khoảng 31 ký tự ở cỡ 14 px, kể cả nhãn tiếng Việt dài.\n- **Cùng một độ rộng ở mọi sản phẩm**, để trang luôn bắt đầu ở cùng một chỗ khi người dùng chuyển giữa các sản phẩm.\n- **Không kéo giãn.** Một độ rộng duy nhất giữ các sản phẩm giống nhau. Panel kéo giãn được còn cần thêm cách đổi cỡ không phải kéo (WCAG 2.5.7).\n- **Rail** chỉ hiện icon. Nhãn của từng mục hiện trong tooltip.\n\n### Nhãn dài\n\n<LayoutDemo kind=\"navlabels\" />\n\n1. Trước hết, viết nhãn ngắn hơn.\n2. Nếu vẫn không vừa, cắt bằng dấu ba chấm và hiện nhãn đầy đủ trong tooltip, chỉ khi nhãn bị cắt.\n3. Không bao giờ nới rộng menu bên vì một nhãn. Sản phẩm có nhãn dài ở khắp nơi có thể chọn một độ rộng từ 240 đến 320 px cho toàn sản phẩm, và ghi lại quyết định đó.\n\n## Page header\n\n**Phần đầu của mọi trang: breadcrumb, tiêu đề, trạng thái và nút hành động của trang.**\n\n<LayoutDemo kind=\"pageheader\" />\n\n| Hàng | Chứa | Khi nào |\n|---|---|---|\n| Breadcrumb | Các trang cấp trên của trang này | Từ cấp thứ hai trở xuống |\n| Hàng tiêu đề | Tiêu đề trang (`heading.large`) và trạng thái ở bên trái; nút hành động của trang ở bên phải, nút chính đứng cuối | Luôn có |\n| Mô tả | Một dòng giới thiệu trang | Không bắt buộc |\n| Tab hoặc bộ lọc | Các góc nhìn của cùng một trang | Không bắt buộc |\n\n- **Page header trải hết vùng nội dung ở mọi độ rộng trang.** Chỉ phần nội dung bên dưới theo [Full, Wide hoặc Narrow](/vi/foundations/styles/layout/page-widths/), nên tiêu đề và nút hành động của trang luôn nằm cùng một chỗ trên mọi trang.\n- Breadcrumb thuộc về trang, không thuộc header: nó đổi theo từng trang, còn header thì giữ nguyên.\n- Ngữ cảnh của cả sản phẩm, như workspace, nằm trên header.\n\n## Panel bên\n\nPanel đặt cạnh nội dung chính, như chi tiết của dòng đang chọn, chiếm các cột của lưới: 4 trên 12 cột từ 1024 px và 3 trên 12 cột từ 1440 px. Dưới 1024 px nó mở thành drawer phủ lên trang. Xem phần span ở trang [Lưới](/vi/foundations/styles/layout/grid/#span).\n\n## Khoảng cách trong khung\n\n**Mọi thứ trong khung thẳng hàng theo hai mép: cách mép trái cửa sổ 20 px, và lề trang.**\n\n| Giữa | Khoảng cách |\n|---|---|\n| Mép cửa sổ và logo; mép cửa sổ và icon của menu bên | 20 px, `space.250` |\n| Các mục trong menu bên và mép của menu | 8 px, `space.100` |\n| Hai mục liền nhau trong menu bên (mỗi mục cao 32 px) | 4 px, `space.050` |\n| Nội dung và menu bên, header hoặc mép cửa sổ | Lề trang: 16, 24 hoặc 32 px ([Lưới](/vi/foundations/styles/layout/grid/)) |\n| Breadcrumb và tiêu đề | 8 px, `space.100` |\n| Tiêu đề và mô tả | 4 px, `space.050` |\n| Page header và nội dung | 24 px, `space.300` |\n\nMép 20 px của logo lấy từ menu bên: 8 px thụt vào cộng 12 px padding ngang của một control 32 px. Nhờ vậy logo nằm ngay trên các icon.\n",
1447
+ "raw": "---\ntitle: Khung ứng dụng\ndescription: Header, menu bên và page header lặp lại trên mọi trang, kích thước của chúng, và khoảng cách giúp chúng thẳng hàng.\norder: 1\n---\nimport LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Header, menu bên và page header lặp lại trên mọi trang, ở cùng vị trí và cùng kích thước.**\n\n## Header\n\n**Cao 48 px, trải hết chiều ngang. Chứa những gì thuộc về cả sản phẩm.**\n\n| Phần | Giá trị |\n|---|---|\n| Chiều cao | 48 px: một control 32 px, cách 8 px phía trên và phía dưới. Đường kẻ 1 px dưới header không tính vào |\n| Chứa | Nút menu (dưới 1024 px), logo, tìm kiếm toàn cục, chuyển workspace, thông báo, tài khoản |\n| Không chứa | Breadcrumb và nút hành động của trang. Chúng đổi theo từng trang, nên nằm trong page header |\n\n## Menu bên\n\n**Rộng 280 px khi mở, thu thành rail 64 px khi gọn, thành drawer khi dưới 1024 px. Mọi sản phẩm Beehexa dùng cùng các độ rộng này.**\n\n| Cửa sổ | Menu bên |\n|---|---|\n| Dưới 1024 px | Ẩn. Nút menu trên header mở nó thành drawer phủ lên trang. |\n| Từ 1024 px trở lên | Mở ở 280 px. Người dùng có thể thu gọn thành rail 64 px, và lựa chọn này được ghi nhớ. |\n\n- **280 px** chứa vừa nhãn khoảng 31 ký tự ở cỡ 14 px, kể cả nhãn tiếng Việt dài.\n- **Cùng một độ rộng ở mọi sản phẩm**, để trang luôn bắt đầu ở cùng một chỗ khi người dùng chuyển giữa các sản phẩm.\n- **Không kéo giãn.** Một độ rộng duy nhất giữ các sản phẩm giống nhau. Panel kéo giãn được còn cần thêm cách đổi cỡ không phải kéo (WCAG 2.5.7).\n- **Rail** chỉ hiện icon. Nhãn của từng mục hiện trong tooltip.\n\n### Nhãn dài\n\n<LayoutDemo kind=\"navlabels\" />\n\n1. Trước hết, viết nhãn ngắn hơn.\n2. Nếu vẫn không vừa, cắt bằng dấu ba chấm và hiện nhãn đầy đủ trong tooltip, chỉ khi nhãn bị cắt.\n3. Không bao giờ nới rộng menu bên vì một nhãn. Sản phẩm có nhãn dài ở khắp nơi có thể chọn một độ rộng từ 240 đến 320 px cho toàn sản phẩm, và ghi lại quyết định đó.\n\n## Page header\n\n**Phần đầu của mọi trang: breadcrumb, tiêu đề, trạng thái và nút hành động của trang.**\n\n<LayoutDemo kind=\"pageheader\" />\n\n| Hàng | Chứa | Khi nào |\n|---|---|---|\n| Breadcrumb | Các trang cấp trên của trang này | Từ cấp thứ hai trở xuống |\n| Hàng tiêu đề | Tiêu đề trang (`heading.large`) và trạng thái ở bên trái; nút hành động của trang ở bên phải, nút chính đứng cuối | Luôn có |\n| Mô tả | Một dòng giới thiệu trang | Không bắt buộc |\n| Tab hoặc bộ lọc | Các góc nhìn của cùng một trang | Không bắt buộc |\n\n- **Page header trải hết vùng nội dung ở mọi độ rộng trang.** Chỉ phần nội dung bên dưới theo [Full, Wide hoặc Narrow](/vi/foundations/styles/layout/page-widths/), nên tiêu đề và nút hành động của trang luôn nằm cùng một chỗ trên mọi trang.\n- Breadcrumb thuộc về trang, không thuộc header: nó đổi theo từng trang, còn header thì giữ nguyên.\n- Ngữ cảnh của cả sản phẩm, như workspace, nằm trên header.\n\n## Panel bên\n\nPanel đặt cạnh nội dung chính, như chi tiết của dòng đang chọn, chiếm các cột của lưới: 4 trên 12 cột từ 1024 px và 3 trên 12 cột từ 1440 px. Dưới 1024 px nó mở thành drawer phủ lên trang. Xem phần span ở trang [Lưới](/vi/foundations/styles/layout/grid/#span).\n\n## Khoảng cách trong khung\n\n**Mọi thứ trong khung thẳng hàng theo hai mép: cách mép trái cửa sổ 20 px, và lề trang.**\n\n| Giữa | Khoảng cách |\n|---|---|\n| Mép cửa sổ và logo; mép cửa sổ và icon của menu bên | 20 px, `space.250` |\n| Các mục trong menu bên và mép của menu | 8 px, `space.100` |\n| Hai mục liền nhau trong menu bên (mỗi mục cao 32 px) | 4 px, `space.050` |\n| Nội dung và menu bên, header hoặc mép cửa sổ | Lề trang: 16, 24 hoặc 32 px ([Lưới](/vi/foundations/styles/layout/grid/)) |\n| Breadcrumb và tiêu đề | 8 px, `space.100` |\n| Tiêu đề và mô tả | 4 px, `space.050` |\n| Page header và nội dung | 24 px, `space.300` |\n\nMép 20 px của logo lấy từ menu bên: 8 px thụt vào cộng 12 px padding ngang của một control 32 px. Nhờ vậy logo nằm ngay trên các icon.\n",
1448
+ "frontmatter": {
1449
+ "title": "Khung ứng dụng",
1450
+ "description": "Header, menu bên và page header lặp lại trên mọi trang, kích thước của chúng, và khoảng cách giúp chúng thẳng hàng.",
1451
+ "order": 1
1452
+ }
1453
+ },
1454
+ {
1455
+ "id": "vi/foundations/styles/layout/breakpoints",
1456
+ "path": "src/content-vi/foundations/styles/layout/breakpoints.mdx",
1457
+ "documentPath": "docs/src/content-vi/foundations/styles/layout/breakpoints.mdx",
1458
+ "locale": "vi",
1459
+ "kind": "guidance",
1460
+ "title": "Breakpoint",
1461
+ "status": "active",
1462
+ "releasePhase": null,
1463
+ "planned": [],
1464
+ "body": "import LayoutDemo from '../../../../components/LayoutDemo.astro';\nimport TokenTable from '../../../../components/TokenTable.astro';\n\n**Bố cục đổi ở ba độ rộng cửa sổ: 768, 1024 và 1440 px. Mọi màn hình cũng phải dùng được ở 320 px.**\n\n<LayoutDemo kind=\"breakpoints\" />\n\n## Những gì thay đổi\n\n| Breakpoint | Từ | Cửa sổ | Thay đổi |\n|---|---|---|---|\n| `xs` | 0 | Điện thoại và cửa sổ nhỏ | Một bố cục co giãn: 4 cột, gutter và lề trang 16 px, nội dung một cột. Menu bên nằm trong drawer. |\n| `md` | 768 px | Máy tính bảng, cửa sổ hẹp | 8 cột. Gutter và lề trang 24 px. Menu bên vẫn nằm trong drawer. |\n| `lg` | 1024 px | Laptop, kể cả màn hình 1280 và 1366 px | 12 cột. Menu bên mở ở 280 px, hoặc thu thành rail 64 px. Có thể đặt panel bên cạnh panel chính. |\n| `xl` | 1440 px | Máy bàn, kể cả màn hình 1536 và 1920 px | Lề trang 32 px. Bốn card một hàng. |\n\n- **Dưới 768 px là một bố cục.** Các cột giãn theo cửa sổ, từ 320 đến 767 px. Card hay bảng bên trong vẫn có thể đổi theo độ rộng khung chứa của chính nó, bằng container query.\n- **320 px không phải là breakpoint.** Đó là cửa sổ hẹp nhất mà mọi màn hình phải dùng được, cũng chính là cửa sổ 1280 px phóng to 400% (WCAG 1.4.10).\n\n## Thứ tự thiết kế\n\n**Thiết kế cho máy tính trước, rồi điều chỉnh màn hình cho cửa sổ nhỏ hơn. Viết CSS từ cửa sổ nhỏ nhất trở lên.**\n\nSản phẩm Beehexa chủ yếu được dùng trên máy tính, nên màn hình chính bắt đầu từ độ rộng người dùng hay dùng nhất.\n\n1. Thiết kế ở 1440 px, và kiểm tra ở 1280 px.\n2. Điều chỉnh cho 1024 px, rồi 768 px.\n3. Điều chỉnh cho 360 px, và kiểm tra ở 320 px.\n\nTrong code, style gốc dành cho cửa sổ nhỏ nhất, và mỗi breakpoint bổ sung thêm bằng `min-width`. Làm vậy thì ít quy tắc phải gỡ ngược lại hơn.\n\n## Kiểm tra mọi màn hình ở\n\n| Cửa sổ | Vì sao |\n|---|---|\n| 1440 và 1280 px | Máy bàn và laptop người dùng hay dùng nhất |\n| 1024 px | Ngay trên mốc menu bên chuyển thành drawer |\n| 768 px | Máy tính bảng, và mốc chuyển sang 8 cột |\n| Khoảng 844 × 390 px | Điện thoại xoay ngang: đủ rộng cho bố cục máy tính bảng nhưng thấp |\n| 360 và 320 px | Điện thoại, và cửa sổ hẹp nhất được phép |\n| Phóng to 400% | Người dùng phóng to trang |\n\n## Token\n\n<TokenTable prefix=\"breakpoint\" />\n\n## Cách dùng\n\n- Viết media query bằng `min-width`: `@media (min-width: 768px)`.\n- Không dùng được CSS custom property trong media query. Dùng giá trị pixel của các token này.\n- Đổi bố cục tại breakpoint, không bao giờ đổi token khoảng cách hay cỡ chữ bên trong component.\n",
1465
+ "raw": "---\ntitle: Breakpoint\ndescription: Bốn độ rộng cửa sổ nơi bố cục Beehexa thay đổi, mỗi mốc đổi những gì, và thứ tự thiết kế.\norder: 4\n---\nimport LayoutDemo from '../../../../components/LayoutDemo.astro';\nimport TokenTable from '../../../../components/TokenTable.astro';\n\n**Bố cục đổi ở ba độ rộng cửa sổ: 768, 1024 và 1440 px. Mọi màn hình cũng phải dùng được ở 320 px.**\n\n<LayoutDemo kind=\"breakpoints\" />\n\n## Những gì thay đổi\n\n| Breakpoint | Từ | Cửa sổ | Thay đổi |\n|---|---|---|---|\n| `xs` | 0 | Điện thoại và cửa sổ nhỏ | Một bố cục co giãn: 4 cột, gutter và lề trang 16 px, nội dung một cột. Menu bên nằm trong drawer. |\n| `md` | 768 px | Máy tính bảng, cửa sổ hẹp | 8 cột. Gutter và lề trang 24 px. Menu bên vẫn nằm trong drawer. |\n| `lg` | 1024 px | Laptop, kể cả màn hình 1280 và 1366 px | 12 cột. Menu bên mở ở 280 px, hoặc thu thành rail 64 px. Có thể đặt panel bên cạnh panel chính. |\n| `xl` | 1440 px | Máy bàn, kể cả màn hình 1536 và 1920 px | Lề trang 32 px. Bốn card một hàng. |\n\n- **Dưới 768 px là một bố cục.** Các cột giãn theo cửa sổ, từ 320 đến 767 px. Card hay bảng bên trong vẫn có thể đổi theo độ rộng khung chứa của chính nó, bằng container query.\n- **320 px không phải là breakpoint.** Đó là cửa sổ hẹp nhất mà mọi màn hình phải dùng được, cũng chính là cửa sổ 1280 px phóng to 400% (WCAG 1.4.10).\n\n## Thứ tự thiết kế\n\n**Thiết kế cho máy tính trước, rồi điều chỉnh màn hình cho cửa sổ nhỏ hơn. Viết CSS từ cửa sổ nhỏ nhất trở lên.**\n\nSản phẩm Beehexa chủ yếu được dùng trên máy tính, nên màn hình chính bắt đầu từ độ rộng người dùng hay dùng nhất.\n\n1. Thiết kế ở 1440 px, và kiểm tra ở 1280 px.\n2. Điều chỉnh cho 1024 px, rồi 768 px.\n3. Điều chỉnh cho 360 px, và kiểm tra ở 320 px.\n\nTrong code, style gốc dành cho cửa sổ nhỏ nhất, và mỗi breakpoint bổ sung thêm bằng `min-width`. Làm vậy thì ít quy tắc phải gỡ ngược lại hơn.\n\n## Kiểm tra mọi màn hình ở\n\n| Cửa sổ | Vì sao |\n|---|---|\n| 1440 và 1280 px | Máy bàn và laptop người dùng hay dùng nhất |\n| 1024 px | Ngay trên mốc menu bên chuyển thành drawer |\n| 768 px | Máy tính bảng, và mốc chuyển sang 8 cột |\n| Khoảng 844 × 390 px | Điện thoại xoay ngang: đủ rộng cho bố cục máy tính bảng nhưng thấp |\n| 360 và 320 px | Điện thoại, và cửa sổ hẹp nhất được phép |\n| Phóng to 400% | Người dùng phóng to trang |\n\n## Token\n\n<TokenTable prefix=\"breakpoint\" />\n\n## Cách dùng\n\n- Viết media query bằng `min-width`: `@media (min-width: 768px)`.\n- Không dùng được CSS custom property trong media query. Dùng giá trị pixel của các token này.\n- Đổi bố cục tại breakpoint, không bao giờ đổi token khoảng cách hay cỡ chữ bên trong component.\n",
1466
+ "frontmatter": {
1467
+ "title": "Breakpoint",
1468
+ "description": "Bốn độ rộng cửa sổ nơi bố cục Beehexa thay đổi, mỗi mốc đổi những gì, và thứ tự thiết kế.",
1469
+ "order": 4
1470
+ }
1471
+ },
1472
+ {
1473
+ "id": "vi/foundations/styles/layout/grid",
1474
+ "path": "src/content-vi/foundations/styles/layout/grid.mdx",
1475
+ "documentPath": "docs/src/content-vi/foundations/styles/layout/grid.mdx",
1476
+ "locale": "vi",
1477
+ "kind": "guidance",
1478
+ "title": "Lưới",
1479
+ "status": "active",
1480
+ "releasePhase": null,
1481
+ "planned": [],
1482
+ "body": "import LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Dàn vùng nội dung chính trên 4 cột ở điện thoại, 8 cột ở máy tính bảng và 12 cột từ 1024 px.**\n\n<LayoutDemo kind=\"grid\" />\n\n## Cột, gutter và lề\n\n| Cửa sổ | Số cột | Gutter | Lề trang |\n|---|---|---|---|\n| Dưới 768 px | 4 | 16 px | 16 px |\n| 768 đến 1023 px | 8 | 24 px | 24 px |\n| 1024 đến 1439 px | 12 | 24 px | 24 px |\n| Từ 1440 px trở lên | 12 | 24 px | 32 px |\n\nCác giá trị đều là token khoảng cách: 16 px là `space.200`, 24 px là `space.300` và 32 px là `space.400`. Các khoảng bắt đầu tại breakpoint `md`, `lg` và `xl`.\n\n- **12 cột** chia được thành nửa, một phần ba, một phần tư và một phần sáu.\n- **4 cột trên điện thoại** cho hai nửa hoặc bốn phần tư. **8 cột trên máy tính bảng** giữ nguyên các nửa và phần tư đó nhưng rộng rãi hơn.\n- **Gutter** là 16 px trên điện thoại và 24 px từ 768 px, khi đã đủ chỗ để tách các card rõ hơn.\n- **Lề trang** bắt đầu từ 16 px và tăng lên 32 px trên màn hình rộng, để nội dung không chạm mép cửa sổ lớn.\n- **Mọi giá trị đều là token khoảng cách và là bội số của 8 px**, như line height của chữ, nên card, chữ và control thẳng hàng với nhau.\n\nDùng cùng gutter giữa các hàng, để card cách nhau theo chiều dọc bằng theo chiều ngang.\n\n## Cột co giãn\n\n**Cột giãn theo cửa sổ. Gutter và lề giữ cố định trong mỗi khoảng.**\n\nCửa sổ rộng hơn thì cột rộng hơn, không phải thêm khoảng trống. Tới breakpoint kế tiếp, gutter, lề hoặc số cột mới thay đổi.\n\n## Lưới nằm ở đâu\n\n**Lưới chỉ trải trên vùng nội dung chính.**\n\n- Header và menu bên không nằm trên lưới. Lưới bắt đầu từ chỗ menu bên kết thúc, nên các cột luôn chia đều vùng nội dung.\n- Menu bên giữ độ rộng cố định thay vì chiếm cột. Nếu tính bằng cột, nó sẽ to nhỏ theo cửa sổ, và khi thu thành rail thì số cột bị lệch.\n- Breakpoint vẫn đọc theo độ rộng cửa sổ. Mở hay thu gọn menu bên không làm đổi breakpoint.\n- Nội dung trong panel hoặc card có thể theo độ rộng của khung chứa nó, bằng container query.\n- Trên trang Wide hoặc Narrow, lưới lấp đầy độ rộng đã giới hạn. Xem [Độ rộng trang](/vi/foundations/styles/layout/page-widths/).\n\n## Span\n\nSpan là số cột một phần tử chiếm.\n\n| Bố cục | Dưới 768 px (trên 4) | 768 px (trên 8) | 1024 px (trên 12) | 1440 px (trên 12) |\n|---|---|---|---|---|\n| Card, 1 đến 4 card một hàng | 4 | 4 | 4 | 3 |\n| Panel chính và panel bên | 4 | 8 | 8 + 4 | 9 + 3 |\n| Ô tóm tắt | 2 | 2 | 3 | 2 |\n\nTrong CSS, lưới chỉ cần vài dòng:\n\n```css\n.page-grid {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: var(--bh-space-200);\n padding-inline: var(--bh-space-200);\n}\n@media (min-width: 768px) {\n .page-grid {\n grid-template-columns: repeat(8, minmax(0, 1fr));\n gap: var(--bh-space-300);\n padding-inline: var(--bh-space-300);\n }\n}\n@media (min-width: 1024px) {\n .page-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }\n}\n@media (min-width: 1440px) {\n .page-grid { padding-inline: var(--bh-space-400); }\n}\n```\n\n## Thứ gì đặt trên lưới\n\n- Các vùng của trang căn theo cột: card, panel, cột form, ô tóm tắt.\n- Control bên trong một vùng thì không. Trong card, dùng token khoảng cách.\n- Bảng dữ liệu lấp đầy vùng của nó. Không chia cột bảng theo lưới.\n\nXem [Breakpoint](/vi/foundations/styles/layout/breakpoints/) để biết khi nào lưới thay đổi.\n",
1483
+ "raw": "---\ntitle: Lưới\ndescription: Lưới co giãn 4, 8 hoặc 12 cột trong vùng nội dung chính, với gutter và lề trang lấy từ token khoảng cách.\norder: 3\n---\nimport LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Dàn vùng nội dung chính trên 4 cột ở điện thoại, 8 cột ở máy tính bảng và 12 cột từ 1024 px.**\n\n<LayoutDemo kind=\"grid\" />\n\n## Cột, gutter và lề\n\n| Cửa sổ | Số cột | Gutter | Lề trang |\n|---|---|---|---|\n| Dưới 768 px | 4 | 16 px | 16 px |\n| 768 đến 1023 px | 8 | 24 px | 24 px |\n| 1024 đến 1439 px | 12 | 24 px | 24 px |\n| Từ 1440 px trở lên | 12 | 24 px | 32 px |\n\nCác giá trị đều là token khoảng cách: 16 px là `space.200`, 24 px là `space.300` và 32 px là `space.400`. Các khoảng bắt đầu tại breakpoint `md`, `lg` và `xl`.\n\n- **12 cột** chia được thành nửa, một phần ba, một phần tư và một phần sáu.\n- **4 cột trên điện thoại** cho hai nửa hoặc bốn phần tư. **8 cột trên máy tính bảng** giữ nguyên các nửa và phần tư đó nhưng rộng rãi hơn.\n- **Gutter** là 16 px trên điện thoại và 24 px từ 768 px, khi đã đủ chỗ để tách các card rõ hơn.\n- **Lề trang** bắt đầu từ 16 px và tăng lên 32 px trên màn hình rộng, để nội dung không chạm mép cửa sổ lớn.\n- **Mọi giá trị đều là token khoảng cách và là bội số của 8 px**, như line height của chữ, nên card, chữ và control thẳng hàng với nhau.\n\nDùng cùng gutter giữa các hàng, để card cách nhau theo chiều dọc bằng theo chiều ngang.\n\n## Cột co giãn\n\n**Cột giãn theo cửa sổ. Gutter và lề giữ cố định trong mỗi khoảng.**\n\nCửa sổ rộng hơn thì cột rộng hơn, không phải thêm khoảng trống. Tới breakpoint kế tiếp, gutter, lề hoặc số cột mới thay đổi.\n\n## Lưới nằm ở đâu\n\n**Lưới chỉ trải trên vùng nội dung chính.**\n\n- Header và menu bên không nằm trên lưới. Lưới bắt đầu từ chỗ menu bên kết thúc, nên các cột luôn chia đều vùng nội dung.\n- Menu bên giữ độ rộng cố định thay vì chiếm cột. Nếu tính bằng cột, nó sẽ to nhỏ theo cửa sổ, và khi thu thành rail thì số cột bị lệch.\n- Breakpoint vẫn đọc theo độ rộng cửa sổ. Mở hay thu gọn menu bên không làm đổi breakpoint.\n- Nội dung trong panel hoặc card có thể theo độ rộng của khung chứa nó, bằng container query.\n- Trên trang Wide hoặc Narrow, lưới lấp đầy độ rộng đã giới hạn. Xem [Độ rộng trang](/vi/foundations/styles/layout/page-widths/).\n\n## Span\n\nSpan là số cột một phần tử chiếm.\n\n| Bố cục | Dưới 768 px (trên 4) | 768 px (trên 8) | 1024 px (trên 12) | 1440 px (trên 12) |\n|---|---|---|---|---|\n| Card, 1 đến 4 card một hàng | 4 | 4 | 4 | 3 |\n| Panel chính và panel bên | 4 | 8 | 8 + 4 | 9 + 3 |\n| Ô tóm tắt | 2 | 2 | 3 | 2 |\n\nTrong CSS, lưới chỉ cần vài dòng:\n\n```css\n.page-grid {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: var(--bh-space-200);\n padding-inline: var(--bh-space-200);\n}\n@media (min-width: 768px) {\n .page-grid {\n grid-template-columns: repeat(8, minmax(0, 1fr));\n gap: var(--bh-space-300);\n padding-inline: var(--bh-space-300);\n }\n}\n@media (min-width: 1024px) {\n .page-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }\n}\n@media (min-width: 1440px) {\n .page-grid { padding-inline: var(--bh-space-400); }\n}\n```\n\n## Thứ gì đặt trên lưới\n\n- Các vùng của trang căn theo cột: card, panel, cột form, ô tóm tắt.\n- Control bên trong một vùng thì không. Trong card, dùng token khoảng cách.\n- Bảng dữ liệu lấp đầy vùng của nó. Không chia cột bảng theo lưới.\n\nXem [Breakpoint](/vi/foundations/styles/layout/breakpoints/) để biết khi nào lưới thay đổi.\n",
1484
+ "frontmatter": {
1485
+ "title": "Lưới",
1486
+ "description": "Lưới co giãn 4, 8 hoặc 12 cột trong vùng nội dung chính, với gutter và lề trang lấy từ token khoảng cách.",
1487
+ "order": 3
1488
+ }
1489
+ },
1490
+ {
1491
+ "id": "vi/foundations/styles/layout/index",
1492
+ "path": "src/content-vi/foundations/styles/layout/index.mdx",
1493
+ "documentPath": "docs/src/content-vi/foundations/styles/layout/index.mdx",
1494
+ "locale": "vi",
1495
+ "kind": "guidance",
1496
+ "title": "Bố cục",
1497
+ "status": "active",
1498
+ "releasePhase": null,
1499
+ "planned": [],
1500
+ "body": "import LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Mọi ứng dụng Beehexa dùng chung một khung: header chạy ngang phía trên, menu bên ở bên trái, và trang nằm cạnh menu.**\n\nNgười dùng chuyển qua lại giữa các màn hình cả ngày. Khi menu, ô tìm kiếm và các nút hành động của trang luôn ở cùng một chỗ, họ tìm thấy mà không cần nhìn.\n\n<LayoutDemo kind=\"anatomy\" />\n\n## Mỗi phần được quy định ở đâu\n\n| Phần | Quy định gì | Trang |\n|---|---|---|\n| Header, menu bên, page header | Các phần lặp lại trên mọi trang, kích thước và khoảng cách giữa chúng | [Khung ứng dụng](/vi/foundations/styles/layout/app-frame/) |\n| Độ rộng nội dung | Full, Wide hoặc Narrow, theo nội dung của trang | [Độ rộng trang](/vi/foundations/styles/layout/page-widths/) |\n| Cột | Cột, gutter và lề trang trong vùng nội dung | [Lưới](/vi/foundations/styles/layout/grid/) |\n| Độ rộng cửa sổ | Bố cục đổi ở đâu, và thứ tự thiết kế | [Breakpoint](/vi/foundations/styles/layout/breakpoints/) |\n| Chiều cao control | 24, 32 và 40 px, và mật độ | [Kích thước và mật độ](/vi/foundations/styles/size-and-density/) |\n| Khoảng cách giữa các phần tử | Các bậc khoảng cách | [Khoảng cách](/vi/foundations/styles/spacing/) |\n",
1501
+ "raw": "---\ntitle: Bố cục\ndescription: Khung chung của mọi ứng dụng Beehexa (header, menu bên, page header và nội dung) và các trang quy định kích thước của nó.\norder: 4\nsidebarLabel: Tổng quan\n---\nimport LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Mọi ứng dụng Beehexa dùng chung một khung: header chạy ngang phía trên, menu bên ở bên trái, và trang nằm cạnh menu.**\n\nNgười dùng chuyển qua lại giữa các màn hình cả ngày. Khi menu, ô tìm kiếm và các nút hành động của trang luôn ở cùng một chỗ, họ tìm thấy mà không cần nhìn.\n\n<LayoutDemo kind=\"anatomy\" />\n\n## Mỗi phần được quy định ở đâu\n\n| Phần | Quy định gì | Trang |\n|---|---|---|\n| Header, menu bên, page header | Các phần lặp lại trên mọi trang, kích thước và khoảng cách giữa chúng | [Khung ứng dụng](/vi/foundations/styles/layout/app-frame/) |\n| Độ rộng nội dung | Full, Wide hoặc Narrow, theo nội dung của trang | [Độ rộng trang](/vi/foundations/styles/layout/page-widths/) |\n| Cột | Cột, gutter và lề trang trong vùng nội dung | [Lưới](/vi/foundations/styles/layout/grid/) |\n| Độ rộng cửa sổ | Bố cục đổi ở đâu, và thứ tự thiết kế | [Breakpoint](/vi/foundations/styles/layout/breakpoints/) |\n| Chiều cao control | 24, 32 và 40 px, và mật độ | [Kích thước và mật độ](/vi/foundations/styles/size-and-density/) |\n| Khoảng cách giữa các phần tử | Các bậc khoảng cách | [Khoảng cách](/vi/foundations/styles/spacing/) |\n",
1502
+ "frontmatter": {
1503
+ "title": "Bố cục",
1504
+ "description": "Khung chung của mọi ứng dụng Beehexa (header, menu bên, page header và nội dung) và các trang quy định kích thước của nó.",
1505
+ "order": 4,
1506
+ "sidebarLabel": "Tổng quan"
1507
+ }
1508
+ },
1509
+ {
1510
+ "id": "vi/foundations/styles/layout/page-widths",
1511
+ "path": "src/content-vi/foundations/styles/layout/page-widths.mdx",
1512
+ "documentPath": "docs/src/content-vi/foundations/styles/layout/page-widths.mdx",
1513
+ "locale": "vi",
1514
+ "kind": "guidance",
1515
+ "title": "Độ rộng trang",
1516
+ "status": "active",
1517
+ "releasePhase": null,
1518
+ "planned": [],
1519
+ "body": "import LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Mỗi trang chọn một trong ba độ rộng, theo nội dung của trang.**\n\n<LayoutDemo kind=\"widths\" />\n\n| Độ rộng | Tối đa | Dùng cho |\n|---|---|---|\n| Full | Không giới hạn | Bảng, danh sách, log, trình dựng và canvas |\n| Wide | 1280 px | Dashboard, trang chi tiết, trang tổng quan cài đặt, trang thông thường |\n| Narrow | 768 px | Form, form cài đặt, các bước wizard, trang hướng dẫn và tài liệu |\n\n- **Full.** Bảng và log hiện được nhiều cột, nhiều dòng hơn khi dùng hết cửa sổ.\n- **Wide.** Card và panel giữ cỡ vừa mắt để lướt nhanh trên màn hình lớn.\n- **Narrow.** Form một cột điền nhanh, mắt không phải đi xa từ nhãn tới ô nhập.\n- Mức tối đa là độ rộng của nội dung. Lề trang nằm ngoài mức này.\n- Độ rộng chỉ áp dụng cho nội dung. [Page header](/vi/foundations/styles/layout/app-frame/#page-header) phía trên luôn trải hết vùng nội dung, nên tiêu đề và các nút hành động của trang không xê dịch khi chuyển trang.\n\n## Căn chỉnh\n\n**Nội dung Wide hoặc Narrow được căn giữa trong vùng bên cạnh menu bên. Page header vẫn trải hết vùng.**\n\nKhi menu bên mở hoặc đóng, trang dời theo tâm mới.\n\n## Chữ chạy dài\n\n**Chữ chạy hết chiều rộng cột của nó. Để dòng không quá dài, đặt nội dung chữ dài trên trang Narrow.**\n\nCột Narrow 768 px chứa khoảng 100 ký tự mỗi dòng với chữ 16 px. Trang hướng dẫn hay tài liệu là trang Narrow; mục lục đặt bên cạnh không tính vào 768 px.\n",
1520
+ "raw": "---\ntitle: Độ rộng trang\ndescription: Nội dung Full, Wide hoặc Narrow, chọn theo nội dung của trang, và độ dài một dòng chữ.\norder: 2\n---\nimport LayoutDemo from '../../../../components/LayoutDemo.astro';\n\n**Mỗi trang chọn một trong ba độ rộng, theo nội dung của trang.**\n\n<LayoutDemo kind=\"widths\" />\n\n| Độ rộng | Tối đa | Dùng cho |\n|---|---|---|\n| Full | Không giới hạn | Bảng, danh sách, log, trình dựng và canvas |\n| Wide | 1280 px | Dashboard, trang chi tiết, trang tổng quan cài đặt, trang thông thường |\n| Narrow | 768 px | Form, form cài đặt, các bước wizard, trang hướng dẫn và tài liệu |\n\n- **Full.** Bảng và log hiện được nhiều cột, nhiều dòng hơn khi dùng hết cửa sổ.\n- **Wide.** Card và panel giữ cỡ vừa mắt để lướt nhanh trên màn hình lớn.\n- **Narrow.** Form một cột điền nhanh, mắt không phải đi xa từ nhãn tới ô nhập.\n- Mức tối đa là độ rộng của nội dung. Lề trang nằm ngoài mức này.\n- Độ rộng chỉ áp dụng cho nội dung. [Page header](/vi/foundations/styles/layout/app-frame/#page-header) phía trên luôn trải hết vùng nội dung, nên tiêu đề và các nút hành động của trang không xê dịch khi chuyển trang.\n\n## Căn chỉnh\n\n**Nội dung Wide hoặc Narrow được căn giữa trong vùng bên cạnh menu bên. Page header vẫn trải hết vùng.**\n\nKhi menu bên mở hoặc đóng, trang dời theo tâm mới.\n\n## Chữ chạy dài\n\n**Chữ chạy hết chiều rộng cột của nó. Để dòng không quá dài, đặt nội dung chữ dài trên trang Narrow.**\n\nCột Narrow 768 px chứa khoảng 100 ký tự mỗi dòng với chữ 16 px. Trang hướng dẫn hay tài liệu là trang Narrow; mục lục đặt bên cạnh không tính vào 768 px.\n",
1521
+ "frontmatter": {
1522
+ "title": "Độ rộng trang",
1523
+ "description": "Nội dung Full, Wide hoặc Narrow, chọn theo nội dung của trang, và độ dài một dòng chữ.",
1524
+ "order": 2
1525
+ }
1526
+ },
1527
+ {
1528
+ "id": "vi/foundations/styles/logos/downloads-and-terms",
1529
+ "path": "src/content-vi/foundations/styles/logos/downloads-and-terms.mdx",
1530
+ "documentPath": "docs/src/content-vi/foundations/styles/logos/downloads-and-terms.mdx",
1531
+ "locale": "vi",
1532
+ "kind": "guidance",
1533
+ "title": "Tải về và điều khoản",
1534
+ "status": "active",
1535
+ "releasePhase": null,
1536
+ "planned": [],
1537
+ "body": "import LogoHero from '../../../../components/logos/LogoHero.astro';\n\n## Gói file\n\n<LogoHero />\n\n| Thư mục | Nội dung |\n|---|---|\n| `lockups/` | Lockup beehexa và HexaSync, mỗi loại bốn bản màu, SVG, artboard đã có vùng trống |\n| `icon/` | Icon màu vàng, trắng và xám ghi, SVG, có vùng trống |\n| `favicon-web/` | favicon.svg, favicon.ico và favicon PNG 16, 32, 48 px, apple-touch-icon, icon web app 192 và 512 px, icon maskable, avatar 800 px, site.webmanifest |\n| `license/` | Giấy phép SIL Open Font License của Inter |\n| `README.md` | Tóm tắt luật |\n\n## Dùng file nào\n\n| Bạn cần | Dùng |\n|---|---|\n| Logo trên website hoặc ứng dụng | Ảnh PNG xuất ở 3× từ `lockups/beehexa-horizontal-1-light.svg` (nền sáng) hoặc `-2-dark.svg` (nền tối), hiển thị ở 1×. Xem [hiển thị sắc nét](/vi/foundations/styles/logos/using-the-logo/#hiển-thị-sắc-nét). |\n| Logo trong tài liệu, slide hoặc bản in | `lockups/beehexa-horizontal-1-light.svg` trên nền sáng, `-2-dark.svg` trên nền tối |\n| Logo trên ảnh hoặc nền màu đậm | `-3-white.svg` |\n| In một màu, khắc, đóng dấu | `-4-graphite.svg` |\n| Favicon | `favicon-web/favicon.svg` và `favicon.ico` |\n| Icon ứng dụng hoặc avatar mạng xã hội | `favicon-web/apple-touch-icon.png`, `icon-192.png`, `icon-512.png`, `icon-maskable-512.png`, `avatar-800.png` |\n| Icon trong bố cục của bạn | `icon/beehexa-icon-*.svg` |\n| PNG hoặc PDF | Xuất từ SVG ở đúng cỡ cần dùng. Không phóng to một file PNG nhỏ. |\n\n## Mã màu\n\n| Màu | HEX | RGB | In |\n|---|---|---|---|\n| Vàng | #FCB017 | 252 176 23 | Chưa chốt |\n| Xám ghi | #2B2A28 | 43 42 40 | Chưa chốt |\n| Trắng | #FFFFFF | 255 255 255 | Màu giấy |\n\nMã CMYK và Pantone sẽ có sau khi in thử. Brand guide 2025 ghi PMS 1235 C cho màu vàng; hãy kiểm trên giấy trước khi dùng, vì màu vàng này in CMYK trên giấy không tráng phủ thường bị xỉn.\n\n## Font chữ\n\nWordmark dùng Inter Display và đã chuyển thành nét vẽ, nên không cần cài font để dùng logo. Inter dùng giấy phép SIL Open Font License 1.1, cho phép dùng trong logo. Giấy phép có trong gói file.\n\n## Nhãn hiệu\n\nLogo Beehexa đã đăng ký nhãn hiệu tại Việt Nam, số 4-0358730-000, nhóm 9, 35 và 42. Việc đăng ký cho logo như trên site này đang được xác nhận với đại diện sở hữu công nghiệp.\n\n## Điều khoản sử dụng\n\n> Bản nháp, chờ pháp lý duyệt. Câu hỏi gửi về [hello@beehexa.com](mailto:hello@beehexa.com?subject=Logo%20use).\n\nBạn được dùng logo Beehexa và HexaSync để nói về Beehexa, để thể hiện sản phẩm của bạn tích hợp với HexaSync, hoặc trong tin tức và bài đánh giá về chúng tôi, với điều kiện:\n\n- dùng file trong gói mà không chỉnh sửa, theo trang [Cách dùng logo](/vi/foundations/styles/logos/using-the-logo/);\n- không ngụ ý Beehexa tài trợ, bảo chứng hay là đối tác của bạn nếu chưa có thoả thuận bằng văn bản;\n- không dùng logo, icon hay hình na ná trong tên sản phẩm, logo, tên miền, icon ứng dụng hay tài khoản mạng xã hội của bạn;\n- không để logo của chúng tôi là thành phần nổi bật nhất trong tài liệu của bạn.\n\nChúng tôi có thể yêu cầu bạn sửa hoặc ngừng bất kỳ cách dùng logo nào.\n",
1538
+ "raw": "---\ntitle: Tải về và điều khoản\ndescription: Mọi file logo, file nào dùng cho việc gì, mã màu, giấy phép font và điều khoản dùng nhãn hiệu Beehexa.\norder: 5\naudience: designer, developer, đối tác, báo chí\nowner: Brand\nupdated: 2026-10-24\n---\nimport LogoHero from '../../../../components/logos/LogoHero.astro';\n\n## Gói file\n\n<LogoHero />\n\n| Thư mục | Nội dung |\n|---|---|\n| `lockups/` | Lockup beehexa và HexaSync, mỗi loại bốn bản màu, SVG, artboard đã có vùng trống |\n| `icon/` | Icon màu vàng, trắng và xám ghi, SVG, có vùng trống |\n| `favicon-web/` | favicon.svg, favicon.ico và favicon PNG 16, 32, 48 px, apple-touch-icon, icon web app 192 và 512 px, icon maskable, avatar 800 px, site.webmanifest |\n| `license/` | Giấy phép SIL Open Font License của Inter |\n| `README.md` | Tóm tắt luật |\n\n## Dùng file nào\n\n| Bạn cần | Dùng |\n|---|---|\n| Logo trên website hoặc ứng dụng | Ảnh PNG xuất ở 3× từ `lockups/beehexa-horizontal-1-light.svg` (nền sáng) hoặc `-2-dark.svg` (nền tối), hiển thị ở 1×. Xem [hiển thị sắc nét](/vi/foundations/styles/logos/using-the-logo/#hiển-thị-sắc-nét). |\n| Logo trong tài liệu, slide hoặc bản in | `lockups/beehexa-horizontal-1-light.svg` trên nền sáng, `-2-dark.svg` trên nền tối |\n| Logo trên ảnh hoặc nền màu đậm | `-3-white.svg` |\n| In một màu, khắc, đóng dấu | `-4-graphite.svg` |\n| Favicon | `favicon-web/favicon.svg` và `favicon.ico` |\n| Icon ứng dụng hoặc avatar mạng xã hội | `favicon-web/apple-touch-icon.png`, `icon-192.png`, `icon-512.png`, `icon-maskable-512.png`, `avatar-800.png` |\n| Icon trong bố cục của bạn | `icon/beehexa-icon-*.svg` |\n| PNG hoặc PDF | Xuất từ SVG ở đúng cỡ cần dùng. Không phóng to một file PNG nhỏ. |\n\n## Mã màu\n\n| Màu | HEX | RGB | In |\n|---|---|---|---|\n| Vàng | #FCB017 | 252 176 23 | Chưa chốt |\n| Xám ghi | #2B2A28 | 43 42 40 | Chưa chốt |\n| Trắng | #FFFFFF | 255 255 255 | Màu giấy |\n\nMã CMYK và Pantone sẽ có sau khi in thử. Brand guide 2025 ghi PMS 1235 C cho màu vàng; hãy kiểm trên giấy trước khi dùng, vì màu vàng này in CMYK trên giấy không tráng phủ thường bị xỉn.\n\n## Font chữ\n\nWordmark dùng Inter Display và đã chuyển thành nét vẽ, nên không cần cài font để dùng logo. Inter dùng giấy phép SIL Open Font License 1.1, cho phép dùng trong logo. Giấy phép có trong gói file.\n\n## Nhãn hiệu\n\nLogo Beehexa đã đăng ký nhãn hiệu tại Việt Nam, số 4-0358730-000, nhóm 9, 35 và 42. Việc đăng ký cho logo như trên site này đang được xác nhận với đại diện sở hữu công nghiệp.\n\n## Điều khoản sử dụng\n\n> Bản nháp, chờ pháp lý duyệt. Câu hỏi gửi về [hello@beehexa.com](mailto:hello@beehexa.com?subject=Logo%20use).\n\nBạn được dùng logo Beehexa và HexaSync để nói về Beehexa, để thể hiện sản phẩm của bạn tích hợp với HexaSync, hoặc trong tin tức và bài đánh giá về chúng tôi, với điều kiện:\n\n- dùng file trong gói mà không chỉnh sửa, theo trang [Cách dùng logo](/vi/foundations/styles/logos/using-the-logo/);\n- không ngụ ý Beehexa tài trợ, bảo chứng hay là đối tác của bạn nếu chưa có thoả thuận bằng văn bản;\n- không dùng logo, icon hay hình na ná trong tên sản phẩm, logo, tên miền, icon ứng dụng hay tài khoản mạng xã hội của bạn;\n- không để logo của chúng tôi là thành phần nổi bật nhất trong tài liệu của bạn.\n\nChúng tôi có thể yêu cầu bạn sửa hoặc ngừng bất kỳ cách dùng logo nào.\n",
1539
+ "frontmatter": {
1540
+ "title": "Tải về và điều khoản",
1541
+ "description": "Mọi file logo, file nào dùng cho việc gì, mã màu, giấy phép font và điều khoản dùng nhãn hiệu Beehexa.",
1542
+ "order": 5,
1543
+ "audience": "designer, developer, đối tác, báo chí",
1544
+ "owner": "Brand",
1545
+ "updated": "2026-10-24"
1546
+ }
1547
+ },
1548
+ {
1549
+ "id": "vi/foundations/styles/logos/index",
1550
+ "path": "src/content-vi/foundations/styles/logos/index.mdx",
1551
+ "documentPath": "docs/src/content-vi/foundations/styles/logos/index.mdx",
1552
+ "locale": "vi",
1553
+ "kind": "guidance",
1554
+ "title": "Logo",
1555
+ "status": "active",
1556
+ "releasePhase": null,
1557
+ "planned": [],
1558
+ "body": "import LogoHero from '../../../../components/logos/LogoHero.astro';\nimport LogoAnatomy from '../../../../components/logos/LogoAnatomy.astro';\nimport LogoConstruction from '../../../../components/logos/LogoConstruction.astro';\nimport LogoMeanings from '../../../../components/logos/LogoMeanings.astro';\n\n## Tải về\n\n<LogoHero />\n\n## Cấu tạo\n\nLockup gồm icon và wordmark đặt cạnh nhau. Mọi số đo dùng chung một đơn vị: cạnh của lục giác, cũng chính là x-height của wordmark.\n\n<LogoAnatomy />\n\nChỉ có hai dạng: lockup ngang này và [icon đứng riêng](/vi/foundations/styles/logos/using-the-logo/#icon-đứng-riêng). Không có bản xếp dọc.\n\n## Dựng hình\n\nIcon được vẽ trên lưới tam giác đều, nên ai cũng vẽ lại được chính xác: một lục giác đều đỉnh nhọn, ba lớp, cạnh nghiêng 30°.\n\n<LogoConstruction />\n\n## Một icon, ba ý nghĩa\n\n> Như con ong xây tổ, Beehexa ghép từng hệ thống thành một khối vững chắc, rồi đưa doanh nghiệp bay lên.\n\nBa ý nghĩa lồng vào nhau: phần vàng là thứ Beehexa xây, phần trắng là điều Beehexa mang lại.\n\n<LogoMeanings />\n\n## Tóm tắt luật\n\n| Luật | Giá trị | Chi tiết |\n|---|---|---|\n| Dạng logo | Lockup ngang; icon đứng riêng | [Cấu tạo](#cấu-tạo) |\n| Bản màu | 4 bản, 3 màu: vàng #FCB017, xám ghi #2B2A28, trắng | [Bản màu](/vi/foundations/styles/logos/using-the-logo/#bản-màu) |\n| Vùng trống | 1 x-height (một cạnh lục giác) ở mọi phía | [Vùng trống](/vi/foundations/styles/logos/using-the-logo/#vùng-trống) |\n| Cỡ tối thiểu | Lockup rộng 100 px hoặc 25 mm; icon cao 16 px hoặc 6 mm | [Cỡ tối thiểu](/vi/foundations/styles/logos/using-the-logo/#cỡ-tối-thiểu) |\n| Icon trên nền sáng | Xám ghi, hoặc vàng trên ô xám ghi | [Icon đứng riêng](/vi/foundations/styles/logos/using-the-logo/#icon-đứng-riêng) |\n| Cách viết | Logo ghi “beehexa”, viết thường. Logo sản phẩm giữ cách viết của sản phẩm: “HexaSync”. Trong câu văn, viết Beehexa. | [Logo sản phẩm](/vi/foundations/styles/logos/product-logos/) |\n\n## Khác gì so với logo 2018\n\n| | Logo 2018 | Logo mới |\n|---|---|---|\n| Font chữ | Ubuntu, font của hãng khác, thiếu chữ tiếng Việt | Inter Display, font của Beehexa, đã chuyển thành nét vẽ |\n| Màu chữ | Vàng | Xám ghi trên nền sáng, trắng trên nền tối |\n| Icon | Không có lưới; nét mảnh hơn khe (0.8 : 1) | Lưới 28 dải; nét bằng khe (1 : 1), nét dày hơn 11% |\n| Khoảng cách icon–chữ | Không có luật | 10 dải, đo từ chính icon |\n| Vùng trống | Một lớp chevron, khoảng 0.22 × chiều cao icon | 1 x-height |\n| Cỡ tối thiểu | 120 px hoặc 30 mm | 100 px hoặc 25 mm |\n| Bản màu | Toàn bộ màu vàng | 4 bản |\n\nLogo 2018 vẫn nằm trên các tài liệu đang có cho tới khi logo mới ra mắt. Không dùng nó cho việc mới.\n",
1559
+ "raw": "---\ntitle: Logo\ndescription: Logo Beehexa và logo của từng sản phẩm, cùng các luật và file để dùng trên web, ấn phẩm in và trong sản phẩm.\norder: 12\nsidebarLabel: Tổng quan\naudience: web, in ấn, giao diện sản phẩm\nowner: Brand\nupdated: 2026-10-23\n---\nimport LogoHero from '../../../../components/logos/LogoHero.astro';\nimport LogoAnatomy from '../../../../components/logos/LogoAnatomy.astro';\nimport LogoConstruction from '../../../../components/logos/LogoConstruction.astro';\nimport LogoMeanings from '../../../../components/logos/LogoMeanings.astro';\n\n## Tải về\n\n<LogoHero />\n\n## Cấu tạo\n\nLockup gồm icon và wordmark đặt cạnh nhau. Mọi số đo dùng chung một đơn vị: cạnh của lục giác, cũng chính là x-height của wordmark.\n\n<LogoAnatomy />\n\nChỉ có hai dạng: lockup ngang này và [icon đứng riêng](/vi/foundations/styles/logos/using-the-logo/#icon-đứng-riêng). Không có bản xếp dọc.\n\n## Dựng hình\n\nIcon được vẽ trên lưới tam giác đều, nên ai cũng vẽ lại được chính xác: một lục giác đều đỉnh nhọn, ba lớp, cạnh nghiêng 30°.\n\n<LogoConstruction />\n\n## Một icon, ba ý nghĩa\n\n> Như con ong xây tổ, Beehexa ghép từng hệ thống thành một khối vững chắc, rồi đưa doanh nghiệp bay lên.\n\nBa ý nghĩa lồng vào nhau: phần vàng là thứ Beehexa xây, phần trắng là điều Beehexa mang lại.\n\n<LogoMeanings />\n\n## Tóm tắt luật\n\n| Luật | Giá trị | Chi tiết |\n|---|---|---|\n| Dạng logo | Lockup ngang; icon đứng riêng | [Cấu tạo](#cấu-tạo) |\n| Bản màu | 4 bản, 3 màu: vàng #FCB017, xám ghi #2B2A28, trắng | [Bản màu](/vi/foundations/styles/logos/using-the-logo/#bản-màu) |\n| Vùng trống | 1 x-height (một cạnh lục giác) ở mọi phía | [Vùng trống](/vi/foundations/styles/logos/using-the-logo/#vùng-trống) |\n| Cỡ tối thiểu | Lockup rộng 100 px hoặc 25 mm; icon cao 16 px hoặc 6 mm | [Cỡ tối thiểu](/vi/foundations/styles/logos/using-the-logo/#cỡ-tối-thiểu) |\n| Icon trên nền sáng | Xám ghi, hoặc vàng trên ô xám ghi | [Icon đứng riêng](/vi/foundations/styles/logos/using-the-logo/#icon-đứng-riêng) |\n| Cách viết | Logo ghi “beehexa”, viết thường. Logo sản phẩm giữ cách viết của sản phẩm: “HexaSync”. Trong câu văn, viết Beehexa. | [Logo sản phẩm](/vi/foundations/styles/logos/product-logos/) |\n\n## Khác gì so với logo 2018\n\n| | Logo 2018 | Logo mới |\n|---|---|---|\n| Font chữ | Ubuntu, font của hãng khác, thiếu chữ tiếng Việt | Inter Display, font của Beehexa, đã chuyển thành nét vẽ |\n| Màu chữ | Vàng | Xám ghi trên nền sáng, trắng trên nền tối |\n| Icon | Không có lưới; nét mảnh hơn khe (0.8 : 1) | Lưới 28 dải; nét bằng khe (1 : 1), nét dày hơn 11% |\n| Khoảng cách icon–chữ | Không có luật | 10 dải, đo từ chính icon |\n| Vùng trống | Một lớp chevron, khoảng 0.22 × chiều cao icon | 1 x-height |\n| Cỡ tối thiểu | 120 px hoặc 30 mm | 100 px hoặc 25 mm |\n| Bản màu | Toàn bộ màu vàng | 4 bản |\n\nLogo 2018 vẫn nằm trên các tài liệu đang có cho tới khi logo mới ra mắt. Không dùng nó cho việc mới.\n",
1560
+ "frontmatter": {
1561
+ "title": "Logo",
1562
+ "description": "Logo Beehexa và logo của từng sản phẩm, cùng các luật và file để dùng trên web, ấn phẩm in và trong sản phẩm.",
1563
+ "order": 12,
1564
+ "sidebarLabel": "Tổng quan",
1565
+ "audience": "web, in ấn, giao diện sản phẩm",
1566
+ "owner": "Brand",
1567
+ "updated": "2026-10-23"
1568
+ }
1569
+ },
1570
+ {
1571
+ "id": "vi/foundations/styles/logos/placement-and-containers",
1572
+ "path": "src/content-vi/foundations/styles/logos/placement-and-containers.mdx",
1573
+ "documentPath": "docs/src/content-vi/foundations/styles/logos/placement-and-containers.mdx",
1574
+ "locale": "vi",
1575
+ "kind": "guidance",
1576
+ "title": "Vị trí và khung chứa",
1577
+ "status": "active",
1578
+ "releasePhase": null,
1579
+ "planned": [],
1580
+ "body": "import LogoInUse from '../../../../components/logos/LogoInUse.astro';\nimport LogoContainer from '../../../../components/logos/LogoContainer.astro';\nimport LogoMistakes from '../../../../components/logos/LogoMistakes.astro';\n\n## Trên website\n\n- Đặt lockup ở bên trái header và link về trang chủ.\n- Cỡ: icon 24–32 px trong header cao 56–64 px. Site này dùng icon 24 px trong header 56 px.\n- Giữ [vùng trống](/vi/foundations/styles/logos/using-the-logo/#vùng-trống) và làm theo phần [hiển thị sắc nét](/vi/foundations/styles/logos/using-the-logo/#hiển-thị-sắc-nét).\n- Bên trong HexaSync, dùng logo HexaSync. Xem [Logo sản phẩm](/vi/foundations/styles/logos/product-logos/).\n\n<LogoInUse only={['header', 'app']} />\n\n## Trong tài liệu và slide\n\n- Đặt lockup ở góc trên bên trái trang đầu hoặc slide bìa, giữ đủ vùng trống.\n- In rộng tối thiểu 25 mm.\n- Chọn bản màu theo nền: bản 1 trên giấy và slide nền sáng, bản 2 trên slide nền tối.\n\n<LogoInUse only={['document', 'slide']} />\n\n## Trong email\n\n- Đặt lockup dưới tên người gửi, dạng PNG xuất ở 2×, rộng tối thiểu 100 px. Nhiều ứng dụng email không hiển thị SVG.\n- Dùng alt text “Beehexa”, để chữ ký vẫn đọc được khi ảnh bị chặn.\n\n<LogoInUse only={['email']} />\n\n## Trên ấn phẩm in\n\n- Danh thiếp: lockup ở giữa mặt trước, bản 2 trên nền xám ghi; tên và thông tin ở mặt sau, nền trắng.\n- Lockup rộng tối thiểu 25 mm, và vùng trống không bị nếp gấp, đường cắt hay lỗ đục lấn vào.\n\n<LogoInUse only={['card']} />\n\n## Trên ảnh và nền màu thương hiệu\n\n- Trên ảnh, dùng bản 3 (trắng) ở vùng ảnh ít chi tiết, thường là một góc, giữ vùng trống. Không đặt ô nền sau logo để cứu một bức ảnh rối: hãy chọn khung cắt khác.\n- Trên nền vàng thương hiệu, dùng bản 4 (xám ghi).\n\n<LogoInUse only={['photo', 'yellow']} />\n\n## Cạnh logo đối tác\n\nKhi Beehexa xuất hiện cùng đối tác, ví dụ trên trang tích hợp, dùng lockup ngang. Hai logo có cùng trọng lượng thị giác, mỗi logo giữ vùng trống riêng, ngăn nhau bằng một vạch dọc mảnh.\n\n<LogoInUse only={['partner']} />\n\n## Icon trong ô: luật ô 3 cạnh\n\nIcon ứng dụng và avatar đặt icon trong một ô, và nền tảng sẽ cắt ô đó thành hình vuông bo góc hoặc hình tròn. Mép ô là ranh giới, nên icon dùng luật riêng, đo bằng cạnh lục giác:\n\n- Ô rộng 3 cạnh.\n- Icon cao 2 cạnh, bằng hai phần ba ô, nằm giữa.\n- Phía trên và phía dưới còn nửa cạnh.\n\n<LogoContainer />\n\n| File | Ô | Chiều cao icon | Nền |\n|---|---|---|---|\n| apple-touch-icon.png | 180 px | 120 px | Xám ghi #2B2A28 |\n| icon-192.png, icon-512.png | 192 và 512 px | 128 và 341 px | Xám ghi #2B2A28 |\n| icon-maskable-512.png | 512 px | 341 px, nằm trong vòng an toàn 80% | Xám ghi #2B2A28 |\n| avatar-800.png | 800 px | 533 px | Xám ghi #2B2A28 |\n\nIcon vàng trên ô xám ghi: giữ màu thương hiệu và đạt 7.76 : 1.\n\n## Favicon\n\nFavicon là icon đứng riêng, màu vàng, nền trong suốt, phủ kín ô vuông của nó.\n\n| File | Cỡ | Ghi chú |\n|---|---|---|\n| favicon.svg | Mọi cỡ | Trình duyệt hiện nay dùng file này. Cạnh mịn, vẽ từ icon gốc. |\n| favicon.ico | 16, 32 và 48 px | Cho trình duyệt và công cụ cũ. Mỗi cỡ được vẽ to rồi thu nhỏ, nên cạnh vẫn mịn. |\n\n```html\n<link rel=\"icon\" href=\"/favicon.ico\" sizes=\"48x48\">\n<link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\">\n<link rel=\"apple-touch-icon\" href=\"/apple-touch-icon.png\">\n<link rel=\"manifest\" href=\"/site.webmanifest\">\n```\n\n<LogoInUse only={['tab', 'avatar']} />\n\n## Lỗi hay gặp\n\n<LogoMistakes />\n",
1581
+ "raw": "---\ntitle: Vị trí và khung chứa\ndescription: Logo đặt ở đâu trên website, trong tài liệu, email, ấn phẩm in, trên ảnh và cạnh đối tác; icon nằm thế nào trong icon ứng dụng, avatar và favicon; và các lỗi cần tránh.\norder: 2\naudience: web, giao diện sản phẩm, tài liệu\nowner: Brand\nupdated: 2026-10-23\n---\nimport LogoInUse from '../../../../components/logos/LogoInUse.astro';\nimport LogoContainer from '../../../../components/logos/LogoContainer.astro';\nimport LogoMistakes from '../../../../components/logos/LogoMistakes.astro';\n\n## Trên website\n\n- Đặt lockup ở bên trái header và link về trang chủ.\n- Cỡ: icon 24–32 px trong header cao 56–64 px. Site này dùng icon 24 px trong header 56 px.\n- Giữ [vùng trống](/vi/foundations/styles/logos/using-the-logo/#vùng-trống) và làm theo phần [hiển thị sắc nét](/vi/foundations/styles/logos/using-the-logo/#hiển-thị-sắc-nét).\n- Bên trong HexaSync, dùng logo HexaSync. Xem [Logo sản phẩm](/vi/foundations/styles/logos/product-logos/).\n\n<LogoInUse only={['header', 'app']} />\n\n## Trong tài liệu và slide\n\n- Đặt lockup ở góc trên bên trái trang đầu hoặc slide bìa, giữ đủ vùng trống.\n- In rộng tối thiểu 25 mm.\n- Chọn bản màu theo nền: bản 1 trên giấy và slide nền sáng, bản 2 trên slide nền tối.\n\n<LogoInUse only={['document', 'slide']} />\n\n## Trong email\n\n- Đặt lockup dưới tên người gửi, dạng PNG xuất ở 2×, rộng tối thiểu 100 px. Nhiều ứng dụng email không hiển thị SVG.\n- Dùng alt text “Beehexa”, để chữ ký vẫn đọc được khi ảnh bị chặn.\n\n<LogoInUse only={['email']} />\n\n## Trên ấn phẩm in\n\n- Danh thiếp: lockup ở giữa mặt trước, bản 2 trên nền xám ghi; tên và thông tin ở mặt sau, nền trắng.\n- Lockup rộng tối thiểu 25 mm, và vùng trống không bị nếp gấp, đường cắt hay lỗ đục lấn vào.\n\n<LogoInUse only={['card']} />\n\n## Trên ảnh và nền màu thương hiệu\n\n- Trên ảnh, dùng bản 3 (trắng) ở vùng ảnh ít chi tiết, thường là một góc, giữ vùng trống. Không đặt ô nền sau logo để cứu một bức ảnh rối: hãy chọn khung cắt khác.\n- Trên nền vàng thương hiệu, dùng bản 4 (xám ghi).\n\n<LogoInUse only={['photo', 'yellow']} />\n\n## Cạnh logo đối tác\n\nKhi Beehexa xuất hiện cùng đối tác, ví dụ trên trang tích hợp, dùng lockup ngang. Hai logo có cùng trọng lượng thị giác, mỗi logo giữ vùng trống riêng, ngăn nhau bằng một vạch dọc mảnh.\n\n<LogoInUse only={['partner']} />\n\n## Icon trong ô: luật ô 3 cạnh\n\nIcon ứng dụng và avatar đặt icon trong một ô, và nền tảng sẽ cắt ô đó thành hình vuông bo góc hoặc hình tròn. Mép ô là ranh giới, nên icon dùng luật riêng, đo bằng cạnh lục giác:\n\n- Ô rộng 3 cạnh.\n- Icon cao 2 cạnh, bằng hai phần ba ô, nằm giữa.\n- Phía trên và phía dưới còn nửa cạnh.\n\n<LogoContainer />\n\n| File | Ô | Chiều cao icon | Nền |\n|---|---|---|---|\n| apple-touch-icon.png | 180 px | 120 px | Xám ghi #2B2A28 |\n| icon-192.png, icon-512.png | 192 và 512 px | 128 và 341 px | Xám ghi #2B2A28 |\n| icon-maskable-512.png | 512 px | 341 px, nằm trong vòng an toàn 80% | Xám ghi #2B2A28 |\n| avatar-800.png | 800 px | 533 px | Xám ghi #2B2A28 |\n\nIcon vàng trên ô xám ghi: giữ màu thương hiệu và đạt 7.76 : 1.\n\n## Favicon\n\nFavicon là icon đứng riêng, màu vàng, nền trong suốt, phủ kín ô vuông của nó.\n\n| File | Cỡ | Ghi chú |\n|---|---|---|\n| favicon.svg | Mọi cỡ | Trình duyệt hiện nay dùng file này. Cạnh mịn, vẽ từ icon gốc. |\n| favicon.ico | 16, 32 và 48 px | Cho trình duyệt và công cụ cũ. Mỗi cỡ được vẽ to rồi thu nhỏ, nên cạnh vẫn mịn. |\n\n```html\n<link rel=\"icon\" href=\"/favicon.ico\" sizes=\"48x48\">\n<link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\">\n<link rel=\"apple-touch-icon\" href=\"/apple-touch-icon.png\">\n<link rel=\"manifest\" href=\"/site.webmanifest\">\n```\n\n<LogoInUse only={['tab', 'avatar']} />\n\n## Lỗi hay gặp\n\n<LogoMistakes />\n",
1582
+ "frontmatter": {
1583
+ "title": "Vị trí và khung chứa",
1584
+ "description": "Logo đặt ở đâu trên website, trong tài liệu, email, ấn phẩm in, trên ảnh và cạnh đối tác; icon nằm thế nào trong icon ứng dụng, avatar và favicon; và các lỗi cần tránh.",
1585
+ "order": 2,
1586
+ "audience": "web, giao diện sản phẩm, tài liệu",
1587
+ "owner": "Brand",
1588
+ "updated": "2026-10-23"
1589
+ }
1590
+ },
1591
+ {
1592
+ "id": "vi/foundations/styles/logos/product-logos",
1593
+ "path": "src/content-vi/foundations/styles/logos/product-logos.mdx",
1594
+ "documentPath": "docs/src/content-vi/foundations/styles/logos/product-logos.mdx",
1595
+ "locale": "vi",
1596
+ "kind": "guidance",
1597
+ "title": "Logo sản phẩm",
1598
+ "status": "active",
1599
+ "releasePhase": null,
1600
+ "planned": [],
1601
+ "body": "import LogoPair from '../../../../components/logos/LogoPair.astro';\nimport LogoInUse from '../../../../components/logos/LogoInUse.astro';\n\n## HexaSync\n\n<LogoPair kind=\"hexasync\" name=\"HexaSync\" />\n\nLockup HexaSync được dựng đúng như lockup công ty: cùng icon, tên sản phẩm bằng Inter Display cùng độ đậm 500, cùng khoảng cách và cùng [vùng trống](/vi/foundations/styles/logos/using-the-logo/#vùng-trống). Đuôi chữ “y” thò xuống dưới icon.\n\nMọi luật trên trang [Cách dùng logo](/vi/foundations/styles/logos/using-the-logo/) đều áp dụng: bốn bản màu, cỡ tối thiểu, các lỗi dùng sai.\n\n## Logo nào dùng ở đâu\n\n| Nơi dùng | Logo |\n|---|---|\n| Bên trong ứng dụng web HexaSync | HexaSync |\n| Trang sản phẩm HexaSync, trang connector và marketplace | HexaSync |\n| Website công ty, hợp đồng, hoá đơn, tuyển dụng, mạng xã hội | beehexa |\n| Tài liệu nói về nhiều sản phẩm | beehexa |\n\nKhông đặt logo beehexa và HexaSync cạnh nhau: hai logo dùng chung icon, đặt chung trông như lỗi. Chọn một theo ngữ cảnh.\n\n## HexaSync khi dùng thực tế\n\n- **Thanh ứng dụng:** bản nền tối trên thanh xám ghi, ở bên trái, link về trang chủ sản phẩm.\n- **Màn hình đăng nhập và màn hình trống:** bản màu, đặt giữa, phía trên nội dung.\n- **Marketplace và trang connector:** ô icon ứng dụng, cạnh đó là tên “HexaSync” viết bằng chữ. Các trang này cắt ảnh thành ô vuông, nên lockup không vừa.\n\n<LogoInUse only={['app', 'login', 'marketplace']} />\n\n## Icon và khung chứa\n\nSản phẩm không có icon riêng. HexaSync dùng file icon Beehexa cho favicon, icon ứng dụng và avatar, dựng theo [luật ô 3 cạnh](/vi/foundations/styles/logos/placement-and-containers/#icon-trong-ô-luật-ô-3-cạnh). Tên sản phẩm nằm ở tên ứng dụng, tiêu đề trang và alt text, không nằm trong icon.\n\n## Cách viết tên\n\n- Logo công ty viết thường: “beehexa”.\n- Logo sản phẩm giữ cách viết của sản phẩm: “HexaSync”, viết liền, H và S viết hoa.\n\n## Logo cho sản phẩm mới\n\nHiện mọi lockup sản phẩm đều dùng icon Beehexa với tên sản phẩm bên cạnh. Để có logo cho sản phẩm mới:\n\n1. Gửi cho người phụ trách Brand qua [hello@beehexa.com](mailto:hello@beehexa.com?subject=New%20product%20logo), kèm tên sản phẩm đúng như cách sẽ viết.\n2. Brand dựng lockup từ file gốc: icon, tên bằng Inter Display đã chuyển thành nét vẽ, đúng độ đậm đã chọn, cùng khoảng cách.\n3. File được thêm vào [gói tải về](/vi/foundations/styles/logos/downloads-and-terms/).\n\nKhông tự vẽ logo sản phẩm, và không tạo icon riêng cho một sản phẩm.\n",
1602
+ "raw": "---\ntitle: Logo sản phẩm\ndescription: Logo các sản phẩm của Beehexa, bắt đầu từ HexaSync, và khi nào dùng chúng thay cho logo công ty.\norder: 3\naudience: sản phẩm, marketing\nowner: Brand\nupdated: 2026-10-23\n---\nimport LogoPair from '../../../../components/logos/LogoPair.astro';\nimport LogoInUse from '../../../../components/logos/LogoInUse.astro';\n\n## HexaSync\n\n<LogoPair kind=\"hexasync\" name=\"HexaSync\" />\n\nLockup HexaSync được dựng đúng như lockup công ty: cùng icon, tên sản phẩm bằng Inter Display cùng độ đậm 500, cùng khoảng cách và cùng [vùng trống](/vi/foundations/styles/logos/using-the-logo/#vùng-trống). Đuôi chữ “y” thò xuống dưới icon.\n\nMọi luật trên trang [Cách dùng logo](/vi/foundations/styles/logos/using-the-logo/) đều áp dụng: bốn bản màu, cỡ tối thiểu, các lỗi dùng sai.\n\n## Logo nào dùng ở đâu\n\n| Nơi dùng | Logo |\n|---|---|\n| Bên trong ứng dụng web HexaSync | HexaSync |\n| Trang sản phẩm HexaSync, trang connector và marketplace | HexaSync |\n| Website công ty, hợp đồng, hoá đơn, tuyển dụng, mạng xã hội | beehexa |\n| Tài liệu nói về nhiều sản phẩm | beehexa |\n\nKhông đặt logo beehexa và HexaSync cạnh nhau: hai logo dùng chung icon, đặt chung trông như lỗi. Chọn một theo ngữ cảnh.\n\n## HexaSync khi dùng thực tế\n\n- **Thanh ứng dụng:** bản nền tối trên thanh xám ghi, ở bên trái, link về trang chủ sản phẩm.\n- **Màn hình đăng nhập và màn hình trống:** bản màu, đặt giữa, phía trên nội dung.\n- **Marketplace và trang connector:** ô icon ứng dụng, cạnh đó là tên “HexaSync” viết bằng chữ. Các trang này cắt ảnh thành ô vuông, nên lockup không vừa.\n\n<LogoInUse only={['app', 'login', 'marketplace']} />\n\n## Icon và khung chứa\n\nSản phẩm không có icon riêng. HexaSync dùng file icon Beehexa cho favicon, icon ứng dụng và avatar, dựng theo [luật ô 3 cạnh](/vi/foundations/styles/logos/placement-and-containers/#icon-trong-ô-luật-ô-3-cạnh). Tên sản phẩm nằm ở tên ứng dụng, tiêu đề trang và alt text, không nằm trong icon.\n\n## Cách viết tên\n\n- Logo công ty viết thường: “beehexa”.\n- Logo sản phẩm giữ cách viết của sản phẩm: “HexaSync”, viết liền, H và S viết hoa.\n\n## Logo cho sản phẩm mới\n\nHiện mọi lockup sản phẩm đều dùng icon Beehexa với tên sản phẩm bên cạnh. Để có logo cho sản phẩm mới:\n\n1. Gửi cho người phụ trách Brand qua [hello@beehexa.com](mailto:hello@beehexa.com?subject=New%20product%20logo), kèm tên sản phẩm đúng như cách sẽ viết.\n2. Brand dựng lockup từ file gốc: icon, tên bằng Inter Display đã chuyển thành nét vẽ, đúng độ đậm đã chọn, cùng khoảng cách.\n3. File được thêm vào [gói tải về](/vi/foundations/styles/logos/downloads-and-terms/).\n\nKhông tự vẽ logo sản phẩm, và không tạo icon riêng cho một sản phẩm.\n",
1603
+ "frontmatter": {
1604
+ "title": "Logo sản phẩm",
1605
+ "description": "Logo các sản phẩm của Beehexa, bắt đầu từ HexaSync, và khi nào dùng chúng thay cho logo công ty.",
1606
+ "order": 3,
1607
+ "audience": "sản phẩm, marketing",
1608
+ "owner": "Brand",
1609
+ "updated": "2026-10-23"
1610
+ }
1611
+ },
1612
+ {
1613
+ "id": "vi/foundations/styles/logos/using-the-logo",
1614
+ "path": "src/content-vi/foundations/styles/logos/using-the-logo.mdx",
1615
+ "documentPath": "docs/src/content-vi/foundations/styles/logos/using-the-logo.mdx",
1616
+ "locale": "vi",
1617
+ "kind": "guidance",
1618
+ "title": "Cách dùng logo",
1619
+ "status": "active",
1620
+ "releasePhase": null,
1621
+ "planned": [],
1622
+ "body": "import LogoColourVersions from '../../../../components/logos/LogoColourVersions.astro';\nimport LogoClearSpace from '../../../../components/logos/LogoClearSpace.astro';\nimport LogoMinSize from '../../../../components/logos/LogoMinSize.astro';\nimport LogoMisuse from '../../../../components/logos/LogoMisuse.astro';\n\n## Bản màu\n\nBốn bản, làm từ ba màu: vàng #FCB017, xám ghi #2B2A28 và trắng. Hãy chọn bản có độ tương phản cao nhất với nền của bạn.\n\n<LogoColourVersions />\n\nWCAG không đặt mức tương phản tối thiểu cho logo (Understanding 1.4.3 và 1.4.11), nhưng logo không ai nhìn rõ thì không ai nhớ. Chúng tôi đặt mỗi bản ở nơi nó nổi bật, nhắm tới mức 3 : 1 mà WCAG đặt cho các hình đồ hoạ khác. Đó là lý do icon vàng không đứng riêng trên nền sáng; ngoại lệ duy nhất là favicon (xem [icon đứng riêng](#icon-đứng-riêng)).\n\n## Vùng trống\n\nGiữ một lề trống rộng **x** ở cả bốn phía: không chữ, không hình, không mép trang lấn vào. x là x-height của wordmark, tức chiều cao chữ thường, và bằng đúng một cạnh của lục giác. Vì x là một phần của logo, lề trống to nhỏ theo logo.\n\n<LogoClearSpace />\n\nFile gốc đã có sẵn lề này trong artboard. Căn theo artboard, không căn theo hình vẽ, là đủ vùng trống.\n\n## Cỡ tối thiểu\n\n<LogoMinSize />\n\n| | Màn hình | In |\n|---|---|---|\n| Lockup, bề rộng | 100 px | 25 mm |\n| Icon đứng riêng, chiều cao | 16 px | 6 mm |\n\n## Hiển thị sắc nét\n\nCạnh của icon nghiêng 30°, nên trên màn hình 100% (1×) chúng hiện răng cưa khi logo rơi vào giữa hai pixel.\n\n- Đặt chiều cao và vị trí logo bằng số nguyên pixel.\n- Trên màn hình, hiển thị logo bằng ảnh PNG xuất ở gấp 3 lần cỡ hiển thị, không dùng SVG. Trình duyệt thu nhỏ ảnh lớn, làm mềm cạnh một chút và giấu răng cưa. Mọi logo trên site này, kể cả header, đều làm như vậy.\n- Cách làm: xuất file SVG gốc từ Figma, Illustrator hoặc Inkscape ở gấp 3 lần cỡ cần dùng. Cần logo cao 30 px thì xuất ảnh cao 90 px rồi hiển thị ở 30 px. Ảnh lớn hơn nhiều vẫn dùng được, nhưng nặng hơn khi tải và mỗi trình duyệt thu nhỏ hơi khác nhau.\n- Không vẽ lại icon cho khớp lưới pixel: làm vậy sẽ hỏng lục giác đều và góc 30°.\n- Trong tài liệu, slide và bản in, dùng SVG.\n\n## Icon đứng riêng\n\nChỉ dùng icon không có wordmark khi tên đã có trên màn hình, hoặc khi không đủ chỗ cho lockup: favicon, icon ứng dụng, avatar và giao diện sản phẩm cỡ nhỏ.\n\n| Nền | Màu icon |\n|---|---|\n| Tối | Vàng |\n| Sáng | Xám ghi, hoặc vàng trên ô xám ghi |\n| Ảnh hoặc màu đậm | Trắng |\n\nVàng trên trắng chỉ đạt 1.85 : 1. Đi cùng wordmark thì không sao, vì chữ xám ghi gánh phần đọc; đứng riêng thì icon gần như biến mất. Ngoại lệ duy nhất là favicon: dùng màu vàng để tab trình duyệt có màu thương hiệu.\n\n## Dùng sai\n\n<LogoMisuse />\n\n## Alt text và link\n\n- Logo đứng riêng: alt text là “Beehexa”, hoặc tên sản phẩm như “HexaSync”. Không thêm chữ “logo”.\n- Logo là link về trang chủ: “Beehexa – Trang chủ”, để người dùng biết link dẫn đi đâu.\n- Khi tên đã được viết ngay cạnh logo, logo chỉ để trang trí: để alt text rỗng.\n- Logo là link thì cần có viền focus nhìn thấy được, như mọi link khác. WCAG chỉ miễn yêu cầu về màu của logo, không miễn cho phần điều khiển bao quanh nó.\n",
1623
+ "raw": "---\ntitle: Cách dùng logo\ndescription: Bản màu, nền, vùng trống, cỡ tối thiểu, icon đứng riêng và những điều không được làm.\norder: 1\naudience: mọi người đặt logo\nowner: Brand\nupdated: 2026-10-23\n---\nimport LogoColourVersions from '../../../../components/logos/LogoColourVersions.astro';\nimport LogoClearSpace from '../../../../components/logos/LogoClearSpace.astro';\nimport LogoMinSize from '../../../../components/logos/LogoMinSize.astro';\nimport LogoMisuse from '../../../../components/logos/LogoMisuse.astro';\n\n## Bản màu\n\nBốn bản, làm từ ba màu: vàng #FCB017, xám ghi #2B2A28 và trắng. Hãy chọn bản có độ tương phản cao nhất với nền của bạn.\n\n<LogoColourVersions />\n\nWCAG không đặt mức tương phản tối thiểu cho logo (Understanding 1.4.3 và 1.4.11), nhưng logo không ai nhìn rõ thì không ai nhớ. Chúng tôi đặt mỗi bản ở nơi nó nổi bật, nhắm tới mức 3 : 1 mà WCAG đặt cho các hình đồ hoạ khác. Đó là lý do icon vàng không đứng riêng trên nền sáng; ngoại lệ duy nhất là favicon (xem [icon đứng riêng](#icon-đứng-riêng)).\n\n## Vùng trống\n\nGiữ một lề trống rộng **x** ở cả bốn phía: không chữ, không hình, không mép trang lấn vào. x là x-height của wordmark, tức chiều cao chữ thường, và bằng đúng một cạnh của lục giác. Vì x là một phần của logo, lề trống to nhỏ theo logo.\n\n<LogoClearSpace />\n\nFile gốc đã có sẵn lề này trong artboard. Căn theo artboard, không căn theo hình vẽ, là đủ vùng trống.\n\n## Cỡ tối thiểu\n\n<LogoMinSize />\n\n| | Màn hình | In |\n|---|---|---|\n| Lockup, bề rộng | 100 px | 25 mm |\n| Icon đứng riêng, chiều cao | 16 px | 6 mm |\n\n## Hiển thị sắc nét\n\nCạnh của icon nghiêng 30°, nên trên màn hình 100% (1×) chúng hiện răng cưa khi logo rơi vào giữa hai pixel.\n\n- Đặt chiều cao và vị trí logo bằng số nguyên pixel.\n- Trên màn hình, hiển thị logo bằng ảnh PNG xuất ở gấp 3 lần cỡ hiển thị, không dùng SVG. Trình duyệt thu nhỏ ảnh lớn, làm mềm cạnh một chút và giấu răng cưa. Mọi logo trên site này, kể cả header, đều làm như vậy.\n- Cách làm: xuất file SVG gốc từ Figma, Illustrator hoặc Inkscape ở gấp 3 lần cỡ cần dùng. Cần logo cao 30 px thì xuất ảnh cao 90 px rồi hiển thị ở 30 px. Ảnh lớn hơn nhiều vẫn dùng được, nhưng nặng hơn khi tải và mỗi trình duyệt thu nhỏ hơi khác nhau.\n- Không vẽ lại icon cho khớp lưới pixel: làm vậy sẽ hỏng lục giác đều và góc 30°.\n- Trong tài liệu, slide và bản in, dùng SVG.\n\n## Icon đứng riêng\n\nChỉ dùng icon không có wordmark khi tên đã có trên màn hình, hoặc khi không đủ chỗ cho lockup: favicon, icon ứng dụng, avatar và giao diện sản phẩm cỡ nhỏ.\n\n| Nền | Màu icon |\n|---|---|\n| Tối | Vàng |\n| Sáng | Xám ghi, hoặc vàng trên ô xám ghi |\n| Ảnh hoặc màu đậm | Trắng |\n\nVàng trên trắng chỉ đạt 1.85 : 1. Đi cùng wordmark thì không sao, vì chữ xám ghi gánh phần đọc; đứng riêng thì icon gần như biến mất. Ngoại lệ duy nhất là favicon: dùng màu vàng để tab trình duyệt có màu thương hiệu.\n\n## Dùng sai\n\n<LogoMisuse />\n\n## Alt text và link\n\n- Logo đứng riêng: alt text là “Beehexa”, hoặc tên sản phẩm như “HexaSync”. Không thêm chữ “logo”.\n- Logo là link về trang chủ: “Beehexa – Trang chủ”, để người dùng biết link dẫn đi đâu.\n- Khi tên đã được viết ngay cạnh logo, logo chỉ để trang trí: để alt text rỗng.\n- Logo là link thì cần có viền focus nhìn thấy được, như mọi link khác. WCAG chỉ miễn yêu cầu về màu của logo, không miễn cho phần điều khiển bao quanh nó.\n",
1624
+ "frontmatter": {
1625
+ "title": "Cách dùng logo",
1626
+ "description": "Bản màu, nền, vùng trống, cỡ tối thiểu, icon đứng riêng và những điều không được làm.",
1627
+ "order": 1,
1628
+ "audience": "mọi người đặt logo",
1629
+ "owner": "Brand",
1630
+ "updated": "2026-10-23"
1631
+ }
1632
+ },
1633
+ {
1634
+ "id": "vi/foundations/styles/opacity",
1635
+ "path": "src/content-vi/foundations/styles/opacity.mdx",
1636
+ "documentPath": "docs/src/content-vi/foundations/styles/opacity.mdx",
1637
+ "locale": "vi",
1638
+ "kind": "guidance",
1639
+ "title": "Độ mờ",
1640
+ "status": "planned",
1641
+ "releasePhase": null,
1642
+ "planned": [
1643
+ "Chỗ được dùng độ trong suốt: lớp phủ sau dialog, lớp phủ trên ảnh",
1644
+ "Vì sao hover, pressed và disabled dùng bậc màu, không dùng độ mờ",
1645
+ "Token độ mờ, nếu cần"
1646
+ ],
1647
+ "body": "",
1648
+ "raw": "---\ntitle: \"Độ mờ\"\ndescription: \"Khi nào được dùng độ trong suốt, và vì sao trạng thái và control disabled dùng màu thay vì độ mờ.\"\norder: 10.5\nplanned:\n - \"Chỗ được dùng độ trong suốt: lớp phủ sau dialog, lớp phủ trên ảnh\"\n - \"Vì sao hover, pressed và disabled dùng bậc màu, không dùng độ mờ\"\n - \"Token độ mờ, nếu cần\"\n---\n",
1649
+ "frontmatter": {
1650
+ "title": "Độ mờ",
1651
+ "description": "Khi nào được dùng độ trong suốt, và vì sao trạng thái và control disabled dùng màu thay vì độ mờ.",
1652
+ "order": 10.5,
1653
+ "planned": [
1654
+ "Chỗ được dùng độ trong suốt: lớp phủ sau dialog, lớp phủ trên ảnh",
1655
+ "Vì sao hover, pressed và disabled dùng bậc màu, không dùng độ mờ",
1656
+ "Token độ mờ, nếu cần"
1657
+ ]
1658
+ }
1659
+ },
1660
+ {
1661
+ "id": "vi/foundations/styles/radius",
1662
+ "path": "src/content-vi/foundations/styles/radius.mdx",
1663
+ "documentPath": "docs/src/content-vi/foundations/styles/radius.mdx",
1664
+ "locale": "vi",
1665
+ "kind": "guidance",
1666
+ "title": "Bo góc",
1667
+ "status": "active",
1668
+ "releasePhase": null,
1669
+ "planned": [],
1670
+ "body": "import ShapeDemo from '../../../components/ShapeDemo.astro';\nimport TokenTable from '../../../components/TokenTable.astro';\n\n**Mọi góc bo đều là token radius. Chọn bậc theo loại phần tử, rồi kiểm lại với khung chứa nó.**\n\n## Thang bo góc\n\nTám bậc. Số trong tên token theo thang khoảng cách: `radius.100` là 8 px, giống `space.100`.\n\n<ShapeDemo kind=\"radius-scale\" />\n\n## Ví dụ\n\n### `radius.0` · vuông\n\nNhững cạnh chạm mép màn hình: header của trang, bảng tràn hết chiều ngang và panel chạy sát mép.\n\n<ShapeDemo kind=\"radius-use\" item=\"0\" />\n\n### `radius.050` · 4 px\n\nPhần tử nhỏ: checkbox, tag, badge và các mục trong menu.\n\n<ShapeDemo kind=\"radius-use\" item=\"050\" />\n\n### `radius.100` · 8 px\n\nControl và các bề mặt nhỏ mở ra từ control: button, ô nhập, select, menu, popover, tooltip và alert. Ô nhập và button luôn dùng chung giá trị này.\n\n<ShapeDemo kind=\"radius-use\" item=\"100\" />\n\n### `radius.150` · 12 px\n\nCard, và nhóm control có padding 4 px, như segmented control.\n\n<ShapeDemo kind=\"radius-use\" item=\"150\" />\n\n### `radius.200` · 16 px\n\nDialog và drawer, và nhóm control có padding 8 px.\n\n<ShapeDemo kind=\"radius-use\" item=\"200\" />\n\n### `radius.full` · viên thuốc\n\nAvatar, switch và chip trạng thái dạng viên thuốc.\n\n<ShapeDemo kind=\"radius-use\" item=\"full\" />\n\n## Hình nằm trong hình\n\n**Radius bên trong = radius bên ngoài − padding.** Dùng khi padding nhỏ hơn radius bên ngoài. Khi padding lớn hơn, phần tử bên trong giữ radius của nó, miễn là không lớn hơn radius bên ngoài.\n\n<ShapeDemo kind=\"nesting\" />\n\n`radius.025` và `radius.075` chỉ dùng cho các trường hợp này. Không component nào dùng chúng mặc định.\n\nTheo luật khoảng cách, kết quả luôn là một bậc trong thang: 2 px không bao giờ là padding, và 6 px chỉ là padding bên trong component.\n\nKhi nội dung nằm sát mép trong một hộp có viền 1 px, cắt nó bằng `overflow: hidden`. Không tạo giá trị radius − 1.\n\n## Focus ring\n\nFocus ring nằm cách phần tử 2 px về phía ngoài, và trình duyệt tự bo nó theo góc: button 8 px có ring 10 px. Không cần token radius. Xem [Viền](/vi/foundations/styles/border/) cho chính ring.\n\n<ShapeDemo kind=\"focus-radius\" />\n\n## Nên và không nên\n\n<ShapeDemo kind=\"dodont\" item=\"nested\" />\n<ShapeDemo kind=\"dodont\" item=\"controls\" />\n<ShapeDemo kind=\"dodont\" item=\"corners\" />\n\n## Code\n\n```css\n.card {\n border-radius: var(--bh-radius-150);\n padding: var(--bh-space-050);\n}\n.card img {\n border-radius: var(--bh-radius-100); /* 12 − 4 = 8 */\n}\n```\n\n## Token\n\n<TokenTable prefix=\"radius\" />\n\n## Liên quan\n\n- [Viền](/vi/foundations/styles/border/): độ dày viền, thanh đang chọn và focus ring.\n- [Khoảng cách](/vi/foundations/styles/spacing/): các giá trị padding dùng trong quy tắc lồng nhau.\n",
1671
+ "raw": "---\ntitle: Bo góc\ndescription: Tám bậc bo góc, phần tử nào dùng bậc nào, và cách bo góc cho hình nằm trong hình khác.\norder: 6\n---\nimport ShapeDemo from '../../../components/ShapeDemo.astro';\nimport TokenTable from '../../../components/TokenTable.astro';\n\n**Mọi góc bo đều là token radius. Chọn bậc theo loại phần tử, rồi kiểm lại với khung chứa nó.**\n\n## Thang bo góc\n\nTám bậc. Số trong tên token theo thang khoảng cách: `radius.100` là 8 px, giống `space.100`.\n\n<ShapeDemo kind=\"radius-scale\" />\n\n## Ví dụ\n\n### `radius.0` · vuông\n\nNhững cạnh chạm mép màn hình: header của trang, bảng tràn hết chiều ngang và panel chạy sát mép.\n\n<ShapeDemo kind=\"radius-use\" item=\"0\" />\n\n### `radius.050` · 4 px\n\nPhần tử nhỏ: checkbox, tag, badge và các mục trong menu.\n\n<ShapeDemo kind=\"radius-use\" item=\"050\" />\n\n### `radius.100` · 8 px\n\nControl và các bề mặt nhỏ mở ra từ control: button, ô nhập, select, menu, popover, tooltip và alert. Ô nhập và button luôn dùng chung giá trị này.\n\n<ShapeDemo kind=\"radius-use\" item=\"100\" />\n\n### `radius.150` · 12 px\n\nCard, và nhóm control có padding 4 px, như segmented control.\n\n<ShapeDemo kind=\"radius-use\" item=\"150\" />\n\n### `radius.200` · 16 px\n\nDialog và drawer, và nhóm control có padding 8 px.\n\n<ShapeDemo kind=\"radius-use\" item=\"200\" />\n\n### `radius.full` · viên thuốc\n\nAvatar, switch và chip trạng thái dạng viên thuốc.\n\n<ShapeDemo kind=\"radius-use\" item=\"full\" />\n\n## Hình nằm trong hình\n\n**Radius bên trong = radius bên ngoài − padding.** Dùng khi padding nhỏ hơn radius bên ngoài. Khi padding lớn hơn, phần tử bên trong giữ radius của nó, miễn là không lớn hơn radius bên ngoài.\n\n<ShapeDemo kind=\"nesting\" />\n\n`radius.025` và `radius.075` chỉ dùng cho các trường hợp này. Không component nào dùng chúng mặc định.\n\nTheo luật khoảng cách, kết quả luôn là một bậc trong thang: 2 px không bao giờ là padding, và 6 px chỉ là padding bên trong component.\n\nKhi nội dung nằm sát mép trong một hộp có viền 1 px, cắt nó bằng `overflow: hidden`. Không tạo giá trị radius − 1.\n\n## Focus ring\n\nFocus ring nằm cách phần tử 2 px về phía ngoài, và trình duyệt tự bo nó theo góc: button 8 px có ring 10 px. Không cần token radius. Xem [Viền](/vi/foundations/styles/border/) cho chính ring.\n\n<ShapeDemo kind=\"focus-radius\" />\n\n## Nên và không nên\n\n<ShapeDemo kind=\"dodont\" item=\"nested\" />\n<ShapeDemo kind=\"dodont\" item=\"controls\" />\n<ShapeDemo kind=\"dodont\" item=\"corners\" />\n\n## Code\n\n```css\n.card {\n border-radius: var(--bh-radius-150);\n padding: var(--bh-space-050);\n}\n.card img {\n border-radius: var(--bh-radius-100); /* 12 − 4 = 8 */\n}\n```\n\n## Token\n\n<TokenTable prefix=\"radius\" />\n\n## Liên quan\n\n- [Viền](/vi/foundations/styles/border/): độ dày viền, thanh đang chọn và focus ring.\n- [Khoảng cách](/vi/foundations/styles/spacing/): các giá trị padding dùng trong quy tắc lồng nhau.\n",
1672
+ "frontmatter": {
1673
+ "title": "Bo góc",
1674
+ "description": "Tám bậc bo góc, phần tử nào dùng bậc nào, và cách bo góc cho hình nằm trong hình khác.",
1675
+ "order": 6
1676
+ }
1677
+ },
1678
+ {
1679
+ "id": "vi/foundations/styles/size-and-density",
1680
+ "path": "src/content-vi/foundations/styles/size-and-density.mdx",
1681
+ "documentPath": "docs/src/content-vi/foundations/styles/size-and-density.mdx",
1682
+ "locale": "vi",
1683
+ "kind": "guidance",
1684
+ "title": "Kích thước và mật độ",
1685
+ "status": "active",
1686
+ "releasePhase": null,
1687
+ "planned": [],
1688
+ "body": "import LayoutDemo from '../../../components/LayoutDemo.astro';\nimport TokenTable from '../../../components/TokenTable.astro';\n\n**Mọi control có ba chiều cao: 24, 32 và 40 px. Các control trên cùng một hàng dùng chung một chiều cao.**\n\nControl là những thứ người dùng bấm vào hoặc gõ vào: nút, ô nhập, select, segmented control và tab. Chiều cao cố định giữ một hàng control thẳng hàng, dù chữ bên trong dài ngắn thế nào.\n\n<LayoutDemo kind=\"controls\" />\n\n| Cỡ | Chiều cao | Ở đâu |\n|---|---|---|\n| Nhỏ | 24 px | Bảng dày đặc và thanh công cụ của chúng, bộ lọc, tag |\n| Mặc định | 32 px | Form, nút, header, thanh công cụ, mọi chỗ còn lại |\n| Lớn | 40 px | Trang đăng nhập và onboarding. Có thể dùng cho thao tác chính trên màn hình cảm ứng |\n\n- Giữ các control cùng chiều cao trên cùng một hàng. Nút 24 px cạnh ô nhập 32 px trông bị lệch.\n- Đặt chiều cao bằng token kích thước, không dùng padding. Chữ nằm giữa chiều cao.\n\n## Vùng bấm\n\n**Mọi control đều bấm được trong vùng ít nhất 24 × 24 px, và chạm được trong vùng 44 × 44 px trên màn hình cảm ứng.**\n\n- 24 px là cỡ vùng bấm tối thiểu của WCAG 2.2 (SC 2.5.8). Mọi chiều cao control đều đạt mức này.\n- Trên màn hình cảm ứng, giữ nguyên chiều cao nhìn thấy và mở rộng vùng phản hồi khi chạm lên ít nhất 44 × 44 px (`size.target.touch`).\n\n## Mật độ\n\n**Hiện Beehexa chỉ có một mật độ: mặc định.**\n\nMột mật độ nghĩa là mọi màn hình được thiết kế và kiểm tra ở một cỡ. Mật độ gọn có thể ra sau; nó sẽ giảm chiều cao control và khoảng cách cùng lúc, và màn hình nào dùng token sẽ không cần sửa gì.\n\nTrước khi có mật độ gọn, hãy làm bảng dày đặc bằng control và dòng cỡ nhỏ (24 px), không dùng token khoảng cách nhỏ hơn.\n\n## Token\n\n<TokenTable prefix=\"size\" />\n",
1689
+ "raw": "---\ntitle: Kích thước và mật độ\ndescription: Ba chiều cao control, cỡ vùng người dùng có thể bấm hoặc chạm, và mật độ của màn hình Beehexa.\norder: 5\n---\nimport LayoutDemo from '../../../components/LayoutDemo.astro';\nimport TokenTable from '../../../components/TokenTable.astro';\n\n**Mọi control có ba chiều cao: 24, 32 và 40 px. Các control trên cùng một hàng dùng chung một chiều cao.**\n\nControl là những thứ người dùng bấm vào hoặc gõ vào: nút, ô nhập, select, segmented control và tab. Chiều cao cố định giữ một hàng control thẳng hàng, dù chữ bên trong dài ngắn thế nào.\n\n<LayoutDemo kind=\"controls\" />\n\n| Cỡ | Chiều cao | Ở đâu |\n|---|---|---|\n| Nhỏ | 24 px | Bảng dày đặc và thanh công cụ của chúng, bộ lọc, tag |\n| Mặc định | 32 px | Form, nút, header, thanh công cụ, mọi chỗ còn lại |\n| Lớn | 40 px | Trang đăng nhập và onboarding. Có thể dùng cho thao tác chính trên màn hình cảm ứng |\n\n- Giữ các control cùng chiều cao trên cùng một hàng. Nút 24 px cạnh ô nhập 32 px trông bị lệch.\n- Đặt chiều cao bằng token kích thước, không dùng padding. Chữ nằm giữa chiều cao.\n\n## Vùng bấm\n\n**Mọi control đều bấm được trong vùng ít nhất 24 × 24 px, và chạm được trong vùng 44 × 44 px trên màn hình cảm ứng.**\n\n- 24 px là cỡ vùng bấm tối thiểu của WCAG 2.2 (SC 2.5.8). Mọi chiều cao control đều đạt mức này.\n- Trên màn hình cảm ứng, giữ nguyên chiều cao nhìn thấy và mở rộng vùng phản hồi khi chạm lên ít nhất 44 × 44 px (`size.target.touch`).\n\n## Mật độ\n\n**Hiện Beehexa chỉ có một mật độ: mặc định.**\n\nMột mật độ nghĩa là mọi màn hình được thiết kế và kiểm tra ở một cỡ. Mật độ gọn có thể ra sau; nó sẽ giảm chiều cao control và khoảng cách cùng lúc, và màn hình nào dùng token sẽ không cần sửa gì.\n\nTrước khi có mật độ gọn, hãy làm bảng dày đặc bằng control và dòng cỡ nhỏ (24 px), không dùng token khoảng cách nhỏ hơn.\n\n## Token\n\n<TokenTable prefix=\"size\" />\n",
1690
+ "frontmatter": {
1691
+ "title": "Kích thước và mật độ",
1692
+ "description": "Ba chiều cao control, cỡ vùng người dùng có thể bấm hoặc chạm, và mật độ của màn hình Beehexa.",
1693
+ "order": 5
1694
+ }
1695
+ },
1696
+ {
1697
+ "id": "vi/foundations/styles/spacing",
1698
+ "path": "src/content-vi/foundations/styles/spacing.mdx",
1699
+ "documentPath": "docs/src/content-vi/foundations/styles/spacing.mdx",
1700
+ "locale": "vi",
1701
+ "kind": "guidance",
1702
+ "title": "Khoảng cách",
1703
+ "status": "active",
1704
+ "releasePhase": null,
1705
+ "planned": [],
1706
+ "body": "import SpacingDemo from '../../../components/SpacingDemo.astro';\n\n**Mọi khoảng trống đều là một token khoảng cách. Chọn bậc theo mức độ hai thứ thuộc về nhau.**\n\nNhững thứ thuộc về nhau thì đặt gần nhau. Các nhóm khác nhau thì cách xa hơn. Người đọc nhận ra các nhóm trước khi đọc một chữ nào.\n\n<SpacingDemo kind=\"anatomy\" />\n\n## Thang khoảng cách\n\n**14 bậc trên nền 8 px. Mỗi bậc có việc riêng, ghi ngay bên cạnh.**\n\nSố trong tên token là phần trăm của 8 px: `space.100` là 8 px, `space.200` là 16 px, và `space.075` là 6 px. Các bậc càng lớn càng cách xa nhau, vì chênh 4 px thấy rõ giữa các khoảng nhỏ nhưng gần như vô hình giữa các khoảng lớn.\n\n<SpacingDemo kind=\"scale\" />\n\nKhi hai thứ có thể dùng một trong hai bậc, hãy hỏi chúng thuộc về nhau tới mức nào. Càng liên quan thì khoảng càng nhỏ.\n\n### Padding và gap\n\n<SpacingDemo kind=\"padding-gap\" />\n\n- Padding là khoảng trống bên trong một phần tử. Đặt trên chính phần tử đó.\n- Gap là khoảng trống giữa các phần tử. Đặt trên phần tử cha bằng `gap`, trong bố cục flex hoặc grid.\n- Tránh dùng margin giữa các phần tử cùng cấp. Margin cộng dồn ở chỗ hai phần tử gặp nhau và để thừa khoảng sau phần tử cuối; `gap` không gặp cả hai vấn đề đó.\n- Đo padding từ mép ngoài, tính cả viền. Ô nhập 32 px có viền 1 px thì có 11 px padding bên trong viền, nên chữ cách mép 12 px.\n\n## Nền 8 px\n\n**Từ 8 px trở lên, mọi khoảng đều là bội số của 4 px. Dưới 8 px, thang có thêm hai bậc không chia hết cho 4: 2 và 6 px.**\n\n| Khoảng | Các bậc | Dùng cho |\n|---|---|---|\n| Gọn, dưới 8 px | 2, 4, 6 | Chỉ bên trong component |\n| Từ 8 px | 8, 12, 16, 20, 24, 32, 40, 48, 64, 80 | Component, bố cục và các phần của trang |\n\n- Line height của chữ cũng là bội số của 4 px (xem [Kiểu chữ](/vi/foundations/styles/typography/)). Chữ, control và khoảng trống thẳng hàng với nhau.\n- Chỉ dùng `space.025` (2 px) để xê dịch một thứ nhỏ vào đúng chỗ: badge trên icon, chấm trạng thái cạnh chữ. Không dùng giữa các control hay làm padding.\n- Chỉ dùng `space.075` (6 px) bên trong component, ở hai chỗ: trên và dưới nhãn của control 32 px, vì (32 − 20) ÷ 2 = 6, và hai bên tooltip. Không dùng cho bố cục, khoảng cách giữa các phần, padding của card, hay giữa icon và chữ: khoảng đó là 4 px cạnh chữ 14 px và 8 px cạnh chữ 16 px trở lên.\n- Viền và vòng focus không phải khoảng cách. Đừng tính chúng vào, trừ khi tính padding như trên.\n\n### Không có khoảng âm\n\nKhông có token khoảng cách âm.\n\n- Khi hai thứ chồng lên nhau, như một chồng avatar, component tự quy định phần chồng.\n- Không dùng margin âm để kéo một phần tử cho thẳng hàng. Hãy sửa khoảng cách xung quanh nó.\n\n## Nên và không nên\n\n<SpacingDemo kind=\"dodont\" item=\"grouping\" />\n<SpacingDemo kind=\"dodont\" item=\"scale\" />\n<SpacingDemo kind=\"dodont\" item=\"nudge\" />\n\n## Chữ tiếng Việt\n\nChữ tiếng Việt cần dòng cao hơn để chứa dấu. Text style đã tự thêm chiều cao đó (xem [Kiểu chữ](/vi/foundations/styles/typography/)), nên khoảng cách không đổi: dùng cùng token cho cả hai ngôn ngữ.\n\nNhãn tiếng Việt thường dài hơn nhãn tiếng Anh. Hãy cho nhãn xuống dòng, hoặc chừa đủ chỗ trong khung chứa. Không bớt khoảng cách để nhét vừa nhãn.\n\n## Liên quan\n\n- [Khung ứng dụng](/vi/foundations/styles/layout/app-frame/): khoảng cách giúp header, menu bên và page header thẳng hàng.\n- [Lưới](/vi/foundations/styles/layout/grid/): cột, gutter và lề trang ở mỗi breakpoint.\n- [Kích thước và mật độ](/vi/foundations/styles/size-and-density/): chiều cao control.\n",
1707
+ "raw": "---\ntitle: Khoảng cách\ndescription: Thang khoảng cách 14 bậc trên nền 8 px cho padding, gap và margin, và cách chọn bậc.\norder: 3\n---\nimport SpacingDemo from '../../../components/SpacingDemo.astro';\n\n**Mọi khoảng trống đều là một token khoảng cách. Chọn bậc theo mức độ hai thứ thuộc về nhau.**\n\nNhững thứ thuộc về nhau thì đặt gần nhau. Các nhóm khác nhau thì cách xa hơn. Người đọc nhận ra các nhóm trước khi đọc một chữ nào.\n\n<SpacingDemo kind=\"anatomy\" />\n\n## Thang khoảng cách\n\n**14 bậc trên nền 8 px. Mỗi bậc có việc riêng, ghi ngay bên cạnh.**\n\nSố trong tên token là phần trăm của 8 px: `space.100` là 8 px, `space.200` là 16 px, và `space.075` là 6 px. Các bậc càng lớn càng cách xa nhau, vì chênh 4 px thấy rõ giữa các khoảng nhỏ nhưng gần như vô hình giữa các khoảng lớn.\n\n<SpacingDemo kind=\"scale\" />\n\nKhi hai thứ có thể dùng một trong hai bậc, hãy hỏi chúng thuộc về nhau tới mức nào. Càng liên quan thì khoảng càng nhỏ.\n\n### Padding và gap\n\n<SpacingDemo kind=\"padding-gap\" />\n\n- Padding là khoảng trống bên trong một phần tử. Đặt trên chính phần tử đó.\n- Gap là khoảng trống giữa các phần tử. Đặt trên phần tử cha bằng `gap`, trong bố cục flex hoặc grid.\n- Tránh dùng margin giữa các phần tử cùng cấp. Margin cộng dồn ở chỗ hai phần tử gặp nhau và để thừa khoảng sau phần tử cuối; `gap` không gặp cả hai vấn đề đó.\n- Đo padding từ mép ngoài, tính cả viền. Ô nhập 32 px có viền 1 px thì có 11 px padding bên trong viền, nên chữ cách mép 12 px.\n\n## Nền 8 px\n\n**Từ 8 px trở lên, mọi khoảng đều là bội số của 4 px. Dưới 8 px, thang có thêm hai bậc không chia hết cho 4: 2 và 6 px.**\n\n| Khoảng | Các bậc | Dùng cho |\n|---|---|---|\n| Gọn, dưới 8 px | 2, 4, 6 | Chỉ bên trong component |\n| Từ 8 px | 8, 12, 16, 20, 24, 32, 40, 48, 64, 80 | Component, bố cục và các phần của trang |\n\n- Line height của chữ cũng là bội số của 4 px (xem [Kiểu chữ](/vi/foundations/styles/typography/)). Chữ, control và khoảng trống thẳng hàng với nhau.\n- Chỉ dùng `space.025` (2 px) để xê dịch một thứ nhỏ vào đúng chỗ: badge trên icon, chấm trạng thái cạnh chữ. Không dùng giữa các control hay làm padding.\n- Chỉ dùng `space.075` (6 px) bên trong component, ở hai chỗ: trên và dưới nhãn của control 32 px, vì (32 − 20) ÷ 2 = 6, và hai bên tooltip. Không dùng cho bố cục, khoảng cách giữa các phần, padding của card, hay giữa icon và chữ: khoảng đó là 4 px cạnh chữ 14 px và 8 px cạnh chữ 16 px trở lên.\n- Viền và vòng focus không phải khoảng cách. Đừng tính chúng vào, trừ khi tính padding như trên.\n\n### Không có khoảng âm\n\nKhông có token khoảng cách âm.\n\n- Khi hai thứ chồng lên nhau, như một chồng avatar, component tự quy định phần chồng.\n- Không dùng margin âm để kéo một phần tử cho thẳng hàng. Hãy sửa khoảng cách xung quanh nó.\n\n## Nên và không nên\n\n<SpacingDemo kind=\"dodont\" item=\"grouping\" />\n<SpacingDemo kind=\"dodont\" item=\"scale\" />\n<SpacingDemo kind=\"dodont\" item=\"nudge\" />\n\n## Chữ tiếng Việt\n\nChữ tiếng Việt cần dòng cao hơn để chứa dấu. Text style đã tự thêm chiều cao đó (xem [Kiểu chữ](/vi/foundations/styles/typography/)), nên khoảng cách không đổi: dùng cùng token cho cả hai ngôn ngữ.\n\nNhãn tiếng Việt thường dài hơn nhãn tiếng Anh. Hãy cho nhãn xuống dòng, hoặc chừa đủ chỗ trong khung chứa. Không bớt khoảng cách để nhét vừa nhãn.\n\n## Liên quan\n\n- [Khung ứng dụng](/vi/foundations/styles/layout/app-frame/): khoảng cách giúp header, menu bên và page header thẳng hàng.\n- [Lưới](/vi/foundations/styles/layout/grid/): cột, gutter và lề trang ở mỗi breakpoint.\n- [Kích thước và mật độ](/vi/foundations/styles/size-and-density/): chiều cao control.\n",
1708
+ "frontmatter": {
1709
+ "title": "Khoảng cách",
1710
+ "description": "Thang khoảng cách 14 bậc trên nền 8 px cho padding, gap và margin, và cách chọn bậc.",
1711
+ "order": 3
1712
+ }
1713
+ },
1714
+ {
1715
+ "id": "vi/foundations/styles/typography/code",
1716
+ "path": "src/content-vi/foundations/styles/typography/code.mdx",
1717
+ "documentPath": "docs/src/content-vi/foundations/styles/typography/code.mdx",
1718
+ "locale": "vi",
1719
+ "kind": "guidance",
1720
+ "title": "Code",
1721
+ "status": "active",
1722
+ "releasePhase": null,
1723
+ "planned": [],
1724
+ "body": "import TokenTable from '../../../../components/TokenTable.astro';\nimport TypeDemo from '../../../../components/TypeDemo.astro';\n\n## Font stack\n\nDùng token, không tự viết danh sách font.\n\n```css\n/* font.family.sans */\nfont-family: Inter, \"Noto Sans\", system-ui, sans-serif;\n\n/* font.family.mono */\nfont-family: \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n```\n\nNoto Sans là font dự phòng vì có đủ chữ tiếng Việt và ký hiệu ₫, và có cỡ gần với Inter (x-height 0.536 em so với 0.546 của Inter), nên trang chuyển sang font dự phòng vẫn giữ bố cục.\n\n## Lấy font\n\n- **Trên web,** hãy tự host font. Dùng bản Inter trong kho Google Fonts (`github.com/google/fonts`, `ofl/inter`): bản này được hinting cho chữ nhỏ trên Windows và giữ đủ mọi tính năng OpenType. Không link tới Google Fonts API: file ở đó bỏ mất `cv05`, `cv08`, `ss02` và `zero`, trong khi `cv05` và `cv08` được bật mặc định (xem [Chữ số và mã](#chữ-số-và-mã)). Site này phục vụ các file đó, chia thành các bộ ký tự Latin, Latin Extended và tiếng Việt.\n- **Trên máy tính,** để dùng trong Figma, slide và tài liệu, cài Inter từ Google Fonts và JetBrains Mono từ JetBrains. Bản Inter của Google Fonts cũng tránh được lỗi dấu bị cắt trong các ứng dụng Windows cũ như Office.\n- Giấy phép của cả hai font đều cho phép dùng trong sản phẩm, tài liệu và logo.\n\n## Chữ số và mã\n\n`cv05` và `cv08` được bật cho mọi chữ Inter. Chúng cho chữ l thường có đuôi và chữ I hoa có chân, nên l, I và 1 không bao giờ trông giống nhau trong tên, ID và key. Bật các tính năng còn lại ở nơi cần; giữ nguyên đoạn văn.\n\n- **Bảng và giá trị thay đổi:** dùng số đều cột (`font-variant-numeric: tabular-nums`), để chữ số thẳng cột và bộ đếm không bị giật.\n- **Mã mà người dùng đọc hoặc gõ,** như mã đơn hàng, SKU và API key: thêm số 0 có gạch chéo (`zero`) cho Inter, hoặc đặt chúng bằng JetBrains Mono (`code.default`). JetBrains Mono không có `cv05` hay `cv08`, nên code trông vẫn như cũ.\n\n<TypeDemo kind=\"numbers\" />\n\n<TypeDemo kind=\"features\" />\n\nMọi text style được áp dụng bằng thuộc tính rút gọn `font`, và thuộc tính này đặt lại `font-feature-settings`. Vì vậy các tính năng được đặt trên mọi thành phần từ một biến, `--bh-font-features`; muốn thêm tính năng, hãy đổi biến, không đổi thuộc tính.\n\n```css\n/* Base: on every element */\n:root { --bh-font-features: \"cv05\", \"cv08\"; }\n*, ::before, ::after { font-feature-settings: var(--bh-font-features) !important; }\n\n/* Opt in where needed */\n.table-number { font-variant-numeric: tabular-nums; }\n.code-value { --bh-font-features: \"cv05\", \"cv08\", \"zero\"; }\n```\n\n## Token\n<TokenTable prefix=\"font\" />\n",
1725
+ "raw": "---\ntitle: Code\ndescription: Font stack, cách lấy font, tính năng OpenType cho chữ số và mã, và các token chữ.\norder: 3\n---\nimport TokenTable from '../../../../components/TokenTable.astro';\nimport TypeDemo from '../../../../components/TypeDemo.astro';\n\n## Font stack\n\nDùng token, không tự viết danh sách font.\n\n```css\n/* font.family.sans */\nfont-family: Inter, \"Noto Sans\", system-ui, sans-serif;\n\n/* font.family.mono */\nfont-family: \"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n```\n\nNoto Sans là font dự phòng vì có đủ chữ tiếng Việt và ký hiệu ₫, và có cỡ gần với Inter (x-height 0.536 em so với 0.546 của Inter), nên trang chuyển sang font dự phòng vẫn giữ bố cục.\n\n## Lấy font\n\n- **Trên web,** hãy tự host font. Dùng bản Inter trong kho Google Fonts (`github.com/google/fonts`, `ofl/inter`): bản này được hinting cho chữ nhỏ trên Windows và giữ đủ mọi tính năng OpenType. Không link tới Google Fonts API: file ở đó bỏ mất `cv05`, `cv08`, `ss02` và `zero`, trong khi `cv05` và `cv08` được bật mặc định (xem [Chữ số và mã](#chữ-số-và-mã)). Site này phục vụ các file đó, chia thành các bộ ký tự Latin, Latin Extended và tiếng Việt.\n- **Trên máy tính,** để dùng trong Figma, slide và tài liệu, cài Inter từ Google Fonts và JetBrains Mono từ JetBrains. Bản Inter của Google Fonts cũng tránh được lỗi dấu bị cắt trong các ứng dụng Windows cũ như Office.\n- Giấy phép của cả hai font đều cho phép dùng trong sản phẩm, tài liệu và logo.\n\n## Chữ số và mã\n\n`cv05` và `cv08` được bật cho mọi chữ Inter. Chúng cho chữ l thường có đuôi và chữ I hoa có chân, nên l, I và 1 không bao giờ trông giống nhau trong tên, ID và key. Bật các tính năng còn lại ở nơi cần; giữ nguyên đoạn văn.\n\n- **Bảng và giá trị thay đổi:** dùng số đều cột (`font-variant-numeric: tabular-nums`), để chữ số thẳng cột và bộ đếm không bị giật.\n- **Mã mà người dùng đọc hoặc gõ,** như mã đơn hàng, SKU và API key: thêm số 0 có gạch chéo (`zero`) cho Inter, hoặc đặt chúng bằng JetBrains Mono (`code.default`). JetBrains Mono không có `cv05` hay `cv08`, nên code trông vẫn như cũ.\n\n<TypeDemo kind=\"numbers\" />\n\n<TypeDemo kind=\"features\" />\n\nMọi text style được áp dụng bằng thuộc tính rút gọn `font`, và thuộc tính này đặt lại `font-feature-settings`. Vì vậy các tính năng được đặt trên mọi thành phần từ một biến, `--bh-font-features`; muốn thêm tính năng, hãy đổi biến, không đổi thuộc tính.\n\n```css\n/* Base: on every element */\n:root { --bh-font-features: \"cv05\", \"cv08\"; }\n*, ::before, ::after { font-feature-settings: var(--bh-font-features) !important; }\n\n/* Opt in where needed */\n.table-number { font-variant-numeric: tabular-nums; }\n.code-value { --bh-font-features: \"cv05\", \"cv08\", \"zero\"; }\n```\n\n## Token\n<TokenTable prefix=\"font\" />\n",
1726
+ "frontmatter": {
1727
+ "title": "Code",
1728
+ "description": "Font stack, cách lấy font, tính năng OpenType cho chữ số và mã, và các token chữ.",
1729
+ "order": 3
1730
+ }
1731
+ },
1732
+ {
1733
+ "id": "vi/foundations/styles/typography/index",
1734
+ "path": "src/content-vi/foundations/styles/typography/index.mdx",
1735
+ "documentPath": "docs/src/content-vi/foundations/styles/typography/index.mdx",
1736
+ "locale": "vi",
1737
+ "kind": "guidance",
1738
+ "title": "Kiểu chữ",
1739
+ "status": "active",
1740
+ "releasePhase": null,
1741
+ "planned": [],
1742
+ "body": "import TypeDemo from '../../../../components/TypeDemo.astro';\n\n## Font chữ\n\nHai font là đủ cho mọi thứ: Inter cho chữ giao diện và chữ để đọc, JetBrains Mono cho code.\n\n<TypeDemo kind=\"faces\" />\n\nInter được chọn vì:\n\n- x-height cao, nên chữ giao diện cỡ nhỏ vẫn dễ đọc.\n- Có đủ chữ tiếng Việt, kể cả ký hiệu ₫.\n- Có tính năng OpenType giúp phân biệt các ký tự dễ nhầm như l, I và 1. Điều này quan trọng với một sản phẩm đầy mã đơn hàng và API key.\n- Là mã nguồn mở theo giấy phép SIL Open Font License, nên tự host và nhúng được.\n- Là font của wordmark Beehexa, nên chữ trong sản phẩm và logo cùng một họ.\n\nInter có trục optical size: từ 32 px trở lên, font được vẽ thành Inter Display, khoảng cách chữ khít hơn cho tiêu đề. Trình duyệt tự áp dụng; hãy để `font-optical-sizing` ở `auto`.\n\n## Text style\n\nChữ được định dạng bằng **text style**, không dùng cỡ chữ rời. Mỗi text style là một token mang cùng lúc cỡ chữ, line height, độ đậm và font, đặt tên theo vai trò. Mười bốn text style trong năm nhóm đủ cho mọi sản phẩm, tài liệu và trang web của Beehexa.\n\n<TypeDemo kind=\"styles\" />\n\n- **Display** chỉ dùng cho trang marketing. Màn hình sản phẩm bắt đầu từ `heading.xlarge`.\n- **Heading** dùng cho tiêu đề trang, phần, card và nhóm. Mỗi trang dùng một `heading.large`, làm tiêu đề trang.\n- **Body** dùng cho đoạn văn. `body.default` (14 px) là mặc định trong giao diện sản phẩm; `body.large` (16 px) dùng cho chữ mà người dùng đọc kỹ thay vì lướt.\n- **Label** dùng cho chữ trên hoặc cạnh control: nút, nhãn của form, tab, menu, badge.\n- **Code** dùng cho code, ID và key.\n\n## Độ đậm\n\n| Độ đậm | Token | Dùng |\n|---|---|---|\n| 400 | `font.weight.regular` | Đoạn văn |\n| 500 | `font.weight.medium` | Nhãn |\n| 600 | `font.weight.semibold` | Tiêu đề |\n| 700 | `font.weight.bold` | Chỉ cho display |\n\nKhông dùng độ đậm nhẹ hơn 400: nét mảnh bị đứt ở chữ nhỏ. Đoạn văn in đậm không phải là tiêu đề. Khi cần nhấn mạnh vì ý nghĩa, hãy dùng `<strong>` hoặc `<em>`, để trình đọc màn hình cũng nhận được.\n\n## Khoảng cách chữ\n\nĐể ở 0. Trục optical size của Inter đã làm khít chữ lớn, nên tiêu đề không cần letter-spacing âm, và chữ nhỏ giữ khoảng cách mặc định.\n\n## Line height\n\nLine height là một phần của mỗi text style và nằm trên lưới 4 px: mọi giá trị đều là bội số của 4 px, nên chữ thẳng hàng với khoảng cách và component.\n\n- Text style body và label dùng 1.3–1.5 lần cỡ chữ (14/20, 12/16, 16/24), đủ khoảng trống giữa các dòng chữ giao diện mà không làm đoạn văn bị loãng.\n- Tiêu đề càng lớn line height càng khít, khoảng 1.1–1.25 ở cỡ display, để chữ lớn vẫn liền một khối.\n- Chữ tiếng Việt dùng giá trị cao hơn; xem phần [Tiếng Việt](/foundations/styles/typography/vietnamese/).\n",
1743
+ "raw": "---\ntitle: Kiểu chữ\ndescription: Hai font chữ và mười bốn text style, cùng độ đậm, khoảng cách chữ và line height.\norder: 2\nsidebarLabel: Overview\n---\nimport TypeDemo from '../../../../components/TypeDemo.astro';\n\n## Font chữ\n\nHai font là đủ cho mọi thứ: Inter cho chữ giao diện và chữ để đọc, JetBrains Mono cho code.\n\n<TypeDemo kind=\"faces\" />\n\nInter được chọn vì:\n\n- x-height cao, nên chữ giao diện cỡ nhỏ vẫn dễ đọc.\n- Có đủ chữ tiếng Việt, kể cả ký hiệu ₫.\n- Có tính năng OpenType giúp phân biệt các ký tự dễ nhầm như l, I và 1. Điều này quan trọng với một sản phẩm đầy mã đơn hàng và API key.\n- Là mã nguồn mở theo giấy phép SIL Open Font License, nên tự host và nhúng được.\n- Là font của wordmark Beehexa, nên chữ trong sản phẩm và logo cùng một họ.\n\nInter có trục optical size: từ 32 px trở lên, font được vẽ thành Inter Display, khoảng cách chữ khít hơn cho tiêu đề. Trình duyệt tự áp dụng; hãy để `font-optical-sizing` ở `auto`.\n\n## Text style\n\nChữ được định dạng bằng **text style**, không dùng cỡ chữ rời. Mỗi text style là một token mang cùng lúc cỡ chữ, line height, độ đậm và font, đặt tên theo vai trò. Mười bốn text style trong năm nhóm đủ cho mọi sản phẩm, tài liệu và trang web của Beehexa.\n\n<TypeDemo kind=\"styles\" />\n\n- **Display** chỉ dùng cho trang marketing. Màn hình sản phẩm bắt đầu từ `heading.xlarge`.\n- **Heading** dùng cho tiêu đề trang, phần, card và nhóm. Mỗi trang dùng một `heading.large`, làm tiêu đề trang.\n- **Body** dùng cho đoạn văn. `body.default` (14 px) là mặc định trong giao diện sản phẩm; `body.large` (16 px) dùng cho chữ mà người dùng đọc kỹ thay vì lướt.\n- **Label** dùng cho chữ trên hoặc cạnh control: nút, nhãn của form, tab, menu, badge.\n- **Code** dùng cho code, ID và key.\n\n## Độ đậm\n\n| Độ đậm | Token | Dùng |\n|---|---|---|\n| 400 | `font.weight.regular` | Đoạn văn |\n| 500 | `font.weight.medium` | Nhãn |\n| 600 | `font.weight.semibold` | Tiêu đề |\n| 700 | `font.weight.bold` | Chỉ cho display |\n\nKhông dùng độ đậm nhẹ hơn 400: nét mảnh bị đứt ở chữ nhỏ. Đoạn văn in đậm không phải là tiêu đề. Khi cần nhấn mạnh vì ý nghĩa, hãy dùng `<strong>` hoặc `<em>`, để trình đọc màn hình cũng nhận được.\n\n## Khoảng cách chữ\n\nĐể ở 0. Trục optical size của Inter đã làm khít chữ lớn, nên tiêu đề không cần letter-spacing âm, và chữ nhỏ giữ khoảng cách mặc định.\n\n## Line height\n\nLine height là một phần của mỗi text style và nằm trên lưới 4 px: mọi giá trị đều là bội số của 4 px, nên chữ thẳng hàng với khoảng cách và component.\n\n- Text style body và label dùng 1.3–1.5 lần cỡ chữ (14/20, 12/16, 16/24), đủ khoảng trống giữa các dòng chữ giao diện mà không làm đoạn văn bị loãng.\n- Tiêu đề càng lớn line height càng khít, khoảng 1.1–1.25 ở cỡ display, để chữ lớn vẫn liền một khối.\n- Chữ tiếng Việt dùng giá trị cao hơn; xem phần [Tiếng Việt](/foundations/styles/typography/vietnamese/).\n",
1744
+ "frontmatter": {
1745
+ "title": "Kiểu chữ",
1746
+ "description": "Hai font chữ và mười bốn text style, cùng độ đậm, khoảng cách chữ và line height.",
1747
+ "order": 2,
1748
+ "sidebarLabel": "Overview"
1749
+ }
1750
+ },
1751
+ {
1752
+ "id": "vi/foundations/styles/typography/usage",
1753
+ "path": "src/content-vi/foundations/styles/typography/usage.mdx",
1754
+ "documentPath": "docs/src/content-vi/foundations/styles/typography/usage.mdx",
1755
+ "locale": "vi",
1756
+ "kind": "guidance",
1757
+ "title": "Cách dùng",
1758
+ "status": "active",
1759
+ "releasePhase": null,
1760
+ "planned": [],
1761
+ "body": "import TypeDemo from '../../../../components/TypeDemo.astro';\n\n## Text style nào dùng ở đâu\n\nGiao diện sản phẩm dùng các text style này; trang component ghi rõ text style của từng phần. Khi một phần không có trong danh sách, dùng text style của phần gần nhất có cùng vai trò.\n\n| Phần | Text style |\n|---|---|\n| **Cấu trúc trang** | |\n| Tiêu đề trang | `heading.large` |\n| Tiêu đề phần | `heading.medium` |\n| Breadcrumb | `body.small` |\n| Tiêu đề lớn ở màn hình trống và onboarding | `heading.xlarge` |\n| **Khung chứa** | |\n| Tiêu đề card, panel và drawer | `heading.small` |\n| Tiêu đề mục trong lưới hoặc danh sách nhiều card | `heading.xsmall` |\n| Mô tả của card | `body.default` |\n| Tiêu đề dialog | `heading.medium` |\n| Nội dung dialog | `body.default` |\n| Tiêu đề nhóm trong form, danh sách hoặc menu | `heading.xsmall` |\n| **Form** | |\n| Nhãn của trường nhập | `label.default` |\n| Chữ trong ô nhập và placeholder | `body.default` |\n| Helper text và thông báo lỗi | `body.small` |\n| Chữ của checkbox và radio | `body.default` |\n| **Hành động và điều hướng** | |\n| Nút, nút dạng link | `label.default` |\n| Nút nhỏ | `label.small` |\n| Tab, mục menu, mục điều hướng bên | `label.default` |\n| Mục điều hướng trên cùng | `label.default` |\n| **Dữ liệu** | |\n| Header của bảng | `label.small` |\n| Ô của bảng | `body.default` |\n| Số trong bảng | `body.default` với số đều cột |\n| ID, SKU, key trong bảng | `code.default` |\n| Badge, tag, trạng thái | `label.small` |\n| Số trong card, như một KPI | `heading.large` với số đều cột |\n| Nhãn dưới con số | `body.small` |\n| **Phản hồi** | |\n| Tiêu đề banner và toast | `heading.xsmall` |\n| Nội dung banner và toast | `body.default` |\n| Tooltip | `body.small` |\n| Mốc thời gian, metadata | `body.small` |\n| **Đọc** | |\n| Bài hướng dẫn, tài liệu, nội dung email | `body.large` |\n| Code trong dòng | Font của `code.default` ở cỡ chữ xung quanh |\n\n<TypeDemo kind=\"ui\" />\n\n## Trên website và tài liệu\n\nWebsite và tài liệu, kể cả site này, dùng cùng các text style. Có hai điểm khác giao diện sản phẩm: tiêu đề trang lớn hơn một bậc, và đoạn văn dùng `body.large`, vì người dùng đọc kỹ các trang này thay vì lướt.\n\n| Phần | Text style |\n|---|---|\n| **Header của site** | |\n| Mục điều hướng trên cùng | `label.default` |\n| Ô tìm kiếm | `body.default` |\n| Gợi ý phím tắt | `label.small` |\n| Tiêu đề kết quả tìm kiếm | `label.default` |\n| Mô tả kết quả tìm kiếm | `body.small` |\n| **Sidebar** | |\n| Mục lớn | `heading.xsmall` |\n| Nhãn nhóm | `label.small` |\n| Trang và trang con | `label.default` |\n| **Mục lục** | |\n| Tiêu đề (\"Trên trang này\") | `heading.xsmall` |\n| Link | `label.default` |\n| **Trang** | |\n| Breadcrumb | `body.small` |\n| Tiêu đề trang | `heading.xlarge` |\n| Đoạn dẫn dưới tiêu đề | `body.large` |\n| Tiêu đề phần (`h2`) | `heading.large` |\n| Tiêu đề phần con (`h3`) | `heading.medium` |\n| Tiêu đề nhỏ (`h4`) | `heading.small` |\n| Đoạn văn và danh sách | `body.large` |\n| Chữ trong bảng | `body.default` |\n| Header của bảng | `label.small` |\n| Khối code | `code.default` |\n| Code trong dòng | Font của `code.default` ở cỡ chữ xung quanh |\n| Tiêu đề card | `heading.small` |\n| Chữ trong card | `body.default` |\n| Badge trạng thái | `label.small` |\n| Tab | `label.default` |\n| Link trang trước và trang sau | Nhãn `body.small`, tên trang `heading.small` |\n| Footer và thông tin trang | `body.small` |\n\n## Cách dùng text style\n\nTrong CSS, mỗi text style là một khai báo `font`:\n\n```css\n.page-title { font: var(--bh-font-heading-large); }\n.card-title { font: var(--bh-font-heading-small); }\n.field-label { font: var(--bh-font-label-default); }\n.helper-text { font: var(--bh-font-body-small); }\n.kpi-value { font: var(--bh-font-heading-large); font-variant-numeric: tabular-nums; }\n```\n\n- Dùng nguyên cả text style. Không lấy cỡ chữ của nó rồi tự đặt độ đậm hay line height: một text style gần giống trông như lỗi khi đứng cạnh text style thật.\n- Không tạo text style mới cho một màn hình. Nếu thiếu một vai trò, hãy thêm nó vào đây trước.\n- Đặt màu riêng, bằng các token `color.text.*`.\n- Thể hiện mục được chọn, như trang hoặc tab hiện tại, bằng màu và vạch chỉ báo, không bằng chữ đậm hơn: chữ đậm hơn sẽ rộng ra và đẩy các chữ bên cạnh.\n- Chữ đậm trong đoạn văn (`<strong>`, `<b>`) là semibold, 600. Độ đậm 700 chỉ dành cho text style display.\n- Khi một dòng trộn nhiều text style, như mã đơn hàng ở `code.default`, một badge và số tiền ở `body.default`, hãy căn chữ theo đường chân chữ (`vertical-align: baseline`, hoặc `align-items: baseline` trong flex), không căn giữa. Mỗi text style nằm khác nhau trong line height của nó, nên căn giữa làm chữ ở các độ cao khác nhau.\n\n\n## Cỡ chữ trên màn hình nhỏ\n\n- Text style của sản phẩm giữ nguyên cỡ trên mọi màn hình. Chữ đổi cỡ giữa các breakpoint làm màn hình nhiều dữ liệu khó làm quen hơn.\n- Text style display giảm cỡ dưới 768 px (`breakpoint.md`): `display.large` và `display.medium` thành `display.small`, còn `display.small` thành `heading.xlarge`.\n- Mọi cỡ chữ tính bằng `rem`, nên chữ theo cài đặt và mức zoom trình duyệt của người đọc.\n\n## Thứ bậc\n\n- Mỗi trang một tiêu đề trang (`h1`). Đi xuống các cấp tiêu đề theo thứ tự, không bỏ cấp.\n- Thể hiện cấu trúc bằng tiêu đề, không bằng chữ đậm hay đoạn văn cỡ lớn hơn.\n- Thể hiện mức quan trọng bằng cỡ chữ và độ đậm trước. Không chỉ dựa vào màu.\n\n## Dễ đọc\n\n- Giữ mỗi dòng khoảng 100 ký tự trở xuống: đặt nội dung chữ dài trên trang Narrow (xem [Độ rộng trang](/vi/foundations/styles/layout/page-widths/)).\n- Căn chữ trái, mép phải để tự nhiên. Không căn đều hai bên; chỉ căn giữa chữ ngắn và đứng riêng.\n- Viết hoa chữ đầu câu. Không viết hoa toàn bộ: đọc chậm hơn, và trong tiếng Việt các dấu chen vào dòng trên.\n- Dùng chữ nghiêng ít thôi, cho tên tác phẩm và thuật ngữ.\n\n## Chữ dài\n\nTên đơn hàng, URL và ID không có giới hạn độ dài.\n\n- Cắt ngắn chữ một dòng bằng dấu ba chấm, và luôn có cách khác để đọc đủ giá trị, như tooltip hoặc màn hình chi tiết.\n- Cho các chuỗi dài liền mạch, như URL và key, được xuống dòng ở bất kỳ đâu thay vì tràn ra ngoài.\n- Không bao giờ cắt ngắn chữ mà người dùng cần để hoàn thành công việc.\n\n## Khả năng tiếp cận\n\n- Chữ cần độ tương phản tối thiểu 4.5 : 1 với nền; chữ lớn (24 px, hoặc 18.66 px đậm) tối thiểu 3 : 1. Xem [Màu sắc](/vi/foundations/styles/color/).\n- Đặt cỡ chữ bằng `rem` và không bao giờ chặn zoom, để chữ phóng được tới 200% (WCAG 1.4.4).\n- Không đặt chữ trong ảnh. Chữ thật phóng to được, dịch được và đọc thành tiếng được.\n",
1762
+ "raw": "---\ntitle: Cách dùng\ndescription: Text style nào dùng cho phần nào trên màn hình, và các quy tắc về thứ bậc, độ dễ đọc và chữ dài.\norder: 1\n---\nimport TypeDemo from '../../../../components/TypeDemo.astro';\n\n## Text style nào dùng ở đâu\n\nGiao diện sản phẩm dùng các text style này; trang component ghi rõ text style của từng phần. Khi một phần không có trong danh sách, dùng text style của phần gần nhất có cùng vai trò.\n\n| Phần | Text style |\n|---|---|\n| **Cấu trúc trang** | |\n| Tiêu đề trang | `heading.large` |\n| Tiêu đề phần | `heading.medium` |\n| Breadcrumb | `body.small` |\n| Tiêu đề lớn ở màn hình trống và onboarding | `heading.xlarge` |\n| **Khung chứa** | |\n| Tiêu đề card, panel và drawer | `heading.small` |\n| Tiêu đề mục trong lưới hoặc danh sách nhiều card | `heading.xsmall` |\n| Mô tả của card | `body.default` |\n| Tiêu đề dialog | `heading.medium` |\n| Nội dung dialog | `body.default` |\n| Tiêu đề nhóm trong form, danh sách hoặc menu | `heading.xsmall` |\n| **Form** | |\n| Nhãn của trường nhập | `label.default` |\n| Chữ trong ô nhập và placeholder | `body.default` |\n| Helper text và thông báo lỗi | `body.small` |\n| Chữ của checkbox và radio | `body.default` |\n| **Hành động và điều hướng** | |\n| Nút, nút dạng link | `label.default` |\n| Nút nhỏ | `label.small` |\n| Tab, mục menu, mục điều hướng bên | `label.default` |\n| Mục điều hướng trên cùng | `label.default` |\n| **Dữ liệu** | |\n| Header của bảng | `label.small` |\n| Ô của bảng | `body.default` |\n| Số trong bảng | `body.default` với số đều cột |\n| ID, SKU, key trong bảng | `code.default` |\n| Badge, tag, trạng thái | `label.small` |\n| Số trong card, như một KPI | `heading.large` với số đều cột |\n| Nhãn dưới con số | `body.small` |\n| **Phản hồi** | |\n| Tiêu đề banner và toast | `heading.xsmall` |\n| Nội dung banner và toast | `body.default` |\n| Tooltip | `body.small` |\n| Mốc thời gian, metadata | `body.small` |\n| **Đọc** | |\n| Bài hướng dẫn, tài liệu, nội dung email | `body.large` |\n| Code trong dòng | Font của `code.default` ở cỡ chữ xung quanh |\n\n<TypeDemo kind=\"ui\" />\n\n## Trên website và tài liệu\n\nWebsite và tài liệu, kể cả site này, dùng cùng các text style. Có hai điểm khác giao diện sản phẩm: tiêu đề trang lớn hơn một bậc, và đoạn văn dùng `body.large`, vì người dùng đọc kỹ các trang này thay vì lướt.\n\n| Phần | Text style |\n|---|---|\n| **Header của site** | |\n| Mục điều hướng trên cùng | `label.default` |\n| Ô tìm kiếm | `body.default` |\n| Gợi ý phím tắt | `label.small` |\n| Tiêu đề kết quả tìm kiếm | `label.default` |\n| Mô tả kết quả tìm kiếm | `body.small` |\n| **Sidebar** | |\n| Mục lớn | `heading.xsmall` |\n| Nhãn nhóm | `label.small` |\n| Trang và trang con | `label.default` |\n| **Mục lục** | |\n| Tiêu đề (\"Trên trang này\") | `heading.xsmall` |\n| Link | `label.default` |\n| **Trang** | |\n| Breadcrumb | `body.small` |\n| Tiêu đề trang | `heading.xlarge` |\n| Đoạn dẫn dưới tiêu đề | `body.large` |\n| Tiêu đề phần (`h2`) | `heading.large` |\n| Tiêu đề phần con (`h3`) | `heading.medium` |\n| Tiêu đề nhỏ (`h4`) | `heading.small` |\n| Đoạn văn và danh sách | `body.large` |\n| Chữ trong bảng | `body.default` |\n| Header của bảng | `label.small` |\n| Khối code | `code.default` |\n| Code trong dòng | Font của `code.default` ở cỡ chữ xung quanh |\n| Tiêu đề card | `heading.small` |\n| Chữ trong card | `body.default` |\n| Badge trạng thái | `label.small` |\n| Tab | `label.default` |\n| Link trang trước và trang sau | Nhãn `body.small`, tên trang `heading.small` |\n| Footer và thông tin trang | `body.small` |\n\n## Cách dùng text style\n\nTrong CSS, mỗi text style là một khai báo `font`:\n\n```css\n.page-title { font: var(--bh-font-heading-large); }\n.card-title { font: var(--bh-font-heading-small); }\n.field-label { font: var(--bh-font-label-default); }\n.helper-text { font: var(--bh-font-body-small); }\n.kpi-value { font: var(--bh-font-heading-large); font-variant-numeric: tabular-nums; }\n```\n\n- Dùng nguyên cả text style. Không lấy cỡ chữ của nó rồi tự đặt độ đậm hay line height: một text style gần giống trông như lỗi khi đứng cạnh text style thật.\n- Không tạo text style mới cho một màn hình. Nếu thiếu một vai trò, hãy thêm nó vào đây trước.\n- Đặt màu riêng, bằng các token `color.text.*`.\n- Thể hiện mục được chọn, như trang hoặc tab hiện tại, bằng màu và vạch chỉ báo, không bằng chữ đậm hơn: chữ đậm hơn sẽ rộng ra và đẩy các chữ bên cạnh.\n- Chữ đậm trong đoạn văn (`<strong>`, `<b>`) là semibold, 600. Độ đậm 700 chỉ dành cho text style display.\n- Khi một dòng trộn nhiều text style, như mã đơn hàng ở `code.default`, một badge và số tiền ở `body.default`, hãy căn chữ theo đường chân chữ (`vertical-align: baseline`, hoặc `align-items: baseline` trong flex), không căn giữa. Mỗi text style nằm khác nhau trong line height của nó, nên căn giữa làm chữ ở các độ cao khác nhau.\n\n\n## Cỡ chữ trên màn hình nhỏ\n\n- Text style của sản phẩm giữ nguyên cỡ trên mọi màn hình. Chữ đổi cỡ giữa các breakpoint làm màn hình nhiều dữ liệu khó làm quen hơn.\n- Text style display giảm cỡ dưới 768 px (`breakpoint.md`): `display.large` và `display.medium` thành `display.small`, còn `display.small` thành `heading.xlarge`.\n- Mọi cỡ chữ tính bằng `rem`, nên chữ theo cài đặt và mức zoom trình duyệt của người đọc.\n\n## Thứ bậc\n\n- Mỗi trang một tiêu đề trang (`h1`). Đi xuống các cấp tiêu đề theo thứ tự, không bỏ cấp.\n- Thể hiện cấu trúc bằng tiêu đề, không bằng chữ đậm hay đoạn văn cỡ lớn hơn.\n- Thể hiện mức quan trọng bằng cỡ chữ và độ đậm trước. Không chỉ dựa vào màu.\n\n## Dễ đọc\n\n- Giữ mỗi dòng khoảng 100 ký tự trở xuống: đặt nội dung chữ dài trên trang Narrow (xem [Độ rộng trang](/vi/foundations/styles/layout/page-widths/)).\n- Căn chữ trái, mép phải để tự nhiên. Không căn đều hai bên; chỉ căn giữa chữ ngắn và đứng riêng.\n- Viết hoa chữ đầu câu. Không viết hoa toàn bộ: đọc chậm hơn, và trong tiếng Việt các dấu chen vào dòng trên.\n- Dùng chữ nghiêng ít thôi, cho tên tác phẩm và thuật ngữ.\n\n## Chữ dài\n\nTên đơn hàng, URL và ID không có giới hạn độ dài.\n\n- Cắt ngắn chữ một dòng bằng dấu ba chấm, và luôn có cách khác để đọc đủ giá trị, như tooltip hoặc màn hình chi tiết.\n- Cho các chuỗi dài liền mạch, như URL và key, được xuống dòng ở bất kỳ đâu thay vì tràn ra ngoài.\n- Không bao giờ cắt ngắn chữ mà người dùng cần để hoàn thành công việc.\n\n## Khả năng tiếp cận\n\n- Chữ cần độ tương phản tối thiểu 4.5 : 1 với nền; chữ lớn (24 px, hoặc 18.66 px đậm) tối thiểu 3 : 1. Xem [Màu sắc](/vi/foundations/styles/color/).\n- Đặt cỡ chữ bằng `rem` và không bao giờ chặn zoom, để chữ phóng được tới 200% (WCAG 1.4.4).\n- Không đặt chữ trong ảnh. Chữ thật phóng to được, dịch được và đọc thành tiếng được.\n",
1763
+ "frontmatter": {
1764
+ "title": "Cách dùng",
1765
+ "description": "Text style nào dùng cho phần nào trên màn hình, và các quy tắc về thứ bậc, độ dễ đọc và chữ dài.",
1766
+ "order": 1
1767
+ }
1768
+ },
1769
+ {
1770
+ "id": "vi/foundations/styles/typography/vietnamese",
1771
+ "path": "src/content-vi/foundations/styles/typography/vietnamese.mdx",
1772
+ "documentPath": "docs/src/content-vi/foundations/styles/typography/vietnamese.mdx",
1773
+ "locale": "vi",
1774
+ "kind": "guidance",
1775
+ "title": "Tiếng Việt",
1776
+ "status": "active",
1777
+ "releasePhase": null,
1778
+ "planned": [],
1779
+ "body": "import TypeDemo from '../../../../components/TypeDemo.astro';\n\n**Chữ tiếng Việt dùng line height cao hơn, để dấu chồng nhau không chạm dòng trên và không bị cắt.**\n\nChữ được đánh dấu `lang=\"vi\"` dùng line height cao hơn. Tiếng Việt có một số chữ hoa mang hai dấu chồng nhau, như Ấ, Ổ và Ẫ, nên cao vượt hẳn các chữ khác. Ở line height của tiếng Anh, các dấu này chạm vào dòng trên và bị cắt trong các thành phần một dòng có ẩn phần tràn, như ô bảng bị cắt ngắn và chữ trên nút.\n\nLine height là khoảng cách từ dòng này tới dòng kế tiếp, nên chỉ thấy rõ khi chữ có từ hai dòng. Mỗi dải tô màu bên dưới là một dòng:\n\n<TypeDemo kind=\"leading\" />\n\nLớp tiếng Việt chỉ đổi line height; cỡ chữ, độ đậm và font giữ nguyên. Mỗi giá trị là bội số nhỏ nhất của 4 px giữ được mọi chữ tiếng Việt trong line box của chính nó, nên dấu không chạm dòng trên và không bị cắt.\n\n| Text style | Tiếng Anh | Tiếng Việt |\n|---|---|---|\n| `display.large` | <span class=\"type-num\">72/80</span> | <span class=\"type-num\">72/108</span> |\n| `display.medium` | <span class=\"type-num\">60/68</span> | <span class=\"type-num\">60/88</span> |\n| `display.small` | <span class=\"type-num\">48/56</span> | <span class=\"type-num\">48/72</span> |\n| `heading.xlarge` | <span class=\"type-num\">32/40</span> | <span class=\"type-num\">32/48</span> |\n| `heading.large` | <span class=\"type-num\">24/32</span> | <span class=\"type-num\">24/40</span> |\n| `heading.medium` | <span class=\"type-num\">20/28</span> | <span class=\"type-num\">20/32</span> |\n| `heading.small` | <span class=\"type-num\">16/24</span> | <span class=\"type-num\">16/24</span> (giữ nguyên) |\n| `heading.xsmall` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/24</span> |\n| `body.large` | <span class=\"type-num\">16/24</span> | <span class=\"type-num\">16/24</span> (giữ nguyên) |\n| `body.default` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/24</span> |\n| `body.small` | <span class=\"type-num\">12/16</span> | <span class=\"type-num\">12/20</span> |\n| `label.default` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/24</span> |\n| `label.small` | <span class=\"type-num\">12/16</span> | <span class=\"type-num\">12/20</span> |\n| `code.default` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/20</span> (giữ nguyên) |\n\nMỗi ô dưới đây là một dòng có ẩn phần tràn, line box được vẽ viền.\n\n<TypeDemo kind=\"vietnamese\" />\n\n- **Đánh dấu ngôn ngữ.** Đặt `lang=\"vi\"` trên `<html>` cho trang tiếng Việt, hoặc trên thành phần chứa chữ tiếng Việt. Chữ được đánh dấu ngôn ngữ khác bên trong nó, như `lang=\"en\"`, trở về giá trị tiếng Anh.\n- **Dùng token.** Token text style tự chuyển khi gặp `lang=\"vi\"` (`:lang(vi)` trong `tokens.css`). Code không đọc được biến CSS, như theme Ant Design Vue, lấy giá trị `vi` từ `tokens.js`.\n- **Cho component giãn ra.** Control hoặc dòng có chiều cao cố định phải vừa line height tiếng Việt: nhãn 14 px cần dòng cao 24 px, nên hãy tính chiều cao từ padding cộng line height, không đặt một con số cố định.\n- **Không cắt chữ theo chiều dọc.** Tránh `overflow: hidden` trên khung không có padding dọc. Khi buộc phải cắt ngắn, hãy cắt theo chiều ngang và để line box giữ các dấu.\n- **Kiểm tra bằng chuỗi này** ở mọi component và mọi trạng thái: **ỔN ĐỊNH · ẤN ĐỘ · ẪM · Ở ĐÂY CÓ ƯU ĐÃI**.\n\nJetBrains Mono vẽ dấu tiếng Việt bên trong line box của nó, nên `code.default` giữ 14/20. Site này cũng phục vụ bộ ký tự tiếng Việt của font này, nên tiếng Việt trong code không bị chuyển sang font khác.\n\n",
1780
+ "raw": "---\ntitle: Tiếng Việt\ndescription: Line height cao hơn cho chữ tiếng Việt, và cách giữ cho dấu không bị cắt.\norder: 2\n---\nimport TypeDemo from '../../../../components/TypeDemo.astro';\n\n**Chữ tiếng Việt dùng line height cao hơn, để dấu chồng nhau không chạm dòng trên và không bị cắt.**\n\nChữ được đánh dấu `lang=\"vi\"` dùng line height cao hơn. Tiếng Việt có một số chữ hoa mang hai dấu chồng nhau, như Ấ, Ổ và Ẫ, nên cao vượt hẳn các chữ khác. Ở line height của tiếng Anh, các dấu này chạm vào dòng trên và bị cắt trong các thành phần một dòng có ẩn phần tràn, như ô bảng bị cắt ngắn và chữ trên nút.\n\nLine height là khoảng cách từ dòng này tới dòng kế tiếp, nên chỉ thấy rõ khi chữ có từ hai dòng. Mỗi dải tô màu bên dưới là một dòng:\n\n<TypeDemo kind=\"leading\" />\n\nLớp tiếng Việt chỉ đổi line height; cỡ chữ, độ đậm và font giữ nguyên. Mỗi giá trị là bội số nhỏ nhất của 4 px giữ được mọi chữ tiếng Việt trong line box của chính nó, nên dấu không chạm dòng trên và không bị cắt.\n\n| Text style | Tiếng Anh | Tiếng Việt |\n|---|---|---|\n| `display.large` | <span class=\"type-num\">72/80</span> | <span class=\"type-num\">72/108</span> |\n| `display.medium` | <span class=\"type-num\">60/68</span> | <span class=\"type-num\">60/88</span> |\n| `display.small` | <span class=\"type-num\">48/56</span> | <span class=\"type-num\">48/72</span> |\n| `heading.xlarge` | <span class=\"type-num\">32/40</span> | <span class=\"type-num\">32/48</span> |\n| `heading.large` | <span class=\"type-num\">24/32</span> | <span class=\"type-num\">24/40</span> |\n| `heading.medium` | <span class=\"type-num\">20/28</span> | <span class=\"type-num\">20/32</span> |\n| `heading.small` | <span class=\"type-num\">16/24</span> | <span class=\"type-num\">16/24</span> (giữ nguyên) |\n| `heading.xsmall` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/24</span> |\n| `body.large` | <span class=\"type-num\">16/24</span> | <span class=\"type-num\">16/24</span> (giữ nguyên) |\n| `body.default` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/24</span> |\n| `body.small` | <span class=\"type-num\">12/16</span> | <span class=\"type-num\">12/20</span> |\n| `label.default` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/24</span> |\n| `label.small` | <span class=\"type-num\">12/16</span> | <span class=\"type-num\">12/20</span> |\n| `code.default` | <span class=\"type-num\">14/20</span> | <span class=\"type-num\">14/20</span> (giữ nguyên) |\n\nMỗi ô dưới đây là một dòng có ẩn phần tràn, line box được vẽ viền.\n\n<TypeDemo kind=\"vietnamese\" />\n\n- **Đánh dấu ngôn ngữ.** Đặt `lang=\"vi\"` trên `<html>` cho trang tiếng Việt, hoặc trên thành phần chứa chữ tiếng Việt. Chữ được đánh dấu ngôn ngữ khác bên trong nó, như `lang=\"en\"`, trở về giá trị tiếng Anh.\n- **Dùng token.** Token text style tự chuyển khi gặp `lang=\"vi\"` (`:lang(vi)` trong `tokens.css`). Code không đọc được biến CSS, như theme Ant Design Vue, lấy giá trị `vi` từ `tokens.js`.\n- **Cho component giãn ra.** Control hoặc dòng có chiều cao cố định phải vừa line height tiếng Việt: nhãn 14 px cần dòng cao 24 px, nên hãy tính chiều cao từ padding cộng line height, không đặt một con số cố định.\n- **Không cắt chữ theo chiều dọc.** Tránh `overflow: hidden` trên khung không có padding dọc. Khi buộc phải cắt ngắn, hãy cắt theo chiều ngang và để line box giữ các dấu.\n- **Kiểm tra bằng chuỗi này** ở mọi component và mọi trạng thái: **ỔN ĐỊNH · ẤN ĐỘ · ẪM · Ở ĐÂY CÓ ƯU ĐÃI**.\n\nJetBrains Mono vẽ dấu tiếng Việt bên trong line box của nó, nên `code.default` giữ 14/20. Site này cũng phục vụ bộ ký tự tiếng Việt của font này, nên tiếng Việt trong code không bị chuyển sang font khác.\n\n",
1781
+ "frontmatter": {
1782
+ "title": "Tiếng Việt",
1783
+ "description": "Line height cao hơn cho chữ tiếng Việt, và cách giữ cho dấu không bị cắt.",
1784
+ "order": 2
1785
+ }
1786
+ },
1787
+ {
1788
+ "id": "vi/foundations/styles/z-index",
1789
+ "path": "src/content-vi/foundations/styles/z-index.mdx",
1790
+ "documentPath": "docs/src/content-vi/foundations/styles/z-index.mdx",
1791
+ "locale": "vi",
1792
+ "kind": "guidance",
1793
+ "title": "Z-index",
1794
+ "status": "planned",
1795
+ "releasePhase": null,
1796
+ "planned": [
1797
+ "Tên các lớp và thứ tự",
1798
+ "Mỗi lớp phủ dùng lớp nào: dropdown, popover, tooltip, dialog, drawer, toast",
1799
+ "Lớp và đổ bóng đi cùng nhau thế nào"
1800
+ ],
1801
+ "body": "",
1802
+ "raw": "---\ntitle: \"Z-index\"\ndescription: \"Thứ tự các lớp chồng lên nhau: cái gì nằm trên cái gì, từ header dính đầu trang tới dialog và toast.\"\norder: 8.5\nplanned:\n - \"Tên các lớp và thứ tự\"\n - \"Mỗi lớp phủ dùng lớp nào: dropdown, popover, tooltip, dialog, drawer, toast\"\n - \"Lớp và đổ bóng đi cùng nhau thế nào\"\n---\n",
1803
+ "frontmatter": {
1804
+ "title": "Z-index",
1805
+ "description": "Thứ tự các lớp chồng lên nhau: cái gì nằm trên cái gì, từ header dính đầu trang tới dialog và toast.",
1806
+ "order": 8.5,
1807
+ "planned": [
1808
+ "Tên các lớp và thứ tự",
1809
+ "Mỗi lớp phủ dùng lớp nào: dropdown, popover, tooltip, dialog, drawer, toast",
1810
+ "Lớp và đổ bóng đi cùng nhau thế nào"
1811
+ ]
1812
+ }
1813
+ }
1814
+ ]