@beehexa/design-rules 0.0.0-stage → 2611.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -2
- package/dist/AGENTS.md +24 -0
- package/dist/catalog.json +1814 -0
- package/dist/docs/public/_redirects +7 -0
- package/dist/docs/public/apple-touch-icon.png +0 -0
- package/dist/docs/public/brand/logos/app/apple-touch-icon.png +0 -0
- package/dist/docs/public/brand/logos/app/avatar-800.png +0 -0
- package/dist/docs/public/brand/logos/app/icon-192.png +0 -0
- package/dist/docs/public/brand/logos/app/icon-512.png +0 -0
- package/dist/docs/public/brand/logos/app/icon-maskable-512.png +0 -0
- package/dist/docs/public/brand/logos/archive/d-550/beehexa-horizontal-1-light.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/beehexa-horizontal-2-dark.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/beehexa-horizontal-3-white.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/beehexa-horizontal-4-graphite.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/hexasync-horizontal-1-light.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/hexasync-horizontal-2-dark.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/hexasync-horizontal-3-white.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/hexasync-horizontal-4-graphite.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/ui/beehexa-d-550-dark.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/ui/beehexa-d-550-light.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/ui/beehexa-design-d-550-dark.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/ui/beehexa-design-d-550-light.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/ui/hexasync-d-550-dark.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/ui/hexasync-d-550-light.svg +1 -0
- package/dist/docs/public/brand/logos/archive/d-550/ui/png/beehexa-design-d-550-dark@3x.png +0 -0
- package/dist/docs/public/brand/logos/archive/d-550/ui/png/beehexa-design-d-550-light@3x.png +0 -0
- package/dist/docs/public/brand/logos/beehexa-logo.zip +0 -0
- package/dist/docs/public/brand/logos/fig/anatomy-en.png +0 -0
- package/dist/docs/public/brand/logos/fig/anatomy-vi.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-dark-12.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-dark-14.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-dark-28.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-dark-32.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-dark-56.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-graphite-28.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-graphite-32.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-light-14.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-light-21.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-light-22.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-light-24.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-light-28.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-light-32.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-light-36-7c3aed7c3aed.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-light-36-swap.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-light-36.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-light-56.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-white-20.png +0 -0
- package/dist/docs/public/brand/logos/fig/beehexa-white-32.png +0 -0
- package/dist/docs/public/brand/logos/fig/clearspace.png +0 -0
- package/dist/docs/public/brand/logos/fig/construction-en.png +0 -0
- package/dist/docs/public/brand/logos/fig/construction-vi.png +0 -0
- package/dist/docs/public/brand/logos/fig/container-en.png +0 -0
- package/dist/docs/public/brand/logos/fig/container-vi.png +0 -0
- package/dist/docs/public/brand/logos/fig/hexasync-dark-20.png +0 -0
- package/dist/docs/public/brand/logos/fig/hexasync-dark-28.png +0 -0
- package/dist/docs/public/brand/logos/fig/hexasync-dark-48.png +0 -0
- package/dist/docs/public/brand/logos/fig/hexasync-light-19.png +0 -0
- package/dist/docs/public/brand/logos/fig/hexasync-light-28.png +0 -0
- package/dist/docs/public/brand/logos/fig/hexasync-light-48.png +0 -0
- package/dist/docs/public/brand/logos/fig/icon-graphite-14.png +0 -0
- package/dist/docs/public/brand/logos/fig/icon-graphite-16.png +0 -0
- package/dist/docs/public/brand/logos/fig/icon-light-16.png +0 -0
- package/dist/docs/public/brand/logos/fig/icon-light-24.png +0 -0
- package/dist/docs/public/brand/logos/fig/icon-light-48.png +0 -0
- package/dist/docs/public/brand/logos/fig/icon-light-92.png +0 -0
- package/dist/docs/public/brand/logos/fig/meaning-bee-en.png +0 -0
- package/dist/docs/public/brand/logos/fig/meaning-bee-vi.png +0 -0
- package/dist/docs/public/brand/logos/fig/meaning-outline-en.png +0 -0
- package/dist/docs/public/brand/logos/fig/meaning-outline-vi.png +0 -0
- package/dist/docs/public/brand/logos/fig/meaning-stack-en.png +0 -0
- package/dist/docs/public/brand/logos/fig/meaning-stack-vi.png +0 -0
- package/dist/docs/public/brand/logos/fig/misuse-serif.png +0 -0
- package/dist/docs/public/brand/logos/icon/beehexa-icon-graphite.svg +1 -0
- package/dist/docs/public/brand/logos/icon/beehexa-icon-white.svg +1 -0
- package/dist/docs/public/brand/logos/icon/beehexa-icon-yellow.svg +1 -0
- package/dist/docs/public/brand/logos/lockups/beehexa-horizontal-1-light.svg +1 -0
- package/dist/docs/public/brand/logos/lockups/beehexa-horizontal-2-dark.svg +1 -0
- package/dist/docs/public/brand/logos/lockups/beehexa-horizontal-3-white.svg +1 -0
- package/dist/docs/public/brand/logos/lockups/beehexa-horizontal-4-graphite.svg +1 -0
- package/dist/docs/public/brand/logos/lockups/hexasync-horizontal-1-light.svg +1 -0
- package/dist/docs/public/brand/logos/lockups/hexasync-horizontal-2-dark.svg +1 -0
- package/dist/docs/public/brand/logos/lockups/hexasync-horizontal-3-white.svg +1 -0
- package/dist/docs/public/brand/logos/lockups/hexasync-horizontal-4-graphite.svg +1 -0
- package/dist/docs/public/brand/logos/ui/beehexa-dark.svg +1 -0
- package/dist/docs/public/brand/logos/ui/beehexa-design-dark.svg +1 -0
- package/dist/docs/public/brand/logos/ui/beehexa-design-light.svg +1 -0
- package/dist/docs/public/brand/logos/ui/beehexa-icon-yellow.svg +1 -0
- package/dist/docs/public/brand/logos/ui/beehexa-light.svg +1 -0
- package/dist/docs/public/brand/logos/ui/hexasync-dark.svg +1 -0
- package/dist/docs/public/brand/logos/ui/hexasync-light.svg +1 -0
- package/dist/docs/public/brand/logos/ui/png/beehexa-design-dark@3x.png +0 -0
- package/dist/docs/public/brand/logos/ui/png/beehexa-design-light@3x.png +0 -0
- package/dist/docs/public/favicon.ico +0 -0
- package/dist/docs/public/favicon.svg +1 -0
- package/dist/docs/public/fonts/LICENSE-Inter.txt +93 -0
- package/dist/docs/public/fonts/LICENSE-JetBrainsMono.txt +93 -0
- package/dist/docs/public/fonts/inter-latin-ext-opsz-wght-italic.woff2 +0 -0
- package/dist/docs/public/fonts/inter-latin-ext-opsz-wght-normal.woff2 +0 -0
- package/dist/docs/public/fonts/inter-latin-opsz-wght-italic.woff2 +0 -0
- package/dist/docs/public/fonts/inter-latin-opsz-wght-normal.woff2 +0 -0
- package/dist/docs/public/fonts/inter-vietnamese-opsz-wght-italic.woff2 +0 -0
- package/dist/docs/public/fonts/inter-vietnamese-opsz-wght-normal.woff2 +0 -0
- package/dist/docs/public/fonts/jetbrains-mono-latin-ext-wght-normal.woff2 +0 -0
- package/dist/docs/public/fonts/jetbrains-mono-latin-wght-normal.woff2 +0 -0
- package/dist/docs/public/fonts/jetbrains-mono-vietnamese-wght-normal.woff2 +0 -0
- package/dist/docs/public/icon-192.png +0 -0
- package/dist/docs/public/icon-512.png +0 -0
- package/dist/docs/public/icon-maskable-512.png +0 -0
- package/dist/docs/public/robots.txt +4 -0
- package/dist/docs/public/site.webmanifest +21 -0
- package/dist/docs/scripts/color-pairs.mjs +46 -0
- package/dist/docs/scripts/contrast-exceptions.mjs +6 -0
- package/dist/docs/scripts/token-utils.d.mts +26 -0
- package/dist/docs/scripts/token-utils.mjs +114 -0
- package/dist/docs/src/brand/Beehexa-brandguide-full-mar12.pdf +0 -0
- package/dist/docs/src/brand/color+typoDirections.pdf +0 -0
- package/dist/docs/src/brand/structure-proposal.md +227 -0
- package/dist/docs/src/components/ChildPages.astro +25 -0
- package/dist/docs/src/components/CodeExample.astro +18 -0
- package/dist/docs/src/components/ColorDemo.astro +794 -0
- package/dist/docs/src/components/ColorExample.astro +32 -0
- package/dist/docs/src/components/ColorSwatch.astro +20 -0
- package/dist/docs/src/components/ComponentTabs.astro +21 -0
- package/dist/docs/src/components/DocsFooter.astro +25 -0
- package/dist/docs/src/components/HelpOptions.astro +20 -0
- package/dist/docs/src/components/IconBrowser.astro +257 -0
- package/dist/docs/src/components/IconDemo.astro +185 -0
- package/dist/docs/src/components/InDevelopment.astro +29 -0
- package/dist/docs/src/components/LayoutDemo.astro +384 -0
- package/dist/docs/src/components/Logo.astro +25 -0
- package/dist/docs/src/components/PhaseTable.astro +22 -0
- package/dist/docs/src/components/RoleGuides.astro +48 -0
- package/dist/docs/src/components/ShapeDemo.astro +239 -0
- package/dist/docs/src/components/ShapePin.astro +22 -0
- package/dist/docs/src/components/Sidebar.astro +206 -0
- package/dist/docs/src/components/SiteHeader.astro +211 -0
- package/dist/docs/src/components/SpacingDemo.astro +172 -0
- package/dist/docs/src/components/StatusBadge.astro +22 -0
- package/dist/docs/src/components/SystemAreas.astro +29 -0
- package/dist/docs/src/components/TableOfContents.astro +47 -0
- package/dist/docs/src/components/TokenTable.astro +40 -0
- package/dist/docs/src/components/TypeDemo.astro +249 -0
- package/dist/docs/src/components/logos/Fig.astro +28 -0
- package/dist/docs/src/components/logos/LogoAnatomy.astro +101 -0
- package/dist/docs/src/components/logos/LogoClearSpace.astro +81 -0
- package/dist/docs/src/components/logos/LogoColourVersions.astro +45 -0
- package/dist/docs/src/components/logos/LogoConstruction.astro +84 -0
- package/dist/docs/src/components/logos/LogoContainer.astro +84 -0
- package/dist/docs/src/components/logos/LogoHero.astro +42 -0
- package/dist/docs/src/components/logos/LogoInUse.astro +197 -0
- package/dist/docs/src/components/logos/LogoMeanings.astro +75 -0
- package/dist/docs/src/components/logos/LogoMinSize.astro +55 -0
- package/dist/docs/src/components/logos/LogoMistakes.astro +109 -0
- package/dist/docs/src/components/logos/LogoMisuse.astro +96 -0
- package/dist/docs/src/components/logos/LogoPair.astro +26 -0
- package/dist/docs/src/components/logos/LogoSvg.astro +68 -0
- package/dist/docs/src/content/components/button/accessibility.mdx +18 -0
- package/dist/docs/src/content/components/button/changelog.mdx +6 -0
- package/dist/docs/src/content/components/button/code.mdx +27 -0
- package/dist/docs/src/content/components/button/examples.mdx +21 -0
- package/dist/docs/src/content/components/button/meta.json +5 -0
- package/dist/docs/src/content/components/button/usage.mdx +18 -0
- package/dist/docs/src/content/foundations/guidelines/accessibility.mdx +19 -0
- package/dist/docs/src/content/foundations/guidelines/content.mdx +25 -0
- package/dist/docs/src/content/foundations/index.mdx +9 -0
- package/dist/docs/src/content/foundations/styles/border.mdx +89 -0
- package/dist/docs/src/content/foundations/styles/color/accessibility.mdx +32 -0
- package/dist/docs/src/content/foundations/styles/color/dark-mode.mdx +22 -0
- package/dist/docs/src/content/foundations/styles/color/index.mdx +65 -0
- package/dist/docs/src/content/foundations/styles/color/palette.mdx +57 -0
- package/dist/docs/src/content/foundations/styles/color/tokens.mdx +55 -0
- package/dist/docs/src/content/foundations/styles/color/usage.mdx +111 -0
- package/dist/docs/src/content/foundations/styles/data-visualization.mdx +11 -0
- package/dist/docs/src/content/foundations/styles/elevation.mdx +12 -0
- package/dist/docs/src/content/foundations/styles/icons/accessibility.mdx +72 -0
- package/dist/docs/src/content/foundations/styles/icons/code.mdx +171 -0
- package/dist/docs/src/content/foundations/styles/icons/index.mdx +62 -0
- package/dist/docs/src/content/foundations/styles/icons/library.mdx +19 -0
- package/dist/docs/src/content/foundations/styles/icons/usage.mdx +100 -0
- package/dist/docs/src/content/foundations/styles/illustration.mdx +9 -0
- package/dist/docs/src/content/foundations/styles/interaction-states.mdx +49 -0
- package/dist/docs/src/content/foundations/styles/layout/app-frame.mdx +81 -0
- package/dist/docs/src/content/foundations/styles/layout/breakpoints.mdx +56 -0
- package/dist/docs/src/content/foundations/styles/layout/grid.mdx +87 -0
- package/dist/docs/src/content/foundations/styles/layout/index.mdx +24 -0
- package/dist/docs/src/content/foundations/styles/layout/overlays.mdx +45 -0
- package/dist/docs/src/content/foundations/styles/layout/page-widths.mdx +38 -0
- package/dist/docs/src/content/foundations/styles/logos/downloads-and-terms.mdx +65 -0
- package/dist/docs/src/content/foundations/styles/logos/index.mdx +64 -0
- package/dist/docs/src/content/foundations/styles/logos/placement-and-containers.mdx +96 -0
- package/dist/docs/src/content/foundations/styles/logos/product-logos.mdx +56 -0
- package/dist/docs/src/content/foundations/styles/logos/using-the-logo.mdx +70 -0
- package/dist/docs/src/content/foundations/styles/motion.mdx +11 -0
- package/dist/docs/src/content/foundations/styles/opacity.mdx +9 -0
- package/dist/docs/src/content/foundations/styles/radius.mdx +98 -0
- package/dist/docs/src/content/foundations/styles/size-and-density.mdx +41 -0
- package/dist/docs/src/content/foundations/styles/spacing.mdx +70 -0
- package/dist/docs/src/content/foundations/styles/typography/code.mdx +53 -0
- package/dist/docs/src/content/foundations/styles/typography/index.mdx +58 -0
- package/dist/docs/src/content/foundations/styles/typography/usage.mdx +144 -0
- package/dist/docs/src/content/foundations/styles/typography/vietnamese.mdx +46 -0
- package/dist/docs/src/content/foundations/styles/z-index.mdx +9 -0
- package/dist/docs/src/content/foundations/tokens/all-tokens.mdx +36 -0
- package/dist/docs/src/content/foundations/tokens/index.mdx +27 -0
- package/dist/docs/src/content/get-started/content.mdx +14 -0
- package/dist/docs/src/content/get-started/design.mdx +30 -0
- package/dist/docs/src/content/get-started/develop.mdx +59 -0
- package/dist/docs/src/content/get-started/get-help.mdx +19 -0
- package/dist/docs/src/content/get-started/index.mdx +50 -0
- package/dist/docs/src/content/news/2026-10-16-site-structure.md +15 -0
- package/dist/docs/src/content/news/2026-10-20-docs-site.md +13 -0
- package/dist/docs/src/content/release-phases/index.mdx +12 -0
- package/dist/docs/src/content/tools/ai-agents.mdx +49 -0
- package/dist/docs/src/content/tools/ant-design-vue-theme.mdx +138 -0
- package/dist/docs/src/content/tools/eslint.mdx +15 -0
- package/dist/docs/src/content/tools/index.mdx +7 -0
- package/dist/docs/src/content/tools/stylelint.mdx +19 -0
- package/dist/docs/src/content-vi/foundations/styles/border.mdx +89 -0
- package/dist/docs/src/content-vi/foundations/styles/color/accessibility.mdx +32 -0
- package/dist/docs/src/content-vi/foundations/styles/color/dark-mode.mdx +22 -0
- package/dist/docs/src/content-vi/foundations/styles/color/index.mdx +65 -0
- package/dist/docs/src/content-vi/foundations/styles/color/palette.mdx +57 -0
- package/dist/docs/src/content-vi/foundations/styles/color/tokens.mdx +55 -0
- package/dist/docs/src/content-vi/foundations/styles/color/usage.mdx +111 -0
- package/dist/docs/src/content-vi/foundations/styles/data-visualization.mdx +11 -0
- package/dist/docs/src/content-vi/foundations/styles/icons/accessibility.mdx +72 -0
- package/dist/docs/src/content-vi/foundations/styles/icons/code.mdx +170 -0
- package/dist/docs/src/content-vi/foundations/styles/icons/index.mdx +62 -0
- package/dist/docs/src/content-vi/foundations/styles/icons/library.mdx +19 -0
- package/dist/docs/src/content-vi/foundations/styles/icons/usage.mdx +100 -0
- package/dist/docs/src/content-vi/foundations/styles/illustration.mdx +9 -0
- package/dist/docs/src/content-vi/foundations/styles/interaction-states.mdx +49 -0
- package/dist/docs/src/content-vi/foundations/styles/layout/app-frame.mdx +77 -0
- package/dist/docs/src/content-vi/foundations/styles/layout/breakpoints.mdx +56 -0
- package/dist/docs/src/content-vi/foundations/styles/layout/grid.mdx +87 -0
- package/dist/docs/src/content-vi/foundations/styles/layout/index.mdx +24 -0
- package/dist/docs/src/content-vi/foundations/styles/layout/page-widths.mdx +34 -0
- package/dist/docs/src/content-vi/foundations/styles/logos/downloads-and-terms.mdx +65 -0
- package/dist/docs/src/content-vi/foundations/styles/logos/index.mdx +64 -0
- package/dist/docs/src/content-vi/foundations/styles/logos/placement-and-containers.mdx +96 -0
- package/dist/docs/src/content-vi/foundations/styles/logos/product-logos.mdx +56 -0
- package/dist/docs/src/content-vi/foundations/styles/logos/using-the-logo.mdx +70 -0
- package/dist/docs/src/content-vi/foundations/styles/opacity.mdx +9 -0
- package/dist/docs/src/content-vi/foundations/styles/radius.mdx +98 -0
- package/dist/docs/src/content-vi/foundations/styles/size-and-density.mdx +41 -0
- package/dist/docs/src/content-vi/foundations/styles/spacing.mdx +70 -0
- package/dist/docs/src/content-vi/foundations/styles/typography/code.mdx +53 -0
- package/dist/docs/src/content-vi/foundations/styles/typography/index.mdx +58 -0
- package/dist/docs/src/content-vi/foundations/styles/typography/usage.mdx +144 -0
- package/dist/docs/src/content-vi/foundations/styles/typography/vietnamese.mdx +46 -0
- package/dist/docs/src/content-vi/foundations/styles/z-index.mdx +9 -0
- package/dist/docs/src/content.config.ts +68 -0
- package/dist/docs/src/lib/brand.ts +57 -0
- package/dist/docs/src/lib/contrast.ts +34 -0
- package/dist/docs/src/lib/i18n.ts +152 -0
- package/dist/docs/src/lib/icons.ts +46 -0
- package/dist/docs/src/lib/logo-geometry.ts +30 -0
- package/dist/docs/src/lib/lucide-categories.json +1 -0
- package/dist/docs/src/lib/lucide-data.ts +40 -0
- package/dist/docs/src/lib/navigation.ts +222 -0
- package/dist/docs/src/lib/release-phases.ts +10 -0
- package/dist/docs/src/lib/routes.ts +40 -0
- package/dist/docs/src/lib/token-descriptions-vi.ts +40 -0
- package/dist/docs/src/lib/tokens.ts +67 -0
- package/dist/docs/src/lib/tri-grid.ts +28 -0
- package/dist/docs/src/styles/chrome.css +122 -0
- package/dist/docs/src/styles/color.css +270 -0
- package/dist/docs/src/styles/docs.css +323 -0
- package/dist/docs/src/styles/global.css +66 -0
- package/dist/docs/src/styles/icons.css +135 -0
- package/dist/docs/src/styles/layout.css +165 -0
- package/dist/docs/src/styles/logos.css +236 -0
- package/dist/docs/src/styles/shapes.css +139 -0
- package/dist/docs/src/styles/tokens.css +461 -0
- package/dist/docs/src/styles/tokens.js +425 -0
- package/dist/docs/src/styles/typography.css +91 -0
- package/dist/docs/tokens/border.json +26 -0
- package/dist/docs/tokens/breakpoints.json +8 -0
- package/dist/docs/tokens/color.json +1350 -0
- package/dist/docs/tokens/elevation.json +26 -0
- package/dist/docs/tokens/layout.json +29 -0
- package/dist/docs/tokens/motion.json +12 -0
- package/dist/docs/tokens/radius.json +44 -0
- package/dist/docs/tokens/size.json +13 -0
- package/dist/docs/tokens/spacing.json +18 -0
- package/dist/docs/tokens/states.json +12 -0
- package/dist/docs/tokens/typography.json +220 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +1823 -0
- package/package.json +31 -4
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { areaOf, sectionOf, siteAreas } from '../lib/navigation';
|
|
3
|
+
import { basePath, langOf, localize, t, viPublic } from '../lib/i18n';
|
|
4
|
+
|
|
5
|
+
// Header logo: "beehexa design", PNG drawn at 3× and shrunk by the browser to a 24 px icon
|
|
6
|
+
// (28 px image: 2 px above and below the icon, so the icon is its centre; the "g" of "design"
|
|
7
|
+
// hangs into the bottom 2 px). Shrinking a larger picture
|
|
8
|
+
// softens the edges a little, which hides the stair steps of the 30° edges on 100% scale
|
|
9
|
+
// screens. One image per tone (light, dark); chrome.css shows the one for the page theme. At 188 px wide it fits next to the section links at every width, so there is no
|
|
10
|
+
// shorter version. Never crop the image to the ink: the "g" then loses its bottom row.
|
|
11
|
+
const png = (kind: string, tone: string) => `/brand/logos/ui/png/${kind}-${tone}@3x.png`;
|
|
12
|
+
const tones = ['light', 'dark'] as const;
|
|
13
|
+
import '../styles/chrome.css';
|
|
14
|
+
// Icons: Lucide (decision 26). 16 px next to 14 px text, 20 px in the header toolbar.
|
|
15
|
+
import SearchIcon from '@lucide/astro/icons/search';
|
|
16
|
+
import Moon from '@lucide/astro/icons/moon';
|
|
17
|
+
import Sun from '@lucide/astro/icons/sun';
|
|
18
|
+
import Menu from '@lucide/astro/icons/menu';
|
|
19
|
+
|
|
20
|
+
const lang = langOf(Astro.url.pathname);
|
|
21
|
+
const T = t(lang);
|
|
22
|
+
const base = basePath(Astro.url.pathname);
|
|
23
|
+
const current = areaOf(sectionOf(base));
|
|
24
|
+
const areaLabel = (id: string) => (id === 'news' ? T.news : T.designSystem);
|
|
25
|
+
// The same page in the other language.
|
|
26
|
+
const otherLang = lang === 'vi' ? 'en' : 'vi';
|
|
27
|
+
const otherHref = localize(base, otherLang);
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
<header class="site-header">
|
|
31
|
+
<div class="header-inner">
|
|
32
|
+
<a class="header-brand" href={localize('/get-started/', lang)} aria-label={`beehexa design – ${T.home}`}>
|
|
33
|
+
{tones.map((t) => <img class:list={['header-logo-img', `logo-${t}`]} src={png('beehexa-design', t)} alt="" height="28" />)}
|
|
34
|
+
</a>
|
|
35
|
+
|
|
36
|
+
<nav class="header-nav" aria-label="Site">
|
|
37
|
+
{siteAreas.map((area) => (
|
|
38
|
+
<a href={localize(area.href, lang)} aria-current={area.id === current ? 'page' : undefined}>{areaLabel(area.id)}</a>
|
|
39
|
+
))}
|
|
40
|
+
</nav>
|
|
41
|
+
|
|
42
|
+
<div class="header-tools">
|
|
43
|
+
<div class="search" data-search>
|
|
44
|
+
<SearchIcon size={16} class="search-icon" />
|
|
45
|
+
<input
|
|
46
|
+
type="search"
|
|
47
|
+
placeholder={T.search}
|
|
48
|
+
aria-label={T.searchLabel}
|
|
49
|
+
role="combobox"
|
|
50
|
+
aria-expanded="false"
|
|
51
|
+
aria-controls="search-results"
|
|
52
|
+
aria-autocomplete="list"
|
|
53
|
+
autocomplete="off"
|
|
54
|
+
data-search-input
|
|
55
|
+
/>
|
|
56
|
+
<kbd class="search-hint" aria-hidden="true">Ctrl K</kbd>
|
|
57
|
+
<ul data-empty={T.searchEmpty} class="search-results" id="search-results" role="listbox" aria-label={T.search} hidden data-search-results></ul>
|
|
58
|
+
</div>
|
|
59
|
+
<button class="icon-button search-open" type="button" aria-label={T.search} data-search-open>
|
|
60
|
+
<SearchIcon size={20} />
|
|
61
|
+
</button>
|
|
62
|
+
{viPublic && <a class="icon-button lang-switch" href={otherHref} hreflang={otherLang} lang={otherLang} aria-label={T.otherLang} title={T.otherLang}>{T.otherLangShort}</a>}
|
|
63
|
+
<button class="icon-button" type="button" aria-label={T.themeDark} data-theme-toggle data-label-dark={T.themeDark} data-label-light={T.themeLight}>
|
|
64
|
+
<Moon size={20} class="theme-moon" />
|
|
65
|
+
<Sun size={20} class="theme-sun" />
|
|
66
|
+
</button>
|
|
67
|
+
<details class="header-menu">
|
|
68
|
+
<summary class="icon-button" aria-label={T.menu}>
|
|
69
|
+
<Menu size={20} />
|
|
70
|
+
</summary>
|
|
71
|
+
<nav aria-label="Site">
|
|
72
|
+
{siteAreas.map((area) => (
|
|
73
|
+
<a href={localize(area.href, lang)} aria-current={area.id === current ? 'page' : undefined}>{areaLabel(area.id)}</a>
|
|
74
|
+
))}
|
|
75
|
+
{viPublic && <a class="menu-lang" href={otherHref} hreflang={otherLang} lang={otherLang}>{T.otherLang}</a>}
|
|
76
|
+
</nav>
|
|
77
|
+
</details>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</header>
|
|
81
|
+
|
|
82
|
+
<script>
|
|
83
|
+
type Page = { title: string; section: string; description: string; href: string };
|
|
84
|
+
|
|
85
|
+
const root = document.querySelector<HTMLElement>('[data-search]')!;
|
|
86
|
+
const input = root.querySelector<HTMLInputElement>('[data-search-input]')!;
|
|
87
|
+
const list = root.querySelector<HTMLUListElement>('[data-search-results]')!;
|
|
88
|
+
let pages: Page[] | undefined;
|
|
89
|
+
let results: Page[] = [];
|
|
90
|
+
let active = -1;
|
|
91
|
+
|
|
92
|
+
async function load() {
|
|
93
|
+
if (pages) return pages;
|
|
94
|
+
const response = await fetch('/search.json');
|
|
95
|
+
pages = (await response.json()) as Page[];
|
|
96
|
+
return pages;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function score(page: Page, words: string[]) {
|
|
100
|
+
const title = page.title.toLowerCase();
|
|
101
|
+
const text = `${title} ${page.section} ${page.description}`.toLowerCase();
|
|
102
|
+
if (!words.every((word) => text.includes(word))) return 0;
|
|
103
|
+
return words.reduce((sum, word) => sum + (title.startsWith(word) ? 4 : title.includes(word) ? 2 : 1), 0);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function render() {
|
|
107
|
+
list.replaceChildren();
|
|
108
|
+
if (!input.value.trim()) {
|
|
109
|
+
list.hidden = true;
|
|
110
|
+
input.setAttribute('aria-expanded', 'false');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (results.length === 0) {
|
|
114
|
+
const empty = document.createElement('li');
|
|
115
|
+
empty.className = 'search-empty';
|
|
116
|
+
empty.textContent = list.dataset.empty ?? '';
|
|
117
|
+
list.append(empty);
|
|
118
|
+
}
|
|
119
|
+
results.forEach((page, index) => {
|
|
120
|
+
const item = document.createElement('li');
|
|
121
|
+
item.id = `search-result-${index}`;
|
|
122
|
+
item.setAttribute('role', 'option');
|
|
123
|
+
item.setAttribute('aria-selected', String(index === active));
|
|
124
|
+
const link = document.createElement('a');
|
|
125
|
+
link.href = document.documentElement.lang === 'vi' ? `/vi${page.href}` : page.href;
|
|
126
|
+
link.tabIndex = -1;
|
|
127
|
+
const title = document.createElement('b');
|
|
128
|
+
title.textContent = page.title;
|
|
129
|
+
const meta = document.createElement('span');
|
|
130
|
+
meta.textContent = page.section;
|
|
131
|
+
link.append(title, meta);
|
|
132
|
+
item.append(link);
|
|
133
|
+
list.append(item);
|
|
134
|
+
});
|
|
135
|
+
list.hidden = false;
|
|
136
|
+
input.setAttribute('aria-expanded', 'true');
|
|
137
|
+
input.setAttribute('aria-activedescendant', active >= 0 ? `search-result-${active}` : '');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
input.addEventListener('focus', () => void load());
|
|
141
|
+
input.addEventListener('input', async () => {
|
|
142
|
+
const words = input.value.toLowerCase().split(/\s+/).filter(Boolean);
|
|
143
|
+
const all = await load();
|
|
144
|
+
results = all
|
|
145
|
+
.map((page) => ({ page, s: score(page, words) }))
|
|
146
|
+
.filter((row) => row.s > 0)
|
|
147
|
+
.sort((a, b) => b.s - a.s)
|
|
148
|
+
.slice(0, 8)
|
|
149
|
+
.map((row) => row.page);
|
|
150
|
+
active = results.length ? 0 : -1;
|
|
151
|
+
render();
|
|
152
|
+
});
|
|
153
|
+
input.addEventListener('keydown', (event) => {
|
|
154
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
155
|
+
event.preventDefault();
|
|
156
|
+
if (!results.length) return;
|
|
157
|
+
active = (active + (event.key === 'ArrowDown' ? 1 : -1) + results.length) % results.length;
|
|
158
|
+
render();
|
|
159
|
+
} else if (event.key === 'Enter' && results[active]) {
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
location.href = document.documentElement.lang === 'vi' ? `/vi${results[active].href}` : results[active].href;
|
|
162
|
+
} else if (event.key === 'Escape') {
|
|
163
|
+
input.value = '';
|
|
164
|
+
results = [];
|
|
165
|
+
render();
|
|
166
|
+
document.body.removeAttribute('data-search-open');
|
|
167
|
+
input.blur();
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
document.addEventListener('click', (event) => {
|
|
171
|
+
if (!root.contains(event.target as Node)) {
|
|
172
|
+
list.hidden = true;
|
|
173
|
+
input.setAttribute('aria-expanded', 'false');
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
document.addEventListener('keydown', (event) => {
|
|
177
|
+
if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'k') {
|
|
178
|
+
event.preventDefault();
|
|
179
|
+
document.body.setAttribute('data-search-open', '');
|
|
180
|
+
input.focus();
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
document.querySelector('[data-search-open]')?.addEventListener('click', () => {
|
|
184
|
+
document.body.setAttribute('data-search-open', '');
|
|
185
|
+
input.focus();
|
|
186
|
+
});
|
|
187
|
+
input.addEventListener('blur', () => {
|
|
188
|
+
setTimeout(() => {
|
|
189
|
+
if (!root.contains(document.activeElement)) document.body.removeAttribute('data-search-open');
|
|
190
|
+
}, 150);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
const isMac = /Mac|iPhone|iPad/.test(navigator.platform);
|
|
194
|
+
if (isMac) root.querySelector('.search-hint')!.textContent = '⌘ K';
|
|
195
|
+
|
|
196
|
+
const toggle = document.querySelector<HTMLButtonElement>('[data-theme-toggle]');
|
|
197
|
+
const sync = () => {
|
|
198
|
+
const dark = document.documentElement.dataset.theme === 'dark';
|
|
199
|
+
toggle?.setAttribute('aria-label', (dark ? toggle!.dataset.labelLight : toggle!.dataset.labelDark) ?? '');
|
|
200
|
+
document.querySelector('meta[name="theme-color"]')?.setAttribute('content', getComputedStyle(document.documentElement).getPropertyValue('--bh-color-surface-page').trim() || (dark ? '#181717' : '#ffffff'));
|
|
201
|
+
};
|
|
202
|
+
sync();
|
|
203
|
+
toggle?.addEventListener('click', () => {
|
|
204
|
+
const next = document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark';
|
|
205
|
+
document.documentElement.dataset.theme = next;
|
|
206
|
+
try {
|
|
207
|
+
localStorage.setItem('bh-theme', next);
|
|
208
|
+
} catch {}
|
|
209
|
+
sync();
|
|
210
|
+
});
|
|
211
|
+
</script>
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Illustrations for the Spacing page. Sizes come from tokens/spacing.json through the CSS
|
|
3
|
+
// variables, so every bar and gap on the page is the real value.
|
|
4
|
+
import '../styles/layout.css';
|
|
5
|
+
import { tokensByPrefix } from '../lib/tokens';
|
|
6
|
+
import { tokenDescriptionsVi } from '../lib/token-descriptions-vi';
|
|
7
|
+
import { langOf } from '../lib/i18n';
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
kind: 'scale' | 'anatomy' | 'padding-gap' | 'dodont';
|
|
11
|
+
/** For kind="dodont": which pair to show. */
|
|
12
|
+
item?: 'scale' | 'grouping' | 'nudge';
|
|
13
|
+
}
|
|
14
|
+
const { kind, item } = Astro.props;
|
|
15
|
+
const vi = langOf(Astro.url.pathname) === 'vi';
|
|
16
|
+
const L = (en: string, viText: string) => (vi ? viText : en);
|
|
17
|
+
|
|
18
|
+
// Rem to px at the default 16 px root size.
|
|
19
|
+
const toPx = (value: string) => (value.endsWith('rem') ? parseFloat(value) * 16 : parseFloat(value) || 0);
|
|
20
|
+
const scale = tokensByPrefix('space')
|
|
21
|
+
.map((t) => ({ ...t, px: toPx(t.resolved), use: (vi ? tokenDescriptionsVi[t.name] ?? t.description : t.description).replace(/^\d+( px)?\. /, '') }))
|
|
22
|
+
.sort((a, b) => a.px - b.px);
|
|
23
|
+
|
|
24
|
+
const store = '<svg class="sp-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 9l1.5-5h15L21 9"/><path d="M4 9v11h16V9"/><path d="M3 9h18"/><path d="M9 20v-6h6v6"/></svg>';
|
|
25
|
+
const bell = '<svg class="sp-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg>';
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
{kind === 'scale' && (
|
|
29
|
+
<ul class="sp-scale sp-root" aria-label={L('Spacing scale', 'Thang khoảng cách')}>
|
|
30
|
+
{scale.map((t) => (
|
|
31
|
+
<li>
|
|
32
|
+
<span class="sp-name"><code>{t.name}</code><span class="sp-var">{t.cssVar}</span></span>
|
|
33
|
+
<span class="sp-px">{t.px} px<small>{t.resolved}</small></span>
|
|
34
|
+
<span class="sp-bar-cell" aria-hidden="true">
|
|
35
|
+
<span class:list={['sp-bar', { 'is-zero': t.px === 0, 'is-hairline': t.px > 0 && t.px < 4 }]} style={t.px === 0 ? undefined : `width: var(${t.cssVar})`}></span>
|
|
36
|
+
</span>
|
|
37
|
+
<span class="sp-use">{t.use}</span>
|
|
38
|
+
</li>
|
|
39
|
+
))}
|
|
40
|
+
</ul>
|
|
41
|
+
)}
|
|
42
|
+
|
|
43
|
+
{kind === 'anatomy' && (
|
|
44
|
+
<figure class="sp-figure sp-root">
|
|
45
|
+
<div class="sp-stage">
|
|
46
|
+
<div class="sp-card" role="img" aria-label={L('A card for connecting an online store, with each space marked: 24 px card padding, 4 px between the icon and the title and between the title and the description, 20 px under the heading, 8 px between each label and its field, 12 px inside the field, 16 px between fields, 32 px before the buttons and 8 px between them.', 'Card kết nối cửa hàng online, có đánh dấu từng khoảng: padding card 24 px, 4 px giữa icon và tiêu đề và giữa tiêu đề và mô tả, 20 px dưới tiêu đề, 8 px giữa nhãn và ô nhập, 12 px bên trong ô nhập, 16 px giữa các ô nhập, 32 px trước các nút và 8 px giữa hai nút.')}>
|
|
47
|
+
<div class="sp-card-pad sp-stack">
|
|
48
|
+
<span class="sp-tag">24</span>
|
|
49
|
+
<div class="sp-row">
|
|
50
|
+
<Fragment set:html={store} />
|
|
51
|
+
<span class="sp-gap is-h" style="width: var(--bh-space-050)"><span class="sp-tag">4</span></span>
|
|
52
|
+
<span class="sp-title">{L('Online store', 'Cửa hàng online')}</span>
|
|
53
|
+
</div>
|
|
54
|
+
<span class="sp-gap is-v" style="height: var(--bh-space-050)"><span class="sp-tag">4</span></span>
|
|
55
|
+
<span class="sp-desc">{L('Connect the store to sync orders and stock.', 'Kết nối cửa hàng để đồng bộ đơn hàng và tồn kho.')}</span>
|
|
56
|
+
<span class="sp-gap is-v" style="height: var(--bh-space-250)"><span class="sp-tag">20</span></span>
|
|
57
|
+
<span class="sp-label">{L('Store URL', 'URL cửa hàng')}</span>
|
|
58
|
+
<span class="sp-gap is-v" style="height: var(--bh-space-100)"><span class="sp-tag">8</span></span>
|
|
59
|
+
<span class="sp-input">
|
|
60
|
+
<span class="sp-gap is-h" style="width: var(--bh-space-150)"><span class="sp-tag is-below">12</span></span>
|
|
61
|
+
<span>mystore.example.com</span>
|
|
62
|
+
</span>
|
|
63
|
+
<span class="sp-gap is-v" style="height: var(--bh-space-200)"><span class="sp-tag">16</span></span>
|
|
64
|
+
<span class="sp-label">{L('API key', 'API key')}</span>
|
|
65
|
+
<span class="sp-gap is-v" style="height: var(--bh-space-100)"><span class="sp-tag">8</span></span>
|
|
66
|
+
<span class="sp-input">
|
|
67
|
+
<span class="sp-gap is-h" style="width: var(--bh-space-150)"></span>
|
|
68
|
+
<span>{L('Paste the key from the store', 'Dán key lấy từ cửa hàng')}</span>
|
|
69
|
+
</span>
|
|
70
|
+
<span class="sp-gap is-v" style="height: var(--bh-space-400)"><span class="sp-tag">32</span></span>
|
|
71
|
+
<div class="sp-row is-end">
|
|
72
|
+
<span class="sp-btn">{L('Cancel', 'Huỷ')}</span>
|
|
73
|
+
<span class="sp-gap is-h" style="width: var(--bh-space-100)"><span class="sp-tag">8</span></span>
|
|
74
|
+
<span class="sp-btn is-primary">{L('Connect', 'Kết nối')}</span>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
<figcaption><span class="sp-legend"><span class="sp-swatch" aria-hidden="true"></span> {L('Tinted areas are space, marked in px. Small steps hold things that belong together; large steps separate groups.', 'Vùng tô màu là khoảng trống, ghi bằng px. Bậc nhỏ giữ các thứ thuộc về nhau ở gần nhau; bậc lớn tách các nhóm.')}</span></figcaption>
|
|
80
|
+
</figure>
|
|
81
|
+
)}
|
|
82
|
+
|
|
83
|
+
{kind === 'padding-gap' && (
|
|
84
|
+
<div class="sp-pair sp-root">
|
|
85
|
+
<figure>
|
|
86
|
+
<div class="sp-pair-stage"><span class="sp-padbox">{L('Card content', 'Nội dung card')}</span></div>
|
|
87
|
+
<figcaption><b>Padding</b><span>{L('Space inside an element, between its edge and its content. Set on the element.', 'Khoảng trống bên trong một phần tử, giữa mép và nội dung của nó. Đặt trên chính phần tử đó.')}</span></figcaption>
|
|
88
|
+
</figure>
|
|
89
|
+
<figure>
|
|
90
|
+
<div class="sp-pair-stage">
|
|
91
|
+
<span class="sp-row">
|
|
92
|
+
<span class="sp-chip">{L('Orders', 'Đơn hàng')}</span>
|
|
93
|
+
<span class="sp-gap is-h" style="width: var(--bh-space-100)"></span>
|
|
94
|
+
<span class="sp-chip">{L('Products', 'Sản phẩm')}</span>
|
|
95
|
+
<span class="sp-gap is-h" style="width: var(--bh-space-100)"></span>
|
|
96
|
+
<span class="sp-chip">{L('Stock', 'Tồn kho')}</span>
|
|
97
|
+
</span>
|
|
98
|
+
</div>
|
|
99
|
+
<figcaption><b>Gap</b><span>{vi ? <Fragment>Khoảng trống giữa các phần tử. Đặt trên phần tử cha bằng <code>gap</code>, không dùng margin trên phần tử con.</Fragment> : <Fragment>Space between elements. Set on their parent with <code>gap</code>, never as margins on the children.</Fragment>}</span></figcaption>
|
|
100
|
+
</figure>
|
|
101
|
+
</div>
|
|
102
|
+
)}
|
|
103
|
+
|
|
104
|
+
{kind === 'dodont' && (
|
|
105
|
+
<div class="sp-dd sp-root">
|
|
106
|
+
<figure class="sp-dd-panel is-do">
|
|
107
|
+
<figcaption><span aria-hidden="true">✓</span> {L('Do', 'Nên')}</figcaption>
|
|
108
|
+
<div class="sp-dd-stage">
|
|
109
|
+
{item === 'scale' && (<code>gap: var(--bh-space-200);<br />padding: var(--bh-space-300);</code>)}
|
|
110
|
+
{item === 'grouping' && (
|
|
111
|
+
<div class="sp-mini" role="img" aria-label={L('Two groups of fields: each label sits 8 px above its field, fields are 16 px apart and the groups 32 px apart.', 'Hai nhóm ô nhập: nhãn cách ô của nó 8 px, các ô cách nhau 16 px và các nhóm cách nhau 32 px.')}>
|
|
112
|
+
<span class="sp-mini-group">{L('Store', 'Cửa hàng')}</span>
|
|
113
|
+
<span style="height: var(--bh-space-100)"></span>
|
|
114
|
+
<span class="sp-label">{L('Store URL', 'URL cửa hàng')}</span>
|
|
115
|
+
<span style="height: var(--bh-space-100)"></span>
|
|
116
|
+
<span class="sp-input"><span style="width: var(--bh-space-150)"></span><span>mystore.example.com</span></span>
|
|
117
|
+
<span style="height: var(--bh-space-400)"></span>
|
|
118
|
+
<span class="sp-mini-group">{L('Sync', 'Đồng bộ')}</span>
|
|
119
|
+
<span style="height: var(--bh-space-100)"></span>
|
|
120
|
+
<span class="sp-label">{L('Every', 'Mỗi')}</span>
|
|
121
|
+
<span style="height: var(--bh-space-100)"></span>
|
|
122
|
+
<span class="sp-input"><span style="width: var(--bh-space-150)"></span><span>{L('15 minutes', '15 phút')}</span></span>
|
|
123
|
+
</div>
|
|
124
|
+
)}
|
|
125
|
+
{item === 'nudge' && (
|
|
126
|
+
<span class="sp-dd-row" style="gap: var(--bh-space-100)">
|
|
127
|
+
<span class="sp-badge-host" role="img" aria-label={L('Bell icon with a red dot 2 px from its corner', 'Icon chuông với chấm đỏ cách góc 2 px')}><Fragment set:html={bell} /><span class="sp-badge"></span></span>
|
|
128
|
+
<span class="sp-btn">{L('Cancel', 'Huỷ')}</span>
|
|
129
|
+
<span class="sp-btn is-primary">{L('Save', 'Lưu')}</span>
|
|
130
|
+
</span>
|
|
131
|
+
)}
|
|
132
|
+
</div>
|
|
133
|
+
<p>
|
|
134
|
+
{item === 'scale' && L('Use a spacing token for every padding, gap and margin.', 'Dùng token khoảng cách cho mọi padding, gap và margin.')}
|
|
135
|
+
{item === 'grouping' && L('Put a label closer to its own field than to anything else, and groups further apart than fields.', 'Đặt nhãn gần ô của nó hơn mọi thứ khác, và các nhóm cách xa nhau hơn các ô.')}
|
|
136
|
+
{item === 'nudge' && L('Use 2 px only to nudge a badge or a dot. Buttons stay 8 px apart.', 'Chỉ dùng 2 px để xê dịch badge hoặc chấm. Các nút vẫn cách nhau 8 px.')}
|
|
137
|
+
</p>
|
|
138
|
+
</figure>
|
|
139
|
+
<figure class="sp-dd-panel is-dont">
|
|
140
|
+
<figcaption><span aria-hidden="true">✕</span> {L('Don’t', 'Không nên')}</figcaption>
|
|
141
|
+
<div class="sp-dd-stage">
|
|
142
|
+
{item === 'scale' && (<code>gap: 18px;<br />padding: 13px 22px;</code>)}
|
|
143
|
+
{item === 'grouping' && (
|
|
144
|
+
<div class="sp-mini" role="img" aria-label={L('The same fields with 16 px everywhere: labels float halfway between two fields and the groups run together.', 'Cùng các ô đó nhưng chỗ nào cũng 16 px: nhãn lơ lửng giữa hai ô và các nhóm dính vào nhau.')}>
|
|
145
|
+
<span class="sp-mini-group">{L('Store', 'Cửa hàng')}</span>
|
|
146
|
+
<span style="height: var(--bh-space-200)"></span>
|
|
147
|
+
<span class="sp-label">{L('Store URL', 'URL cửa hàng')}</span>
|
|
148
|
+
<span style="height: var(--bh-space-200)"></span>
|
|
149
|
+
<span class="sp-input"><span style="width: var(--bh-space-150)"></span><span>mystore.example.com</span></span>
|
|
150
|
+
<span style="height: var(--bh-space-200)"></span>
|
|
151
|
+
<span class="sp-mini-group">{L('Sync', 'Đồng bộ')}</span>
|
|
152
|
+
<span style="height: var(--bh-space-200)"></span>
|
|
153
|
+
<span class="sp-label">{L('Every', 'Mỗi')}</span>
|
|
154
|
+
<span style="height: var(--bh-space-200)"></span>
|
|
155
|
+
<span class="sp-input"><span style="width: var(--bh-space-150)"></span><span>{L('15 minutes', '15 phút')}</span></span>
|
|
156
|
+
</div>
|
|
157
|
+
)}
|
|
158
|
+
{item === 'nudge' && (
|
|
159
|
+
<span class="sp-dd-row" style="gap: var(--bh-space-025)">
|
|
160
|
+
<span class="sp-btn">{L('Cancel', 'Huỷ')}</span>
|
|
161
|
+
<span class="sp-btn is-primary">{L('Save', 'Lưu')}</span>
|
|
162
|
+
</span>
|
|
163
|
+
)}
|
|
164
|
+
</div>
|
|
165
|
+
<p>
|
|
166
|
+
{item === 'scale' && L('Pixel values off the scale. Nothing lines up, and each screen drifts a little further.', 'Giá trị pixel ngoài thang. Không gì thẳng hàng, và mỗi màn hình lại lệch thêm một chút.')}
|
|
167
|
+
{item === 'grouping' && L('The same space everywhere. Readers cannot tell which label belongs to which field.', 'Chỗ nào cũng cùng một khoảng. Người đọc không biết nhãn nào thuộc ô nào.')}
|
|
168
|
+
{item === 'nudge' && L('Controls 2 px apart. They read as one control and are easy to tap by mistake.', 'Các control cách nhau 2 px. Trông như một control và dễ bấm nhầm.')}
|
|
169
|
+
</p>
|
|
170
|
+
</figure>
|
|
171
|
+
</div>
|
|
172
|
+
)}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { releasePhaseLabels, type ReleasePhase } from '../lib/release-phases';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
status: ReleasePhase;
|
|
6
|
+
// Set to false inside another link, such as a sidebar item or a card.
|
|
7
|
+
link?: boolean;
|
|
8
|
+
// Default (20 px) in lists, the sidebar and running text; large (24 px) once per page, next to the title.
|
|
9
|
+
size?: 'default' | 'large';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { status, link = true, size = 'default' } = Astro.props;
|
|
13
|
+
const Tag = link ? 'a' : 'span';
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<Tag
|
|
17
|
+
class:list={['status-badge', `status-${status}`, { 'is-large': size === 'large' }]}
|
|
18
|
+
href={link ? '/release-phases/' : undefined}
|
|
19
|
+
title={link ? 'About release phases' : undefined}
|
|
20
|
+
>
|
|
21
|
+
{releasePhaseLabels[status]}
|
|
22
|
+
</Tag>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { getCollection } from 'astro:content';
|
|
3
|
+
|
|
4
|
+
// What is in the system, with live page counts.
|
|
5
|
+
const docs = await getCollection('docs');
|
|
6
|
+
const count = (section: string) => docs.filter((entry) => entry.id.startsWith(`${section}/`)).length;
|
|
7
|
+
const components = (await getCollection('components')).length;
|
|
8
|
+
const news = (await getCollection('news')).length;
|
|
9
|
+
const plural = (n: number, word: string) => `${n} ${word}${n === 1 ? '' : 's'}`;
|
|
10
|
+
|
|
11
|
+
const areas = [
|
|
12
|
+
{ title: 'Foundations', href: '/foundations/', text: 'Tokens, guidelines and styles such as color, type and logos.', meta: plural(count('foundations'), 'page') },
|
|
13
|
+
{ title: 'Components', href: '/components/', text: 'Building blocks with usage, code and accessibility notes.', meta: plural(components, 'component') },
|
|
14
|
+
{ title: 'Tools', href: '/tools/', text: 'Lint rules, the Ant Design Vue theme and docs for AI agents.', meta: plural(count('tools'), 'tool') },
|
|
15
|
+
{ title: 'News', href: '/news/', text: 'Changes to the system, newest first.', meta: plural(news, 'post') },
|
|
16
|
+
];
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
<ul class="card-grid area-grid">
|
|
20
|
+
{areas.map((area) => (
|
|
21
|
+
<li>
|
|
22
|
+
<a class="card" href={area.href}>
|
|
23
|
+
{area.title}
|
|
24
|
+
<p>{area.text}</p>
|
|
25
|
+
<span class="card-meta">{area.meta}</span>
|
|
26
|
+
</a>
|
|
27
|
+
</li>
|
|
28
|
+
))}
|
|
29
|
+
</ul>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { MarkdownHeading } from 'astro';
|
|
3
|
+
import { langOf, t } from '../lib/i18n';
|
|
4
|
+
import ChevronDown from '@lucide/astro/icons/chevron-down';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
headings: MarkdownHeading[];
|
|
8
|
+
// "aside" is the right-hand column; "menu" is the folded list on small screens.
|
|
9
|
+
variant?: 'aside' | 'menu';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { variant = 'aside' } = Astro.props;
|
|
13
|
+
const T = t(langOf(Astro.url.pathname));
|
|
14
|
+
const headings = Astro.props.headings.filter((heading) => heading.depth === 2 || heading.depth === 3);
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
{headings.length > 1 && variant === 'aside' && (
|
|
18
|
+
<nav class="toc" aria-labelledby="toc-title">
|
|
19
|
+
<p class="toc-title" id="toc-title">{T.onThisPage}</p>
|
|
20
|
+
<ul>
|
|
21
|
+
{headings.map((heading) => (
|
|
22
|
+
<li class={`toc-depth-${heading.depth}`}><a href={`#${heading.slug}`} data-toc-link>{heading.text}</a></li>
|
|
23
|
+
))}
|
|
24
|
+
</ul>
|
|
25
|
+
</nav>
|
|
26
|
+
)}
|
|
27
|
+
{headings.length > 1 && variant === 'menu' && (
|
|
28
|
+
<details class="toc-menu">
|
|
29
|
+
<summary>{T.onThisPage}<ChevronDown size={16} class="toc-menu-chevron" /></summary>
|
|
30
|
+
<nav aria-label={T.onThisPage}>
|
|
31
|
+
<ul>
|
|
32
|
+
{headings.map((heading) => (
|
|
33
|
+
<li class={`toc-depth-${heading.depth}`}><a href={`#${heading.slug}`} data-toc-link>{heading.text}</a></li>
|
|
34
|
+
))}
|
|
35
|
+
</ul>
|
|
36
|
+
</nav>
|
|
37
|
+
</details>
|
|
38
|
+
)}
|
|
39
|
+
|
|
40
|
+
<style>
|
|
41
|
+
/* The folded list's chevron: a 16 px Lucide icon next to the 14 px label, 4 px apart. */
|
|
42
|
+
.toc-menu summary { display: flex; align-items: center; gap: var(--bh-space-050); }
|
|
43
|
+
.toc-menu summary::after { content: none; }
|
|
44
|
+
.toc-menu :global(.toc-menu-chevron) { flex: none; transition: transform 150ms ease; }
|
|
45
|
+
.toc-menu[open] :global(.toc-menu-chevron) { transform: rotate(180deg); }
|
|
46
|
+
@media (prefers-reduced-motion: reduce) { .toc-menu :global(.toc-menu-chevron) { transition: none; } }
|
|
47
|
+
</style>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tokensByPrefix } from '../lib/tokens';
|
|
3
|
+
import { tokenDescriptionsVi } from '../lib/token-descriptions-vi';
|
|
4
|
+
import { langOf } from '../lib/i18n';
|
|
5
|
+
|
|
6
|
+
// Lists every token whose name starts with `prefix`, read from tokens/*.json.
|
|
7
|
+
interface Props {
|
|
8
|
+
prefix: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const tokens = tokensByPrefix(Astro.props.prefix);
|
|
12
|
+
const vi = langOf(Astro.url.pathname) === 'vi';
|
|
13
|
+
const L = (en: string, viText: string) => (vi ? viText : en);
|
|
14
|
+
const describe = (name: string, en: string) => (vi ? tokenDescriptionsVi[name] ?? en : en);
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<div class="table-wrap">
|
|
18
|
+
<table class="token-table">
|
|
19
|
+
<thead>
|
|
20
|
+
<tr><th scope="col">Token</th><th scope="col">{L('Value', 'Giá trị')}</th><th scope="col">{L('Description', 'Mô tả')}</th></tr>
|
|
21
|
+
</thead>
|
|
22
|
+
<tbody>
|
|
23
|
+
{tokens.map((token) => (
|
|
24
|
+
<tr>
|
|
25
|
+
<td><code>{token.cssVar}</code></td>
|
|
26
|
+
<td>
|
|
27
|
+
<span class="token-value">
|
|
28
|
+
{token.type === 'color' && <span class="swatch" style={`background: var(${token.cssVar})`} aria-hidden="true"></span>}
|
|
29
|
+
<code>{token.value}</code>
|
|
30
|
+
</span>
|
|
31
|
+
{token.value !== token.resolved && <span class="token-resolved">{token.resolved}</span>}
|
|
32
|
+
{token.darkResolved && <span class="token-resolved">{L('Dark', 'Tối')}: {token.dark && token.dark !== token.darkResolved ? `${token.dark} → ` : ''}{token.darkResolved}</span>}
|
|
33
|
+
{token.viResolved && <span class="token-resolved">{L('Vietnamese', 'Tiếng Việt')} (<code>lang="vi"</code>): {token.viResolved}</span>}
|
|
34
|
+
</td>
|
|
35
|
+
<td>{describe(token.name, token.description)}</td>
|
|
36
|
+
</tr>
|
|
37
|
+
))}
|
|
38
|
+
</tbody>
|
|
39
|
+
</table>
|
|
40
|
+
</div>
|