create-inox-app 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -0
- package/dist/cli.js +22196 -0
- package/dist/prompt-Bp8saGVV.js +852 -0
- package/dist/templates/base/.gitignore.hbs +9 -0
- package/dist/templates/base/package.json.hbs +29 -0
- package/dist/templates/base/packages/typescript-config/base.json +17 -0
- package/dist/templates/base/packages/typescript-config/nextjs.json +8 -0
- package/dist/templates/base/packages/typescript-config/package.json +10 -0
- package/dist/templates/base/packages/typescript-config/react-library.json +7 -0
- package/dist/templates/base/turbo.json.hbs +32 -0
- package/dist/templates/ci/.gitlab-ci.yml.hbs +70 -0
- package/dist/templates/ci/scripts/build.sh.hbs +94 -0
- package/dist/templates/ci/scripts/prebuild.sh.hbs +11 -0
- package/dist/templates/claude-config/app/.agents/skills/agent-browser/SKILL.md +325 -0
- package/dist/templates/claude-config/app/.agents/skills/agent-browser/references/authentication.md +202 -0
- package/dist/templates/claude-config/app/.agents/skills/agent-browser/references/commands.md +259 -0
- package/dist/templates/claude-config/app/.agents/skills/agent-browser/references/proxy-support.md +188 -0
- package/dist/templates/claude-config/app/.agents/skills/agent-browser/references/session-management.md +193 -0
- package/dist/templates/claude-config/app/.agents/skills/agent-browser/references/snapshot-refs.md +194 -0
- package/dist/templates/claude-config/app/.agents/skills/agent-browser/references/video-recording.md +173 -0
- package/dist/templates/claude-config/app/.agents/skills/agent-browser/templates/authenticated-session.sh +100 -0
- package/dist/templates/claude-config/app/.agents/skills/agent-browser/templates/capture-workflow.sh +69 -0
- package/dist/templates/claude-config/app/.agents/skills/agent-browser/templates/form-automation.sh +62 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/SKILL.md +150 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/agent.md +131 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/artifact.md +84 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/attachments.md +190 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/audio-player.md +134 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/canvas.md +32 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/chain-of-thought.md +81 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/checkpoint.md +163 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/code-block.md +170 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/commit.md +177 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/confirmation.md +252 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/connection.md +32 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/context.md +126 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/controls.md +30 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/conversation.md +210 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/edge.md +50 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/environment-variables.md +102 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/file-tree.md +72 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/image.md +143 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/inline-citation.md +293 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/jsx-preview.md +101 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/message.md +256 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/mic-selector.md +186 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/model-selector.md +112 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/node.md +71 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/open-in-chat.md +67 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/package-info.md +95 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/panel.md +31 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/persona.md +158 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/plan.md +79 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/prompt-input.md +555 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/queue.md +172 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/reasoning.md +219 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/sandbox.md +126 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/schema-display.md +102 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/shimmer.md +48 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/snippet.md +64 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/sources.md +193 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/speech-input.md +160 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/stack-trace.md +218 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/suggestion.md +121 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/task.md +215 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/terminal.md +103 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/test-results.md +157 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/tool.md +275 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/toolbar.md +30 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/transcription.md +120 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/voice-selector.md +241 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/references/web-preview.md +197 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/agent.tsx +61 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/artifact.tsx +111 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/attachments-inline.tsx +117 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/attachments-list.tsx +88 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/attachments.tsx +78 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/audio-player-remote.tsx +35 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/audio-player.tsx +69 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/chain-of-thought.tsx +74 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/checkpoint.tsx +90 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/code-block-dark.tsx +46 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/code-block.tsx +115 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/commit.tsx +94 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/confirmation-accepted.tsx +35 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/confirmation-rejected.tsx +35 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/confirmation-request.tsx +54 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/confirmation.tsx +53 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/context.tsx +45 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/conversation.tsx +176 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/environment-variables.tsx +55 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/file-tree-basic.tsx +14 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/file-tree-expanded.tsx +17 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/file-tree-selection.tsx +20 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/file-tree.tsx +38 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/image.tsx +20 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/inline-citation.tsx +95 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/jsx-preview.tsx +99 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/message.tsx +324 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/mic-selector.tsx +46 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/model-selector.tsx +362 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/open-in-chat.tsx +33 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/package-info.tsx +46 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/persona-command.tsx +96 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/persona-glint.tsx +96 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/persona-halo.tsx +96 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/persona-mana.tsx +96 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/persona-obsidian.tsx +96 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/persona-opal.tsx +96 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/plan.tsx +63 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/prompt-input-cursor.tsx +459 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/prompt-input-tooltip.tsx +40 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/prompt-input.tsx +247 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/queue-prompt-input.tsx +367 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/queue.tsx +276 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/reasoning.tsx +67 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/sandbox.tsx +166 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/schema-display-basic.tsx +7 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/schema-display-body.tsx +20 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/schema-display-nested.tsx +23 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/schema-display-params.tsx +16 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/schema-display.tsx +110 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/shimmer-duration.tsx +29 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/shimmer-elements.tsx +39 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/shimmer.tsx +17 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/snippet-plain.tsx +19 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/snippet.tsx +25 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/sources-custom.tsx +34 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/sources.tsx +27 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/speech-input.tsx +79 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/stack-trace-collapsed.tsx +39 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/stack-trace-no-internal.tsx +41 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/stack-trace.tsx +54 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/suggestion-input.tsx +137 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/suggestion.tsx +28 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/task.tsx +60 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/terminal-basic.tsx +7 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/terminal-clear.tsx +19 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/terminal-streaming.tsx +38 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/terminal.tsx +77 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/test-results-basic.tsx +27 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/test-results-errors.tsx +51 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/test-results-suites.tsx +40 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/test-results.tsx +78 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/tool-input-available.tsx +31 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/tool-input-streaming.tsx +30 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/tool-output-available.tsx +76 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/tool-output-error.tsx +45 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/tool.tsx +205 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/transcription.tsx +284 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/voice-selector.tsx +228 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-elements/scripts/web-preview.tsx +99 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-sdk/SKILL.md +78 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-sdk/references/ai-gateway.md +66 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-sdk/references/common-errors.md +439 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-sdk/references/devtools.md +52 -0
- package/dist/templates/claude-config/app/.agents/skills/ai-sdk/references/type-safe-agents.md +200 -0
- package/dist/templates/claude-config/app/.agents/skills/better-auth-best-practices/SKILL.md +166 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/SKILL.md +37 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/accessibility.mdx +819 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/as-child.mdx +324 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/composition.mdx +239 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/data-attributes.mdx +413 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/definitions.mdx +258 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/design-tokens.mdx +57 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/docs.mdx +155 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/marketplaces.mdx +144 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/npm.mdx +166 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/polymorphism.mdx +583 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/principles.mdx +61 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/registry.mdx +169 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/state.mdx +99 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/styling.mdx +286 -0
- package/dist/templates/claude-config/app/.agents/skills/building-components/references/types.mdx +191 -0
- package/dist/templates/claude-config/app/.agents/skills/docker-expert/SKILL.md +409 -0
- package/dist/templates/claude-config/app/.agents/skills/email-and-password-best-practices/SKILL.md +224 -0
- package/dist/templates/claude-config/app/.agents/skills/find-skills/SKILL.md +133 -0
- package/dist/templates/claude-config/app/.agents/skills/frontend-design/LICENSE.txt +177 -0
- package/dist/templates/claude-config/app/.agents/skills/frontend-design/SKILL.md +42 -0
- package/dist/templates/claude-config/app/.agents/skills/git-commit/SKILL.md +124 -0
- package/dist/templates/claude-config/app/.agents/skills/gitlab-ci-patterns/SKILL.md +271 -0
- package/dist/templates/claude-config/app/.agents/skills/hono/SKILL.md +90 -0
- package/dist/templates/claude-config/app/.agents/skills/langfuse-observability/SKILL.md +139 -0
- package/dist/templates/claude-config/app/.agents/skills/logging-best-practices/SKILL.md +127 -0
- package/dist/templates/claude-config/app/.agents/skills/logging-best-practices/rules/context.md +157 -0
- package/dist/templates/claude-config/app/.agents/skills/logging-best-practices/rules/pitfalls.md +118 -0
- package/dist/templates/claude-config/app/.agents/skills/logging-best-practices/rules/structure.md +193 -0
- package/dist/templates/claude-config/app/.agents/skills/logging-best-practices/rules/wide-events.md +113 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/SKILL.md +153 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/async-patterns.md +87 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/bundling.md +180 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/data-patterns.md +297 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/debug-tricks.md +105 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/directives.md +73 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/error-handling.md +227 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/file-conventions.md +140 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/font.md +245 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/functions.md +108 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/hydration-error.md +91 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/image.md +173 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/metadata.md +301 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/parallel-routes.md +287 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/route-handlers.md +146 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/rsc-boundaries.md +159 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/runtime-selection.md +39 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/scripts.md +141 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/self-hosting.md +371 -0
- package/dist/templates/claude-config/app/.agents/skills/next-best-practices/suspense-boundaries.md +67 -0
- package/dist/templates/claude-config/app/.agents/skills/next-cache-components/SKILL.md +411 -0
- package/dist/templates/claude-config/app/.agents/skills/next-upgrade/SKILL.md +50 -0
- package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/SKILL.md +179 -0
- package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/CHEATSHEET.md +418 -0
- package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/MIGRATIONS.md +536 -0
- package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/PERFORMANCE.md +559 -0
- package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/POSTGRES.md +588 -0
- package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/QUERIES.md +764 -0
- package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/RELATIONS.md +624 -0
- package/dist/templates/claude-config/app/.agents/skills/postgres-drizzle/references/SCHEMA.md +554 -0
- package/dist/templates/claude-config/app/.agents/skills/skill-creator/LICENSE.txt +202 -0
- package/dist/templates/claude-config/app/.agents/skills/skill-creator/SKILL.md +356 -0
- package/dist/templates/claude-config/app/.agents/skills/skill-creator/references/output-patterns.md +82 -0
- package/dist/templates/claude-config/app/.agents/skills/skill-creator/references/workflows.md +28 -0
- package/dist/templates/claude-config/app/.agents/skills/skill-creator/scripts/init_skill.py +303 -0
- package/dist/templates/claude-config/app/.agents/skills/skill-creator/scripts/package_skill.py +113 -0
- package/dist/templates/claude-config/app/.agents/skills/skill-creator/scripts/quick_validate.py +95 -0
- package/dist/templates/claude-config/app/.agents/skills/streamdown/SKILL.md +164 -0
- package/dist/templates/claude-config/app/.agents/skills/streamdown/assets/examples/basic-streaming.tsx +34 -0
- package/dist/templates/claude-config/app/.agents/skills/streamdown/assets/examples/custom-security.tsx +38 -0
- package/dist/templates/claude-config/app/.agents/skills/streamdown/assets/examples/full-featured.tsx +60 -0
- package/dist/templates/claude-config/app/.agents/skills/streamdown/assets/examples/static-mode.tsx +17 -0
- package/dist/templates/claude-config/app/.agents/skills/streamdown/assets/examples/with-caret.tsx +39 -0
- package/dist/templates/claude-config/app/.agents/skills/streamdown/references/api.md +278 -0
- package/dist/templates/claude-config/app/.agents/skills/streamdown/references/features.md +201 -0
- package/dist/templates/claude-config/app/.agents/skills/streamdown/references/plugins.md +239 -0
- package/dist/templates/claude-config/app/.agents/skills/streamdown/references/security.md +192 -0
- package/dist/templates/claude-config/app/.agents/skills/streamdown/references/styling.md +166 -0
- package/dist/templates/claude-config/app/.agents/skills/tdd/SKILL.md +107 -0
- package/dist/templates/claude-config/app/.agents/skills/tdd/deep-modules.md +33 -0
- package/dist/templates/claude-config/app/.agents/skills/tdd/interface-design.md +31 -0
- package/dist/templates/claude-config/app/.agents/skills/tdd/mocking.md +60 -0
- package/dist/templates/claude-config/app/.agents/skills/tdd/refactoring.md +10 -0
- package/dist/templates/claude-config/app/.agents/skills/tdd/tests.md +61 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/SKILL.md +914 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/command/turborepo.md +70 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/best-practices/RULE.md +241 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/best-practices/dependencies.md +246 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/best-practices/packages.md +335 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/best-practices/structure.md +270 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/boundaries/RULE.md +126 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/caching/RULE.md +107 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/caching/gotchas.md +169 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/caching/remote-cache.md +127 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/ci/RULE.md +79 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/ci/github-actions.md +162 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/ci/patterns.md +145 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/ci/vercel.md +103 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/cli/RULE.md +100 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/cli/commands.md +297 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/configuration/RULE.md +211 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/configuration/global-options.md +191 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/configuration/gotchas.md +348 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/configuration/tasks.md +281 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/environment/RULE.md +96 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/environment/gotchas.md +141 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/environment/modes.md +101 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/filtering/RULE.md +148 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/filtering/patterns.md +152 -0
- package/dist/templates/claude-config/app/.agents/skills/turborepo/references/watch/RULE.md +99 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/AGENTS.md +917 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/SKILL.md +88 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +94 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/architecture-compound-components.md +108 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md +84 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md +94 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/react19-no-forwardref.md +42 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/state-context-interface.md +191 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/state-decouple-implementation.md +103 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-composition-patterns/rules/state-lift-state.md +125 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/AGENTS.md +2883 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/SKILL.md +138 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/async-api-routes.md +35 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/async-dependencies.md +48 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/async-parallel.md +24 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/bundle-conditional.md +37 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +48 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +34 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/bundle-preload.md +44 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/client-event-listeners.md +78 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +74 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +110 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-cache-storage.md +68 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-length-check-first.md +50 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +32 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +36 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +72 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +26 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +77 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +56 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +36 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/dist/templates/claude-config/app/.agents/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
- package/dist/templates/claude-config/app/.agents/skills/web-design-guidelines/SKILL.md +40 -0
- package/dist/templates/claude-config/app/.agents/skills/workflow/SKILL.md +181 -0
- package/dist/templates/claude-config/app/.claude/commands/council.md +7 -0
- package/dist/templates/claude-config/app/.claude/commands/deslop.md +25 -0
- package/dist/templates/claude-config/app/.claude/commands/diagram.md +101 -0
- package/dist/templates/claude-config/app/.claude/commands/fix-merge.md +47 -0
- package/dist/templates/claude-config/app/.claude/commands/you-might-not-need-an-effect.md +10 -0
- package/dist/templates/claude-config/app/.claude/hooks/post-tool-use-tracker.sh +187 -0
- package/dist/templates/claude-config/app/.claude/hooks/skill-activation-prompt.sh +5 -0
- package/dist/templates/claude-config/app/.claude/hooks/skill-activation-prompt.ts +134 -0
- package/dist/templates/claude-config/app/.claude/rules/comments.md +12 -0
- package/dist/templates/claude-config/app/.claude/rules/typescript.md +31 -0
- package/dist/templates/claude-config/app/.claude/settings.json.hbs +74 -0
- package/dist/templates/claude-config/app/.claude/skills/skill-rules.json.hbs +309 -0
- package/dist/templates/claude-config/app/AGENTS.md.hbs +185 -0
- package/dist/templates/claude-config/app/CLAUDE.md.hbs +5 -0
- package/dist/templates/claude-config/kustomize/.agents/skills/git-commit/SKILL.md +124 -0
- package/dist/templates/claude-config/kustomize/.agents/skills/k8s-manifest-generator/SKILL.md +534 -0
- package/dist/templates/claude-config/kustomize/.agents/skills/k8s-manifest-generator/assets/configmap-template.yaml +296 -0
- package/dist/templates/claude-config/kustomize/.agents/skills/k8s-manifest-generator/assets/deployment-template.yaml +203 -0
- package/dist/templates/claude-config/kustomize/.agents/skills/k8s-manifest-generator/assets/service-template.yaml +171 -0
- package/dist/templates/claude-config/kustomize/.agents/skills/k8s-manifest-generator/references/deployment-spec.md +780 -0
- package/dist/templates/claude-config/kustomize/.agents/skills/k8s-manifest-generator/references/service-spec.md +748 -0
- package/dist/templates/claude-config/kustomize/.claude/settings.json +42 -0
- package/dist/templates/claude-config/kustomize/.claude/skills/git-commit/SKILL.md +124 -0
- package/dist/templates/claude-config/kustomize/.claude/skills/k8s-manifest-generator/SKILL.md +534 -0
- package/dist/templates/claude-config/kustomize/.claude/skills/k8s-manifest-generator/assets/configmap-template.yaml +296 -0
- package/dist/templates/claude-config/kustomize/.claude/skills/k8s-manifest-generator/assets/deployment-template.yaml +203 -0
- package/dist/templates/claude-config/kustomize/.claude/skills/k8s-manifest-generator/assets/service-template.yaml +171 -0
- package/dist/templates/claude-config/kustomize/.claude/skills/k8s-manifest-generator/references/deployment-spec.md +780 -0
- package/dist/templates/claude-config/kustomize/.claude/skills/k8s-manifest-generator/references/service-spec.md +748 -0
- package/dist/templates/docker/.dockerignore.hbs +8 -0
- package/dist/templates/docker/Dockerfile.hbs +81 -0
- package/dist/templates/docker/docker-compose.yml.hbs +55 -0
- package/dist/templates/kustomize/base/deployments/app.yaml.hbs +44 -0
- package/dist/templates/kustomize/base/ingress/app.yaml.hbs +20 -0
- package/dist/templates/kustomize/base/jobs/app-jobs.yaml.hbs +43 -0
- package/dist/templates/kustomize/base/kustomization.yaml.hbs +13 -0
- package/dist/templates/kustomize/base/secrets/regcred.yaml.hbs +7 -0
- package/dist/templates/kustomize/base/services/app.yaml.hbs +12 -0
- package/dist/templates/kustomize/overlays/{{env}}/configs/app.config.env.hbs +21 -0
- package/dist/templates/kustomize/overlays/{{env}}/configs/paradedb.config.env.hbs +3 -0
- package/dist/templates/kustomize/overlays/{{env}}/deployments/paradedb.yaml.hbs +28 -0
- package/dist/templates/kustomize/overlays/{{env}}/deployments/redis.yaml.hbs +18 -0
- package/dist/templates/kustomize/overlays/{{env}}/kustomization.yaml.hbs +36 -0
- package/dist/templates/kustomize/overlays/{{env}}/patch-operation/ingress-host.yaml.hbs +15 -0
- package/dist/templates/kustomize/overlays/{{env}}/services/paradedb.yaml.hbs +11 -0
- package/dist/templates/kustomize/overlays/{{env}}/services/redis.yaml.hbs +11 -0
- package/dist/templates/kustomize/overlays/{{env}}/storage/paradedb-pvc.yaml.hbs +10 -0
- package/dist/templates/presets/ai-chat-app/apps/web/.env.example +11 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/api/auth/[...all]/route.ts +5 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/api/chat/input-guardrail.ts +47 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/api/chat/route.ts +266 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/api/chat/sessions/[id]/messages/route.ts +38 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/api/chat/sessions/[id]/route.ts +59 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/api/chat/sessions/route.ts +24 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/api/health/route.ts +21 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/chat/[id]/page.tsx +54 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/chat/layout.tsx +23 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/chat/page.tsx +9 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/error.tsx +20 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/global-error.tsx +42 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/globals.css +187 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/layout.tsx.hbs +30 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/login/login-form.tsx +96 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/login/page.tsx +14 -0
- package/dist/templates/presets/ai-chat-app/apps/web/app/not-found.tsx +15 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/code-block.tsx +518 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/context.tsx +356 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/conversation.tsx +150 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/environment-variables.tsx +303 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/message.tsx +295 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/prompt-input.tsx +1179 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/sources.tsx +54 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ai-elements/tool.tsx +157 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/app-sidebar.tsx +110 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/chat-sessions-provider.tsx +89 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/chat-sidebar-list.tsx +174 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/chat-view.tsx +156 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/accordion.tsx +72 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/alert-dialog.tsx +162 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/alert.tsx +73 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/aspect-ratio.tsx +22 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/avatar.tsx +93 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/badge.tsx +49 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/breadcrumb.tsx +103 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/button-group.tsx +78 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/button.tsx +60 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/calendar.tsx +185 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/card.tsx +92 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/carousel.tsx +231 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/chart.tsx +325 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/checkbox.tsx +28 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/collapsible.tsx +17 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/combobox.tsx +273 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/command.tsx +181 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/context-menu.tsx +245 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/dialog.tsx +135 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/direction.tsx +3 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/drawer.tsx +120 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/dropdown-menu.tsx +258 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/empty.tsx +94 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/field.tsx +224 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/hover-card.tsx +46 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/input-group.tsx +146 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/input-otp.tsx +86 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/input.tsx +20 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/item.tsx +188 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/kbd.tsx +26 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/label.tsx +20 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/menubar.tsx +270 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/native-select.tsx +43 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/navigation-menu.tsx +161 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/pagination.tsx +118 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/popover.tsx +77 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/progress.tsx +66 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/radio-group.tsx +39 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/resizable.tsx +42 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/scroll-area.tsx +51 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/select.tsx +190 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/separator.tsx +21 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/sheet.tsx +125 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/sidebar.tsx +689 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/skeleton.tsx +13 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/slider.tsx +54 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/sonner.tsx +45 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/spinner.tsx +15 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/switch.tsx +32 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/table.tsx +89 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/tabs.tsx +75 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/textarea.tsx +18 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/toggle-group.tsx +87 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/toggle.tsx +44 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components/ui/tooltip.tsx +54 -0
- package/dist/templates/presets/ai-chat-app/apps/web/components.json +20 -0
- package/dist/templates/presets/ai-chat-app/apps/web/drizzle.config.ts +10 -0
- package/dist/templates/presets/ai-chat-app/apps/web/env.ts +30 -0
- package/dist/templates/presets/ai-chat-app/apps/web/hooks/use-mobile.ts +19 -0
- package/dist/templates/presets/ai-chat-app/apps/web/instrumentation.ts +21 -0
- package/dist/templates/presets/ai-chat-app/apps/web/lib/auth-client.ts +3 -0
- package/dist/templates/presets/ai-chat-app/apps/web/lib/auth-session.ts +9 -0
- package/dist/templates/presets/ai-chat-app/apps/web/lib/auth.ts +16 -0
- package/dist/templates/presets/ai-chat-app/apps/web/lib/db/index.ts +11 -0
- package/dist/templates/presets/ai-chat-app/apps/web/lib/db/migrate.ts +53 -0
- package/dist/templates/presets/ai-chat-app/apps/web/lib/db/schema.ts +94 -0
- package/dist/templates/presets/ai-chat-app/apps/web/lib/db/seed.ts +123 -0
- package/dist/templates/presets/ai-chat-app/apps/web/lib/group-by-date.ts +34 -0
- package/dist/templates/presets/ai-chat-app/apps/web/lib/logger.ts +21 -0
- package/dist/templates/presets/ai-chat-app/apps/web/lib/openrouter.ts +7 -0
- package/dist/templates/presets/ai-chat-app/apps/web/lib/schemas/auth.ts +8 -0
- package/dist/templates/presets/ai-chat-app/apps/web/lib/utils.ts +4 -0
- package/dist/templates/presets/ai-chat-app/apps/web/next-env.d.ts +6 -0
- package/dist/templates/presets/ai-chat-app/apps/web/next.config.ts +14 -0
- package/dist/templates/presets/ai-chat-app/apps/web/package.json +70 -0
- package/dist/templates/presets/ai-chat-app/apps/web/postcss.config.mjs +7 -0
- package/dist/templates/presets/ai-chat-app/apps/web/proxy.ts +13 -0
- package/dist/templates/presets/ai-chat-app/apps/web/tsconfig.json +14 -0
- package/dist/templates/presets/blank/apps/web/.env.example +1 -0
- package/dist/templates/presets/blank/apps/web/app/api/health/route.ts +11 -0
- package/dist/templates/presets/blank/apps/web/app/globals.css +49 -0
- package/dist/templates/presets/blank/apps/web/app/layout.tsx.hbs +30 -0
- package/dist/templates/presets/blank/apps/web/app/page.tsx.hbs +10 -0
- package/dist/templates/presets/blank/apps/web/env.ts +10 -0
- package/dist/templates/presets/blank/apps/web/next-env.d.ts +2 -0
- package/dist/templates/presets/blank/apps/web/next.config.ts +9 -0
- package/dist/templates/presets/blank/apps/web/package.json.hbs +27 -0
- package/dist/templates/presets/blank/apps/web/postcss.config.mjs +7 -0
- package/dist/templates/presets/blank/apps/web/tsconfig.json +14 -0
- package/dist/templates/tooling/.oxfmtrc.json +6 -0
- package/dist/templates/tooling/.oxlintrc.json +20 -0
- package/dist/templates/tooling/commitlint.config.ts.hbs +3 -0
- package/dist/templates/tooling/lefthook.yml.hbs +25 -0
- package/package.json +47 -0
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Polymorphism
|
|
3
|
+
description: How to use the `as` prop to change the rendered HTML element while preserving component functionality.
|
|
4
|
+
type: reference
|
|
5
|
+
summary: The as prop pattern for polymorphic components, compared with Radix UI's Slot-based asChild approach with TypeScript best practices.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /composition
|
|
8
|
+
- /types
|
|
9
|
+
related:
|
|
10
|
+
- /as-child
|
|
11
|
+
- /accessibility
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
The `as` prop is a fundamental pattern in modern React component libraries that allows you to change the underlying HTML element or component that gets rendered.
|
|
15
|
+
|
|
16
|
+
Popularized by libraries like [Styled Components](https://styled-components.com/), [Emotion](https://emotion.sh/), and [Chakra UI](https://chakra-ui.com/), this pattern provides flexibility in choosing semantic HTML while maintaining component styling and behavior.
|
|
17
|
+
|
|
18
|
+
The `as` prop enables polymorphic components - components that can render as different element types while preserving their core functionality:
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
<Button as="a" href="/home">
|
|
22
|
+
Go Home
|
|
23
|
+
</Button>
|
|
24
|
+
|
|
25
|
+
<Button as="button" type="submit">
|
|
26
|
+
Submit Form
|
|
27
|
+
</Button>
|
|
28
|
+
|
|
29
|
+
<Button as="div" role="button" tabIndex={0}>
|
|
30
|
+
Custom Element
|
|
31
|
+
</Button>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Understanding `as`
|
|
35
|
+
|
|
36
|
+
The `as` prop allows you to override the default element type of a component. Instead of being locked into a specific HTML element, you can adapt the component to render as any valid HTML tag or even another React component.
|
|
37
|
+
|
|
38
|
+
For example:
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
// Default renders as a div
|
|
42
|
+
<Box>Content</Box>
|
|
43
|
+
|
|
44
|
+
// Renders as a section
|
|
45
|
+
<Box as="section">Content</Box>
|
|
46
|
+
|
|
47
|
+
// Renders as a nav
|
|
48
|
+
<Box as="nav">Content</Box>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This renders different HTML elements:
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<!-- Default -->
|
|
55
|
+
<div>Content</div>
|
|
56
|
+
|
|
57
|
+
<!-- With as="section" -->
|
|
58
|
+
<section>Content</section>
|
|
59
|
+
|
|
60
|
+
<!-- With as="nav" -->
|
|
61
|
+
<nav>Content</nav>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Implementation Methods
|
|
65
|
+
|
|
66
|
+
There are two main approaches to implementing polymorphic components: a manual implementation and using Radix UI's `Slot` component.
|
|
67
|
+
|
|
68
|
+
### Manual Implementation
|
|
69
|
+
|
|
70
|
+
The `as` prop implementation uses dynamic component rendering:
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
// Simplified implementation
|
|
74
|
+
function Component({ as: Element = "div", children, ...props }) {
|
|
75
|
+
return <Element {...props}>{children}</Element>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// More complete implementation with TypeScript
|
|
79
|
+
type PolymorphicProps<E extends React.ElementType> = {
|
|
80
|
+
as?: E;
|
|
81
|
+
children?: React.ReactNode;
|
|
82
|
+
} & React.ComponentPropsWithoutRef<E>;
|
|
83
|
+
|
|
84
|
+
function Component<E extends React.ElementType = "div">({
|
|
85
|
+
as,
|
|
86
|
+
children,
|
|
87
|
+
...props
|
|
88
|
+
}: PolymorphicProps<E>) {
|
|
89
|
+
const Element = as || "div";
|
|
90
|
+
return <Element {...props}>{children}</Element>;
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The component:
|
|
95
|
+
|
|
96
|
+
1. Accepts an `as` prop with a default element type
|
|
97
|
+
2. Uses the provided element or fallback to default
|
|
98
|
+
3. Spreads all other props to the rendered element
|
|
99
|
+
4. Maintains type safety with TypeScript generics
|
|
100
|
+
|
|
101
|
+
### Using Radix UI Slot
|
|
102
|
+
|
|
103
|
+
[Radix UI](https://www.radix-ui.com/) provides a `Slot` component that offers a more powerful alternative to the `as` prop pattern. Instead of just changing the element type, `Slot` merges props with the child component, enabling composition patterns.
|
|
104
|
+
|
|
105
|
+
First, install the package:
|
|
106
|
+
|
|
107
|
+
```package-install
|
|
108
|
+
npm install @radix-ui/react-slot
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The `asChild` pattern uses a boolean prop instead of specifying the element type:
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
115
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
116
|
+
|
|
117
|
+
const itemVariants = cva("rounded-lg border p-4", {
|
|
118
|
+
variants: {
|
|
119
|
+
variant: {
|
|
120
|
+
default: "bg-white",
|
|
121
|
+
primary: "bg-blue-500 text-white",
|
|
122
|
+
},
|
|
123
|
+
size: {
|
|
124
|
+
default: "h-10 px-4",
|
|
125
|
+
sm: "h-8 px-3",
|
|
126
|
+
lg: "h-12 px-6",
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
defaultVariants: {
|
|
130
|
+
variant: "default",
|
|
131
|
+
size: "default",
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
function Item({
|
|
136
|
+
className,
|
|
137
|
+
variant = "default",
|
|
138
|
+
size = "default",
|
|
139
|
+
asChild = false,
|
|
140
|
+
...props
|
|
141
|
+
}: React.ComponentProps<"div"> &
|
|
142
|
+
VariantProps<typeof itemVariants> & { asChild?: boolean }) {
|
|
143
|
+
const Comp = asChild ? Slot : "div";
|
|
144
|
+
return (
|
|
145
|
+
<Comp
|
|
146
|
+
data-slot="item"
|
|
147
|
+
data-variant={variant}
|
|
148
|
+
data-size={size}
|
|
149
|
+
className={cn(itemVariants({ variant, size, className }))}
|
|
150
|
+
{...props}
|
|
151
|
+
/>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Now you can use it in two ways:
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
// Default: renders as a div
|
|
160
|
+
<Item variant="primary">Content</Item>
|
|
161
|
+
|
|
162
|
+
// With asChild: merges props with child component
|
|
163
|
+
<Item variant="primary" asChild>
|
|
164
|
+
<a href="/home">Link with Item styles</a>
|
|
165
|
+
</Item>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The `Slot` component:
|
|
169
|
+
|
|
170
|
+
1. Clones the child element
|
|
171
|
+
2. Merges the component's props (className, data attributes, etc.) with the child's props
|
|
172
|
+
3. Forwards refs correctly
|
|
173
|
+
4. Handles event handler composition
|
|
174
|
+
|
|
175
|
+
### Comparison: `as` vs `asChild`
|
|
176
|
+
|
|
177
|
+
**`as` prop (manual implementation):**
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
// Explicit element type
|
|
181
|
+
<Button as="a" href="/home">Link Button</Button>
|
|
182
|
+
<Button as="button" type="submit">Submit Button</Button>
|
|
183
|
+
|
|
184
|
+
// Simple, predictable API
|
|
185
|
+
// Limited to element types
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**`asChild` with Slot:**
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
// Implicit from child
|
|
192
|
+
<Button asChild>
|
|
193
|
+
<a href="/home">Link Button</a>
|
|
194
|
+
</Button>
|
|
195
|
+
|
|
196
|
+
<Button asChild>
|
|
197
|
+
<button type="submit">Submit Button</button>
|
|
198
|
+
</Button>
|
|
199
|
+
|
|
200
|
+
// More flexible composition
|
|
201
|
+
// Works with any component
|
|
202
|
+
// Better prop merging
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Key differences:**
|
|
206
|
+
|
|
207
|
+
| Feature | `as` prop | `asChild` + Slot |
|
|
208
|
+
| ------------------------- | ------------------- | -------------------------------- |
|
|
209
|
+
| **API Style** | `<Button as="a">` | `<Button asChild><a /></Button>` |
|
|
210
|
+
| **Element Type** | Specified in prop | Inferred from child |
|
|
211
|
+
| **Component Composition** | Limited | Full support |
|
|
212
|
+
| **Prop Merging** | Basic spread | Intelligent merging |
|
|
213
|
+
| **Ref Forwarding** | Manual setup needed | Built-in |
|
|
214
|
+
| **Event Handlers** | May conflict | Composed correctly |
|
|
215
|
+
| **Library Size** | No dependency | Requires `@radix-ui/react-slot` |
|
|
216
|
+
|
|
217
|
+
### When to Use Each Approach
|
|
218
|
+
|
|
219
|
+
**Use `as` prop when:**
|
|
220
|
+
|
|
221
|
+
- You want a simpler API surface
|
|
222
|
+
- You're primarily switching between HTML elements
|
|
223
|
+
- You want to avoid additional dependencies
|
|
224
|
+
- The component is simple and doesn't need complex prop merging
|
|
225
|
+
|
|
226
|
+
**Use `asChild` + Slot when:**
|
|
227
|
+
|
|
228
|
+
- You need to compose with other components
|
|
229
|
+
- You want automatic prop merging behavior
|
|
230
|
+
- You're building a component library similar to Radix UI or shadcn/ui
|
|
231
|
+
- You need reliable ref forwarding across different component types
|
|
232
|
+
|
|
233
|
+
## Key Benefits
|
|
234
|
+
|
|
235
|
+
### 1. Semantic HTML Flexibility
|
|
236
|
+
|
|
237
|
+
The `as` prop ensures you can always use the most semantically appropriate HTML element:
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
// Navigation container
|
|
241
|
+
<Container as="nav" className="navigation">
|
|
242
|
+
<NavItems />
|
|
243
|
+
</Container>
|
|
244
|
+
|
|
245
|
+
// Main content area
|
|
246
|
+
<Container as="main" className="content">
|
|
247
|
+
<Article />
|
|
248
|
+
</Container>
|
|
249
|
+
|
|
250
|
+
// Sidebar
|
|
251
|
+
<Container as="aside" className="sidebar">
|
|
252
|
+
<Widgets />
|
|
253
|
+
</Container>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### 2. Component Reusability
|
|
257
|
+
|
|
258
|
+
One component can serve multiple purposes without creating variants:
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
// Text component used for different elements
|
|
262
|
+
<Text as="h1" size="2xl">Page Title</Text>
|
|
263
|
+
<Text as="p" size="md">Body paragraph</Text>
|
|
264
|
+
<Text as="span" size="sm">Inline text</Text>
|
|
265
|
+
<Text as="label" size="sm">Form label</Text>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 3. Accessibility Improvements
|
|
269
|
+
|
|
270
|
+
Choose elements that provide the best accessibility for each context:
|
|
271
|
+
|
|
272
|
+
```tsx
|
|
273
|
+
// Link that looks like a button
|
|
274
|
+
<Button as="a" href="/signup">
|
|
275
|
+
Sign Up Now
|
|
276
|
+
</Button>
|
|
277
|
+
|
|
278
|
+
// Button that submits a form
|
|
279
|
+
<Button as="button" type="submit">
|
|
280
|
+
Submit
|
|
281
|
+
</Button>
|
|
282
|
+
|
|
283
|
+
// Heading with button styles
|
|
284
|
+
<Button as="h2" role="presentation">
|
|
285
|
+
Section Title
|
|
286
|
+
</Button>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### 4. Style System Integration
|
|
290
|
+
|
|
291
|
+
Maintain consistent styling while changing elements:
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
const Card = styled.div`
|
|
295
|
+
padding: 1rem;
|
|
296
|
+
border-radius: 8px;
|
|
297
|
+
background: white;
|
|
298
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
299
|
+
`;
|
|
300
|
+
|
|
301
|
+
// Same styles, different elements
|
|
302
|
+
<Card as="article">Article content</Card>
|
|
303
|
+
<Card as="section">Section content</Card>
|
|
304
|
+
<Card as="li">List item content</Card>
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Common Use Cases
|
|
308
|
+
|
|
309
|
+
### Typography Components
|
|
310
|
+
|
|
311
|
+
Create flexible text components:
|
|
312
|
+
|
|
313
|
+
```tsx
|
|
314
|
+
function Text({
|
|
315
|
+
as: Element = 'span',
|
|
316
|
+
variant = 'body',
|
|
317
|
+
...props
|
|
318
|
+
}) {
|
|
319
|
+
const className = cn(
|
|
320
|
+
'text-base',
|
|
321
|
+
variant === 'heading' && 'text-2xl font-bold',
|
|
322
|
+
variant === 'body' && 'text-base',
|
|
323
|
+
variant === 'caption' && 'text-sm text-gray-600',
|
|
324
|
+
props.className
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
return <Element className={className} {...props} />;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Usage
|
|
331
|
+
<Text as="h1" variant="heading">Title</Text>
|
|
332
|
+
<Text as="p" variant="body">Paragraph</Text>
|
|
333
|
+
<Text as="figcaption" variant="caption">Caption</Text>
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Layout Components
|
|
337
|
+
|
|
338
|
+
Build semantic layouts:
|
|
339
|
+
|
|
340
|
+
```tsx
|
|
341
|
+
function Flex({ as: Element = 'div', ...props }) {
|
|
342
|
+
return (
|
|
343
|
+
<Element
|
|
344
|
+
className={cn('flex', props.className)}
|
|
345
|
+
{...props}
|
|
346
|
+
/>
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Semantic HTML
|
|
351
|
+
<Flex as="header" className="justify-between">
|
|
352
|
+
<Logo />
|
|
353
|
+
<Navigation />
|
|
354
|
+
</Flex>
|
|
355
|
+
|
|
356
|
+
<Flex as="main" className="flex-col">
|
|
357
|
+
<Content />
|
|
358
|
+
</Flex>
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Interactive Elements
|
|
362
|
+
|
|
363
|
+
Handle different interaction types:
|
|
364
|
+
|
|
365
|
+
```tsx
|
|
366
|
+
function Clickable({ as: Element = 'button', ...props }) {
|
|
367
|
+
const isButton = Element === 'button';
|
|
368
|
+
const isAnchor = Element === 'a';
|
|
369
|
+
|
|
370
|
+
return (
|
|
371
|
+
<Element
|
|
372
|
+
role={!isButton && !isAnchor ? 'button' : undefined}
|
|
373
|
+
tabIndex={!isButton && !isAnchor ? 0 : undefined}
|
|
374
|
+
{...props}
|
|
375
|
+
/>
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Various clickable elements
|
|
380
|
+
<Clickable as="button" onClick={handleClick}>Button</Clickable>
|
|
381
|
+
<Clickable as="a" href="/link">Link</Clickable>
|
|
382
|
+
<Clickable as="div" onClick={handleClick}>Div Button</Clickable>
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## TypeScript Best Practices
|
|
386
|
+
|
|
387
|
+
### Generic Component Types
|
|
388
|
+
|
|
389
|
+
Create fully type-safe polymorphic components:
|
|
390
|
+
|
|
391
|
+
```tsx
|
|
392
|
+
type PolymorphicRef<E extends React.ElementType> =
|
|
393
|
+
React.ComponentPropsWithRef<E>["ref"];
|
|
394
|
+
|
|
395
|
+
type PolymorphicProps<E extends React.ElementType, Props = {}> = Props &
|
|
396
|
+
Omit<React.ComponentPropsWithoutRef<E>, keyof Props> & {
|
|
397
|
+
as?: E;
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
// Component with full type safety
|
|
401
|
+
function Component<E extends React.ElementType = "div">({
|
|
402
|
+
as,
|
|
403
|
+
...props
|
|
404
|
+
}: PolymorphicProps<E, { customProp?: string }>) {
|
|
405
|
+
const Element = as || "div";
|
|
406
|
+
return <Element {...props} />;
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Inferring Props
|
|
411
|
+
|
|
412
|
+
Automatically infer props based on the element:
|
|
413
|
+
|
|
414
|
+
```tsx
|
|
415
|
+
// Props are inferred from the element type
|
|
416
|
+
<Component as="a" href="/home">Home</Component> // ✅ href is valid
|
|
417
|
+
<Component as="div" href="/home">Home</Component> // ❌ TS error: href not valid on div
|
|
418
|
+
|
|
419
|
+
<Component as="button" type="submit">Submit</Component> // ✅ type is valid
|
|
420
|
+
<Component as="span" type="submit">Submit</Component> // ❌ TS error
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Discriminated Unions
|
|
424
|
+
|
|
425
|
+
Use discriminated unions for element-specific props:
|
|
426
|
+
|
|
427
|
+
```tsx
|
|
428
|
+
type ButtonProps =
|
|
429
|
+
| { as: "button"; type?: "submit" | "button" | "reset" }
|
|
430
|
+
| { as: "a"; href: string; target?: string }
|
|
431
|
+
| { as: "div"; role: "button"; tabIndex: number };
|
|
432
|
+
|
|
433
|
+
function Button(props: ButtonProps & { children: React.ReactNode }) {
|
|
434
|
+
const Element = props.as;
|
|
435
|
+
return <Element {...props} />;
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
## Best Practices
|
|
440
|
+
|
|
441
|
+
### 1. Default to Semantic Elements
|
|
442
|
+
|
|
443
|
+
Choose meaningful defaults that represent the most common use case:
|
|
444
|
+
|
|
445
|
+
```tsx
|
|
446
|
+
// ✅ Good defaults
|
|
447
|
+
function Article({ as: Element = "article", ...props }) {}
|
|
448
|
+
function Navigation({ as: Element = "nav", ...props }) {}
|
|
449
|
+
function Heading({ as: Element = "h2", ...props }) {}
|
|
450
|
+
|
|
451
|
+
// ❌ Too generic
|
|
452
|
+
function Component({ as: Element = "div", ...props }) {}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### 2. Document Valid Elements
|
|
456
|
+
|
|
457
|
+
Clearly specify which elements are supported:
|
|
458
|
+
|
|
459
|
+
```tsx
|
|
460
|
+
interface BoxProps {
|
|
461
|
+
/**
|
|
462
|
+
* The HTML element to render as
|
|
463
|
+
* @default 'div'
|
|
464
|
+
* @example 'section', 'article', 'aside', 'main'
|
|
465
|
+
*/
|
|
466
|
+
as?: "div" | "section" | "article" | "aside" | "main" | "header" | "footer";
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### 3. Validate Element Appropriateness
|
|
471
|
+
|
|
472
|
+
Warn when inappropriate elements are used:
|
|
473
|
+
|
|
474
|
+
```tsx
|
|
475
|
+
function Button({ as: Element = "button", ...props }) {
|
|
476
|
+
if (__DEV__ && Element === "div" && !props.role) {
|
|
477
|
+
console.warn(
|
|
478
|
+
'Button: When using as="div", provide role="button" for accessibility',
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
return <Element {...props} />;
|
|
483
|
+
}
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
### 4. Handle Event Handlers Properly
|
|
487
|
+
|
|
488
|
+
Ensure event handlers work across different elements:
|
|
489
|
+
|
|
490
|
+
```tsx
|
|
491
|
+
function Interactive({ as: Element = "button", onClick, ...props }) {
|
|
492
|
+
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
493
|
+
if (Element !== "button" && (e.key === "Enter" || e.key === " ")) {
|
|
494
|
+
onClick?.(e as any);
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
return (
|
|
499
|
+
<Element
|
|
500
|
+
onClick={onClick}
|
|
501
|
+
onKeyDown={Element !== "button" ? handleKeyDown : undefined}
|
|
502
|
+
{...props}
|
|
503
|
+
/>
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
## Common Pitfalls
|
|
509
|
+
|
|
510
|
+
### Invalid HTML Nesting
|
|
511
|
+
|
|
512
|
+
Be careful about HTML nesting rules:
|
|
513
|
+
|
|
514
|
+
```tsx
|
|
515
|
+
// ❌ Invalid - button inside button
|
|
516
|
+
<Button as="button">
|
|
517
|
+
<Button as="button">Nested</Button>
|
|
518
|
+
</Button>
|
|
519
|
+
|
|
520
|
+
// ❌ Invalid - div inside p
|
|
521
|
+
<Text as="p">
|
|
522
|
+
<Box as="div">Invalid nesting</Box>
|
|
523
|
+
</Text>
|
|
524
|
+
|
|
525
|
+
// ✅ Valid nesting
|
|
526
|
+
<Text as="div">
|
|
527
|
+
<Box as="div">Valid nesting</Box>
|
|
528
|
+
</Text>
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Missing Accessibility Attributes
|
|
532
|
+
|
|
533
|
+
Remember to add appropriate ARIA attributes:
|
|
534
|
+
|
|
535
|
+
```tsx
|
|
536
|
+
// ❌ Missing accessibility
|
|
537
|
+
<Box as="nav">
|
|
538
|
+
<MenuItems />
|
|
539
|
+
</Box>
|
|
540
|
+
|
|
541
|
+
// ✅ Proper accessibility
|
|
542
|
+
<Box as="nav" aria-label="Main navigation">
|
|
543
|
+
<MenuItems />
|
|
544
|
+
</Box>
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### Type Safety Loss
|
|
548
|
+
|
|
549
|
+
Avoid using overly permissive types:
|
|
550
|
+
|
|
551
|
+
```tsx
|
|
552
|
+
// ❌ Too permissive - no type safety
|
|
553
|
+
function Component({ as: Element = "div", ...props }: any) {
|
|
554
|
+
return <Element {...props} />;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// ✅ Type safe
|
|
558
|
+
function Component<E extends React.ElementType = "div">({
|
|
559
|
+
as,
|
|
560
|
+
...props
|
|
561
|
+
}: PolymorphicProps<E>) {
|
|
562
|
+
const Element = as || "div";
|
|
563
|
+
return <Element {...props} />;
|
|
564
|
+
}
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
### Performance Considerations
|
|
568
|
+
|
|
569
|
+
Be aware of re-render implications:
|
|
570
|
+
|
|
571
|
+
```tsx
|
|
572
|
+
// ❌ Creates new component on every render
|
|
573
|
+
function Parent() {
|
|
574
|
+
const CustomDiv = (props) => <div {...props} />;
|
|
575
|
+
return <Component as={CustomDiv} />;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// ✅ Stable component reference
|
|
579
|
+
const CustomDiv = (props) => <div {...props} />;
|
|
580
|
+
function Parent() {
|
|
581
|
+
return <Component as={CustomDiv} />;
|
|
582
|
+
}
|
|
583
|
+
```
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Core Principles
|
|
3
|
+
description: When building modern UI components, it's important to keep these core principles in mind.
|
|
4
|
+
type: conceptual
|
|
5
|
+
summary: The foundational values behind the specification including composability, accessibility, customizability, performance, and transparency.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /definitions
|
|
8
|
+
related:
|
|
9
|
+
- /composition
|
|
10
|
+
- /accessibility
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Composability and Reusability
|
|
14
|
+
|
|
15
|
+
Favor composition over inheritance – build components that can be combined and nested to create more complex UIs, rather than relying on deep class hierarchies.
|
|
16
|
+
|
|
17
|
+
Composable components expose a clear API (via props/slots) that allows developers to customize behavior and appearance by plugging in child elements or callbacks.
|
|
18
|
+
|
|
19
|
+
This makes components highly reusable in different contexts. (React’s design reinforces this: “Props and composition give you all the flexibility you need to customize a component’s look and behavior in an explicit and safe way.”)
|
|
20
|
+
|
|
21
|
+
## Accessible by Default
|
|
22
|
+
|
|
23
|
+
Components must be usable by all users. Use semantic HTML elements appropriate to the component’s role (e.g. `<button>` for clickable actions, `<ul>/<li>` for lists, etc.) and augment with WAI-ARIA attributes when necessary.
|
|
24
|
+
|
|
25
|
+
Ensure keyboard navigation and focus management are supported (for example, arrow-key navigation in menus, focus traps in modals). Each component should adhere to accessibility standards and guidelines out of the box.
|
|
26
|
+
|
|
27
|
+
This means providing proper ARIA roles/states and testing with screen readers. Accessibility is not optional – it’s a baseline feature of every component.
|
|
28
|
+
|
|
29
|
+
## Customizability and Theming
|
|
30
|
+
|
|
31
|
+
A component should be easy to restyle or adapt to different design requirements. Avoid hard-coding visual styles that cannot be overridden.
|
|
32
|
+
|
|
33
|
+
Provide mechanisms for theming and styling, such as CSS variables, clearly documented class names, or style props. Ideally, components come with sensible default styling but allow developers to customize appearance with minimal effort (for example, by passing a className or using design tokens).
|
|
34
|
+
|
|
35
|
+
This principle ensures components can fit into any brand or design system without “fighting” against default styles.
|
|
36
|
+
|
|
37
|
+
## Lightweight and Performant
|
|
38
|
+
|
|
39
|
+
Components should be as lean as possible in terms of assets and dependencies. Avoid bloating a component with large library dependencies or overly complex logic, especially if that logic isn’t always needed.
|
|
40
|
+
|
|
41
|
+
Strive for good performance (both rendering and interaction) by minimizing unnecessary re-renders and using efficient algorithms for heavy tasks. If a component is data-intensive (like a large list or table), consider patterns like virtualization or incremental rendering, but keep such features optional.
|
|
42
|
+
|
|
43
|
+
Lightweight components are easier to maintain and faster for end users.
|
|
44
|
+
|
|
45
|
+
## Transparency and Code Ownership
|
|
46
|
+
|
|
47
|
+
In open-source, consumers often benefit from having full visibility and control of component code. This spec encourages an “open-source first” mindset: components should not be black boxes.
|
|
48
|
+
|
|
49
|
+
When developers import or copy your component, they should be able to inspect how it works and modify it if needed. This principle underlies the emerging “copy-and-paste” distribution model (discussed later) where developers integrate component code directly into their projects.
|
|
50
|
+
|
|
51
|
+
By giving users ownership of the code, you increase trust and allow deeper customization.
|
|
52
|
+
|
|
53
|
+
Even if you distribute via a package, embrace transparency by providing source maps, readable code, and thorough documentation.
|
|
54
|
+
|
|
55
|
+
## Well-documented and DX-Friendly
|
|
56
|
+
|
|
57
|
+
A great component is not just code – it comes with clear documentation and examples. From a developer experience (DX) perspective, your components should be easy to learn and integrate.
|
|
58
|
+
|
|
59
|
+
Document each component’s purpose, props, and usage examples. Include notes on accessibility (like keyboard controls or ARIA attributes used) and any customization options.
|
|
60
|
+
|
|
61
|
+
Good documentation reduces misuse and lowers the barrier for adoption. We will cover documentation expectations in the Publish section, but it’s listed here as a principle because planning for good documentation and DX should happen during the design/build phase.
|