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,576 @@
|
|
|
1
|
+
# Icon System Reference
|
|
2
|
+
|
|
3
|
+
Decantr's icon system renders 375 essential stroke-based SVG icons as CSS-masked `<span>` elements. Icons inherit `currentColor`, inject CSS once per name, and tree-shake unused paths at build time.
|
|
4
|
+
|
|
5
|
+
## Rendering Pipeline
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
essential.js → getIconPath(name) → icon(name, opts)
|
|
9
|
+
↓
|
|
10
|
+
buildDataUri(inner, weight, filled)
|
|
11
|
+
↓
|
|
12
|
+
injectIconCSS(name, inner, weight, filled)
|
|
13
|
+
↓
|
|
14
|
+
<span class="d-i d-i-{variantKey}">
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
All icons use a 24×24 viewBox, `stroke-linecap="round"`, `stroke-linejoin="round"`. Default: `stroke-width="2"`, `fill="none"`. Weight and fill options parameterize the SVG wrapper. The `<span>` uses `mask-image` with a data URI — color comes from `currentColor` via the parent's `color` property. Each icon variant is injected into a shared `<style data-decantr-icons>` element exactly once (keyed by name + weight + filled).
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Core API
|
|
22
|
+
|
|
23
|
+
### `icon(name, opts?)` — `decantr/components`
|
|
24
|
+
|
|
25
|
+
Render an icon as a `<span>` element.
|
|
26
|
+
|
|
27
|
+
| Param | Type | Default | Description |
|
|
28
|
+
|-------|------|---------|-------------|
|
|
29
|
+
| `name` | `string` | — | Icon name in kebab-case (e.g. `'check'`, `'chevron-down'`) |
|
|
30
|
+
| `opts.size` | `string\|number` | `'1.25em'` | CSS width and height |
|
|
31
|
+
| `opts.weight` | `string\|number` | `'regular'` | Stroke weight (see Weight table below) |
|
|
32
|
+
| `opts.filled` | `boolean` | `false` | Fill closed shapes |
|
|
33
|
+
| `opts.class` | `string` | — | Additional CSS classes |
|
|
34
|
+
| `...rest` | — | — | Spread to the `<span>` element |
|
|
35
|
+
|
|
36
|
+
**Returns:** `HTMLElement` with `class="d-i d-i-{name}"`, `role="img"`, `aria-hidden="true"`
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
import { icon } from 'decantr/components';
|
|
40
|
+
|
|
41
|
+
icon('check'); // default 1.25em, regular weight
|
|
42
|
+
icon('star', { size: '1em' }); // inline with text
|
|
43
|
+
icon('home', { size: '2rem' }); // large feature icon
|
|
44
|
+
icon('edit', { class: css('_fgprimary') }); // colored
|
|
45
|
+
icon('heart', { filled: true }); // solid heart
|
|
46
|
+
icon('star', { weight: 'bold', filled: true }); // bold + filled
|
|
47
|
+
icon('chevron-down', { weight: 'thin' }); // thin stroke
|
|
48
|
+
icon('circle', { weight: 1.5 }); // numeric weight
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
#### Weight
|
|
52
|
+
|
|
53
|
+
Named or numeric, controls `stroke-width`. Numeric values clamped to `[0.5, 4]`.
|
|
54
|
+
|
|
55
|
+
| Name | stroke-width |
|
|
56
|
+
|------|-------------|
|
|
57
|
+
| `thin` | 1 |
|
|
58
|
+
| `light` | 1.5 |
|
|
59
|
+
| `regular` | 2 (default) |
|
|
60
|
+
| `medium` | 2.5 |
|
|
61
|
+
| `bold` | 3 |
|
|
62
|
+
|
|
63
|
+
Fill-based icons (auto-detected via `fill=` attribute) ignore weight.
|
|
64
|
+
|
|
65
|
+
#### Filled
|
|
66
|
+
|
|
67
|
+
Boolean, default `false`. Adds `fill='black'` alongside stroke attributes in the SVG wrapper. Closed shapes (paths, polygons, circles, rects) fill in; open elements (lines, polylines) remain unchanged. Fill-based icons ignore this option (already filled).
|
|
68
|
+
|
|
69
|
+
#### CSS Class Naming
|
|
70
|
+
|
|
71
|
+
Variants produce CSS class suffixes on `d-i-{name}`:
|
|
72
|
+
|
|
73
|
+
| Variant | CSS class example |
|
|
74
|
+
|---------|------------------|
|
|
75
|
+
| Default (regular, no fill) | `d-i-heart` |
|
|
76
|
+
| Weight only | `d-i-heart--w1` (thin), `d-i-heart--w1p5` (light) |
|
|
77
|
+
| Fill only | `d-i-heart--filled` |
|
|
78
|
+
| Weight + fill | `d-i-heart--w3-filled` (bold + filled) |
|
|
79
|
+
|
|
80
|
+
Decimals use `p` in class names: `1.5` → `w1p5`, `2.5` → `w2p5`.
|
|
81
|
+
|
|
82
|
+
### Registry Functions — `decantr/icons`
|
|
83
|
+
|
|
84
|
+
| Function | Signature | Description |
|
|
85
|
+
|----------|-----------|-------------|
|
|
86
|
+
| `getIconPath` | `(name) → string\|null` | Get SVG inner content for an icon |
|
|
87
|
+
| `registerIcon` | `(name, svgInner)` | Register or override a single icon |
|
|
88
|
+
| `registerIcons` | `(map)` | Bulk-register from `{ name: svgInner }` object |
|
|
89
|
+
| `hasIcon` | `(name) → boolean` | Check if icon is available |
|
|
90
|
+
| `getIconNames` | `() → string[]` | List all available icon names |
|
|
91
|
+
|
|
92
|
+
### `caret(direction?, opts?)` — `decantr/components` (via `_behaviors.js`)
|
|
93
|
+
|
|
94
|
+
Convenience wrapper for chevron icons used as dropdown/expand indicators.
|
|
95
|
+
|
|
96
|
+
| Param | Type | Default | Description |
|
|
97
|
+
|-------|------|---------|-------------|
|
|
98
|
+
| `direction` | `'down'\|'up'\|'left'\|'right'` | `'down'` | Chevron direction |
|
|
99
|
+
| `opts` | `object` | `{}` | Passed to `icon()` |
|
|
100
|
+
|
|
101
|
+
**Returns:** `icon('chevron-{direction}', { size: '1em', class: 'd-caret', ...opts })`
|
|
102
|
+
|
|
103
|
+
CSS classes `.d-caret` (transition on transform) and `.d-caret-open` (`rotate(180deg)`) handle open/close animation.
|
|
104
|
+
|
|
105
|
+
**Used by:** Accordion, Cascader, Combobox, DataTable, Menu, NavigationMenu, Select, TreeSelect
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Size Tiers
|
|
110
|
+
|
|
111
|
+
| Tier | Size | When to use |
|
|
112
|
+
|------|------|-------------|
|
|
113
|
+
| **inline** | `1em` | Inside text-bearing components — Button, Chip, Menu items, Steps, Pickers, carets. Scales with font size. |
|
|
114
|
+
| **default** | `1.25em` | Standalone icons, general purpose. The `icon()` default. |
|
|
115
|
+
| **feature** | `1.5em`–`24px` | Feature cards, settings panels, navigation highlights. |
|
|
116
|
+
| **hero** | `2.5rem`–`3rem` | Empty states, Result status icons, large visual anchors. |
|
|
117
|
+
|
|
118
|
+
**Rule:** Use `1em` when the icon sits beside text (it scales with the text). Use `1.25em`+ when the icon stands alone.
|
|
119
|
+
|
|
120
|
+
From `spatial-guidelines.md` §7:
|
|
121
|
+
|
|
122
|
+
| Context | Icon Size | Text Size | Icon-Text Gap |
|
|
123
|
+
|---------|-----------|-----------|---------------|
|
|
124
|
+
| Small (compact) | 16px | 12-14px | 4px (`_gap1`) |
|
|
125
|
+
| Default | 20-24px | 14-16px | 8px (`_gap2`) |
|
|
126
|
+
| Large | 24-32px | 16-20px | 8-12px (`_gap2`–`_gap3`) |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Component Integration Map
|
|
131
|
+
|
|
132
|
+
Components that accept or render icons. Sizes listed are what the component renders internally.
|
|
133
|
+
|
|
134
|
+
| Component | Prop / Mechanism | Type | Rendered Size | Notes |
|
|
135
|
+
|-----------|-----------------|------|---------------|-------|
|
|
136
|
+
| **Button** | `iconLeft`, `iconRight` | `string\|Node` | `1em` | String auto-wrapped via `icon(name, {size:'1em'})` |
|
|
137
|
+
| **Chip** | child icon node | `Node` | `1em` | `.d-chip-icon` class applied |
|
|
138
|
+
| **Alert** | `icon` | `string\|Node` | component default | Severity icon auto-assigned if omitted |
|
|
139
|
+
| **Input** | `prefix`, `suffix` | `string\|Node` | parent font | Wrapped in `.d-input-prefix`/`.d-input-suffix` |
|
|
140
|
+
| **InputNumber** | `prefix`, `suffix` | `string\|Node` | parent font | Same as Input |
|
|
141
|
+
| **Select** | caret auto-rendered | — | `1em` | `caret('down')` for dropdown arrow |
|
|
142
|
+
| **Combobox** | caret auto-rendered | — | `1em` | `caret('down')` for dropdown arrow |
|
|
143
|
+
| **DatePicker** | calendar icon auto | — | `1em` | `icon('calendar', {size:'1em'})` |
|
|
144
|
+
| **TimePicker** | clock icon auto | — | `1em` | `icon('clock', {size:'1em'})` |
|
|
145
|
+
| **Accordion** | caret auto-rendered | — | `1em` | `caret('down')`, rotates on open |
|
|
146
|
+
| **Menu** | caret on submenus | — | `1em` | `caret('right')` for nested items |
|
|
147
|
+
| **NavigationMenu** | caret auto-rendered | — | `1em` | `caret('down')` for dropdown triggers |
|
|
148
|
+
| **Dropdown** | item `icon` | `string\|Node` | `1em` | `.d-dropdown-item-icon` class |
|
|
149
|
+
| **ContextMenu** | item `icon` | `string\|Node` | `1em` | Same as Dropdown |
|
|
150
|
+
| **DataTable** | sort/expand carets | — | `1em` | Auto-rendered sort indicators and row expand |
|
|
151
|
+
| **Cascader** | caret auto-rendered | — | `1em` | `caret('right')` for navigation |
|
|
152
|
+
| **TreeSelect** | expand caret | — | `0.875em` | Smaller for nested tree items |
|
|
153
|
+
| **Segmented** | item `icon` | `string\|Node` | `1em` | Optional icon per segment |
|
|
154
|
+
| **Steps** | status icons auto | — | component default | Auto check/x for completed/error steps |
|
|
155
|
+
| **Timeline** | `dot` content | `Node` | varies | Custom icon in timeline dot |
|
|
156
|
+
| **BackTop** | arrow-up auto | — | `1.25em` | `icon('arrow-up')` default |
|
|
157
|
+
| **Statistic** | `prefix`, `suffix` | `string\|Node` | parent font | Visual prefix/suffix for numeric value |
|
|
158
|
+
| **Spinner** | loader icon | — | varies | Integrated icon animation |
|
|
159
|
+
| **Badge** | `icon` | `string\|Node` | component default | Optional icon in badge |
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Essential Icon Catalog
|
|
164
|
+
|
|
165
|
+
375 icons organized by semantic category. Canonical machine-readable source: `src/registry/icons.json`.
|
|
166
|
+
|
|
167
|
+
### Navigation (15)
|
|
168
|
+
`check`, `x`, `plus`, `minus`, `chevron-down`, `chevron-up`, `chevron-left`, `chevron-right`, `chevrons-left`, `chevrons-right`, `arrow-left`, `arrow-right`, `arrow-up`, `arrow-down`, `navigation`
|
|
169
|
+
|
|
170
|
+
Directional control, confirmation/dismissal, expand/collapse. The backbone of interactive UI.
|
|
171
|
+
|
|
172
|
+
### Common UI (22)
|
|
173
|
+
`search`, `menu`, `more-horizontal`, `more-vertical`, `external-link`, `home`, `bell`, `settings`, `star`, `edit`, `trash`, `copy`, `eye`, `eye-off`, `filter`, `download`, `upload`, `refresh`, `loader`, `log-out`, `log-in`, `user`
|
|
174
|
+
|
|
175
|
+
General-purpose actions and indicators used across all domain archetypes.
|
|
176
|
+
|
|
177
|
+
### Feedback (9)
|
|
178
|
+
`info`, `alert-triangle`, `alert-circle`, `check-circle`, `x-circle`, `circle-dot`, `flag`, `ban`, `alarm`
|
|
179
|
+
|
|
180
|
+
Status communication. Map directly to Alert/Notification severity variants: `info` → info, `alert-triangle` → warning, `alert-circle` → error, `check-circle` → success, `x-circle` → error/destructive.
|
|
181
|
+
|
|
182
|
+
### Time & Scheduling (11)
|
|
183
|
+
`clock`, `timer`, `hourglass`, `alarm-clock`, `watch`, `watch-smart`, `history`, `calendar`, `calendar-check`, `calendar-plus`, `calendar-x`
|
|
184
|
+
|
|
185
|
+
All scheduling, reminders, deadlines, and time-tracking contexts.
|
|
186
|
+
|
|
187
|
+
### Layout / Data (9)
|
|
188
|
+
`layout-dashboard`, `mail`, `image`, `file`, `folder`, `grip-vertical`, `move`, `blocks`
|
|
189
|
+
|
|
190
|
+
Content type indicators and drag handles. Dashboard and file management contexts.
|
|
191
|
+
|
|
192
|
+
### People & Security (19)
|
|
193
|
+
`user`, `users`, `user-plus`, `user-minus`, `user-check`, `user-x`, `users-round`, `shield`, `shield-check`, `shield-x`, `shield-alert`, `lock`, `lock-keyhole`, `unlock`, `key`, `fingerprint`, `eye-scan`, `id-card`, `passport`
|
|
194
|
+
|
|
195
|
+
Authentication, authorization, team management, and identity verification.
|
|
196
|
+
|
|
197
|
+
### Documents & Data (29)
|
|
198
|
+
`file-text`, `file-plus`, `file-minus`, `file-check`, `file-x`, `file-search`, `file-code`, `file-spreadsheet`, `file-image`, `file-audio`, `file-video`, `files`, `folder-open`, `folder-plus`, `folder-check`, `save`, `printer`, `bookmark`, `bookmark-plus`, `archive`, `clipboard`, `paperclip`, `link`, `unlink`, `hash`, `tag`, `notebook`, `contract`, `invoice`
|
|
199
|
+
|
|
200
|
+
Document actions, file types, and metadata. Content management and file operations.
|
|
201
|
+
|
|
202
|
+
### Communication (29)
|
|
203
|
+
`phone`, `video`, `send`, `at-sign`, `at`, `message-square`, `message-circle`, `reply`, `rss`, `podcast`, `microphone`, `microphone-off`, `headphones`, `megaphone`, `newspaper`, `radio`, `tv`, `cast`, `heart`, `heart-crack`, `thumbs-up`, `thumbs-down`, `smile`, `frown`, `meh`, `laugh`, `angry`, `award`
|
|
204
|
+
|
|
205
|
+
Messaging, social engagement, media, and broadcasting.
|
|
206
|
+
|
|
207
|
+
### Charts & Analytics (6)
|
|
208
|
+
`bar-chart`, `pie-chart`, `trending-up`, `trending-down`, `activity`, `percent`
|
|
209
|
+
|
|
210
|
+
Data visualization indicators. Use `trending-up`/`trending-down` for KPI trend arrows.
|
|
211
|
+
|
|
212
|
+
### Organization (8)
|
|
213
|
+
`list`, `list-ordered`, `grid-3x3`, `inbox`, `layers`, `kanban`, `columns`, `rows`
|
|
214
|
+
|
|
215
|
+
View modes, sorting, and organizational structures.
|
|
216
|
+
|
|
217
|
+
### Navigation & Layout (7)
|
|
218
|
+
`sidebar`, `panel-left`, `panel-right`, `maximize`, `minimize`, `expand`, `shrink`
|
|
219
|
+
|
|
220
|
+
Window and panel management. Dashboard and editor layouts.
|
|
221
|
+
|
|
222
|
+
### Dev & Infrastructure (13)
|
|
223
|
+
`code`, `terminal`, `server`, `database`, `moon`, `sun`, `cloud`, `cloud-upload`, `cloud-download`, `cloud-cog`, `wifi`, `wifi-off`, `bug`
|
|
224
|
+
|
|
225
|
+
Developer tools, infrastructure status, and mode toggles. `moon`/`sun` are the canonical dark/light mode toggle icons.
|
|
226
|
+
|
|
227
|
+
### Business & Finance (14)
|
|
228
|
+
`calculator`, `bank`, `coins`, `piggy-bank`, `invoice`, `contract`, `signature`, `stamp`, `briefcase`, `handshake`, `scale`, `target`, `crown`, `lighthouse`
|
|
229
|
+
|
|
230
|
+
Banking, contracts, professional tools, and financial contexts.
|
|
231
|
+
|
|
232
|
+
### Commerce (22)
|
|
233
|
+
`credit-card`, `shopping-cart`, `shopping-bag`, `store`, `wallet`, `dollar-sign`, `receipt`, `gift`, `coupon`, `barcode`, `qr-code`, `price-tag`, `percent-circle`, `shipping`, `returns`, `truck`, `package`, `box`, `boxes`, `container`, `pallet`, `forklift`
|
|
234
|
+
|
|
235
|
+
Shopping, payments, and logistics.
|
|
236
|
+
|
|
237
|
+
### Media & Creative (16)
|
|
238
|
+
`camera`, `camera-off`, `film`, `palette`, `brush`, `pen-tool`, `eyedropper`, `crop`, `type`, `align-left`, `align-center`, `align-right`, `align-justify`, `sparkles`, `wand`, `eraser`
|
|
239
|
+
|
|
240
|
+
Photography, design tools, and text formatting.
|
|
241
|
+
|
|
242
|
+
### Devices & Technology (13)
|
|
243
|
+
`smartphone`, `tablet`, `laptop`, `monitor`, `bluetooth`, `usb`, `battery`, `battery-charging`, `battery-low`, `signal`, `satellite`, `robot`, `chip`
|
|
244
|
+
|
|
245
|
+
Hardware, connectivity, and device types.
|
|
246
|
+
|
|
247
|
+
### Workflow & Development (12)
|
|
248
|
+
`git-branch`, `git-merge`, `git-pull-request`, `git-commit`, `milestone`, `workflow`, `variable`, `regex`, `binary`, `webhook`, `api`, `container-ship`
|
|
249
|
+
|
|
250
|
+
Version control, CI/CD, and project management tools.
|
|
251
|
+
|
|
252
|
+
### Healthcare & Wellness (12)
|
|
253
|
+
`stethoscope`, `pill`, `syringe`, `heart-pulse`, `bandage`, `thermometer`, `brain`, `dna`, `accessibility`, `baby`, `apple`, `dumbbell`
|
|
254
|
+
|
|
255
|
+
Medical, wellness, fitness, and accessibility contexts.
|
|
256
|
+
|
|
257
|
+
### Education & Learning (10)
|
|
258
|
+
`book`, `book-open`, `graduation-cap`, `notebook`, `presentation`, `trophy`, `medal`, `school`, `lightbulb`, `puzzle`
|
|
259
|
+
|
|
260
|
+
Learning, achievements, and educational institutions.
|
|
261
|
+
|
|
262
|
+
### Transportation & Travel (11)
|
|
263
|
+
`car`, `bus`, `train`, `bicycle`, `ship`, `rocket`, `helicopter`, `taxi`, `parking`, `fuel`, `map-compass`
|
|
264
|
+
|
|
265
|
+
Vehicles, travel, and logistics.
|
|
266
|
+
|
|
267
|
+
### Food & Hospitality (8)
|
|
268
|
+
`utensils`, `coffee`, `wine`, `pizza`, `cake`, `chef-hat`, `grape`, `wheat`
|
|
269
|
+
|
|
270
|
+
Dining, beverages, and culinary contexts.
|
|
271
|
+
|
|
272
|
+
### Home & Real Estate (10)
|
|
273
|
+
`house`, `apartment`, `sofa`, `lamp`, `bed`, `bath`, `garden`, `door-closed`, `window`, `air-conditioning`
|
|
274
|
+
|
|
275
|
+
Furniture, property, and living spaces.
|
|
276
|
+
|
|
277
|
+
### Weather & Environment (9)
|
|
278
|
+
`umbrella`, `wind`, `droplet`, `snowflake`, `sunrise`, `sunset`, `leaf`, `tree`, `mountain`
|
|
279
|
+
|
|
280
|
+
Climate, nature, and environmental contexts.
|
|
281
|
+
|
|
282
|
+
### Actions (11)
|
|
283
|
+
`undo`, `redo`, `share`, `share-2`, `rotate-cw`, `rotate-ccw`, `scissors`, `zap`, `scan`, `pencil`, `pen`
|
|
284
|
+
|
|
285
|
+
Editing operations and quick actions.
|
|
286
|
+
|
|
287
|
+
### Maps & Location (2)
|
|
288
|
+
`globe`, `map-pin`
|
|
289
|
+
|
|
290
|
+
Geographic and internationalization contexts.
|
|
291
|
+
|
|
292
|
+
### Places (17)
|
|
293
|
+
`building`, `building-2`, `hospital`, `factory`, `warehouse`, `landmark`, `door-open`, `garage`, `fence`, `construction`, `anchor`, `plane`, `map`, `compass`, `route`, `cctv`
|
|
294
|
+
|
|
295
|
+
Physical locations and facility management.
|
|
296
|
+
|
|
297
|
+
### Tools & Config (14)
|
|
298
|
+
`wrench`, `tool`, `hammer`, `screwdriver`, `nut`, `plug`, `cog`, `sliders-horizontal`, `gauge`, `toggle-left`, `toggle-right`, `power`, `cpu`, `hard-drive`
|
|
299
|
+
|
|
300
|
+
Settings, configuration, and system administration.
|
|
301
|
+
|
|
302
|
+
### Tables & Data Grids (15)
|
|
303
|
+
`table`, `table-rows`, `table-columns`, `table-cells`, `layout-grid`, `sort-asc`, `sort-desc`, `arrow-up-down`, `filter-x`, `group`, `ungroup`, `spreadsheet`, `pivot-table`
|
|
304
|
+
|
|
305
|
+
DataTable controls and view configuration. Sort/filter/group affordances.
|
|
306
|
+
|
|
307
|
+
### Shapes & Symbols (9)
|
|
308
|
+
`circle`, `square`, `triangle`, `diamond`, `hexagon`, `infinity`, `asterisk`, `hash-tag`, `parentheses`
|
|
309
|
+
|
|
310
|
+
Geometric shapes and common symbols for UI decoration, status, and categorization.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Content Strategy: When to Use Icons
|
|
315
|
+
|
|
316
|
+
### The Five Functions of Icons
|
|
317
|
+
|
|
318
|
+
| Function | What it communicates | Where it appears |
|
|
319
|
+
|----------|---------------------|-----------------|
|
|
320
|
+
| **Recognition** | Quick identification of action or object | Buttons, nav items, menus |
|
|
321
|
+
| **Scannability** | Visual anchors that break text monotony | KPI cards, feature lists, settings panels |
|
|
322
|
+
| **Affordance** | Signals interactivity or expandability | Dropdown carets, sort indicators, expandable sections |
|
|
323
|
+
| **Status** | Conveys state or feedback type | Alerts, results, step completion, trend indicators |
|
|
324
|
+
| **Density** | Communicates meaning in less space than text | Icon-only buttons, compact toolbars, data table controls |
|
|
325
|
+
|
|
326
|
+
### Mandatory Icon Placement
|
|
327
|
+
|
|
328
|
+
Icons MUST appear in these contexts:
|
|
329
|
+
|
|
330
|
+
1. **Navigation items** (sidebar, menu) — leading icon for scannability
|
|
331
|
+
2. **Empty states** (Result, Empty) — visual focal point required
|
|
332
|
+
3. **Feedback components** (Alert, Banner, Notification, toast) — severity before reading text
|
|
333
|
+
4. **Form triggers** (DatePicker, TimePicker, search inputs) — affordance signal
|
|
334
|
+
5. **Data table controls** (sort, filter, expand, pin) — primary affordance
|
|
335
|
+
6. **Step indicators** — auto check/x plus domain-specific custom icons
|
|
336
|
+
7. **KPI / Statistics** — trend arrows (`trending-up`/`trending-down`), category icons for dashboard anchoring
|
|
337
|
+
|
|
338
|
+
### Recommended Icon Placement
|
|
339
|
+
|
|
340
|
+
Optional but improves visual integrity:
|
|
341
|
+
|
|
342
|
+
- **Button `iconLeft`** for primary CTAs — adds visual weight and recognition
|
|
343
|
+
- **Chip icons** for category disambiguation in tag clouds or filter bars
|
|
344
|
+
- **Menu/Dropdown item icons** for faster scanning in long lists
|
|
345
|
+
- **Card headers** with topic icons for visual grouping
|
|
346
|
+
- **Hero sections** with feature icon alongside headline
|
|
347
|
+
|
|
348
|
+
### When NOT to Use Icons
|
|
349
|
+
|
|
350
|
+
- **Pure text content** — articles, documentation body, prose paragraphs
|
|
351
|
+
- **Purely decorative** — icon with no semantic value adds noise
|
|
352
|
+
- **Already icon-dense areas** — too many icons defeat scannability
|
|
353
|
+
- **Typography components** (Title, Text, Paragraph) — they carry their own visual weight
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Accessibility
|
|
358
|
+
|
|
359
|
+
- Icons render `role="img"` and `aria-hidden="true"` — decorative by default
|
|
360
|
+
- **Icon-only buttons:** place `aria-label` on the `<button>`, NOT the icon
|
|
361
|
+
```javascript
|
|
362
|
+
Button({ 'aria-label': 'Delete', size: 'icon' }, icon('trash'))
|
|
363
|
+
```
|
|
364
|
+
- Never use an icon as the sole conveyor of critical information without adjacent text
|
|
365
|
+
- Color alone is not sufficient — icons help distinguish Alert variants beyond color (e.g., `alert-triangle` for warning vs `info` for info)
|
|
366
|
+
- Icons are static; animated states use CSS transitions on containers (e.g., `.d-caret` → `.d-caret-open`)
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## Custom Icons
|
|
371
|
+
|
|
372
|
+
### Import workflow via `tools/icons.js`
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
node tools/icons.js <svg-dir> [output.js]
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**SVG requirements:** 24×24 viewBox, stroke-based preferred (`fill="none"`, `stroke-width="2"`, `stroke-linecap="round"`, `stroke-linejoin="round"`).
|
|
379
|
+
|
|
380
|
+
| Command | Output |
|
|
381
|
+
|---------|--------|
|
|
382
|
+
| `node tools/icons.js ./my-icons` | `src/icons/custom.js` |
|
|
383
|
+
| `node tools/icons.js ./brand-icons brand.js` | `src/icons/brand.js` |
|
|
384
|
+
| `node tools/icons.js` (no args) | Regenerates `src/registry/icons.json` only |
|
|
385
|
+
|
|
386
|
+
**Generated module:**
|
|
387
|
+
```javascript
|
|
388
|
+
// Generated by tools/icons.js — do not edit
|
|
389
|
+
export const ICONS = {
|
|
390
|
+
'icon-name': '<path d="..."/>',
|
|
391
|
+
};
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
**Registration in app code:**
|
|
395
|
+
```javascript
|
|
396
|
+
import { ICONS } from './icons/custom.js';
|
|
397
|
+
import { registerIcons } from 'decantr/icons';
|
|
398
|
+
registerIcons(ICONS);
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Runtime registration
|
|
402
|
+
|
|
403
|
+
For icons loaded dynamically (e.g., from an API):
|
|
404
|
+
|
|
405
|
+
```javascript
|
|
406
|
+
import { registerIcon, hasIcon } from 'decantr/icons';
|
|
407
|
+
|
|
408
|
+
if (!hasIcon('my-dynamic-icon')) {
|
|
409
|
+
registerIcon('my-dynamic-icon', '<path d="M12 2L22 22H2z"/>');
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
Register custom icons before first render to avoid a flash of missing icons.
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## Third-Party Icon Libraries
|
|
418
|
+
|
|
419
|
+
Decantr's `icon()` renders SVGs via CSS `mask-image`. Third-party libraries fall into two categories: SVG-based (compatible with `icon()`) and font/class-based (bypass `icon()` entirely). The LLM generating code already knows every library's conventions — Decantr provides the hooks, not the adapters.
|
|
420
|
+
|
|
421
|
+
### Config Signal
|
|
422
|
+
|
|
423
|
+
Declare the project's icon library in `decantr.config.json`:
|
|
424
|
+
|
|
425
|
+
```jsonc
|
|
426
|
+
{
|
|
427
|
+
"icons": {
|
|
428
|
+
"library": "material" // informational — tells LLM what conventions to use
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
Decantr does not act on this value. It signals to the LLM which icon library's conventions to follow when generating code. Validated by `decantr validate` (warns on unrecognized libraries).
|
|
434
|
+
|
|
435
|
+
### SVG Libraries (Lucide, Heroicons, Phosphor, Feather, Tabler)
|
|
436
|
+
|
|
437
|
+
These ship SVG data and work directly with `registerIcons()`.
|
|
438
|
+
|
|
439
|
+
**Stroke-based (Lucide, Feather, Heroicons Outline):**
|
|
440
|
+
|
|
441
|
+
```javascript
|
|
442
|
+
import { registerIcons } from 'decantr/icons';
|
|
443
|
+
import lucideIcons from './icons/lucide-data.js'; // generated via tools/icons.js
|
|
444
|
+
registerIcons(lucideIcons);
|
|
445
|
+
|
|
446
|
+
// Then use normally
|
|
447
|
+
icon('search'); // renders Lucide's search icon
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
**Fill-based (Heroicons Solid, Material SVGs, Phosphor Fill):**
|
|
451
|
+
|
|
452
|
+
`buildDataUri()` auto-detects fill-based SVGs. If the inner content contains a `fill=` attribute with a non-`none` value, it uses fill rendering (`fill='black' stroke='none'`). Otherwise it uses stroke rendering (default).
|
|
453
|
+
|
|
454
|
+
```javascript
|
|
455
|
+
// Fill-based SVGs — auto-detected
|
|
456
|
+
registerIcon('home-solid', '<path fill="currentColor" d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>');
|
|
457
|
+
|
|
458
|
+
// SVGs with bare <path> (no fill attr) — add fill="currentColor" when registering
|
|
459
|
+
registerIcon('expand-more', '<path fill="currentColor" d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"/>');
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
**Import workflow:**
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
node tools/icons.js ./lucide-svgs lucide.js # → src/icons/lucide.js
|
|
466
|
+
node tools/icons.js ./heroicons-solid solid.js # → src/icons/solid.js
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### Font-Based Libraries (Google Material Icons, Font Awesome)
|
|
470
|
+
|
|
471
|
+
Font/class-based icon systems use a fundamentally different rendering model (`font-family` + ligatures or `::before` pseudo-elements). They bypass `icon()` entirely — the LLM generates native HTML.
|
|
472
|
+
|
|
473
|
+
**Google Material Icons:**
|
|
474
|
+
|
|
475
|
+
```html
|
|
476
|
+
<!-- Load in index.html -->
|
|
477
|
+
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
```javascript
|
|
481
|
+
// LLM generates native Material Icons markup
|
|
482
|
+
h('span', { class: 'material-icons', 'aria-hidden': 'true' }, 'home')
|
|
483
|
+
h('span', { class: 'material-icons', 'aria-hidden': 'true' }, 'search')
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
**Font Awesome:**
|
|
487
|
+
|
|
488
|
+
```html
|
|
489
|
+
<!-- Load in index.html -->
|
|
490
|
+
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
```javascript
|
|
494
|
+
// LLM generates native Font Awesome markup
|
|
495
|
+
h('i', { class: 'fa-solid fa-house', 'aria-hidden': 'true' })
|
|
496
|
+
h('i', { class: 'fa-solid fa-magnifying-glass', 'aria-hidden': 'true' })
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### Structural Icon Overrides
|
|
500
|
+
|
|
501
|
+
Framework components (Select, Accordion, DataTable, Alert, etc.) use ~15 structural icons internally via `icon()`. These always work with the built-in essential set, regardless of what third-party library the project uses.
|
|
502
|
+
|
|
503
|
+
For visual consistency with an external SVG library, override the structural icons at app startup:
|
|
504
|
+
|
|
505
|
+
```javascript
|
|
506
|
+
import { registerIcon } from 'decantr/icons';
|
|
507
|
+
|
|
508
|
+
// Override structural icons with Material Design SVGs
|
|
509
|
+
registerIcon('chevron-down', '<path fill="currentColor" d="M7 10l5 5 5-5z"/>');
|
|
510
|
+
registerIcon('chevron-up', '<path fill="currentColor" d="M7 14l5-5 5 5z"/>');
|
|
511
|
+
registerIcon('chevron-left', '<path fill="currentColor" d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>');
|
|
512
|
+
registerIcon('chevron-right', '<path fill="currentColor" d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/>');
|
|
513
|
+
registerIcon('check', '<path fill="currentColor" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>');
|
|
514
|
+
registerIcon('x', '<path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>');
|
|
515
|
+
registerIcon('calendar', '<path fill="currentColor" d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11z"/>');
|
|
516
|
+
registerIcon('clock', '<path fill="currentColor" d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/>');
|
|
517
|
+
registerIcon('search', '<path fill="currentColor" d="M15.5 14h-.79l-.28-.27A6.47 6.47 0 0016 9.5 6.5 6.5 0 109.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5z"/>');
|
|
518
|
+
// ... remaining structural icons as needed
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**Structural icon names (15 total):**
|
|
522
|
+
|
|
523
|
+
`chevron-down`, `chevron-up`, `chevron-left`, `chevron-right`, `check`, `x`, `calendar`, `clock`, `search`, `arrow-up`, `grip-vertical`, `info`, `check-circle`, `alert-triangle`, `x-circle`
|
|
524
|
+
|
|
525
|
+
Most SVG icon libraries ship downloadable SVGs alongside any font files — the LLM extracts the appropriate `<path>` data for these overrides.
|
|
526
|
+
|
|
527
|
+
### Summary by Library Type
|
|
528
|
+
|
|
529
|
+
| Library Type | Examples | Integration | `icon()` used? |
|
|
530
|
+
|---|---|---|---|
|
|
531
|
+
| SVG stroke | Lucide, Feather, Heroicons Outline | `registerIcons()` | Yes |
|
|
532
|
+
| SVG fill | Heroicons Solid, Material SVGs, Phosphor Fill | `registerIcons()` (auto-detected) | Yes |
|
|
533
|
+
| Font ligature | Google Material Icons | Load font, native HTML | No — LLM generates `<span class="material-icons">` |
|
|
534
|
+
| CSS class | Font Awesome, Bootstrap Icons | Load CSS, native HTML | No — LLM generates `<i class="fa-solid fa-*">` |
|
|
535
|
+
| Custom SVGs | Company icon sets | `tools/icons.js` → `registerIcons()` | Yes |
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## Build Optimization
|
|
540
|
+
|
|
541
|
+
Tree shaking scans bundled JS for `icon('name')` call patterns and prunes unused SVG path data from the output. Only referenced icons ship in the production bundle.
|
|
542
|
+
|
|
543
|
+
- Essential icons that are never referenced are stripped
|
|
544
|
+
- Custom icons registered via `registerIcons()` are included if the module is imported
|
|
545
|
+
- `hasIcon()` guard calls do not count as icon usage for tree shaking
|
|
546
|
+
|
|
547
|
+
---
|
|
548
|
+
|
|
549
|
+
## Icon-Text Spacing
|
|
550
|
+
|
|
551
|
+
Components handle icon-text gaps internally — do not add manual spacing gaps around icons rendered by components.
|
|
552
|
+
|
|
553
|
+
| Context | Gap Token | Value | Example |
|
|
554
|
+
|---------|-----------|-------|---------|
|
|
555
|
+
| Micro icon-text (label-adjacent) | `--d-sp-1` | 4px | Helper text icon, badge icon |
|
|
556
|
+
| Button icon-label | `--d-sp-2` | 8px | `Button({ iconLeft: 'plus' }, 'Add')` |
|
|
557
|
+
| Alert/Notification icon-body | `--d-sp-3` | 12px | Severity icon to message text |
|
|
558
|
+
|
|
559
|
+
For standalone icon-text pairs outside components, use `_gap1` (4px intimate) or `_gap2` (8px default). See `reference/spatial-guidelines.md` §3 Gestalt Proximity Rules.
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## Quick Reference
|
|
564
|
+
|
|
565
|
+
| Scenario | Icon required? | Size | Code |
|
|
566
|
+
|----------|---------------|------|------|
|
|
567
|
+
| Button with label | Recommended for CTAs | `1em` (auto) | `Button({ iconLeft: 'plus' }, 'Add Item')` |
|
|
568
|
+
| Icon-only button | Yes (only content) | `1em` (auto) | `Button({ 'aria-label': 'Delete', size: 'icon' }, icon('trash'))` |
|
|
569
|
+
| Nav/menu item | Yes (scannability) | `1em` (auto) | `{ label: 'Dashboard', icon: 'layout-dashboard' }` |
|
|
570
|
+
| Alert | Yes (auto-assigned) | component default | `Alert({ variant: 'warning' }, 'Check your input')` |
|
|
571
|
+
| Empty state | Yes (focal point) | `2.5rem`–`3rem` | `icon('inbox', { size: '3rem' })` |
|
|
572
|
+
| Result status | Yes (focal point) | hero tier | `Result({ status: 'success' })` |
|
|
573
|
+
| KPI card | Recommended | `1.5em` | `icon('trending-up', { size: '1.5em' })` |
|
|
574
|
+
| Feature card | Recommended | `1.5em`–`24px` | `icon('shield', { size: '24px' })` |
|
|
575
|
+
| Data table sort | Yes (affordance) | `1em` (auto) | Auto-rendered by DataTable |
|
|
576
|
+
| Standalone decorative | No | — | Use text or visual hierarchy instead |
|