decantr 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +868 -0
- package/CHANGELOG.md +255 -0
- package/CLAUDE.md +178 -0
- package/LICENSE +21 -0
- package/README.md +229 -0
- package/cli/art.js +127 -0
- package/cli/commands/a11y.js +61 -0
- package/cli/commands/audit.js +225 -0
- package/cli/commands/build.js +38 -0
- package/cli/commands/dev.js +18 -0
- package/cli/commands/doctor.js +197 -0
- package/cli/commands/figma-sync.js +48 -0
- package/cli/commands/figma-tokens.js +55 -0
- package/cli/commands/generate.js +26 -0
- package/cli/commands/init.js +116 -0
- package/cli/commands/lint.js +209 -0
- package/cli/commands/mcp.js +530 -0
- package/cli/commands/migrate.js +175 -0
- package/cli/commands/test.js +38 -0
- package/cli/commands/validate.js +354 -0
- package/cli/index.js +113 -0
- package/package.json +95 -0
- package/reference/atoms.md +517 -0
- package/reference/behaviors.md +384 -0
- package/reference/build-tooling.md +275 -0
- package/reference/color-guidelines.md +965 -0
- package/reference/component-lifecycle.md +137 -0
- package/reference/compound-spacing.md +95 -0
- package/reference/decantation-process.md +499 -0
- package/reference/dev-server-routes.md +93 -0
- package/reference/form-system.md +253 -0
- package/reference/i18n.md +336 -0
- package/reference/icons.md +576 -0
- package/reference/llm-primer.md +953 -0
- package/reference/plugins.md +252 -0
- package/reference/registry-consumption.md +76 -0
- package/reference/router.md +217 -0
- package/reference/shells.md +116 -0
- package/reference/spatial-guidelines.md +541 -0
- package/reference/ssr.md +234 -0
- package/reference/state-data.md +215 -0
- package/reference/state-patterns.md +166 -0
- package/reference/state.md +194 -0
- package/reference/style-system.md +110 -0
- package/reference/tokens.md +460 -0
- package/src/app.js +19 -0
- package/src/chart/_animate.js +266 -0
- package/src/chart/_base.js +109 -0
- package/src/chart/_data.js +209 -0
- package/src/chart/_format.js +106 -0
- package/src/chart/_interact.js +364 -0
- package/src/chart/_palette.js +105 -0
- package/src/chart/_renderer.js +52 -0
- package/src/chart/_scene.js +262 -0
- package/src/chart/_shared.js +371 -0
- package/src/chart/index.js +637 -0
- package/src/chart/layouts/_layout-base.js +328 -0
- package/src/chart/layouts/cartesian.js +148 -0
- package/src/chart/layouts/hierarchy.js +562 -0
- package/src/chart/layouts/polar.js +101 -0
- package/src/chart/renderers/canvas.js +179 -0
- package/src/chart/renderers/svg.js +256 -0
- package/src/chart/renderers/webgpu.js +715 -0
- package/src/chart/types/_type-base.js +26 -0
- package/src/chart/types/area.js +134 -0
- package/src/chart/types/bar.js +173 -0
- package/src/chart/types/box-plot.js +125 -0
- package/src/chart/types/bubble.js +63 -0
- package/src/chart/types/candlestick.js +115 -0
- package/src/chart/types/chord.js +85 -0
- package/src/chart/types/combination.js +108 -0
- package/src/chart/types/funnel.js +68 -0
- package/src/chart/types/gauge.js +163 -0
- package/src/chart/types/heatmap.js +98 -0
- package/src/chart/types/histogram.js +71 -0
- package/src/chart/types/line.js +111 -0
- package/src/chart/types/org-chart.js +93 -0
- package/src/chart/types/pie.js +81 -0
- package/src/chart/types/radar.js +96 -0
- package/src/chart/types/radial.js +68 -0
- package/src/chart/types/range-area.js +55 -0
- package/src/chart/types/range-bar.js +61 -0
- package/src/chart/types/sankey.js +73 -0
- package/src/chart/types/scatter.js +66 -0
- package/src/chart/types/sparkline.js +81 -0
- package/src/chart/types/sunburst.js +69 -0
- package/src/chart/types/swimlane.js +88 -0
- package/src/chart/types/treemap.js +62 -0
- package/src/chart/types/waterfall.js +100 -0
- package/src/components/_base.js +1658 -0
- package/src/components/_behaviors.js +1140 -0
- package/src/components/_primitives.js +534 -0
- package/src/components/_qr-encoder.js +539 -0
- package/src/components/accordion.js +207 -0
- package/src/components/affix.js +62 -0
- package/src/components/alert-dialog.js +75 -0
- package/src/components/alert.js +47 -0
- package/src/components/aspect-ratio.js +24 -0
- package/src/components/avatar-group.js +55 -0
- package/src/components/avatar.js +38 -0
- package/src/components/back-top.js +75 -0
- package/src/components/badge.js +74 -0
- package/src/components/banner.js +68 -0
- package/src/components/breadcrumb.js +162 -0
- package/src/components/button.js +115 -0
- package/src/components/calendar.js +131 -0
- package/src/components/card.js +192 -0
- package/src/components/carousel.js +98 -0
- package/src/components/cascader.js +261 -0
- package/src/components/checkbox.js +80 -0
- package/src/components/chip.js +81 -0
- package/src/components/code-block.js +82 -0
- package/src/components/collapsible.js +50 -0
- package/src/components/color-palette.js +438 -0
- package/src/components/color-picker.js +314 -0
- package/src/components/combobox.js +181 -0
- package/src/components/command.js +174 -0
- package/src/components/comment.js +206 -0
- package/src/components/context-menu.js +76 -0
- package/src/components/data-table.js +724 -0
- package/src/components/date-picker.js +217 -0
- package/src/components/date-range-picker.js +244 -0
- package/src/components/datetime-picker.js +271 -0
- package/src/components/descriptions.js +68 -0
- package/src/components/drawer.js +179 -0
- package/src/components/dropdown.js +88 -0
- package/src/components/empty.js +41 -0
- package/src/components/float-button.js +90 -0
- package/src/components/form.js +106 -0
- package/src/components/hover-card.js +49 -0
- package/src/components/icon.js +87 -0
- package/src/components/image.js +97 -0
- package/src/components/index.js +117 -0
- package/src/components/input-group.js +75 -0
- package/src/components/input-number.js +155 -0
- package/src/components/input-otp.js +178 -0
- package/src/components/input.js +91 -0
- package/src/components/kbd.js +36 -0
- package/src/components/label.js +25 -0
- package/src/components/list.js +118 -0
- package/src/components/masked-input.js +236 -0
- package/src/components/mentions.js +165 -0
- package/src/components/menu.js +259 -0
- package/src/components/message.js +80 -0
- package/src/components/modal.js +147 -0
- package/src/components/navigation-menu.js +166 -0
- package/src/components/notification.js +84 -0
- package/src/components/pagination.js +104 -0
- package/src/components/placeholder.js +132 -0
- package/src/components/popconfirm.js +70 -0
- package/src/components/popover.js +58 -0
- package/src/components/progress.js +61 -0
- package/src/components/qrcode.js +251 -0
- package/src/components/radiogroup.js +120 -0
- package/src/components/range-slider.js +176 -0
- package/src/components/rate.js +186 -0
- package/src/components/resizable.js +83 -0
- package/src/components/result.js +57 -0
- package/src/components/scroll-area.js +43 -0
- package/src/components/segmented.js +97 -0
- package/src/components/select.js +165 -0
- package/src/components/separator.js +31 -0
- package/src/components/shell.js +407 -0
- package/src/components/skeleton.js +39 -0
- package/src/components/slider.js +141 -0
- package/src/components/sortable-list.js +176 -0
- package/src/components/space.js +42 -0
- package/src/components/spinner.js +112 -0
- package/src/components/splitter.js +147 -0
- package/src/components/statistic.js +136 -0
- package/src/components/steps.js +99 -0
- package/src/components/switch.js +95 -0
- package/src/components/table.js +44 -0
- package/src/components/tabs.js +216 -0
- package/src/components/tag.js +115 -0
- package/src/components/textarea.js +82 -0
- package/src/components/time-picker.js +153 -0
- package/src/components/time-range-picker.js +170 -0
- package/src/components/timeline.js +226 -0
- package/src/components/toast.js +71 -0
- package/src/components/toggle.js +213 -0
- package/src/components/tooltip.js +57 -0
- package/src/components/tour.js +159 -0
- package/src/components/transfer.js +163 -0
- package/src/components/tree-select.js +274 -0
- package/src/components/tree.js +141 -0
- package/src/components/typography.js +136 -0
- package/src/components/upload.js +118 -0
- package/src/components/visually-hidden.js +20 -0
- package/src/components/watermark.js +124 -0
- package/src/core/index.js +539 -0
- package/src/core/lifecycle.js +69 -0
- package/src/css/atoms.js +651 -0
- package/src/css/components.js +940 -0
- package/src/css/derive.js +1296 -0
- package/src/css/index.js +265 -0
- package/src/css/runtime.js +268 -0
- package/src/css/styles/addons/bioluminescent.js +93 -0
- package/src/css/styles/addons/clay.js +70 -0
- package/src/css/styles/addons/clean.js +57 -0
- package/src/css/styles/addons/command-center.js +143 -0
- package/src/css/styles/addons/dopamine.js +83 -0
- package/src/css/styles/addons/editorial.js +80 -0
- package/src/css/styles/addons/glassmorphism.js +99 -0
- package/src/css/styles/addons/liquid-glass.js +105 -0
- package/src/css/styles/addons/prismatic.js +100 -0
- package/src/css/styles/addons/retro.js +63 -0
- package/src/css/styles/auradecantism.js +96 -0
- package/src/css/theme-registry.js +444 -0
- package/src/data/entity.js +281 -0
- package/src/data/index.js +13 -0
- package/src/data/persist.js +225 -0
- package/src/data/query.js +839 -0
- package/src/data/realtime.js +299 -0
- package/src/data/url.js +177 -0
- package/src/data/worker.js +134 -0
- package/src/explorer/archetypes.js +243 -0
- package/src/explorer/atoms.js +228 -0
- package/src/explorer/charts.js +497 -0
- package/src/explorer/components.js +129 -0
- package/src/explorer/foundations.js +949 -0
- package/src/explorer/icons.js +178 -0
- package/src/explorer/patterns.js +247 -0
- package/src/explorer/recipes.js +194 -0
- package/src/explorer/shared/pattern-examples.js +1337 -0
- package/src/explorer/shared/showcase-renderer.js +958 -0
- package/src/explorer/shared/spec-table.js +41 -0
- package/src/explorer/shared/usage-links.js +87 -0
- package/src/explorer/shell-config.js +10 -0
- package/src/explorer/shells.js +551 -0
- package/src/explorer/styles.js +161 -0
- package/src/explorer/tokens.js +262 -0
- package/src/explorer/tools.js +525 -0
- package/src/form/index.js +804 -0
- package/src/i18n/index.js +251 -0
- package/src/icons/essential.js +479 -0
- package/src/icons/index.js +53 -0
- package/src/plugins/index.js +282 -0
- package/src/registry/archetypes/content-site.json +71 -0
- package/src/registry/archetypes/docs-explorer.json +23 -0
- package/src/registry/archetypes/ecommerce.json +104 -0
- package/src/registry/archetypes/financial-dashboard.json +77 -0
- package/src/registry/archetypes/index.json +41 -0
- package/src/registry/archetypes/portfolio.json +82 -0
- package/src/registry/archetypes/recipe-community.json +159 -0
- package/src/registry/archetypes/saas-dashboard.json +86 -0
- package/src/registry/architect/cross-cutting.json +45 -0
- package/src/registry/architect/domains/ecommerce.json +294 -0
- package/src/registry/architect/domains/financial-services.json +302 -0
- package/src/registry/architect/index.json +26 -0
- package/src/registry/architect/traits.json +379 -0
- package/src/registry/atoms.json +16 -0
- package/src/registry/chart-showcase.json +160 -0
- package/src/registry/chart.json +136 -0
- package/src/registry/components.json +8616 -0
- package/src/registry/core.json +216 -0
- package/src/registry/css.json +319 -0
- package/src/registry/data.json +135 -0
- package/src/registry/foundations.json +11 -0
- package/src/registry/icons.json +463 -0
- package/src/registry/index.json +101 -0
- package/src/registry/patterns/activity-feed.json +37 -0
- package/src/registry/patterns/article-content.json +27 -0
- package/src/registry/patterns/auth-form.json +37 -0
- package/src/registry/patterns/author-card.json +20 -0
- package/src/registry/patterns/card-grid.json +127 -0
- package/src/registry/patterns/category-nav.json +26 -0
- package/src/registry/patterns/chart-grid.json +36 -0
- package/src/registry/patterns/chat-interface.json +37 -0
- package/src/registry/patterns/checklist-card.json +55 -0
- package/src/registry/patterns/comparison-panel.json +27 -0
- package/src/registry/patterns/component-showcase.json +24 -0
- package/src/registry/patterns/contact-form.json +31 -0
- package/src/registry/patterns/cta-section.json +20 -0
- package/src/registry/patterns/data-table.json +37 -0
- package/src/registry/patterns/detail-header.json +83 -0
- package/src/registry/patterns/detail-panel.json +27 -0
- package/src/registry/patterns/explorer-shell.json +22 -0
- package/src/registry/patterns/filter-bar.json +33 -0
- package/src/registry/patterns/filter-sidebar.json +27 -0
- package/src/registry/patterns/form-sections.json +110 -0
- package/src/registry/patterns/goal-tracker.json +27 -0
- package/src/registry/patterns/hero.json +107 -0
- package/src/registry/patterns/index.json +47 -0
- package/src/registry/patterns/kpi-grid.json +36 -0
- package/src/registry/patterns/media-gallery.json +20 -0
- package/src/registry/patterns/order-history.json +20 -0
- package/src/registry/patterns/pagination.json +19 -0
- package/src/registry/patterns/photo-to-recipe.json +36 -0
- package/src/registry/patterns/pipeline-tracker.json +28 -0
- package/src/registry/patterns/post-list.json +27 -0
- package/src/registry/patterns/pricing-table.json +32 -0
- package/src/registry/patterns/scorecard.json +28 -0
- package/src/registry/patterns/search-bar.json +20 -0
- package/src/registry/patterns/specimen-grid.json +19 -0
- package/src/registry/patterns/stat-card.json +55 -0
- package/src/registry/patterns/stats-bar.json +55 -0
- package/src/registry/patterns/steps-card.json +55 -0
- package/src/registry/patterns/table-of-contents.json +19 -0
- package/src/registry/patterns/testimonials.json +21 -0
- package/src/registry/patterns/timeline.json +27 -0
- package/src/registry/patterns/token-inspector.json +21 -0
- package/src/registry/patterns/wizard.json +27 -0
- package/src/registry/recipe-auradecantism.json +69 -0
- package/src/registry/recipe-clean.json +65 -0
- package/src/registry/recipe-command-center.json +78 -0
- package/src/registry/router.json +73 -0
- package/src/registry/schema/README.md +197 -0
- package/src/registry/skeletons.json +259 -0
- package/src/registry/state.json +137 -0
- package/src/registry/tokens.json +40 -0
- package/src/router/hash.js +17 -0
- package/src/router/history.js +18 -0
- package/src/router/index.js +598 -0
- package/src/ssr/index.js +922 -0
- package/src/state/arrays.js +181 -0
- package/src/state/devtools.js +647 -0
- package/src/state/index.js +498 -0
- package/src/state/middleware.js +288 -0
- package/src/state/scheduler.js +206 -0
- package/src/state/store.js +300 -0
- package/src/tags/index.js +19 -0
- package/src/tannins/auth.js +396 -0
- package/src/test/dom.js +352 -0
- package/src/test/index.js +62 -0
- package/src/test/state.js +306 -0
- package/tools/a11y-audit.js +487 -0
- package/tools/analyzer.js +315 -0
- package/tools/audit.js +706 -0
- package/tools/builder.js +1422 -0
- package/tools/css-extract.js +188 -0
- package/tools/dev-server.js +316 -0
- package/tools/dts-gen.js +1260 -0
- package/tools/figma-components.js +329 -0
- package/tools/figma-patterns.js +516 -0
- package/tools/figma-plugin/code.js +453 -0
- package/tools/figma-plugin/manifest.json +14 -0
- package/tools/figma-plugin/ui.html +268 -0
- package/tools/figma-render.js +293 -0
- package/tools/figma-tokens.js +712 -0
- package/tools/figma-upload.js +318 -0
- package/tools/generate.js +738 -0
- package/tools/icons.js +133 -0
- package/tools/init-templates.js +265 -0
- package/tools/install-hooks.sh +5 -0
- package/tools/migrations/0.5.0.js +53 -0
- package/tools/migrations/0.6.0.js +95 -0
- package/tools/minify.js +170 -0
- package/tools/pre-commit +4 -0
- package/tools/registry.js +662 -0
- package/tools/reset-playground.js +61 -0
- package/tools/starter-templates/content-site/app.js +49 -0
- package/tools/starter-templates/content-site/essence.js +19 -0
- package/tools/starter-templates/content-site/pages.js +31 -0
- package/tools/starter-templates/ecommerce/app.js +50 -0
- package/tools/starter-templates/ecommerce/essence.js +19 -0
- package/tools/starter-templates/ecommerce/pages.js +31 -0
- package/tools/starter-templates/landing-page/app.js +38 -0
- package/tools/starter-templates/landing-page/essence.js +18 -0
- package/tools/starter-templates/landing-page/pages.js +21 -0
- package/tools/starter-templates/portfolio/app.js +45 -0
- package/tools/starter-templates/portfolio/essence.js +19 -0
- package/tools/starter-templates/portfolio/pages.js +33 -0
- package/tools/starter-templates/saas-dashboard/app.js +70 -0
- package/tools/starter-templates/saas-dashboard/essence.js +19 -0
- package/tools/starter-templates/saas-dashboard/pages.js +31 -0
- package/tools/verify-pack.js +203 -0
- package/types/chart.d.ts +77 -0
- package/types/components.d.ts +587 -0
- package/types/core.d.ts +89 -0
- package/types/css.d.ts +149 -0
- package/types/data.d.ts +238 -0
- package/types/form.d.ts +164 -0
- package/types/i18n.d.ts +51 -0
- package/types/icons.d.ts +27 -0
- package/types/index.d.ts +13 -0
- package/types/router.d.ts +116 -0
- package/types/ssr.d.ts +102 -0
- package/types/state.d.ts +83 -0
- package/types/tags.d.ts +62 -0
- package/types/tannins.d.ts +63 -0
- package/types/test.d.ts +48 -0
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
# Spatial Design Language
|
|
2
|
+
|
|
3
|
+
Comprehensive spatial intelligence for Decantr. Every spacing, sizing, and layout decision an LLM makes should be traceable to a rule in this document. Spacing is not decoration — it encodes meaning.
|
|
4
|
+
|
|
5
|
+
## The Four Functions of Whitespace
|
|
6
|
+
|
|
7
|
+
| Function | What it communicates | Primary tool |
|
|
8
|
+
|----------|---------------------|-------------|
|
|
9
|
+
| **Grouping** | Related elements are close; unrelated are far | Proximity tiers (§4) |
|
|
10
|
+
| **Hierarchy** | More whitespace = more importance | Visual weight rules (§10) |
|
|
11
|
+
| **Rhythm** | Consistent spacing = scannable, predictable | Vertical rhythm (§9) |
|
|
12
|
+
| **Density** | Less spacing = more information | Density zones (§6), density classes (§17) |
|
|
13
|
+
|
|
14
|
+
In the Decantation Process vocabulary, this is the **Clarity** layer — whitespace, density, and compound spacing derived from the Character trait.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 1. The Spacing Scale
|
|
19
|
+
|
|
20
|
+
Decantr's spacing scale (defined in `css/derive.js` as `--d-sp-*` tokens):
|
|
21
|
+
|
|
22
|
+
| Token | Value | Atom | Usage scope |
|
|
23
|
+
|-------|-------|------|-------------|
|
|
24
|
+
| `--d-sp-0-5` | 2px (0.125rem) | `_p0` | Hairline gaps, badge offsets |
|
|
25
|
+
| `--d-sp-1` | 4px (0.25rem) | `_p1` | Icon-text gaps, helper text, micro-spacing |
|
|
26
|
+
| `--d-sp-1-5` | 6px (0.375rem) | — | Button-sm padding, chip gap |
|
|
27
|
+
| `--d-sp-2` | 8px (0.5rem) | `_p2` | Input padding, control gaps, touch target spacing |
|
|
28
|
+
| `--d-sp-2-5` | 10px (0.625rem) | — | Button-lg padding, tab padding |
|
|
29
|
+
| `--d-sp-3` | 12px (0.75rem) | `_p3` | Cell padding, compound-gap default |
|
|
30
|
+
| `--d-sp-4` | 16px (1rem) | `_p4` | **Anchor value.** Default container padding, form field gaps |
|
|
31
|
+
| `--d-sp-5` | 20px (1.25rem) | `_p5` | Compound-pad (dark themes) |
|
|
32
|
+
| `--d-sp-6` | 24px (1.5rem) | `_p6` | Compound-pad (light themes), card padding |
|
|
33
|
+
| `--d-sp-8` | 32px (2rem) | `_p8` | Section inline padding, hero margins |
|
|
34
|
+
| `--d-sp-10` | 40px (2.5rem) | `_p10` | Large layout spacing |
|
|
35
|
+
| `--d-sp-12` | 48px (3rem) | `_p12` | Section block padding |
|
|
36
|
+
| `--d-sp-16` | 64px (4rem) | `_p16` | Hero block padding, landmark spacing |
|
|
37
|
+
|
|
38
|
+
### Why non-linear
|
|
39
|
+
|
|
40
|
+
The scale follows the Weber-Fechner law: human perception requires proportionally larger differences to notice change at larger magnitudes. The jumps (2→4→8→12→16→24→32→48→64) increase because a 4px difference at 8px is noticeable, but a 4px difference at 48px is invisible.
|
|
41
|
+
|
|
42
|
+
### The 16px anchor
|
|
43
|
+
|
|
44
|
+
16px (`--d-sp-4` / `_p4`) is the gravitational center of the spacing system. It is: the default font size, the default container padding, the default form field gap, and a factor of all common screen widths (320, 768, 1024, 1280, 1440, 1920). When in doubt, 16px is the safe default for general component spacing.
|
|
45
|
+
|
|
46
|
+
### Two scopes
|
|
47
|
+
|
|
48
|
+
| Scope | Range | Purpose | Examples |
|
|
49
|
+
|-------|-------|---------|---------|
|
|
50
|
+
| **Component** | 2-24px (sp-0-5 to sp-6) | Internal padding, gaps between sub-elements | Button padding, icon-text gap, input padding |
|
|
51
|
+
| **Layout** | 24-64px+ (sp-6 to sp-16) | Section margins, page structure, major separators | Hero padding, section gaps, page margins |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 2. Spatial Taxonomy
|
|
56
|
+
|
|
57
|
+
Six concepts that cover nearly all CSS spacing rules (adapted from EightShapes):
|
|
58
|
+
|
|
59
|
+
| Concept | Definition | Ratio | Decantr Pattern | Use Cases |
|
|
60
|
+
|---------|-----------|-------|-----------------|-----------|
|
|
61
|
+
| **Inset** | Equal padding all sides | 1:1:1:1 | `_p4`, `_p6` | Cards, panels, modals, containers, tooltips |
|
|
62
|
+
| **Squish Inset** | Vertical ≈ 50% of horizontal | 0.5:1 | `_py2 _px4`, `_py1 _px3` | Buttons, table cells, list items, chips, tabs |
|
|
63
|
+
| **Stretch Inset** | Vertical > horizontal | 1.5:1 | `_py3 _px2` | Text inputs, textareas, form fields |
|
|
64
|
+
| **Stack** | Vertical gap between siblings | — | `_gap4`, `d-spacey-4` | Vertical content flow (most common) |
|
|
65
|
+
| **Inline** | Horizontal gap between siblings | — | `_gap2`, `d-spacex-2` | Tags, breadcrumbs, button groups, nav items |
|
|
66
|
+
| **Grid** | Layout margins + gutters | — | `_p4 _gap4`, `_gc3 _gap6` | Page layouts, card grids, dashboards |
|
|
67
|
+
|
|
68
|
+
### When to use which
|
|
69
|
+
|
|
70
|
+
- Building a **button or table cell**? → Squish inset (`_py2 _px4`)
|
|
71
|
+
- Building a **text input**? → Stretch inset (`_py3 _px2`)
|
|
72
|
+
- Building a **card or panel**? → Inset (`_p4` or `_p6`)
|
|
73
|
+
- Stacking **vertical items**? → Stack (`_gap4` on flex column)
|
|
74
|
+
- Arranging **horizontal items**? → Inline (`_gap2` on flex row)
|
|
75
|
+
- Building a **page layout**? → Grid (`_gc3 _gap6 _p4`)
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 3. Gestalt Proximity Rules
|
|
80
|
+
|
|
81
|
+
Elements closer together are perceived as related. This is the master spacing principle — it determines which scale value to use based on the semantic relationship between elements.
|
|
82
|
+
|
|
83
|
+
| Tier | Relationship | Scale | Atoms | Examples |
|
|
84
|
+
|------|-------------|-------|-------|---------|
|
|
85
|
+
| **Intimate** | Label→input, icon→text, helper→field | 4-8px | `_gap1`–`_gap2` | Form label above input, icon beside button text, error text below input |
|
|
86
|
+
| **Related** | Field→field, item→item, sibling controls | 12-16px | `_gap3`–`_gap4` | Adjacent form fields, list items, card elements, toolbar buttons |
|
|
87
|
+
| **Grouped** | Group→group, section-header→content | 20-24px | `_gap5`–`_gap6` | Form group → action bar, sidebar sections, card body → footer |
|
|
88
|
+
| **Sectional** | Section→section on a page | 32-48px | `_py8`–`_py12` | Features → testimonials, pricing → CTA, dashboard widgets |
|
|
89
|
+
| **Landmark** | Hero emphasis, page-level breathing | 64-96px | `_py16`–`_py24` | Hero vertical padding, landing page section separation |
|
|
90
|
+
|
|
91
|
+
### The 50% rule
|
|
92
|
+
|
|
93
|
+
Inner-group spacing must be ≤ 50% of inter-group spacing. If items within a group are `_gap2` (8px) apart, groups themselves must be at least `_gap4` (16px) apart, ideally `_gap6` (24px). This ensures visual grouping is unambiguous.
|
|
94
|
+
|
|
95
|
+
### Quick decision flow
|
|
96
|
+
|
|
97
|
+
1. Are these elements part of the **same control**? (icon + label, input + helper) → Intimate
|
|
98
|
+
2. Are they **siblings of the same type**? (field + field, card + card) → Related
|
|
99
|
+
3. Are they **distinct groups** within a section? (form + action bar) → Grouped
|
|
100
|
+
4. Are they **different sections** of a page? → Sectional
|
|
101
|
+
5. Is this a **hero or primary attention area**? → Landmark
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 4. Containment Principle
|
|
106
|
+
|
|
107
|
+
Inner spacing must always be less than outer spacing. This creates visual containment — the Gestalt principle of closure makes padded containers feel like distinct objects.
|
|
108
|
+
|
|
109
|
+
| Container Padding | Internal Gap | Nested Item Gap | Typical Use |
|
|
110
|
+
|-------------------|-------------|-----------------|-------------|
|
|
111
|
+
| `_p8` (32px) | `_gap4`–`_gap6` | `_gap2`–`_gap3` | Page sections, large panels |
|
|
112
|
+
| `_p6` (24px) | `_gap3`–`_gap4` | `_gap2` | Cards, modals, drawers |
|
|
113
|
+
| `_p4` (16px) | `_gap2`–`_gap3` | `_gap1` | Dropdowns, popovers, compact cards |
|
|
114
|
+
| `_p3` (12px) | `_gap2` | `_gap1` | Tooltips, toast bodies, dense panels |
|
|
115
|
+
| `_p2` (8px) | `_gap1` | — | Badges, chips, inline containers |
|
|
116
|
+
|
|
117
|
+
**Rule**: Reduce by 1-2 scale steps per nesting level. If you can't reduce further, the nesting is too deep — flatten the structure.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## 5. Functional Density Zones
|
|
122
|
+
|
|
123
|
+
Different UI regions serve different purposes and demand different spacing:
|
|
124
|
+
|
|
125
|
+
| Zone | Intent | Gap | Padding | Applies To |
|
|
126
|
+
|------|--------|-----|---------|-----------|
|
|
127
|
+
| **Chrome** | Scannable tools, navigation | `_gap1`–`_gap2` | `_p1`–`_p2` | Toolbars, nav bars, breadcrumbs, status bars, tab bars |
|
|
128
|
+
| **Controls** | Interactive efficiency | `_gap3`–`_gap4` | `_p3`–`_p4` | Filter sidebars, form groups, settings panels |
|
|
129
|
+
| **Content** | Readable comfort | `_gap4`–`_gap6` | `_p4`–`_p6` | Card bodies, feature grids, article sections |
|
|
130
|
+
| **Showcase** | Visual impact, breathing room | `_gap6`–`_gap8` | `_py12`–`_py16` | Heroes, CTAs, pricing tables, landing sections |
|
|
131
|
+
| **Data-dense** | Maximum information density | `_gap1`–`_gap2` | `_p2`–`_p3` | Data tables, dashboards, analyst tools, monitoring |
|
|
132
|
+
|
|
133
|
+
### Key rules
|
|
134
|
+
|
|
135
|
+
- Components **inherit their zone's density** — a chip inside chrome doesn't need extra gap
|
|
136
|
+
- A **dashboard page** mixes zones: the toolbar is chrome, the sidebar is controls, the main area is data-dense, and a KPI row might be content
|
|
137
|
+
- **Marketing pages** are mostly showcase + content zones
|
|
138
|
+
- **Application UIs** are mostly controls + content + chrome zones
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 6. Responsive Spatial Behavior
|
|
143
|
+
|
|
144
|
+
### Breakpoint mapping
|
|
145
|
+
|
|
146
|
+
| Class | Width | Grid Columns | Page Margin | Gutter | Nav Pattern |
|
|
147
|
+
|-------|-------|-------------|-------------|--------|-------------|
|
|
148
|
+
| Compact | <640px | 4 | `_px4` (16px) | `_gap4` (16px) | Bottom bar or hamburger |
|
|
149
|
+
| Medium | 640-1023px | 8 | `_px6` (24px) | `_gap4`–`_gap6` | Rail (80px) or collapsible sidebar |
|
|
150
|
+
| Expanded | 1024-1439px | 12 | `_px6`–`_px8` | `_gap6` (24px) | Persistent sidebar (220-360px) |
|
|
151
|
+
| Large | ≥1440px | 12 | auto (centered `_ctrxl`) | `_gap6` (24px) | Persistent sidebar + extra panes |
|
|
152
|
+
|
|
153
|
+
### What reduces at smaller screens
|
|
154
|
+
|
|
155
|
+
| Property | Desktop | Tablet | Mobile | Reduction |
|
|
156
|
+
|----------|---------|--------|--------|-----------|
|
|
157
|
+
| Page margins | 32px | 24px | 16px | ~50% |
|
|
158
|
+
| Grid gutters | 24px | 16-24px | 16px | ~33% |
|
|
159
|
+
| Section padding | `_py16` (64px) | `_py12` (48px) | `_py8` (32px) | ~50% |
|
|
160
|
+
| Card-to-card spacing | 48px | 32px | 16px | ~67% |
|
|
161
|
+
| Display heading size | Scales down | Scales down | Scales down | Per type scale |
|
|
162
|
+
|
|
163
|
+
### What stays constant across breakpoints
|
|
164
|
+
|
|
165
|
+
- Component internal padding (button padding doesn't change)
|
|
166
|
+
- Label-to-input gap (always intimate: `_gap1`–`_gap2`)
|
|
167
|
+
- Body-copy-to-button gap (always ~24px / `_gap6`)
|
|
168
|
+
- Card-title-to-body gap (always ~16px / `_gap4`)
|
|
169
|
+
- Touch target minimums (44px on touch devices)
|
|
170
|
+
|
|
171
|
+
### What transforms (not just shrinks)
|
|
172
|
+
|
|
173
|
+
- **Navigation**: persistent sidebar → rail → bottom bar or hamburger
|
|
174
|
+
- **Side-by-side panes** → stacked vertically
|
|
175
|
+
- **Horizontal tabs** → scrollable tabs or vertical list
|
|
176
|
+
- **Multi-column grid** → fewer columns (not smaller columns)
|
|
177
|
+
- **Decorative elements** may be removed entirely
|
|
178
|
+
- **Content order** may shift via flex direction changes
|
|
179
|
+
|
|
180
|
+
### Canonical responsive layouts (mapped to blend spec)
|
|
181
|
+
|
|
182
|
+
| Layout | <640px | 640-1023px | ≥1024px | Blend Spec |
|
|
183
|
+
|--------|--------|-----------|---------|-----------|
|
|
184
|
+
| **List-Detail** | One pane at a time | One pane at a time | Both side-by-side | `{ "cols": ["list", "detail"], "at": "lg" }` |
|
|
185
|
+
| **Supporting Panel** | Stacked or bottom sheet | 50/50 split | 70/30 split | `{ "cols": ["main", "support"], "span": {"main": 7, "support": 3}, "at": "md" }` |
|
|
186
|
+
| **Feed** | Single column | Auto-fit grid | Auto-fit grid | `_gcaf220` or `_gcaf280` |
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 7. Component Sizing
|
|
191
|
+
|
|
192
|
+
Height is the primary constraint. Padding, font-size, and gap derive from it.
|
|
193
|
+
|
|
194
|
+
### Field sizing tiers
|
|
195
|
+
|
|
196
|
+
| Tier | Height | Pad-Y | Pad-X | Font | Gap | Touch-safe? |
|
|
197
|
+
|------|--------|-------|-------|------|-----|-------------|
|
|
198
|
+
| **xs** | 24px | 4px | 8px | 10px | 4px | No (desktop only) |
|
|
199
|
+
| **sm** | 28px | 4px | 10px | 12px | 6px | No (desktop only) |
|
|
200
|
+
| **md** | 36px | 8px | 16px | 14px | 8px | Acceptable (with invisible padding to 44px) |
|
|
201
|
+
| **lg** | 44px | 10px | 24px | 16px | 10px | Yes (≥44px) |
|
|
202
|
+
|
|
203
|
+
### Inset patterns for components
|
|
204
|
+
|
|
205
|
+
| Component Type | Inset Pattern | Example Atoms | Rationale |
|
|
206
|
+
|---------------|---------------|--------------|-----------|
|
|
207
|
+
| **Buttons, chips, table cells** | Squish (vert ≈ 50% horiz) | `_py2 _px4` | Horizontal text needs room; vertical is constrained by line-height |
|
|
208
|
+
| **Text inputs, textareas** | Stretch (vert > horiz) | `_py3 _px2` | Vertical room for text entry; horizontal edge less critical |
|
|
209
|
+
| **Cards, panels, modals** | Inset (equal all sides) | `_p4`, `_p6` | Even containment boundary |
|
|
210
|
+
| **Tooltips, toasts** | Inset (compact) | `_p2`–`_p3` | Minimal chrome for transient content |
|
|
211
|
+
|
|
212
|
+
### Touch target rules
|
|
213
|
+
|
|
214
|
+
- **WCAG 2.2 AA minimum**: 24×24 CSS px
|
|
215
|
+
- **Recommended**: 44×44px (Apple) / 48×48px (Material)
|
|
216
|
+
- **Minimum gap between adjacent targets**: 8px (`_gap2`)
|
|
217
|
+
- **Compact density is desktop-only** — never apply `.d-compact` to touch-primary interfaces
|
|
218
|
+
- If visible size < 44px, invisible padding must extend the hit area to meet the target
|
|
219
|
+
|
|
220
|
+
### Icon sizing relative to text
|
|
221
|
+
|
|
222
|
+
| Context | Icon Size | Text Size | Line-Height | Icon-Text Gap |
|
|
223
|
+
|---------|-----------|-----------|-------------|--------------|
|
|
224
|
+
| Small (compact) | 16px | 12-14px | 16px | 4px (`_gap1`) |
|
|
225
|
+
| Default | 20-24px | 14-16px | 20-24px | 8px (`_gap2`) |
|
|
226
|
+
| Large | 24-32px | 16-20px | 24-32px | 8-12px (`_gap2`–`_gap3`) |
|
|
227
|
+
|
|
228
|
+
**Rule**: Icon size matches line-height, not font-size. Icon-to-text gap ≈ icon-size / 3.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 8. Typographic Spatial System
|
|
233
|
+
|
|
234
|
+
### Baseline grid
|
|
235
|
+
|
|
236
|
+
All line-heights should be divisible by 4. This aligns with Decantr's 4px half-step (`--d-sp-1`) and ensures vertical rhythm across mixed text sizes.
|
|
237
|
+
|
|
238
|
+
### Heading spacing asymmetry
|
|
239
|
+
|
|
240
|
+
Top-margin > bottom-margin. Ratio: approximately 3:1. This binds headings to the content that follows them, not the content above.
|
|
241
|
+
|
|
242
|
+
| Heading Level | Top Margin | Bottom Margin | Decantr Atoms |
|
|
243
|
+
|--------------|------------|---------------|--------------|
|
|
244
|
+
| Display / Hero | 64px | 16px | `_mt16 _mb4` |
|
|
245
|
+
| Section (h2) | 48px | 16px | `_mt12 _mb4` |
|
|
246
|
+
| Subsection (h3) | 32px | 12px | `_mt8 _mb3` |
|
|
247
|
+
| Minor (h4-h6) | 24px | 8px | `_mt6 _mb2` |
|
|
248
|
+
|
|
249
|
+
### Type-to-CTA spacing
|
|
250
|
+
|
|
251
|
+
| Content Before CTA | Gap | Decantr | Responsive? |
|
|
252
|
+
|--------------------|-----|---------|-------------|
|
|
253
|
+
| Display headline | 32px | `_mt8` | Reduces to 24px on mobile |
|
|
254
|
+
| Section headline | 24px | `_mt6` | Stays constant |
|
|
255
|
+
| Body copy | 24px | `_mt6` | Stays constant |
|
|
256
|
+
| Helper/description text | 16px | `_mt4` | Stays constant |
|
|
257
|
+
|
|
258
|
+
### Prose rhythm
|
|
259
|
+
|
|
260
|
+
The `.d-prose` class handles vertical rhythm for text-heavy content automatically:
|
|
261
|
+
- `> * + *` gets `margin-top: var(--d-sp-4)` (16px)
|
|
262
|
+
- Headings get graduated spacing (larger headings → more top margin)
|
|
263
|
+
- Lists get left padding with per-item spacing
|
|
264
|
+
- Blockquotes get left border + padding
|
|
265
|
+
|
|
266
|
+
**Rule**: Never manually space text blocks within a `.d-prose` container.
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## 9. Visual Weight & Whitespace
|
|
271
|
+
|
|
272
|
+
Heavier visual elements need more surrounding whitespace to feel balanced.
|
|
273
|
+
|
|
274
|
+
### Weight factors (by impact)
|
|
275
|
+
|
|
276
|
+
1. **Size** — Larger elements have more weight, need proportionally more margin
|
|
277
|
+
2. **Contrast** — Dark elements on light backgrounds (or vice versa) carry high weight
|
|
278
|
+
3. **Color saturation** — Vivid/saturated colors weigh more than muted
|
|
279
|
+
4. **Texture/Detail** — Images, dense text, filled icons weigh more than simple shapes
|
|
280
|
+
5. **Shape** — Compact regular shapes (squares) weigh more than open/irregular shapes
|
|
281
|
+
|
|
282
|
+
### Spacing rules by weight
|
|
283
|
+
|
|
284
|
+
| Element | Weight | Surrounding Space | Example |
|
|
285
|
+
|---------|--------|-------------------|---------|
|
|
286
|
+
| Display heading (32px+) | Heavy | 1.5-2× normal gap | `_mt12` vs body's `_mt6` |
|
|
287
|
+
| Hero image | Heavy | `_my8`–`_my16` from neighbors | Full-bleed needs large vertical margin |
|
|
288
|
+
| Data table (aggregate) | Heavy | `_my6`–`_my8` from surrounding content | Dense tables need breathing room |
|
|
289
|
+
| Icon-heavy toolbar | Medium (aggregate) | `_p2` internal (icons create density) | Light padding, icons fill the space |
|
|
290
|
+
| Body paragraph | Light | Standard gap (`_gap4`) | No extra space needed |
|
|
291
|
+
| Metadata (timestamp, tags) | Very light | Minimal (`_gap1`–`_gap2`) | Compact, subordinate |
|
|
292
|
+
|
|
293
|
+
### The asymmetry rule
|
|
294
|
+
|
|
295
|
+
More space **above** heavy elements, less **below**:
|
|
296
|
+
- Headings: `_mt8 _mb3` (not `_my6`) — binds heading to its section
|
|
297
|
+
- Section dividers: more space above than below
|
|
298
|
+
- Cards with bottom actions: actions provide visual weight at the bottom, reducing the need for bottom padding
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## 10. Optical Alignment Corrections
|
|
303
|
+
|
|
304
|
+
Mathematical spacing sometimes looks wrong. These corrections account for human perception:
|
|
305
|
+
|
|
306
|
+
| Situation | Correction | Notes |
|
|
307
|
+
|-----------|-----------|-------|
|
|
308
|
+
| **All-caps button text** | Reduce bottom padding ~2px | No descenders → mathematical center looks bottom-heavy |
|
|
309
|
+
| **Rounded corners** | Add ~2px more internal padding | Prevents content appearing to touch the curve; especially relevant with `--d-radius-lg` |
|
|
310
|
+
| **Icons in containers** | Shift ~2px down from mathematical center | Most icons have more visual weight in upper portion |
|
|
311
|
+
| **Play/arrow icons** | Shift 2-4px right of center | Visual weight is on the left/base of the triangle |
|
|
312
|
+
| **Buttons with leading icon** | Icon-side padding can be 2-4px less | Icon provides visual fill that padding would duplicate |
|
|
313
|
+
| **Cards with full-bleed top image** | No top padding for the image | Compound-pad applies only to text sections |
|
|
314
|
+
| **Circle vs square** at same dimensions | Circle appears ~2-4% smaller | Enlarge circles slightly to appear equal |
|
|
315
|
+
|
|
316
|
+
**Concentric radius rule:** When a rounded-rect child is nested inside a rounded-rect parent with padding between them, the inner radius MUST equal `outer radius − padding`. This produces concentric curves that look intentional. Mismatched radii (e.g., `8px` inner inside `16px` outer with `2px` padding) create a flat-inside-round artifact. In Decantr this is enforced via the `--d-radius-panel` / `--d-radius-inner` token pair in the RADIUS presets in `derive.js`. When adding a new preset, always compute `inner = panel − container padding`.
|
|
317
|
+
|
|
318
|
+
**In Decantr**: Most optical corrections are handled in `_base.js` component CSS. When building new components, visually verify alignment — don't assume mathematical centering is optically correct.
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## 11. Z-Axis Spatial Rules
|
|
323
|
+
|
|
324
|
+
Elevation determines how far floating elements sit from their triggers. Higher elevation = more offset + more shadow.
|
|
325
|
+
|
|
326
|
+
| Component | Offset Token | Value | Z-Index Token | Elevation |
|
|
327
|
+
|-----------|-------------|-------|--------------|-----------|
|
|
328
|
+
| Form dropdowns (Select, Combobox) | `--d-offset-dropdown` | 2px | `--d-z-dropdown` (1000) | Low |
|
|
329
|
+
| Menus, context menus | `--d-offset-menu` | 4px | `--d-z-dropdown` (1000) | Low-medium |
|
|
330
|
+
| Tooltips | `--d-offset-tooltip` | 6px | `--d-z-tooltip` (1500) | Medium |
|
|
331
|
+
| Popovers, hover cards | `--d-offset-popover` | 8px | `--d-z-popover` (1300) | Medium-high |
|
|
332
|
+
| Toasts | Fixed, 24px from viewport edge | — | `--d-z-toast` (1400) | High |
|
|
333
|
+
| Modals, dialogs | Centered with overlay | — | `--d-z-modal` (1200) | Highest |
|
|
334
|
+
| Drawers, sheets | Slide from edge, 0px offset | — | `--d-z-modal` (1200) | Highest |
|
|
335
|
+
|
|
336
|
+
### Rules
|
|
337
|
+
|
|
338
|
+
- **Offset direction**: Floating elements appear in the direction of action — dropdowns go down, tooltips go contextually (prefer above, then flip)
|
|
339
|
+
- **Collision handling**: When a floating element would overflow the viewport, flip to opposite side maintaining the same offset distance
|
|
340
|
+
- **Never hardcode offsets** — always use `--d-offset-*` tokens
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## 12. Component Anatomy Rules
|
|
345
|
+
|
|
346
|
+
### Header / Body / Footer (compound components)
|
|
347
|
+
|
|
348
|
+
All compound components (Card, Modal, Drawer) follow the compound spacing contract:
|
|
349
|
+
|
|
350
|
+
| Section | Padding Rule | Border |
|
|
351
|
+
|---------|-------------|--------|
|
|
352
|
+
| **Header** | `var(--d-compound-pad) var(--d-compound-pad) 0` | No bottom border (unless body scrolls beneath) |
|
|
353
|
+
| **Body** | `var(--d-compound-gap) var(--d-compound-pad)` | None |
|
|
354
|
+
| **Body:last-child** | Adds `padding-bottom: var(--d-compound-pad)` | None |
|
|
355
|
+
| **Footer** | `var(--d-compound-gap) var(--d-compound-pad) var(--d-compound-pad)` | Top separation via compound-gap (not a visible border) — see bordered exception below |
|
|
356
|
+
|
|
357
|
+
**Bordered footer exception:** When a compound footer has a visible `border-top` (e.g. Card), the border already provides inter-section separation. In this case, the footer uses symmetric padding — `var(--d-compound-pad)` on all sides — so content is vertically centered within the bordered zone. The asymmetric `compound-gap` top padding exists only for borderless footers (Modal, Drawer), where the gap itself acts as the separator and the asymmetry is invisible.
|
|
358
|
+
|
|
359
|
+
### Divider placement
|
|
360
|
+
|
|
361
|
+
- **Between siblings**: Use `d-dividey` on parent (never manual `<hr>` above first or below last child)
|
|
362
|
+
- **Footer top**: Always has visual separation from body (compound-gap provides it)
|
|
363
|
+
- **Header bottom**: Only add a border when the body scrolls beneath the header
|
|
364
|
+
- **Inset dividers in lists**: Indent to align with text start, not leading icon
|
|
365
|
+
- **Never**: place a divider between the last item and container edge — padding handles this
|
|
366
|
+
|
|
367
|
+
### Leading / Trailing content
|
|
368
|
+
|
|
369
|
+
| Position | Width | Gap to Main | Alignment |
|
|
370
|
+
|----------|-------|-------------|-----------|
|
|
371
|
+
| **Leading** (icon, avatar, checkbox) | Fixed | `_gap2` (8px) | Center (single-line), top (multi-line) |
|
|
372
|
+
| **Main** (title, description) | Flex-grow | — | Start |
|
|
373
|
+
| **Trailing** (action, badge, chevron) | Fixed | `_gap2` (8px) | Center (single-line), top (multi-line) |
|
|
374
|
+
|
|
375
|
+
### Action placement
|
|
376
|
+
|
|
377
|
+
| Context | Primary Action | Secondary Action | Destructive Action |
|
|
378
|
+
|---------|---------------|-----------------|-------------------|
|
|
379
|
+
| **Dialogs/modals** | Rightmost | Left of primary | Leftmost (with larger gap) |
|
|
380
|
+
| **Cards** | In footer, consistent alignment | Same row | Separate row or leftmost |
|
|
381
|
+
| **Forms** | Submit right-aligned (or left — pick one, never mix) | Cancel left of submit, `_gap2` | — |
|
|
382
|
+
| **Button groups** | `_gap2` between related | `_gap4`–`_gap6` between groups | Isolated with `_mla` (margin-left: auto) |
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## 13. Navigation & Chrome Spacing
|
|
387
|
+
|
|
388
|
+
Navigation is chrome — it's scanned, not read. Tight density zone applies.
|
|
389
|
+
|
|
390
|
+
### Rules
|
|
391
|
+
|
|
392
|
+
- **Grouped nav items** (segmented controls, chip filters) form a single visual unit → `_gap0` to `_gap1`
|
|
393
|
+
- **Internal padding creates separation** — when nav items have their own padding (`_px2 _py1`), external gap between them is redundant or minimal
|
|
394
|
+
- **Logo gets asymmetric spacing** — use `_mr4`–`_mr6` on the logo vs `_gap2` between nav items. This separates identity from navigation
|
|
395
|
+
- **Toolbar grouping** — related tools cluster together (bold/italic/underline: `_gap0` or `_gap1`); unrelated groups separate with `_gap3`–`_gap4` or a `Separator` component
|
|
396
|
+
- **Breadcrumbs** — separator character gets `_gap1`–`_gap2` on each side; breadcrumb items themselves have no extra gap
|
|
397
|
+
- **Tab bars** — tabs use squish inset internally (`_py2 _px4`); the tab container uses `_gap0` because tab borders/indicators handle visual separation
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## 14. Grid & Column System
|
|
402
|
+
|
|
403
|
+
### Decantr grid atoms
|
|
404
|
+
|
|
405
|
+
| Atom | CSS | Use |
|
|
406
|
+
|------|-----|-----|
|
|
407
|
+
| `_gc1`–`_gc12` | `grid-template-columns: repeat(N, minmax(0, 1fr))` | Fixed column count |
|
|
408
|
+
| `_gcaf160`–`_gcaf320` | `repeat(auto-fit, minmax(Npx, 1fr))` | Responsive auto-fit |
|
|
409
|
+
| `_span1`–`_span12` | `grid-column: span N` | Column span |
|
|
410
|
+
| `_spanfull` | `grid-column: 1 / -1` | Full row |
|
|
411
|
+
|
|
412
|
+
### Column count by content type
|
|
413
|
+
|
|
414
|
+
| Content | Desktop Columns | Auto-fit Min | Rationale |
|
|
415
|
+
|---------|----------------|-------------|-----------|
|
|
416
|
+
| Cards/tiles | 3-4 (`_gc3`, `_gc4`) | `_gcaf280` (280px) | Cards need ~280px to show content |
|
|
417
|
+
| KPI/stats | 4 (`_gc4`) | `_gcaf220` (220px) | Compact metrics, smaller minimum |
|
|
418
|
+
| Product grid | 3-4 | `_gcaf220` (220px) | Product cards with image + title + price |
|
|
419
|
+
| Article/documentation | 1 (centered `_ctr`) | — | Single column for readability |
|
|
420
|
+
| Dashboard widgets | 12 with variable `_span` | — | Mixed widget sizes in master grid |
|
|
421
|
+
| Photo/media | 3-6 | `_gcaf160` (160px) | Thumbnails can be small |
|
|
422
|
+
|
|
423
|
+
### Container widths
|
|
424
|
+
|
|
425
|
+
| Atom | Max-width | Use |
|
|
426
|
+
|------|-----------|-----|
|
|
427
|
+
| `_ctrsm` | 640px | Auth forms, settings pages, narrow content |
|
|
428
|
+
| `_ctr` | 960px | Article content, documentation, focused UIs |
|
|
429
|
+
| `_ctrlg` | 1080px | Standard app content, general pages |
|
|
430
|
+
| `_ctrxl` | 1280px | Wide app layouts, dashboards, multi-column |
|
|
431
|
+
|
|
432
|
+
### Max line length
|
|
433
|
+
|
|
434
|
+
Target ~60 characters per line for readability. `_ctr` (960px) with default body font achieves this. For wider containers, use multi-column layouts rather than stretching text across the full width.
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## 15. Micro-Spacing Rules
|
|
439
|
+
|
|
440
|
+
Fine-grained spacing for small elements and intra-component gaps:
|
|
441
|
+
|
|
442
|
+
| Context | Gap (px) | Decantr | Notes |
|
|
443
|
+
|---------|----------|---------|-------|
|
|
444
|
+
| Icon to text (standard) | 8px | `_gap2` | Most common: buttons, list items, badges |
|
|
445
|
+
| Icon to text (compact) | 4px | `_gap1` | Small/dense buttons, breadcrumbs |
|
|
446
|
+
| Label above input | 4-8px | `_gap1`–`_gap2` | Intimate tier — label binds to its field |
|
|
447
|
+
| Helper/error text below input | 4px | `_gap1` | Intimate tier — subordinate to the input |
|
|
448
|
+
| Between form fields | 16px | `_gap4` | Related tier — siblings of same type |
|
|
449
|
+
| Chips/tags gap | 4-8px | `_gap1`–`_gap2` | Inline items, tight grouping |
|
|
450
|
+
| Breadcrumb separator margin | 4-8px each side | `_gap1`–`_gap2` | Separator is not a grouping boundary |
|
|
451
|
+
| Button group gap (related) | 8px | `_gap2` | Related actions (Save / Cancel) |
|
|
452
|
+
| Button group gap (unrelated groups) | 16-24px | `_gap4`–`_gap6` | Separate button clusters |
|
|
453
|
+
| Badge overlap on parent | 25-50% of badge diameter | `_-mt1 _-mr1` | Badge partially covers parent corner |
|
|
454
|
+
| Inline `Kbd` padding | 2-4px horizontal | `_px1` | Minimal chrome |
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
## 16. Density System Integration
|
|
459
|
+
|
|
460
|
+
Decantr's three density classes cascade all spacing tokens to children:
|
|
461
|
+
|
|
462
|
+
| Density | Class | Compound Pad | Compound Gap | Field Height | Field Pad-X | Field Pad-Y |
|
|
463
|
+
|---------|-------|-------------|-------------|-------------|-------------|-------------|
|
|
464
|
+
| **Compact** | `.d-compact` | sp-3 (12px) | sp-2 (8px) | sm (28px) | sp-2-5 (10px) | sp-1 (4px) |
|
|
465
|
+
| **Comfortable** | `.d-comfortable` | sp-5 (20px) | sp-3 (12px) | md (36px) | sp-4 (16px) | sp-2 (8px) |
|
|
466
|
+
| **Spacious** | `.d-spacious` | sp-8 (32px) | sp-4 (16px) | lg (44px) | sp-6 (24px) | sp-2-5 (10px) |
|
|
467
|
+
|
|
468
|
+
### When to use which
|
|
469
|
+
|
|
470
|
+
| Density | When | Examples |
|
|
471
|
+
|---------|------|---------|
|
|
472
|
+
| **Compact** | Data-dense views, mouse/keyboard-primary, scan/compare workflows | Data tables, dashboards, analyst tools, IDE-like UIs |
|
|
473
|
+
| **Comfortable** | General application UI, mixed input modalities | Forms, settings, content pages, standard app views |
|
|
474
|
+
| **Spacious** | Marketing, onboarding, touch-primary, accessibility priority | Landing pages, wizards, mobile-first UIs, accessible contexts |
|
|
475
|
+
|
|
476
|
+
### Rules
|
|
477
|
+
|
|
478
|
+
- **Always default to comfortable.** Compact is opt-in.
|
|
479
|
+
- **Compact is desktop-only** — never apply to touch-primary interfaces
|
|
480
|
+
- **Density cascades** — set `.d-compact` on a parent container and all children (buttons, inputs, selects, cards) adapt automatically
|
|
481
|
+
- **Don't mix densities** in the same visual group — all siblings should share the same density
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## 17. Clarity Profile (Decantation Process)
|
|
486
|
+
|
|
487
|
+
The **Clarity** layer in the Decantation vocabulary governs whitespace. During SETTLE, the LLM determines Character traits which imply a Clarity profile:
|
|
488
|
+
|
|
489
|
+
| Character Trait | Density | Section Padding | Content Gap | Chrome Gap | Zone Emphasis |
|
|
490
|
+
|----------------|---------|-----------------|-------------|------------|--------------|
|
|
491
|
+
| "minimal", "clean" | Spacious | Landmark (`_py16`) | `_gap6` | `_gap2` | Showcase + Content |
|
|
492
|
+
| "professional", "balanced" | Comfortable | Sectional (`_py12`) | `_gap4` | `_gap2` | Content + Controls |
|
|
493
|
+
| "tactical", "dense" | Compact | Grouped (`_py8`) | `_gap3` | `_gap1` | Data-dense + Chrome |
|
|
494
|
+
| "editorial", "luxurious" | Spacious | Landmark (`_py24`) | `_gap8` | `_gap2` | Showcase |
|
|
495
|
+
| "technical", "utilitarian" | Compact | Sectional (`_py8`) | `_gap3` | `_gap1` | Controls + Data-dense |
|
|
496
|
+
|
|
497
|
+
During DECANT, each page's blend spec inherits the Clarity profile. The `surface` atoms on each page should reflect the zone and the Character-derived density.
|
|
498
|
+
|
|
499
|
+
### Cork rule (anti-drift)
|
|
500
|
+
|
|
501
|
+
Once a Clarity profile is established in the Essence, all subsequent pages must maintain it. A "minimal" site should never suddenly have compact chrome gaps. Drift is detected by comparing new page atoms against the Clarity profile.
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
## 18. Quick Reference Decision Table
|
|
506
|
+
|
|
507
|
+
When you need to decide spacing, use this lookup:
|
|
508
|
+
|
|
509
|
+
| I'm spacing... | Tier | Gap | Padding | Reference |
|
|
510
|
+
|----------------|------|-----|---------|-----------|
|
|
511
|
+
| Icon next to its label | Intimate | `_gap1`–`_gap2` | — | §15 Micro-spacing |
|
|
512
|
+
| Form label above its input | Intimate | `_gap1` | — | §3 Proximity |
|
|
513
|
+
| Adjacent form fields | Related | `_gap4` | — | §3 Proximity |
|
|
514
|
+
| A button's content | — | — | `_py2 _px4` (squish) | §2 Taxonomy |
|
|
515
|
+
| A text input's content | — | — | `_py3 _px2` (stretch) | §2 Taxonomy |
|
|
516
|
+
| Inside a card | — | — | `_p4`–`_p6` (inset) | §2 Taxonomy |
|
|
517
|
+
| Between card sections (header/body) | Grouped | compound-gap | compound-pad | §12 Anatomy |
|
|
518
|
+
| Nav bar items | Chrome | `_gap1`–`_gap2` | `_p1`–`_p2` | §5 Zones, §13 Chrome |
|
|
519
|
+
| Dashboard widgets | Data-dense | `_gap3`–`_gap4` | `_p3` | §5 Zones |
|
|
520
|
+
| Sections on a landing page | Sectional/Landmark | — | `_py12`–`_py16` | §3 Proximity |
|
|
521
|
+
| A hero section | Landmark | `_gap6` internal | `_py16`–`_py24` | §3 Proximity |
|
|
522
|
+
| Heading above its content | Asymmetric | `_mt8 _mb3` | — | §8 Typography |
|
|
523
|
+
| A floating dropdown from trigger | Z-axis | 2px offset | — | §11 Elevation |
|
|
524
|
+
| A tooltip from trigger | Z-axis | 6px offset | — | §11 Elevation |
|
|
525
|
+
| Page layout margins | Grid | — | `_px4` (mobile) → `_px8` (desktop) | §6 Responsive |
|
|
526
|
+
|
|
527
|
+
---
|
|
528
|
+
|
|
529
|
+
## 19. Density Zone Quick Selection
|
|
530
|
+
|
|
531
|
+
| Page Purpose | Zone | Default Gap | Default Padding | Example |
|
|
532
|
+
|--------------|------|-------------|-----------------|---------|
|
|
533
|
+
| Navigation bar, toolbar | Chrome | `_gap1`–`_gap2` | `_p1`–`_p2` | Top nav, breadcrumbs, status bar |
|
|
534
|
+
| Forms, settings, filters | Controls | `_gap3`–`_gap4` | `_p3`–`_p4` | Filter sidebar, settings panel |
|
|
535
|
+
| Articles, features, cards | Content | `_gap4`–`_gap6` | `_p4`–`_p6` | Blog post, feature grid |
|
|
536
|
+
| Hero, CTA, pricing | Showcase | `_gap6`–`_gap8` | `_py12`–`_py16` | Landing page sections |
|
|
537
|
+
| Tables, dashboards, monitoring | Data-dense | `_gap1`–`_gap2` | `_p2`–`_p3` | Analytics dashboard, log viewer |
|
|
538
|
+
|
|
539
|
+
---
|
|
540
|
+
|
|
541
|
+
**See also:** `reference/atoms.md`, `reference/compound-spacing.md`, `reference/tokens.md`, `reference/decantation-process.md`
|