@design-ai/cli 4.55.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/.claude-plugin/plugin.json +164 -0
- package/AGENTS.ko.md +126 -0
- package/AGENTS.md +182 -0
- package/CHANGELOG.md +6883 -0
- package/CLAUDE.md +39 -0
- package/LICENSE +21 -0
- package/README.ko.md +245 -0
- package/README.md +277 -0
- package/agents/README.md +14 -0
- package/agents/a11y-reviewer.md +121 -0
- package/agents/component-architect.md +57 -0
- package/agents/design-critic.md +46 -0
- package/agents/token-extractor.md +63 -0
- package/cli/bin/design-ai-mcp.mjs +6 -0
- package/cli/bin/design-ai.mjs +40 -0
- package/cli/commands/audit.mjs +111 -0
- package/cli/commands/check.mjs +226 -0
- package/cli/commands/doctor.mjs +141 -0
- package/cli/commands/examples.mjs +58 -0
- package/cli/commands/help.mjs +271 -0
- package/cli/commands/install.mjs +161 -0
- package/cli/commands/learn.mjs +1871 -0
- package/cli/commands/list.mjs +143 -0
- package/cli/commands/mcp.mjs +27 -0
- package/cli/commands/pack.mjs +211 -0
- package/cli/commands/prompt.mjs +199 -0
- package/cli/commands/route.mjs +247 -0
- package/cli/commands/search.mjs +60 -0
- package/cli/commands/show.mjs +52 -0
- package/cli/commands/site.mjs +558 -0
- package/cli/commands/status.mjs +161 -0
- package/cli/commands/uninstall.mjs +119 -0
- package/cli/commands/update.mjs +184 -0
- package/cli/commands/version.mjs +94 -0
- package/cli/commands/workspace.mjs +176 -0
- package/cli/lib/brief.mjs +52 -0
- package/cli/lib/check.mjs +642 -0
- package/cli/lib/dispatch.mjs +109 -0
- package/cli/lib/doctor.mjs +505 -0
- package/cli/lib/examples.mjs +258 -0
- package/cli/lib/exec.mjs +63 -0
- package/cli/lib/help-flags.mjs +5 -0
- package/cli/lib/learn.mjs +3694 -0
- package/cli/lib/log.mjs +47 -0
- package/cli/lib/mcp-server.mjs +426 -0
- package/cli/lib/output.mjs +101 -0
- package/cli/lib/pack.mjs +599 -0
- package/cli/lib/paths.mjs +63 -0
- package/cli/lib/prompt.mjs +603 -0
- package/cli/lib/route.mjs +740 -0
- package/cli/lib/search.mjs +158 -0
- package/cli/lib/show.mjs +161 -0
- package/cli/lib/signals.mjs +2337 -0
- package/cli/lib/site.mjs +6617 -0
- package/cli/lib/skill-proposals.mjs +2046 -0
- package/cli/lib/suggest.mjs +66 -0
- package/cli/lib/workspace.mjs +1056 -0
- package/commands/README.md +25 -0
- package/commands/component-spec.md +34 -0
- package/commands/conversational.md +44 -0
- package/commands/design-from-brief.md +141 -0
- package/commands/design-review.md +62 -0
- package/commands/document-from-brief.md +47 -0
- package/commands/extract-tokens.md +38 -0
- package/commands/game-ui.md +40 -0
- package/commands/illustration.md +37 -0
- package/commands/iterate.md +167 -0
- package/commands/motion-design.md +54 -0
- package/commands/palette-from-brand.md +50 -0
- package/commands/print.md +49 -0
- package/commands/slide-deck.md +46 -0
- package/commands/spatial.md +47 -0
- package/commands/stability-review.md +74 -0
- package/commands/video.md +42 -0
- package/commands/website-improvement.md +77 -0
- package/docs/AGENT-DEVELOPMENT.md +658 -0
- package/docs/AI-LEARNING.md +429 -0
- package/docs/AIDER-INTEGRATION.md +224 -0
- package/docs/ARCHITECTURE.ko.md +183 -0
- package/docs/ARCHITECTURE.md +105 -0
- package/docs/CODEX-INTEGRATION.md +311 -0
- package/docs/COMPANY-WEBSITE-DOGFOOD.ko.md +144 -0
- package/docs/COMPANY-WEBSITE-DOGFOOD.md +150 -0
- package/docs/COMPANY-WEBSITE-INTAKE-TEMPLATE.ko.md +153 -0
- package/docs/COMPANY-WEBSITE-INTAKE-TEMPLATE.md +154 -0
- package/docs/CONTRIBUTING.ko.md +203 -0
- package/docs/CONTRIBUTING.md +242 -0
- package/docs/CURSOR-INTEGRATION.md +220 -0
- package/docs/DISTRIBUTION.ko.md +248 -0
- package/docs/DISTRIBUTION.md +253 -0
- package/docs/DOGFOOD-FINDINGS.md +180 -0
- package/docs/DOGFOOD-V4-FINDINGS.md +139 -0
- package/docs/DOGFOOD-V4-MKDOCS-FINDINGS.md +233 -0
- package/docs/DOGFOOD-V4-NPM-FINDINGS.md +157 -0
- package/docs/DOGFOOD-V4-VSCODE-FINDINGS.md +135 -0
- package/docs/FIGMA-INTEGRATION.md +222 -0
- package/docs/MCP-INTEGRATION.md +243 -0
- package/docs/MIGRATION-v4.md +121 -0
- package/docs/PLUGIN-PACKAGING.md +240 -0
- package/docs/PRODUCT-READINESS.md +66 -0
- package/docs/QUICKSTART.ko.md +178 -0
- package/docs/QUICKSTART.md +179 -0
- package/docs/RELEASE-CHECKLIST.md +292 -0
- package/docs/ROADMAP.md +19495 -0
- package/docs/SESSION-LOG.md +940 -0
- package/docs/TOKEN-SYNC.md +237 -0
- package/docs/USING.ko.md +206 -0
- package/docs/USING.md +218 -0
- package/docs/WEBSITE-IMPROVEMENT.ko.md +75 -0
- package/docs/WEBSITE-IMPROVEMENT.md +89 -0
- package/docs/announcements/README.md +56 -0
- package/docs/announcements/dev-to-korea.md +206 -0
- package/docs/announcements/hashnode-post.ko.md +232 -0
- package/docs/announcements/okky-post.ko.md +158 -0
- package/docs/announcements/press-kit.md +101 -0
- package/docs/announcements/reddit-r-korea.md +196 -0
- package/docs/announcements/show-hn.md +114 -0
- package/docs/announcements/twitter-thread.md +255 -0
- package/docs/external-status.md +34 -0
- package/docs/integrations/aider-walkthrough.ko.md +275 -0
- package/docs/integrations/aider-walkthrough.md +274 -0
- package/docs/integrations/codex-walkthrough.ko.md +297 -0
- package/docs/integrations/codex-walkthrough.md +297 -0
- package/docs/integrations/cursor-walkthrough.ko.md +281 -0
- package/docs/integrations/cursor-walkthrough.md +284 -0
- package/docs/integrations/design-ai-mcp-server.md +169 -0
- package/docs/integrations/figma-mcp.md +149 -0
- package/docs/integrations/github-mcp.md +178 -0
- package/docs/integrations/linear-mcp.md +215 -0
- package/docs/integrations/notion-mcp.md +174 -0
- package/docs/integrations/sdk-walkthrough.ko.md +375 -0
- package/docs/integrations/sdk-walkthrough.md +375 -0
- package/docs/integrations/slack-mcp.md +208 -0
- package/docs/integrations/vscode-walkthrough.ko.md +202 -0
- package/docs/integrations/vscode-walkthrough.md +205 -0
- package/docs/requirements.txt +16 -0
- package/docs/site-overrides/extra.css +83 -0
- package/docs/site-overrides/favicon.svg +4 -0
- package/docs/site-overrides/logo.svg +10 -0
- package/docs/site-overrides/main.html +18 -0
- package/docs/website-console/app.js +2540 -0
- package/docs/website-console/index.html +24 -0
- package/docs/website-console/styles.css +975 -0
- package/examples/README.md +252 -0
- package/examples/cases/dogfood-v4-korean-hr-onboarding.md +356 -0
- package/examples/component-accordion-actions.md +153 -0
- package/examples/component-accordion-details.md +147 -0
- package/examples/component-accordion-summary.md +180 -0
- package/examples/component-accordion.md +229 -0
- package/examples/component-account-card.md +284 -0
- package/examples/component-address-input.md +260 -0
- package/examples/component-affix.md +190 -0
- package/examples/component-alert-dialog.md +210 -0
- package/examples/component-alert-title.md +77 -0
- package/examples/component-alert.md +192 -0
- package/examples/component-amount-input.md +278 -0
- package/examples/component-anchor.md +198 -0
- package/examples/component-app-bar.md +249 -0
- package/examples/component-aspect-ratio.md +156 -0
- package/examples/component-auto-complete.md +199 -0
- package/examples/component-avatar-group.md +170 -0
- package/examples/component-avatar.md +191 -0
- package/examples/component-back-top.md +123 -0
- package/examples/component-backdrop.md +148 -0
- package/examples/component-badge.md +181 -0
- package/examples/component-banner.md +237 -0
- package/examples/component-biometric-gate.md +281 -0
- package/examples/component-blockquote.md +153 -0
- package/examples/component-border-beam.md +207 -0
- package/examples/component-bottom-navigation.md +226 -0
- package/examples/component-box.md +112 -0
- package/examples/component-breadcrumb.md +222 -0
- package/examples/component-button-base.md +190 -0
- package/examples/component-button-group.md +117 -0
- package/examples/component-button.md +213 -0
- package/examples/component-calendar.md +280 -0
- package/examples/component-callout.md +131 -0
- package/examples/component-card-actions.md +101 -0
- package/examples/component-card-content.md +90 -0
- package/examples/component-card-header.md +122 -0
- package/examples/component-card-media.md +79 -0
- package/examples/component-card.md +233 -0
- package/examples/component-carousel.md +266 -0
- package/examples/component-cascader.md +135 -0
- package/examples/component-category-picker.md +271 -0
- package/examples/component-chart.md +237 -0
- package/examples/component-chat-interface.md +399 -0
- package/examples/component-checkbox.md +149 -0
- package/examples/component-click-away-listener.md +87 -0
- package/examples/component-code.md +213 -0
- package/examples/component-collapsible.md +219 -0
- package/examples/component-color-picker.md +110 -0
- package/examples/component-combobox.md +267 -0
- package/examples/component-command.md +299 -0
- package/examples/component-config-provider.md +190 -0
- package/examples/component-context-menu.md +179 -0
- package/examples/component-css-baseline.md +148 -0
- package/examples/component-date-picker.md +249 -0
- package/examples/component-descriptions.md +242 -0
- package/examples/component-dialog-actions.md +111 -0
- package/examples/component-dialog-content-text.md +76 -0
- package/examples/component-dialog-content.md +105 -0
- package/examples/component-dialog-title.md +104 -0
- package/examples/component-dialog.md +176 -0
- package/examples/component-divider.md +182 -0
- package/examples/component-doc-page.md +217 -0
- package/examples/component-drawer.md +257 -0
- package/examples/component-dropdown.md +220 -0
- package/examples/component-email-layout.md +253 -0
- package/examples/component-empty-state.md +269 -0
- package/examples/component-empty.md +172 -0
- package/examples/component-fade.md +87 -0
- package/examples/component-feature-grid.md +201 -0
- package/examples/component-field.md +266 -0
- package/examples/component-filled-input.md +114 -0
- package/examples/component-flex.md +117 -0
- package/examples/component-float-button.md +214 -0
- package/examples/component-form-control-label.md +134 -0
- package/examples/component-form-control.md +113 -0
- package/examples/component-form-controls.md +251 -0
- package/examples/component-form-group.md +86 -0
- package/examples/component-form-helper-text.md +95 -0
- package/examples/component-form-label.md +98 -0
- package/examples/component-form.md +291 -0
- package/examples/component-game-hud.md +362 -0
- package/examples/component-game-menu.md +327 -0
- package/examples/component-grid.md +140 -0
- package/examples/component-grow.md +79 -0
- package/examples/component-hero-block.md +252 -0
- package/examples/component-hover-card.md +211 -0
- package/examples/component-icon-button.md +142 -0
- package/examples/component-icon.md +102 -0
- package/examples/component-illustration.md +280 -0
- package/examples/component-image-list.md +107 -0
- package/examples/component-image.md +282 -0
- package/examples/component-input-adornment.md +101 -0
- package/examples/component-input-base.md +134 -0
- package/examples/component-input-number.md +141 -0
- package/examples/component-input-otp.md +271 -0
- package/examples/component-input.md +213 -0
- package/examples/component-item.md +243 -0
- package/examples/component-kbd.md +197 -0
- package/examples/component-krw-amount.md +219 -0
- package/examples/component-label.md +118 -0
- package/examples/component-layout.md +217 -0
- package/examples/component-link.md +223 -0
- package/examples/component-list-item-avatar.md +72 -0
- package/examples/component-list-item-button.md +139 -0
- package/examples/component-list-item-icon.md +82 -0
- package/examples/component-list-item-text.md +98 -0
- package/examples/component-list-item.md +116 -0
- package/examples/component-list-subheader.md +70 -0
- package/examples/component-list.md +198 -0
- package/examples/component-loading-button.md +125 -0
- package/examples/component-loading-sequence.md +254 -0
- package/examples/component-lottie-player.md +279 -0
- package/examples/component-masonry.md +191 -0
- package/examples/component-mentions.md +189 -0
- package/examples/component-menu-item.md +102 -0
- package/examples/component-menu-list.md +98 -0
- package/examples/component-menu.md +139 -0
- package/examples/component-menubar.md +259 -0
- package/examples/component-message.md +162 -0
- package/examples/component-mobile-stepper.md +155 -0
- package/examples/component-modal.md +220 -0
- package/examples/component-navigation-menu.md +295 -0
- package/examples/component-notification.md +166 -0
- package/examples/component-otp-countdown.md +245 -0
- package/examples/component-outlined-input.md +145 -0
- package/examples/component-page-transition.md +281 -0
- package/examples/component-pagination.md +226 -0
- package/examples/component-paper.md +199 -0
- package/examples/component-pass-auth.md +265 -0
- package/examples/component-payment-brand-button.md +253 -0
- package/examples/component-payment-method-selector.md +272 -0
- package/examples/component-payment-receipt.md +277 -0
- package/examples/component-popconfirm.md +144 -0
- package/examples/component-popover.md +239 -0
- package/examples/component-popper.md +129 -0
- package/examples/component-pricing-cards.md +247 -0
- package/examples/component-progress.md +195 -0
- package/examples/component-qr-code.md +201 -0
- package/examples/component-radio.md +167 -0
- package/examples/component-rate.md +202 -0
- package/examples/component-resizable.md +163 -0
- package/examples/component-result.md +270 -0
- package/examples/component-scroll-area.md +199 -0
- package/examples/component-scroll-reveal.md +320 -0
- package/examples/component-segmented.md +178 -0
- package/examples/component-select.md +258 -0
- package/examples/component-separator.md +177 -0
- package/examples/component-sheet.md +277 -0
- package/examples/component-sidebar.md +257 -0
- package/examples/component-skeleton.md +178 -0
- package/examples/component-slide.md +89 -0
- package/examples/component-slider.md +208 -0
- package/examples/component-snackbar-content.md +92 -0
- package/examples/component-snackbar.md +121 -0
- package/examples/component-sonner.md +165 -0
- package/examples/component-space.md +125 -0
- package/examples/component-spatial-locomotion.md +373 -0
- package/examples/component-spatial-panel.md +330 -0
- package/examples/component-speed-dial-action.md +78 -0
- package/examples/component-speed-dial.md +177 -0
- package/examples/component-spin.md +173 -0
- package/examples/component-spinner.md +204 -0
- package/examples/component-splitter.md +210 -0
- package/examples/component-stack.md +130 -0
- package/examples/component-statistic.md +282 -0
- package/examples/component-step-button.md +157 -0
- package/examples/component-step-connector.md +157 -0
- package/examples/component-step-content.md +121 -0
- package/examples/component-step-icon.md +115 -0
- package/examples/component-step-label.md +101 -0
- package/examples/component-step.md +84 -0
- package/examples/component-steps.md +264 -0
- package/examples/component-stock-chart.md +251 -0
- package/examples/component-swipeable-drawer.md +149 -0
- package/examples/component-switch.md +99 -0
- package/examples/component-tab-scroll-button.md +180 -0
- package/examples/component-tab.md +120 -0
- package/examples/component-table-body.md +82 -0
- package/examples/component-table-cell.md +118 -0
- package/examples/component-table-container.md +75 -0
- package/examples/component-table-footer.md +72 -0
- package/examples/component-table-head.md +78 -0
- package/examples/component-table-pagination.md +137 -0
- package/examples/component-table-row.md +113 -0
- package/examples/component-table-sort-label.md +109 -0
- package/examples/component-table.md +202 -0
- package/examples/component-tabs.md +184 -0
- package/examples/component-tag-badge.md +309 -0
- package/examples/component-tag.md +102 -0
- package/examples/component-testimonial-carousel.md +218 -0
- package/examples/component-textarea-autosize.md +114 -0
- package/examples/component-textarea.md +173 -0
- package/examples/component-time-picker.md +205 -0
- package/examples/component-timeline.md +170 -0
- package/examples/component-toast.md +224 -0
- package/examples/component-toggle-button.md +129 -0
- package/examples/component-toggle.md +220 -0
- package/examples/component-toolbar.md +104 -0
- package/examples/component-tooltip.md +178 -0
- package/examples/component-tour.md +176 -0
- package/examples/component-transaction-list-item.md +243 -0
- package/examples/component-transfer.md +156 -0
- package/examples/component-tree-select.md +202 -0
- package/examples/component-tree.md +297 -0
- package/examples/component-typography.md +215 -0
- package/examples/component-upload.md +295 -0
- package/examples/component-video-hero.md +409 -0
- package/examples/component-video-player.md +340 -0
- package/examples/component-voice-input.md +408 -0
- package/examples/component-watermark.md +217 -0
- package/examples/component-zoom.md +92 -0
- package/examples/doc-explanation-example.md +196 -0
- package/examples/doc-how-to-example.md +205 -0
- package/examples/doc-tutorial-example.md +162 -0
- package/examples/dogfood-korean-fintech-system.md +433 -0
- package/examples/email-transactional-example.md +259 -0
- package/examples/palette-saas-violet.md +235 -0
- package/examples/print-business-card-spec.md +205 -0
- package/examples/print-packaging-spec.md +285 -0
- package/examples/report-example.md +228 -0
- package/examples/slide-deck-example.md +237 -0
- package/examples/website-improvement-report.md +128 -0
- package/examples/website-improvement-workspace.json +126 -0
- package/install.sh +189 -0
- package/knowledge/COVERAGE.md +740 -0
- package/knowledge/PRINCIPLES.md +108 -0
- package/knowledge/a11y/contrast.md +70 -0
- package/knowledge/a11y/keyboard-and-focus.md +108 -0
- package/knowledge/colors/color-theory.md +90 -0
- package/knowledge/colors/mui-palette-structure.md +105 -0
- package/knowledge/colors/palettes-by-product-type.md +876 -0
- package/knowledge/components/INDEX.md +231 -0
- package/knowledge/components/index.json +1470 -0
- package/knowledge/components/shadcn-registry.md +159 -0
- package/knowledge/conversational/ai-chat-interfaces.md +323 -0
- package/knowledge/conversational/chatbot-design.md +312 -0
- package/knowledge/conversational/conversational-ui-fundamentals.md +299 -0
- package/knowledge/conversational/korean-voice-conventions.md +281 -0
- package/knowledge/conversational/voice-ui-patterns.md +297 -0
- package/knowledge/design-tokens/ant-design.md +124 -0
- package/knowledge/design-tokens/material-3.md +235 -0
- package/knowledge/design-tokens/polaris-and-carbon.md +231 -0
- package/knowledge/design-tokens/tailwind-v4.md +284 -0
- package/knowledge/game-ui/game-accessibility.md +317 -0
- package/knowledge/game-ui/game-ui-fundamentals.md +281 -0
- package/knowledge/game-ui/hud-design.md +324 -0
- package/knowledge/game-ui/korean-gaming-conventions.md +312 -0
- package/knowledge/game-ui/menu-systems.md +388 -0
- package/knowledge/i18n/korean-app-store-visual.md +223 -0
- package/knowledge/i18n/korean-document-style.md +301 -0
- package/knowledge/i18n/korean-payments.md +211 -0
- package/knowledge/i18n/korean-product-conventions.md +96 -0
- package/knowledge/i18n/korean-publishing.md +139 -0
- package/knowledge/i18n/korean-typography.md +123 -0
- package/knowledge/icons/curated-sets.md +225 -0
- package/knowledge/illustration/hero-illustrations.md +234 -0
- package/knowledge/illustration/illustration-systems.md +221 -0
- package/knowledge/illustration/mascot-design.md +208 -0
- package/knowledge/illustration/spot-illustrations.md +246 -0
- package/knowledge/illustration/svg-optimization.md +308 -0
- package/knowledge/layout/spacing-and-grid.md +119 -0
- package/knowledge/motion/app-loading-sequences.md +277 -0
- package/knowledge/motion/choreography-depth.md +297 -0
- package/knowledge/motion/marketing-motion.md +223 -0
- package/knowledge/motion/micro-interactions.md +266 -0
- package/knowledge/motion/motion-tools.md +281 -0
- package/knowledge/motion/principles.md +126 -0
- package/knowledge/patterns/auth-flow-design.md +316 -0
- package/knowledge/patterns/b2b-onboarding-flows.md +182 -0
- package/knowledge/patterns/brand-identity.md +238 -0
- package/knowledge/patterns/brand-references.md +97 -0
- package/knowledge/patterns/chart-color-encoding.md +269 -0
- package/knowledge/patterns/chart-types.md +344 -0
- package/knowledge/patterns/dashboard-composition.md +299 -0
- package/knowledge/patterns/design-system-qa.md +356 -0
- package/knowledge/patterns/document-typography.md +248 -0
- package/knowledge/patterns/email-design.md +338 -0
- package/knowledge/patterns/empty-states.md +263 -0
- package/knowledge/patterns/error-states.md +318 -0
- package/knowledge/patterns/form-design.md +237 -0
- package/knowledge/patterns/information-architecture.md +341 -0
- package/knowledge/patterns/landing-hero-design.md +283 -0
- package/knowledge/patterns/landing-page-patterns.md +681 -0
- package/knowledge/patterns/list-and-feed.md +371 -0
- package/knowledge/patterns/mobile-navigation.md +278 -0
- package/knowledge/patterns/money-and-amount.md +301 -0
- package/knowledge/patterns/onboarding.md +300 -0
- package/knowledge/patterns/pricing-page-design.md +261 -0
- package/knowledge/patterns/realtime-data.md +280 -0
- package/knowledge/patterns/report-design.md +330 -0
- package/knowledge/patterns/search-ux.md +373 -0
- package/knowledge/patterns/settings-page.md +325 -0
- package/knowledge/patterns/slide-deck-design.md +316 -0
- package/knowledge/patterns/styles-catalog.md +2599 -0
- package/knowledge/patterns/technical-writing.md +306 -0
- package/knowledge/patterns/ui-reasoning.md +1853 -0
- package/knowledge/patterns/ux-guidelines.md +1454 -0
- package/knowledge/platforms/react-native.md +395 -0
- package/knowledge/print/brochures-and-flyers.md +276 -0
- package/knowledge/print/korean-print-conventions.md +284 -0
- package/knowledge/print/packaging.md +321 -0
- package/knowledge/print/print-fundamentals.md +238 -0
- package/knowledge/print/signage-and-posters.md +235 -0
- package/knowledge/print/stationery.md +262 -0
- package/knowledge/spatial/ar-patterns.md +253 -0
- package/knowledge/spatial/comfort-and-accessibility.md +245 -0
- package/knowledge/spatial/spatial-design-fundamentals.md +346 -0
- package/knowledge/spatial/spatial-ui-elements.md +343 -0
- package/knowledge/spatial/vr-patterns.md +302 -0
- package/knowledge/typography/font-pairings.md +332 -0
- package/knowledge/typography/mui-type-scale.md +57 -0
- package/knowledge/typography/type-scale-fundamentals.md +105 -0
- package/knowledge/video/in-product-video.md +277 -0
- package/knowledge/video/korean-video-conventions.md +247 -0
- package/knowledge/video/marketing-video.md +258 -0
- package/knowledge/video/social-and-short-form.md +257 -0
- package/knowledge/video/video-fundamentals.md +296 -0
- package/package.json +106 -0
- package/skills/README.md +39 -0
- package/skills/color-palette/PLAYBOOK.md +175 -0
- package/skills/color-palette/SKILL.md +6 -0
- package/skills/color-palette/TEMPLATE.md +103 -0
- package/skills/component-spec-writer/PLAYBOOK.md +169 -0
- package/skills/component-spec-writer/SKILL.md +6 -0
- package/skills/component-spec-writer/TEMPLATE.md +115 -0
- package/skills/conversational-ui-designer/PLAYBOOK.md +231 -0
- package/skills/conversational-ui-designer/SKILL.md +6 -0
- package/skills/design-broadcast/PLAYBOOK.md +146 -0
- package/skills/design-broadcast/SKILL.md +6 -0
- package/skills/design-critique/PLAYBOOK.md +137 -0
- package/skills/design-critique/SKILL.md +6 -0
- package/skills/design-pr-review/PLAYBOOK.md +171 -0
- package/skills/design-pr-review/SKILL.md +6 -0
- package/skills/design-system-builder/PLAYBOOK.md +218 -0
- package/skills/design-system-builder/SKILL.md +6 -0
- package/skills/design-system-qa/PLAYBOOK.md +163 -0
- package/skills/design-system-qa/SKILL.md +6 -0
- package/skills/document-author/PLAYBOOK.md +167 -0
- package/skills/document-author/SKILL.md +6 -0
- package/skills/figma-token-sync/PLAYBOOK.md +149 -0
- package/skills/figma-token-sync/SKILL.md +6 -0
- package/skills/game-ui-designer/PLAYBOOK.md +209 -0
- package/skills/game-ui-designer/SKILL.md +6 -0
- package/skills/handoff-spec/PLAYBOOK.md +170 -0
- package/skills/handoff-spec/SKILL.md +6 -0
- package/skills/illustration-designer/PLAYBOOK.md +166 -0
- package/skills/illustration-designer/SKILL.md +6 -0
- package/skills/motion-designer/PLAYBOOK.md +223 -0
- package/skills/motion-designer/SKILL.md +6 -0
- package/skills/print-designer/PLAYBOOK.md +209 -0
- package/skills/print-designer/SKILL.md +6 -0
- package/skills/slide-deck-author/PLAYBOOK.md +198 -0
- package/skills/slide-deck-author/SKILL.md +6 -0
- package/skills/spatial-designer/PLAYBOOK.md +238 -0
- package/skills/spatial-designer/SKILL.md +6 -0
- package/skills/ux-audit/PLAYBOOK.md +142 -0
- package/skills/ux-audit/SKILL.md +6 -0
- package/skills/video-designer/PLAYBOOK.md +240 -0
- package/skills/video-designer/SKILL.md +6 -0
- package/skills/website-improvement/PLAYBOOK.md +118 -0
- package/skills/website-improvement/SKILL.md +6 -0
- package/skills/website-improvement/TEMPLATE.md +103 -0
- package/tools/audit/changelog-generate.py +176 -0
- package/tools/audit/check-coverage.py +483 -0
- package/tools/audit/doctor_assertions.py +256 -0
- package/tools/audit/example-qa.py +108 -0
- package/tools/audit/frontmatter-check.py +199 -0
- package/tools/audit/integration-check.py +95 -0
- package/tools/audit/korean-copy-check.py +161 -0
- package/tools/audit/link-check.py +146 -0
- package/tools/audit/local-ci.py +558 -0
- package/tools/audit/package-contents.py +723 -0
- package/tools/audit/package-smoke.py +22443 -0
- package/tools/audit/raw-hex-check.py +252 -0
- package/tools/audit/registry-smoke.py +8188 -0
- package/tools/audit/release-metadata.py +9832 -0
- package/tools/audit/run-all.py +351 -0
- package/tools/audit/smoke_assertions.py +12742 -0
- package/tools/audit/stability-review.py +332 -0
- package/tools/audit/stale-check.py +156 -0
- package/tools/migrations/add-version-frontmatter.py +132 -0
- package/tools/migrations/bump-last-updated.py +131 -0
- package/tools/migrations/promote-stability.py +172 -0
- package/tools/preview/README.md +58 -0
- package/tools/preview/render-tokens.py +454 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# `ColorPicker` — spec
|
|
2
|
+
|
|
3
|
+
> Citing Ant Design `ColorPicker`, MUI (no built-in), shadcn-ui (composition with libraries)
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
Lets users pick a color value. Used in: design tools, theme customizers, content authoring (highlight color, brand color), CRM tag creation.
|
|
8
|
+
|
|
9
|
+
## Anatomy
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Trigger (small swatch): Open (full picker panel):
|
|
13
|
+
┌─────────────┐ ┌─────────────────────────────────┐
|
|
14
|
+
│ ▣ #7C3AED ▾│ │ ┌─────────────────────────┐ │
|
|
15
|
+
└─────────────┘ │ │ │ │ ← saturation/value square
|
|
16
|
+
│ │ [picker dot] │ │
|
|
17
|
+
│ │ │ │
|
|
18
|
+
│ └─────────────────────────┘ │
|
|
19
|
+
│ ──[ hue slider ]──────── │
|
|
20
|
+
│ ──[ alpha slider ]────── │
|
|
21
|
+
│ │
|
|
22
|
+
│ HEX: [#7C3AED ] │
|
|
23
|
+
│ RGB: [124] [58] [237] │
|
|
24
|
+
│ HSL/OKLCH: [...] │
|
|
25
|
+
│ │
|
|
26
|
+
│ Presets: ● ● ● ● ● ● ● ● │
|
|
27
|
+
└─────────────────────────────────┘
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## API
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
<ColorPicker
|
|
34
|
+
value={color}
|
|
35
|
+
onValueChange={setColor}
|
|
36
|
+
format="hex"
|
|
37
|
+
showAlpha
|
|
38
|
+
presets={brandColors}
|
|
39
|
+
/>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
| Prop | Type | Default | Description |
|
|
43
|
+
| --- | --- | --- | --- |
|
|
44
|
+
| `value` | `string` (hex/rgba/oklch) | — | Color value |
|
|
45
|
+
| `onValueChange` | `(value: string) => void` | — | |
|
|
46
|
+
| `format` | `"hex" \| "rgb" \| "hsl" \| "oklch"` | `"hex"` | Output format |
|
|
47
|
+
| `showAlpha` | `boolean` | `false` | Alpha slider |
|
|
48
|
+
| `showInputs` | `boolean` | `true` | Numeric inputs (hex/rgb/hsl) |
|
|
49
|
+
| `presets` | `string[]` | — | Preset swatches at the bottom |
|
|
50
|
+
| `disabled` | `boolean` | `false` | |
|
|
51
|
+
| `triggerStyle` | `"swatch" \| "button"` | `"swatch"` | Compact swatch vs labeled button |
|
|
52
|
+
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | |
|
|
53
|
+
|
|
54
|
+
## Behavior
|
|
55
|
+
|
|
56
|
+
- Click trigger → opens popover with picker.
|
|
57
|
+
- Saturation/value square: drag picker dot to choose; updates live.
|
|
58
|
+
- Hue slider: vertical or horizontal; rotates hue.
|
|
59
|
+
- Alpha slider (if shown): adjusts transparency.
|
|
60
|
+
- Numeric inputs: typing updates picker.
|
|
61
|
+
- Preset swatch click: instant apply.
|
|
62
|
+
|
|
63
|
+
## States
|
|
64
|
+
|
|
65
|
+
Standard popover-trigger states. The picker square + sliders use canvas/SVG; track mouse + keyboard.
|
|
66
|
+
|
|
67
|
+
## Accessibility
|
|
68
|
+
|
|
69
|
+
- Trigger: `role="button"`, `aria-label="Choose color"`, `aria-haspopup="dialog"`.
|
|
70
|
+
- Popover: `role="dialog"`, `aria-label="Color picker"`.
|
|
71
|
+
- Saturation/value square: `role="slider"`, `aria-valuetext` describing current color (e.g., "Hue 285, Saturation 70%, Value 90%").
|
|
72
|
+
- Hue/alpha sliders: standard slider role.
|
|
73
|
+
- Numeric inputs: standard input fields with labels.
|
|
74
|
+
|
|
75
|
+
### Keyboard
|
|
76
|
+
|
|
77
|
+
The square is hard to navigate by keyboard. Provide:
|
|
78
|
+
- `Tab` to reach square; arrow keys move dot by small steps.
|
|
79
|
+
- Numeric inputs: type to set exact value.
|
|
80
|
+
- Preset swatches: tab through, Enter to apply.
|
|
81
|
+
|
|
82
|
+
For users who prefer, the hex input is the primary path on keyboard.
|
|
83
|
+
|
|
84
|
+
## Format conversion
|
|
85
|
+
|
|
86
|
+
Internally, store as a single canonical format (often HSV or RGB), convert to display format on output. Use a library:
|
|
87
|
+
|
|
88
|
+
- `tinycolor2` — robust conversions
|
|
89
|
+
- `chroma.js` — color manipulation
|
|
90
|
+
- `culori` — modern, OKLCH-aware
|
|
91
|
+
|
|
92
|
+
Don't roll your own — color math is hard and there are subtle edge cases.
|
|
93
|
+
|
|
94
|
+
## Don't
|
|
95
|
+
|
|
96
|
+
- Don't use ColorPicker for picking from a fixed brand palette. Use a Tag/swatch picker.
|
|
97
|
+
- Don't auto-apply on hover (only on commit).
|
|
98
|
+
- Don't omit accessible name. Color values aren't enough.
|
|
99
|
+
- Don't show only the picker without numeric inputs — accessibility requires keyboard alternative.
|
|
100
|
+
|
|
101
|
+
## References
|
|
102
|
+
|
|
103
|
+
- Ant Design: [`refs/ant-design/components/color-picker/`](../refs/ant-design/components/color-picker/) — comprehensive. Has presets, alpha, multiple format inputs.
|
|
104
|
+
- MUI: no built-in. Use `react-colorful` or similar.
|
|
105
|
+
- shadcn-ui: no built-in. Compose with `Popover` + `react-colorful`.
|
|
106
|
+
|
|
107
|
+
## Cross-reference
|
|
108
|
+
|
|
109
|
+
- [`knowledge/colors/color-theory.md`](../knowledge/colors/color-theory.md) — color spaces (OKLCH, HSL)
|
|
110
|
+
- [`knowledge/a11y/contrast.md`](../knowledge/a11y/contrast.md) — when picking text colors, verify contrast
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# `Combobox` — spec
|
|
2
|
+
|
|
3
|
+
> Synthesized from shadcn-ui `combobox` (cmdk + Popover) and the WAI-ARIA Combobox pattern. A typeable search field combined with a list of options. Distinct from `Select` (no typing) and `Autocomplete` (more freeform).
|
|
4
|
+
|
|
5
|
+
## Combobox vs Select vs Autocomplete
|
|
6
|
+
|
|
7
|
+
| | Combobox | Select | Autocomplete |
|
|
8
|
+
| --- | --- | --- | --- |
|
|
9
|
+
| Typing | **Yes** (filters list) | No | Yes |
|
|
10
|
+
| Free input | No (must pick from list) | n/a | Yes (often) |
|
|
11
|
+
| Use | Pick from a long list (50+ options) | Pick from a short list (< 20) | Suggest while typing free text |
|
|
12
|
+
| Examples | Country picker, user mention | Sort by, status filter | Address auto-suggest, search bar |
|
|
13
|
+
|
|
14
|
+
The combobox is "Select with search" — typing narrows the list.
|
|
15
|
+
|
|
16
|
+
## Anatomy
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
┌─────────────────────────────────┐
|
|
20
|
+
│ ▼ Search framework... │ ← trigger field (looks like input)
|
|
21
|
+
└─────────────────────────────────┘
|
|
22
|
+
↓ click / focus
|
|
23
|
+
┌─────────────────────────────────┐
|
|
24
|
+
│ ⌕ Type to search... │ ← search input
|
|
25
|
+
│ ─────────────────── │
|
|
26
|
+
│ ▶ React │
|
|
27
|
+
│ Vue │ ← filtered list
|
|
28
|
+
│ Svelte │
|
|
29
|
+
│ Solid │
|
|
30
|
+
│ ─────────────────── │
|
|
31
|
+
│ No results found │ ← empty state
|
|
32
|
+
└─────────────────────────────────┘
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## API
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
const [value, setValue] = useState("");
|
|
39
|
+
const [open, setOpen] = useState(false);
|
|
40
|
+
|
|
41
|
+
<Combobox open={open} onOpenChange={setOpen}>
|
|
42
|
+
<Combobox.Trigger asChild>
|
|
43
|
+
<Button variant="outline" role="combobox" aria-expanded={open}>
|
|
44
|
+
{value ? frameworks.find(f => f.value === value)?.label : "Select framework..."}
|
|
45
|
+
<ChevronIcon />
|
|
46
|
+
</Button>
|
|
47
|
+
</Combobox.Trigger>
|
|
48
|
+
<Combobox.Content>
|
|
49
|
+
<Combobox.Input placeholder="Search framework..." />
|
|
50
|
+
<Combobox.List>
|
|
51
|
+
<Combobox.Empty>No framework found.</Combobox.Empty>
|
|
52
|
+
<Combobox.Group>
|
|
53
|
+
{frameworks.map(f => (
|
|
54
|
+
<Combobox.Item
|
|
55
|
+
key={f.value}
|
|
56
|
+
value={f.value}
|
|
57
|
+
onSelect={(v) => { setValue(v); setOpen(false); }}
|
|
58
|
+
>
|
|
59
|
+
<CheckIcon className={value === f.value ? "" : "invisible"} />
|
|
60
|
+
{f.label}
|
|
61
|
+
</Combobox.Item>
|
|
62
|
+
))}
|
|
63
|
+
</Combobox.Group>
|
|
64
|
+
</Combobox.List>
|
|
65
|
+
</Combobox.Content>
|
|
66
|
+
</Combobox>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Composition
|
|
70
|
+
|
|
71
|
+
| Part | Purpose |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| `Combobox` | Wrapper / state holder |
|
|
74
|
+
| `Trigger` | Element that opens (typically a button styled as input) |
|
|
75
|
+
| `Content` | Floating panel with input + list |
|
|
76
|
+
| `Input` | Search/filter input (auto-focused when open) |
|
|
77
|
+
| `List` | Container for options (virtualizable) |
|
|
78
|
+
| `Empty` | Shown when no items match query |
|
|
79
|
+
| `Item` | Selectable option |
|
|
80
|
+
| `Group` | Grouped section with optional heading |
|
|
81
|
+
| `Separator` | Visual divider |
|
|
82
|
+
|
|
83
|
+
## Variants
|
|
84
|
+
|
|
85
|
+
### Single-select (default)
|
|
86
|
+
|
|
87
|
+
One value at a time. Selecting closes the combobox.
|
|
88
|
+
|
|
89
|
+
### Multi-select
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
const [selected, setSelected] = useState<string[]>([]);
|
|
93
|
+
|
|
94
|
+
<Combobox multiple value={selected} onValueChange={setSelected}>
|
|
95
|
+
<Combobox.Trigger asChild>
|
|
96
|
+
<Button>
|
|
97
|
+
{selected.length > 0
|
|
98
|
+
? `${selected.length} 개 선택됨`
|
|
99
|
+
: "선택"}
|
|
100
|
+
</Button>
|
|
101
|
+
</Combobox.Trigger>
|
|
102
|
+
...
|
|
103
|
+
</Combobox>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Items show check on selected; combobox stays open while user picks multiple.
|
|
107
|
+
|
|
108
|
+
### With creation (creatable)
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
<Combobox.Item createable onSelect={() => createNew(query)}>
|
|
112
|
+
+ Create "{query}"
|
|
113
|
+
</Combobox.Item>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
When user types and no exact match exists, show a "Create" item at the top.
|
|
117
|
+
|
|
118
|
+
## States
|
|
119
|
+
|
|
120
|
+
| State | Visual |
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| Closed | Trigger only |
|
|
123
|
+
| Open | Panel visible; input focused; first item highlighted |
|
|
124
|
+
| Typing | List filters; first match highlighted |
|
|
125
|
+
| Empty results | `Empty` component shown |
|
|
126
|
+
| Selected (single) | Trigger shows selected label |
|
|
127
|
+
| Selected (multi) | Trigger shows count or chips; checks visible in list |
|
|
128
|
+
| Loading (async) | Skeleton or "Searching..." in list |
|
|
129
|
+
| Disabled | Trigger grayed; no events |
|
|
130
|
+
|
|
131
|
+
## Keyboard contract (WAI-ARIA Combobox pattern)
|
|
132
|
+
|
|
133
|
+
| Key | Action |
|
|
134
|
+
| --- | --- |
|
|
135
|
+
| `Enter` / `Space` (on trigger) | Open |
|
|
136
|
+
| Type in input | Filter list |
|
|
137
|
+
| `↓` / `↑` | Navigate items |
|
|
138
|
+
| `Home` / `End` | Jump to first / last |
|
|
139
|
+
| `Enter` (on item) | Select; close (single) or stay open (multi) |
|
|
140
|
+
| `Esc` | Close; return focus to trigger |
|
|
141
|
+
| `Tab` | Close; move to next focusable in document |
|
|
142
|
+
| Click outside | Close |
|
|
143
|
+
|
|
144
|
+
## Tokens consumed
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
--color-bg-default (trigger field bg)
|
|
148
|
+
--color-bg-overlay (panel bg)
|
|
149
|
+
--color-fg-default
|
|
150
|
+
--color-fg-muted (placeholder, group headings)
|
|
151
|
+
--color-bg-overlay-hover (item hover)
|
|
152
|
+
--color-bg-overlay-selected (current focused/highlighted item)
|
|
153
|
+
--color-brand-default (selected check icon)
|
|
154
|
+
--color-border-default
|
|
155
|
+
--shadow-overlay
|
|
156
|
+
--radius-md
|
|
157
|
+
--space-xs, --space-sm
|
|
158
|
+
--font-size-base (input)
|
|
159
|
+
--font-size-sm (group headings)
|
|
160
|
+
--motion-fast (item hover)
|
|
161
|
+
--ease-out
|
|
162
|
+
--z-overlay
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Accessibility
|
|
166
|
+
|
|
167
|
+
- Trigger: `<button role="combobox" aria-expanded aria-haspopup="listbox" aria-controls="combo-list">`.
|
|
168
|
+
- Input: separate from trigger when popup open; `role="combobox"` on input itself.
|
|
169
|
+
- List: `role="listbox"` + `aria-label`.
|
|
170
|
+
- Item: `role="option"` + `aria-selected`.
|
|
171
|
+
- Use `aria-activedescendant` to indicate which item is highlighted (don't move focus to options; keep focus on input so typing works).
|
|
172
|
+
- `aria-live="polite"` on List for screen reader to announce filter changes.
|
|
173
|
+
- Touch target ≥ 36px per item.
|
|
174
|
+
|
|
175
|
+
## Korean IME considerations
|
|
176
|
+
|
|
177
|
+
Korean input uses IME (Input Method Editor) for Hangul composition. Three rules:
|
|
178
|
+
|
|
179
|
+
1. **Don't trigger filter on every `keydown`** during composition — wait for `compositionend`.
|
|
180
|
+
2. **Filter logic should match initial / 초성** — typing "ㄱ" might match "강원도", "기타" (initial-letter search common in Korean).
|
|
181
|
+
3. **Cancel on Esc during composition** — Esc cancels IME composition first, then closes combobox on second press.
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
const [query, setQuery] = useState("");
|
|
185
|
+
const [composing, setComposing] = useState(false);
|
|
186
|
+
|
|
187
|
+
<Combobox.Input
|
|
188
|
+
value={query}
|
|
189
|
+
onChange={(e) => !composing && setQuery(e.target.value)}
|
|
190
|
+
onCompositionStart={() => setComposing(true)}
|
|
191
|
+
onCompositionEnd={(e) => {
|
|
192
|
+
setComposing(false);
|
|
193
|
+
setQuery(e.currentTarget.value);
|
|
194
|
+
}}
|
|
195
|
+
/>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Code example — country picker
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
function CountryPicker({ value, onChange }: Props) {
|
|
202
|
+
const [open, setOpen] = useState(false);
|
|
203
|
+
const country = COUNTRIES.find(c => c.code === value);
|
|
204
|
+
|
|
205
|
+
return (
|
|
206
|
+
<Combobox open={open} onOpenChange={setOpen}>
|
|
207
|
+
<Combobox.Trigger asChild>
|
|
208
|
+
<Button variant="outline" role="combobox">
|
|
209
|
+
{country ? `${country.flag} ${country.name}` : "국가 선택"}
|
|
210
|
+
<ChevronDownIcon />
|
|
211
|
+
</Button>
|
|
212
|
+
</Combobox.Trigger>
|
|
213
|
+
<Combobox.Content className="w-[280px] p-0">
|
|
214
|
+
<Combobox.Input placeholder="국가 검색..." />
|
|
215
|
+
<Combobox.List>
|
|
216
|
+
<Combobox.Empty>일치하는 국가가 없어요.</Combobox.Empty>
|
|
217
|
+
{COUNTRIES.map(c => (
|
|
218
|
+
<Combobox.Item
|
|
219
|
+
key={c.code}
|
|
220
|
+
value={c.name + " " + c.code} // search token
|
|
221
|
+
onSelect={() => { onChange(c.code); setOpen(false); }}
|
|
222
|
+
>
|
|
223
|
+
<span className="mr-2">{c.flag}</span>
|
|
224
|
+
{c.name}
|
|
225
|
+
<CheckIcon
|
|
226
|
+
className={cn("ml-auto", value === c.code ? "" : "invisible")}
|
|
227
|
+
/>
|
|
228
|
+
</Combobox.Item>
|
|
229
|
+
))}
|
|
230
|
+
</Combobox.List>
|
|
231
|
+
</Combobox.Content>
|
|
232
|
+
</Combobox>
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Edge cases
|
|
238
|
+
|
|
239
|
+
- **Very long list (10,000+ items)**: virtualize. Use `react-virtual` inside Combobox.List.
|
|
240
|
+
- **Async fetch as user types**: debounce input; show loading state in list.
|
|
241
|
+
- **No exact match + creatable**: show "Create new" as last item.
|
|
242
|
+
- **Selected value not in list** (stale data): Trigger shows ID or last-known label; refresh on next open.
|
|
243
|
+
- **Disabled items**: render but skip on `Enter`.
|
|
244
|
+
- **Mobile**: open as a Sheet (full-height) instead of a Popover for better thumb reach.
|
|
245
|
+
- **Korean 초성 search** ("ㄱㅇㄷ" → matches "강원도"): requires custom search function with hangul-jaso library.
|
|
246
|
+
|
|
247
|
+
## Don't
|
|
248
|
+
|
|
249
|
+
- Don't use Combobox when a simple Select would do (< 20 items).
|
|
250
|
+
- Don't trigger network search on every keystroke. Debounce 200-300ms.
|
|
251
|
+
- Don't move focus to the option list — keep focus on input (use `aria-activedescendant`).
|
|
252
|
+
- Don't hide the search input when there are < 5 items. Confusing — degrade gracefully to non-search list.
|
|
253
|
+
- Don't show "0 results" without offering a creatable fallback OR a clear-filter shortcut.
|
|
254
|
+
- Don't ignore Korean IME — Hangul composition events matter.
|
|
255
|
+
|
|
256
|
+
## References
|
|
257
|
+
|
|
258
|
+
- shadcn-ui: [`combobox`](../refs/shadcn-ui/apps/v4/registry/new-york-v4/ui/combobox.tsx)
|
|
259
|
+
- WAI-ARIA: [Combobox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/)
|
|
260
|
+
- cmdk library
|
|
261
|
+
|
|
262
|
+
## Cross-reference
|
|
263
|
+
|
|
264
|
+
- [`examples/component-select.md`](component-select.md) — non-search variant
|
|
265
|
+
- [`examples/component-auto-complete.md`](component-auto-complete.md) — freeform variant
|
|
266
|
+
- [`examples/component-command.md`](component-command.md) — command palette (similar primitive)
|
|
267
|
+
- [`knowledge/i18n/korean-typography.md`](../knowledge/i18n/korean-typography.md) — IME handling
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# `CommandPalette` — spec
|
|
2
|
+
|
|
3
|
+
> Synthesized from shadcn-ui `command` (cmdk under the hood). Searchable command/action palette — the canonical "press Cmd+K" pattern popularized by VS Code, Linear, GitHub.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
- **Power-user shortcuts** for any action in the app.
|
|
8
|
+
- **Search across multiple entity types** (users, files, settings, actions).
|
|
9
|
+
- **Replace a sprawling main menu** for keyboard-driven UIs.
|
|
10
|
+
- **AI command surface** — "ask AI", "generate X" entry points.
|
|
11
|
+
|
|
12
|
+
When NOT to use:
|
|
13
|
+
- Simple apps with < 20 actions — overkill.
|
|
14
|
+
- Mobile-primary apps — keyboard shortcuts don't translate (long-press + on-screen invocation needed).
|
|
15
|
+
|
|
16
|
+
## Anatomy
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
[Cmd+K]
|
|
20
|
+
↓
|
|
21
|
+
┌──────────────────────────────────────┐
|
|
22
|
+
│ ⌕ Type a command or search... │
|
|
23
|
+
│ ───────────────────────────────────── │
|
|
24
|
+
│ │
|
|
25
|
+
│ Suggestions │
|
|
26
|
+
│ ───────── │
|
|
27
|
+
│ ▶ Open file... ⌘P │
|
|
28
|
+
│ Run command... ⌘⇧P │
|
|
29
|
+
│ Toggle theme ⌘L │
|
|
30
|
+
│ │
|
|
31
|
+
│ Recent │
|
|
32
|
+
│ ───── │
|
|
33
|
+
│ design-system.md │
|
|
34
|
+
│ Profile settings │
|
|
35
|
+
│ │
|
|
36
|
+
│ Search results — "compo" │
|
|
37
|
+
│ ──────────────────── │
|
|
38
|
+
│ Component spec │
|
|
39
|
+
│ Compose new doc │
|
|
40
|
+
│ │
|
|
41
|
+
└──────────────────────────────────────┘
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## API
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
<CommandPalette open={open} onOpenChange={setOpen}>
|
|
48
|
+
<CommandPalette.Input placeholder="Type a command or search..." />
|
|
49
|
+
<CommandPalette.List>
|
|
50
|
+
<CommandPalette.Empty>No results found.</CommandPalette.Empty>
|
|
51
|
+
|
|
52
|
+
<CommandPalette.Group heading="Suggestions">
|
|
53
|
+
<CommandPalette.Item onSelect={openFile}>
|
|
54
|
+
<FileIcon /> Open file...
|
|
55
|
+
<CommandPalette.Shortcut>⌘P</CommandPalette.Shortcut>
|
|
56
|
+
</CommandPalette.Item>
|
|
57
|
+
<CommandPalette.Item onSelect={runCommand}>
|
|
58
|
+
<TerminalIcon /> Run command...
|
|
59
|
+
<CommandPalette.Shortcut>⌘⇧P</CommandPalette.Shortcut>
|
|
60
|
+
</CommandPalette.Item>
|
|
61
|
+
</CommandPalette.Group>
|
|
62
|
+
|
|
63
|
+
<CommandPalette.Separator />
|
|
64
|
+
|
|
65
|
+
<CommandPalette.Group heading="Recent">
|
|
66
|
+
{recentItems.map(item => (
|
|
67
|
+
<CommandPalette.Item key={item.id} onSelect={() => open(item)}>
|
|
68
|
+
{item.name}
|
|
69
|
+
</CommandPalette.Item>
|
|
70
|
+
))}
|
|
71
|
+
</CommandPalette.Group>
|
|
72
|
+
</CommandPalette.List>
|
|
73
|
+
</CommandPalette>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Composition
|
|
77
|
+
|
|
78
|
+
| Part | Purpose |
|
|
79
|
+
| --- | --- |
|
|
80
|
+
| `CommandPalette` | Wrapper; manages state + keyboard |
|
|
81
|
+
| `Input` | Search field (auto-focuses on open) |
|
|
82
|
+
| `List` | Results container (virtualized for long lists) |
|
|
83
|
+
| `Empty` | Shown when no items match query |
|
|
84
|
+
| `Group` | Section with heading |
|
|
85
|
+
| `Item` | Single command / result |
|
|
86
|
+
| `Shortcut` | Keyboard hint (visual; doesn't bind keys) |
|
|
87
|
+
| `Separator` | Visual divider |
|
|
88
|
+
| `Loading` | Shown while async results load |
|
|
89
|
+
|
|
90
|
+
## Keyboard contract
|
|
91
|
+
|
|
92
|
+
| Key | Action |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| `Cmd+K` / `Ctrl+K` | Open globally |
|
|
95
|
+
| Type | Filter items (substring + fuzzy) |
|
|
96
|
+
| `↓` / `↑` | Navigate items |
|
|
97
|
+
| `Enter` | Activate selected item |
|
|
98
|
+
| `Esc` | Close (or clear input first if non-empty) |
|
|
99
|
+
| `Tab` | Close (no internal tabbing) |
|
|
100
|
+
| `Cmd+Enter` | Open in new tab / new window (if applicable) |
|
|
101
|
+
|
|
102
|
+
Global hotkey activation requires app-level keyboard listener (separate from CommandPalette internals). Standard pattern:
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
const handler = (e: KeyboardEvent) => {
|
|
107
|
+
if ((e.metaKey || e.ctrlKey) && e.key === "k") {
|
|
108
|
+
e.preventDefault();
|
|
109
|
+
setOpen(o => !o);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
document.addEventListener("keydown", handler);
|
|
113
|
+
return () => document.removeEventListener("keydown", handler);
|
|
114
|
+
}, []);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Search modes
|
|
118
|
+
|
|
119
|
+
### Fuzzy / substring (default)
|
|
120
|
+
|
|
121
|
+
Type "comp" → matches "Component spec", "Compose new doc", "Compress files".
|
|
122
|
+
|
|
123
|
+
cmdk uses substring + fuzzy by default with per-item scoring.
|
|
124
|
+
|
|
125
|
+
### Pages / sub-commands
|
|
126
|
+
|
|
127
|
+
Multi-step flows (think VS Code "Go to..." then "File / Symbol / Line"):
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
{!page && (
|
|
131
|
+
<CommandPalette.Group heading="Navigate">
|
|
132
|
+
<CommandPalette.Item onSelect={() => setPage("files")}>Files</CommandPalette.Item>
|
|
133
|
+
<CommandPalette.Item onSelect={() => setPage("symbols")}>Symbols</CommandPalette.Item>
|
|
134
|
+
</CommandPalette.Group>
|
|
135
|
+
)}
|
|
136
|
+
|
|
137
|
+
{page === "files" && (
|
|
138
|
+
<CommandPalette.Group heading="Files">
|
|
139
|
+
{files.map(f => <CommandPalette.Item key={f.path}>{f.name}</CommandPalette.Item>)}
|
|
140
|
+
</CommandPalette.Group>
|
|
141
|
+
)}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`Backspace` on empty input pops back to root page.
|
|
145
|
+
|
|
146
|
+
### Async / remote search
|
|
147
|
+
|
|
148
|
+
For server-fetched results (e.g., GitHub user search):
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
const [query, setQuery] = useState("");
|
|
152
|
+
const { data, isLoading } = useDebouncedQuery(query, 200);
|
|
153
|
+
|
|
154
|
+
<CommandPalette.Input value={query} onValueChange={setQuery} />
|
|
155
|
+
<CommandPalette.List>
|
|
156
|
+
{isLoading && <CommandPalette.Loading>Searching...</CommandPalette.Loading>}
|
|
157
|
+
{!isLoading && data?.length === 0 && <CommandPalette.Empty>No matches.</CommandPalette.Empty>}
|
|
158
|
+
{data?.map(item => <CommandPalette.Item key={item.id}>{item.name}</CommandPalette.Item>)}
|
|
159
|
+
</CommandPalette.List>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Debounce input; show loading state; render empty state on no results.
|
|
163
|
+
|
|
164
|
+
## States
|
|
165
|
+
|
|
166
|
+
| State | Visual |
|
|
167
|
+
| --- | --- |
|
|
168
|
+
| Closed | Hidden |
|
|
169
|
+
| Opening | Modal fade + scale (200ms) |
|
|
170
|
+
| Open, no input | Show suggestions / recent |
|
|
171
|
+
| Typing | Filter / fuzzy match in real-time |
|
|
172
|
+
| Loading (async) | Shimmer or "Searching..." in List |
|
|
173
|
+
| No results | `Empty` rendered |
|
|
174
|
+
| Closing | Reverse |
|
|
175
|
+
|
|
176
|
+
## Visual
|
|
177
|
+
|
|
178
|
+
CommandPalette is a centered Modal (top-positioned more common):
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
[centered horizontally]
|
|
182
|
+
[at ~20% from top of viewport (not center; users scan top-down)]
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Width: 600-720px on desktop; near-full-width on mobile.
|
|
186
|
+
|
|
187
|
+
Backdrop: scrim (semi-opaque dark). Click outside closes.
|
|
188
|
+
|
|
189
|
+
## Tokens consumed
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
--color-bg-overlay-scrim (backdrop)
|
|
193
|
+
--color-bg-default (palette bg)
|
|
194
|
+
--color-fg-default
|
|
195
|
+
--color-fg-muted (groups, shortcut hints)
|
|
196
|
+
--color-bg-secondary (item hover bg)
|
|
197
|
+
--color-brand-default (selected item indicator)
|
|
198
|
+
--color-border-default
|
|
199
|
+
--shadow-overlay
|
|
200
|
+
--radius-lg (palette container)
|
|
201
|
+
--radius-md (items)
|
|
202
|
+
--space-xs, --space-sm, --space-md
|
|
203
|
+
--font-size-base (input)
|
|
204
|
+
--font-size-sm (group headings, shortcuts)
|
|
205
|
+
--motion-fast (item hover)
|
|
206
|
+
--motion-medium (open/close)
|
|
207
|
+
--ease-out
|
|
208
|
+
--z-overlay
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Accessibility
|
|
212
|
+
|
|
213
|
+
- Wrapper: `role="dialog" aria-modal="true" aria-label="Command palette"`.
|
|
214
|
+
- Input: `role="combobox" aria-expanded="true" aria-controls="cmdk-list" aria-activedescendant="<item-id>"`.
|
|
215
|
+
- List: `role="listbox"`.
|
|
216
|
+
- Item: `role="option" aria-selected="true|false"`.
|
|
217
|
+
- Group: `role="group" aria-label="<heading>"`.
|
|
218
|
+
- Empty: `role="status"` for "No results" announcement.
|
|
219
|
+
- Focus trapped in palette; first item auto-selected after typing.
|
|
220
|
+
- Touch target ≥ 36px per item.
|
|
221
|
+
- Korean: Pretendard / NanumSquare body, Pretendard for input. Group headings 합쇼체 ("최근 항목") or English mixed.
|
|
222
|
+
|
|
223
|
+
## Code example
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
function GlobalCommandPalette() {
|
|
227
|
+
const [open, setOpen] = useState(false);
|
|
228
|
+
const [query, setQuery] = useState("");
|
|
229
|
+
const navigate = useNavigate();
|
|
230
|
+
|
|
231
|
+
useGlobalHotkey("cmd+k", () => setOpen(true));
|
|
232
|
+
|
|
233
|
+
return (
|
|
234
|
+
<CommandPalette open={open} onOpenChange={setOpen}>
|
|
235
|
+
<CommandPalette.Input
|
|
236
|
+
value={query}
|
|
237
|
+
onValueChange={setQuery}
|
|
238
|
+
placeholder="명령어 또는 파일을 검색하세요..."
|
|
239
|
+
/>
|
|
240
|
+
<CommandPalette.List>
|
|
241
|
+
<CommandPalette.Empty>일치하는 결과가 없어요.</CommandPalette.Empty>
|
|
242
|
+
|
|
243
|
+
<CommandPalette.Group heading="명령어">
|
|
244
|
+
<CommandPalette.Item onSelect={() => navigate("/new")}>
|
|
245
|
+
<PlusIcon /> 새 문서 만들기
|
|
246
|
+
<CommandPalette.Shortcut>⌘N</CommandPalette.Shortcut>
|
|
247
|
+
</CommandPalette.Item>
|
|
248
|
+
<CommandPalette.Item onSelect={() => toggleTheme()}>
|
|
249
|
+
<SunIcon /> 테마 전환
|
|
250
|
+
<CommandPalette.Shortcut>⌘⇧L</CommandPalette.Shortcut>
|
|
251
|
+
</CommandPalette.Item>
|
|
252
|
+
</CommandPalette.Group>
|
|
253
|
+
|
|
254
|
+
<CommandPalette.Group heading="최근 항목">
|
|
255
|
+
{recents.map(item => (
|
|
256
|
+
<CommandPalette.Item key={item.id} onSelect={() => navigate(item.path)}>
|
|
257
|
+
{item.name}
|
|
258
|
+
</CommandPalette.Item>
|
|
259
|
+
))}
|
|
260
|
+
</CommandPalette.Group>
|
|
261
|
+
</CommandPalette.List>
|
|
262
|
+
</CommandPalette>
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Edge cases
|
|
268
|
+
|
|
269
|
+
- **Long lists (10,000+ items)**: virtualize the List (react-virtual / cmdk built-in).
|
|
270
|
+
- **Disabled items**: render but skip on Enter; visually muted.
|
|
271
|
+
- **Item with multiple actions** (open / open in new tab): show as separate items OR add an "actions" submenu (`Cmd+Enter` for secondary).
|
|
272
|
+
- **Closing while async query in flight**: cancel request OR ignore late response.
|
|
273
|
+
- **Korean IME composition**: don't treat composing characters as final input — debounce / wait for `compositionend`.
|
|
274
|
+
- **Reduced motion**: skip the open/close animation; instant.
|
|
275
|
+
- **Mobile**: full-width palette; on-screen keyboard handling — palette shrinks above keyboard.
|
|
276
|
+
|
|
277
|
+
## Don't
|
|
278
|
+
|
|
279
|
+
- Don't put critical actions ONLY in the palette. They need visible buttons too.
|
|
280
|
+
- Don't forget Esc to close — accessibility foundation.
|
|
281
|
+
- Don't over-pack one palette with 50+ groups; users get lost.
|
|
282
|
+
- Don't put the search input below results — input always at top.
|
|
283
|
+
- Don't lock keyboard shortcuts to one OS (`Cmd` only); use `Cmd` on Mac, `Ctrl` on Win/Linux.
|
|
284
|
+
- Don't use CommandPalette as your only input method — must have alternatives.
|
|
285
|
+
- Don't fail to debounce async queries — server load.
|
|
286
|
+
|
|
287
|
+
## References
|
|
288
|
+
|
|
289
|
+
- shadcn-ui: [`command`](../refs/shadcn-ui/apps/v4/registry/new-york-v4/ui/command.tsx) (cmdk-based)
|
|
290
|
+
- cmdk library by pacocoursey
|
|
291
|
+
- Patterns: VS Code Command Palette, Linear, GitHub global search, Slack `Cmd+K`
|
|
292
|
+
- WAI-ARIA: combobox + listbox pattern
|
|
293
|
+
|
|
294
|
+
## Cross-reference
|
|
295
|
+
|
|
296
|
+
- [`examples/component-dropdown.md`](component-dropdown.md) — for non-search menus
|
|
297
|
+
- [`examples/component-modal.md`](component-modal.md) — focus trap pattern
|
|
298
|
+
- [`examples/component-auto-complete.md`](component-auto-complete.md) — single-field search
|
|
299
|
+
- [`knowledge/a11y/keyboard-and-focus.md`](../knowledge/a11y/keyboard-and-focus.md)
|