@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,190 @@
|
|
|
1
|
+
# `ButtonBase` — spec
|
|
2
|
+
|
|
3
|
+
> Synthesized from MUI `ButtonBase`, with public action-button guidance cross-checked against Ant Design `Button` and shadcn-ui `Button`. `ButtonBase` is a low-level interactive primitive for building design-system controls, not a product-facing component.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
- Building a new design-system primitive such as `IconButton`, `CardActionArea`, `ListItemButton`, `Tab`, `StepButton`, or a toolbar control.
|
|
8
|
+
- You need native button/link semantics, focus-visible handling, disabled behavior, and optional press/ripple feedback without inheriting a visual Button style.
|
|
9
|
+
- You are authoring a library layer where the consumer owns the visual treatment.
|
|
10
|
+
|
|
11
|
+
When NOT to use:
|
|
12
|
+
- Product actions such as "저장", "결제하기", or "삭제" — use `Button`.
|
|
13
|
+
- Icon-only actions — use `IconButton` so the accessible name, size, and variant contract are already enforced.
|
|
14
|
+
- Links inside body copy — use `Link`.
|
|
15
|
+
- Toggle formatting controls — use `Toggle` / `ToggleGroup`.
|
|
16
|
+
|
|
17
|
+
## Anatomy
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
ButtonBase
|
|
21
|
+
├── Root interactive element (`button` by default)
|
|
22
|
+
├── Focus-visible state bridge
|
|
23
|
+
├── Optional TouchRipple layer
|
|
24
|
+
└── Children
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
| Part | Purpose | Required | Default if omitted |
|
|
28
|
+
| --- | --- | --- | --- |
|
|
29
|
+
| Root | Receives events, disabled state, `tabIndex`, and semantic element choice. | yes | `<button type="button">` |
|
|
30
|
+
| Focus-visible bridge | Applies keyboard-only focus state and exposes `onFocusVisible`. | yes | internal state/class |
|
|
31
|
+
| TouchRipple | Optional visual feedback layer for pointer/keyboard press. | no | rendered unless ripple is disabled |
|
|
32
|
+
| Children | The visual content supplied by the composed component. | no | empty interactive shell; avoid in product code |
|
|
33
|
+
|
|
34
|
+
## API
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
<ButtonBase
|
|
38
|
+
component="button"
|
|
39
|
+
type="button"
|
|
40
|
+
focusVisibleClassName="focus-visible"
|
|
41
|
+
onFocusVisible={handleFocusVisible}
|
|
42
|
+
>
|
|
43
|
+
<span className="toolbar-button-content">정렬</span>
|
|
44
|
+
</ButtonBase>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
| Prop | Type | Default | Description |
|
|
48
|
+
| --- | --- | --- | --- |
|
|
49
|
+
| `children` | `ReactNode` | — | Visual content. The composed component must provide text or an accessible label. |
|
|
50
|
+
| `component` | `React.ElementType` | `"button"` | Root element override. Use sparingly and preserve keyboard behavior. |
|
|
51
|
+
| `href` | `string` | — | Switches the root toward link behavior in MUI's overload. |
|
|
52
|
+
| `LinkComponent` | `React.ElementType` | `"a"` | Router-aware link component when `href` / `to` is present. |
|
|
53
|
+
| `type` | `string` | `"button"` | Native button type. Keep the default unless submitting a form intentionally. |
|
|
54
|
+
| `disabled` | `boolean` | `false` | Removes interaction. Non-native roots still need `aria-disabled` handling. |
|
|
55
|
+
| `tabIndex` | `number` | `0` | Keyboard order override. Avoid positive values. |
|
|
56
|
+
| `focusVisibleClassName` | `string` | — | Class applied for keyboard focus-visible styling. |
|
|
57
|
+
| `onFocusVisible` | `(event) => void` | — | Fires when focus was reached through keyboard-like interaction. |
|
|
58
|
+
| `action` | `ref` | — | Imperative handle; supports `focusVisible()`. |
|
|
59
|
+
| `centerRipple` | `boolean` | `false` | Centers ripple instead of starting from pointer location. |
|
|
60
|
+
| `focusRipple` | `boolean` | `false` | Adds keyboard-focus ripple feedback. |
|
|
61
|
+
| `disableRipple` | `boolean` | `false` | Removes ripple. Must be paired with an explicit focus-visible visual. |
|
|
62
|
+
| `disableTouchRipple` | `boolean` | `false` | Removes touch ripple while keeping other focus behavior. |
|
|
63
|
+
| `TouchRippleProps` | `object` | — | Props passed to the ripple layer. Treat as advanced. |
|
|
64
|
+
| `touchRippleRef` | `ref` | — | Imperative access to ripple actions. Treat as internal. |
|
|
65
|
+
| `nativeButton` | `boolean` | inferred | Declares whether a custom component renders a real `<button>`. |
|
|
66
|
+
| `sx` / `classes` | system styles | — | MUI-specific style extension points. Prefer local component tokens in this repo. |
|
|
67
|
+
|
|
68
|
+
## API choices made
|
|
69
|
+
|
|
70
|
+
- Keep `ButtonBase` **advanced/internal**. Product teams should rarely import it directly because it has no visible affordance by itself.
|
|
71
|
+
- Preserve MUI's polymorphic `component` / `LinkComponent` model, but document it as a semantic responsibility: if the root is not a native button or anchor, the wrapper must recreate keyboard activation and ARIA state.
|
|
72
|
+
- Do not expose visual variants here. Variants belong to composed controls (`Button`, `IconButton`, `Toggle`) so the primitive stays stable.
|
|
73
|
+
- Treat ripple as optional decoration. Focus-visible is mandatory whether ripple is on or off.
|
|
74
|
+
|
|
75
|
+
## States
|
|
76
|
+
|
|
77
|
+
| State | Trigger | Visual / behavior |
|
|
78
|
+
| --- | --- | --- |
|
|
79
|
+
| Default | resting | Transparent reset; composed component owns size, color, and layout. |
|
|
80
|
+
| Hover | pointer hover | Optional consumer style using `--color-bg-action-hover`; not defined by the base. |
|
|
81
|
+
| Focus-visible | keyboard focus | 2px outline using `--color-focus-ring`, offset 2px, contrast at least 3:1 against adjacent surfaces. |
|
|
82
|
+
| Active | pointer or keyboard press | Optional pressed layer or ripple; do not rely on motion alone. |
|
|
83
|
+
| Disabled | `disabled` | Remove pointer activation, suppress ripple, expose disabled semantics. |
|
|
84
|
+
| Link mode | `href` / `to` | Behaves as navigation; do not attach form-submit semantics. |
|
|
85
|
+
|
|
86
|
+
## Tokens consumed
|
|
87
|
+
|
|
88
|
+
`ButtonBase` itself should consume only primitive interaction tokens. Composed controls map these to real visual tokens.
|
|
89
|
+
|
|
90
|
+
```css
|
|
91
|
+
--color-focus-ring
|
|
92
|
+
--color-bg-action-hover
|
|
93
|
+
--color-bg-action-active
|
|
94
|
+
--color-text-primary
|
|
95
|
+
--space-1
|
|
96
|
+
--space-2
|
|
97
|
+
--radius-sm
|
|
98
|
+
--motion-fast
|
|
99
|
+
--easing-out
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Accessibility
|
|
103
|
+
|
|
104
|
+
- **Semantic element**: default to `<button type="button">`; use `<a>` only for navigation.
|
|
105
|
+
- **Keyboard**: `Tab` reaches the control, `Enter` and `Space` activate button semantics. Custom roots must implement both keys.
|
|
106
|
+
- **Focus**: visible focus is non-negotiable. If `disableRipple` is true, add a separate focus-visible style; otherwise keyboard users lose the only visible cue.
|
|
107
|
+
- **Disabled**: native `disabled` is enough for real buttons; custom roots need `aria-disabled="true"`, suppressed events, and removal from activation shortcuts.
|
|
108
|
+
- **Touch target**: composed controls must provide at least 44x44 mobile hit area and at least 24x24 WCAG AA web target size.
|
|
109
|
+
- **Name**: icon-only composition requires `aria-label`; decorative icons inside a text label need `aria-hidden="true"`.
|
|
110
|
+
- **Toggle state**: expose `aria-pressed` only for two-state buttons. Do not put `aria-selected` on generic buttons.
|
|
111
|
+
|
|
112
|
+
## Code example — design-system toolbar button
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
type ToolbarButtonProps = {
|
|
116
|
+
label: string;
|
|
117
|
+
selected?: boolean;
|
|
118
|
+
disabled?: boolean;
|
|
119
|
+
onPress: () => void;
|
|
120
|
+
children: React.ReactNode;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export function ToolbarButton({
|
|
124
|
+
label,
|
|
125
|
+
selected = false,
|
|
126
|
+
disabled = false,
|
|
127
|
+
onPress,
|
|
128
|
+
children,
|
|
129
|
+
}: ToolbarButtonProps) {
|
|
130
|
+
return (
|
|
131
|
+
<ButtonBase
|
|
132
|
+
type="button"
|
|
133
|
+
disabled={disabled}
|
|
134
|
+
aria-label={label}
|
|
135
|
+
aria-pressed={selected}
|
|
136
|
+
focusVisibleClassName="toolbar-button-focus-visible"
|
|
137
|
+
className="toolbar-button"
|
|
138
|
+
onClick={onPress}
|
|
139
|
+
>
|
|
140
|
+
{children}
|
|
141
|
+
</ButtonBase>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```css
|
|
147
|
+
.toolbar-button {
|
|
148
|
+
min-width: 44px;
|
|
149
|
+
min-height: 44px;
|
|
150
|
+
border-radius: var(--radius-sm);
|
|
151
|
+
color: var(--color-text-primary);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.toolbar-button:hover {
|
|
155
|
+
background: var(--color-bg-action-hover);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.toolbar-button[aria-pressed="true"] {
|
|
159
|
+
background: var(--color-bg-action-active);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.toolbar-button-focus-visible {
|
|
163
|
+
outline: 2px solid var(--color-focus-ring);
|
|
164
|
+
outline-offset: 2px;
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Edge cases
|
|
169
|
+
|
|
170
|
+
- **Inside a form**: omit `type` and a native button may submit unexpectedly in some wrappers. Keep `type="button"` for non-submit actions.
|
|
171
|
+
- **Router links**: pass a router-aware `LinkComponent`, but keep anchor semantics when the action navigates.
|
|
172
|
+
- **Disabled links**: anchors do not support native `disabled`; use `aria-disabled`, remove `href` or intercept activation, and keep the visual disabled state.
|
|
173
|
+
- **Nested interactive children**: never put another button, input, select, or link inside `ButtonBase`.
|
|
174
|
+
- **No ripple**: disabling ripple is fine for quiet UIs, but the focus-visible ring must still be explicit.
|
|
175
|
+
- **Korean dense toolbars**: reduce visual padding if needed, but keep the hit target through invisible padding or `::before` hit area.
|
|
176
|
+
|
|
177
|
+
## Don't
|
|
178
|
+
|
|
179
|
+
- Don't import `ButtonBase` in product pages when `Button`, `IconButton`, or `Link` fits.
|
|
180
|
+
- Don't render a `<div>` root unless you also implement role, tab stop, disabled suppression, and keyboard activation.
|
|
181
|
+
- Don't remove focus outlines globally to make ripple the only state indicator.
|
|
182
|
+
- Don't use ripple or pressed animation as the only selected-state signal.
|
|
183
|
+
|
|
184
|
+
## References
|
|
185
|
+
|
|
186
|
+
- MUI: [`ButtonBase.d.ts`](../refs/mui/packages/mui-material/src/ButtonBase/ButtonBase.d.ts), [`ButtonBase.js`](../refs/mui/packages/mui-material/src/ButtonBase/ButtonBase.js), [`useButtonBase.ts`](../refs/mui/packages/mui-material/src/ButtonBase/useButtonBase.ts)
|
|
187
|
+
- Ant Design: [`Button.tsx`](../refs/ant-design/components/button/Button.tsx), [`button/index.en-US.md`](../refs/ant-design/components/button/index.en-US.md)
|
|
188
|
+
- shadcn-ui: [`button.tsx`](../refs/shadcn-ui/apps/v4/registry/new-york-v4/ui/button.tsx)
|
|
189
|
+
- Knowledge: [`a11y/keyboard-and-focus.md`](../knowledge/a11y/keyboard-and-focus.md), [`layout/spacing-and-grid.md`](../knowledge/layout/spacing-and-grid.md)
|
|
190
|
+
- Cross-reference: [`component-button.md`](component-button.md), [`component-icon-button.md`](component-icon-button.md), [`component-toggle.md`](component-toggle.md)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# `ButtonGroup` — spec
|
|
2
|
+
|
|
3
|
+
> Synthesized from MUI `ButtonGroup` and shadcn-ui's `button-group`. A horizontal cluster of related buttons, visually unified — no gap between them; shared border for outline variant.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
- Related actions with one shared visual frame ("Save", "Save as...", "Cancel" together).
|
|
8
|
+
- Toolbar action clusters.
|
|
9
|
+
- Segmented-style action button row (different from `ToggleGroup` which has persistent selection).
|
|
10
|
+
|
|
11
|
+
When NOT to use:
|
|
12
|
+
- Mutually exclusive selection — use `ToggleGroup` (single).
|
|
13
|
+
- Independent actions with distinct purposes — use separate `Button`s with gap.
|
|
14
|
+
|
|
15
|
+
## ButtonGroup vs ToggleGroup vs Segmented
|
|
16
|
+
|
|
17
|
+
| | ButtonGroup | ToggleGroup | Segmented |
|
|
18
|
+
| --- | --- | --- | --- |
|
|
19
|
+
| Persistent selection | No | Yes | Yes |
|
|
20
|
+
| Visual shape | Joined buttons | Joined toggle buttons | Pill-style |
|
|
21
|
+
| Use | Action cluster | Multi-select / radio of toggles | iOS-style mode switch |
|
|
22
|
+
|
|
23
|
+
## Anatomy
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
[ Save ][ Save as... ][ Cancel ]
|
|
27
|
+
↑ no gap; shared border
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## API
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
<ButtonGroup>
|
|
34
|
+
<Button onClick={save}>Save</Button>
|
|
35
|
+
<Button onClick={saveAs}>Save as...</Button>
|
|
36
|
+
<Button variant="ghost" onClick={cancel}>Cancel</Button>
|
|
37
|
+
</ButtonGroup>
|
|
38
|
+
|
|
39
|
+
<ButtonGroup variant="outline" orientation="vertical">
|
|
40
|
+
<Button>Option 1</Button>
|
|
41
|
+
<Button>Option 2</Button>
|
|
42
|
+
<Button>Option 3</Button>
|
|
43
|
+
</ButtonGroup>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
| Prop | Type | Default | Description |
|
|
47
|
+
| --- | --- | --- | --- |
|
|
48
|
+
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Direction |
|
|
49
|
+
| `variant` | `"default" \| "outline" \| "ghost"` | `"default"` | Visual style applied to all children |
|
|
50
|
+
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size applied to all children |
|
|
51
|
+
| `disabled` | `boolean` | `false` | Disable all |
|
|
52
|
+
|
|
53
|
+
## States
|
|
54
|
+
|
|
55
|
+
Same as Button — each Button child has its own hover / focus / disabled state.
|
|
56
|
+
|
|
57
|
+
The `ButtonGroup` adjusts:
|
|
58
|
+
- First child: rounded left corners only.
|
|
59
|
+
- Last child: rounded right corners only.
|
|
60
|
+
- Middle children: no rounded corners.
|
|
61
|
+
- Borders: shared (outline variant) — adjacent buttons share a 1px border, not 2px.
|
|
62
|
+
|
|
63
|
+
## Tokens consumed
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
--button-group-divider (subtle line between buttons in default variant)
|
|
67
|
+
--radius-md (only at outer corners)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Otherwise inherits Button's tokens.
|
|
71
|
+
|
|
72
|
+
## Accessibility
|
|
73
|
+
|
|
74
|
+
- `role="group"` + `aria-label` describing the group's purpose.
|
|
75
|
+
- Each Button is independently focusable; standard Button keyboard contract.
|
|
76
|
+
- For toolbars: wrap ButtonGroup in `<div role="toolbar">`.
|
|
77
|
+
|
|
78
|
+
## Code example
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
function EditorToolbar() {
|
|
82
|
+
return (
|
|
83
|
+
<div role="toolbar" aria-label="Text formatting">
|
|
84
|
+
<ButtonGroup>
|
|
85
|
+
<Button onClick={undo} aria-label="실행 취소"><UndoIcon /></Button>
|
|
86
|
+
<Button onClick={redo} aria-label="다시 실행"><RedoIcon /></Button>
|
|
87
|
+
</ButtonGroup>
|
|
88
|
+
|
|
89
|
+
<Separator orientation="vertical" />
|
|
90
|
+
|
|
91
|
+
<ButtonGroup>
|
|
92
|
+
<Button onClick={cut}>잘라내기</Button>
|
|
93
|
+
<Button onClick={copy}>복사</Button>
|
|
94
|
+
<Button onClick={paste}>붙여넣기</Button>
|
|
95
|
+
</ButtonGroup>
|
|
96
|
+
</div>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Don't
|
|
102
|
+
|
|
103
|
+
- Don't use ButtonGroup for mutually exclusive selection. Use ToggleGroup or Segmented.
|
|
104
|
+
- Don't put 5+ buttons in one group — visual clutter; split.
|
|
105
|
+
- Don't mix variants within one group (some outline, some filled).
|
|
106
|
+
- Don't use ButtonGroup as a navigation menu. Use NavigationMenu / Menubar.
|
|
107
|
+
|
|
108
|
+
## References
|
|
109
|
+
|
|
110
|
+
- MUI: [`ButtonGroup`](../refs/mui/packages/mui-material/src/ButtonGroup)
|
|
111
|
+
- shadcn-ui: [`button-group`](../refs/shadcn-ui/apps/v4/registry/new-york-v4/ui/button-group.tsx)
|
|
112
|
+
|
|
113
|
+
## Cross-reference
|
|
114
|
+
|
|
115
|
+
- [`examples/component-button.md`](component-button.md)
|
|
116
|
+
- [`examples/component-toggle.md`](component-toggle.md) — for persistent selection
|
|
117
|
+
- [`examples/component-segmented.md`](component-segmented.md) — pill-style alternative
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# `Button` — spec
|
|
2
|
+
|
|
3
|
+
> Status: example artifact for `component-spec-writer` skill
|
|
4
|
+
> Generated by: `skills/component-spec-writer` skill, citing Ant Design, MUI, and shadcn-ui
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
A button performs an action when activated. The most-used component in any product UI. It must be unmistakable as interactive, support all input modalities, and clearly express priority.
|
|
9
|
+
|
|
10
|
+
## Anatomy
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
Button
|
|
14
|
+
├── [iconStart]? // optional leading icon
|
|
15
|
+
├── label // children — text or ReactNode
|
|
16
|
+
├── [iconEnd]? // optional trailing icon
|
|
17
|
+
└── [loadingIndicator]? // shown when loading
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
| Part | Purpose | Required | Default if omitted |
|
|
21
|
+
| --- | --- | --- | --- |
|
|
22
|
+
| `iconStart` | Visual cue before the label | no | none |
|
|
23
|
+
| `label` | Action text | **yes** (children) | renders empty button — usually a bug |
|
|
24
|
+
| `iconEnd` | Visual cue after the label (e.g., chevron, arrow) | no | none |
|
|
25
|
+
| `loadingIndicator` | Spinner shown when `loading={true}` | no | system default `CircularProgress`-equivalent |
|
|
26
|
+
|
|
27
|
+
Slot rules:
|
|
28
|
+
- `iconStart` and `iconEnd` may not both convey the same meaning. If both are present, they should be complementary (e.g., search icon + chevron-down).
|
|
29
|
+
- When `loading={true}`, the indicator replaces `iconStart` (or center if no start icon). Label stays visible unless `loadingPosition="center"`.
|
|
30
|
+
|
|
31
|
+
## API
|
|
32
|
+
|
|
33
|
+
| Prop | Type | Default | Description |
|
|
34
|
+
| --- | --- | --- | --- |
|
|
35
|
+
| `children` | `ReactNode` | — | Label content. Required for accessible name unless `aria-label` provided. |
|
|
36
|
+
| `variant` | `"solid" \| "outline" \| "ghost" \| "link"` | `"solid"` | Visual emphasis. `solid` is most prominent; `link` reads as text. |
|
|
37
|
+
| `intent` | `"primary" \| "neutral" \| "success" \| "warning" \| "danger"` | `"primary"` | Semantic color. **One** `primary`+`solid` per surface. |
|
|
38
|
+
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Dense → comfortable. |
|
|
39
|
+
| `disabled` | `boolean` | `false` | Removes interactivity. Sets `aria-disabled`, dims appearance. |
|
|
40
|
+
| `loading` | `boolean` | `false` | Shows spinner, blocks clicks, sets `aria-busy="true"`. |
|
|
41
|
+
| `loadingPosition` | `"start" \| "end" \| "center"` | `"start"` | Where the indicator sits. `center` hides label. |
|
|
42
|
+
| `iconStart` | `ReactNode` | — | Leading icon. |
|
|
43
|
+
| `iconEnd` | `ReactNode` | — | Trailing icon. |
|
|
44
|
+
| `fullWidth` | `boolean` | `false` | Stretches to container width. Use sparingly — usually a sign of mobile or form layout. |
|
|
45
|
+
| `href` | `string` | — | If provided, renders `<a>` instead of `<button>`. |
|
|
46
|
+
| `target` | `"_self" \| "_blank" \| "_parent" \| "_top"` | — | Only with `href`. |
|
|
47
|
+
| `asChild` | `boolean` | `false` | Render-as-child (Radix `Slot` pattern) — composes with `<Link>` from routers without nesting `<a>` inside `<button>`. |
|
|
48
|
+
| `type` | `"button" \| "submit" \| "reset"` | `"button"` | HTML form behavior. **Always `"button"` unless inside a form's submit slot** — the default `"submit"` of bare `<button>` is the #1 form bug. |
|
|
49
|
+
| `onClick` | `(e: MouseEvent) => void` | — | Fires on click and on `Enter`/`Space` keypress. |
|
|
50
|
+
|
|
51
|
+
## States
|
|
52
|
+
|
|
53
|
+
| State | Trigger | Visual |
|
|
54
|
+
| --- | --- | --- |
|
|
55
|
+
| Default | resting | base styles per variant + intent |
|
|
56
|
+
| Hover | mouse-over | bg shift (solid: -8% L; outline: bg becomes 5% intent; ghost: bg becomes 8% intent) |
|
|
57
|
+
| Focus-visible | keyboard tab | 2px ring `--color-focus-ring`, 2px offset, 3:1 contrast both sides |
|
|
58
|
+
| Active | press | bg darken 12% from default |
|
|
59
|
+
| Disabled | `disabled={true}` | opacity 0.5, pointer-events: none, `aria-disabled="true"` |
|
|
60
|
+
| Loading | `loading={true}` | spinner replaces start icon; `aria-busy="true"`; click blocked |
|
|
61
|
+
| Read-only | N/A | buttons don't have read-only |
|
|
62
|
+
| Error | parent form invalid | unchanged — error state lives on form fields, not their submit button |
|
|
63
|
+
|
|
64
|
+
`hover` styles must NOT fire on touch devices. Use `@media (hover: hover)` to gate.
|
|
65
|
+
|
|
66
|
+
## Variants
|
|
67
|
+
|
|
68
|
+
### `variant`
|
|
69
|
+
|
|
70
|
+
| Value | Visual | Use |
|
|
71
|
+
| --- | --- | --- |
|
|
72
|
+
| `solid` | filled background, on-color text | primary CTAs |
|
|
73
|
+
| `outline` | transparent bg, intent border, intent text | secondary actions |
|
|
74
|
+
| `ghost` | no border, no bg, intent text on hover-bg | tertiary actions, toolbar items |
|
|
75
|
+
| `link` | text-only, underline on hover | inline within text, low-emphasis nav |
|
|
76
|
+
|
|
77
|
+
### `intent`
|
|
78
|
+
|
|
79
|
+
| Value | Default solid bg | On-color | When |
|
|
80
|
+
| --- | --- | --- | --- |
|
|
81
|
+
| `primary` | `--color-primary-default` | `--color-on-primary` | the main action of the surface |
|
|
82
|
+
| `neutral` | `--color-neutral-200` (light) / `--color-neutral-700` (dark) | `--color-text-primary` | secondary action paired with primary |
|
|
83
|
+
| `success` | `--color-success` | white | rare — confirm of irreversible positive action |
|
|
84
|
+
| `warning` | `--color-warning` | white or near-black | rarely used as button bg; usually as outline |
|
|
85
|
+
| `danger` | `--color-error` | white | destructive actions (delete, leave) |
|
|
86
|
+
|
|
87
|
+
### `size`
|
|
88
|
+
|
|
89
|
+
| Size | Height | Font | Padding | Icon size |
|
|
90
|
+
| --- | --- | --- | --- | --- |
|
|
91
|
+
| `sm` | 32px | 13px | 6px 12px | 14px |
|
|
92
|
+
| `md` | 40px | 14px | 8px 16px | 16px |
|
|
93
|
+
| `lg` | 48px | 16px | 12px 20px | 20px |
|
|
94
|
+
|
|
95
|
+
Icon-only variants get square dimensions matching height.
|
|
96
|
+
|
|
97
|
+
## Tokens consumed
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
--color-primary-default
|
|
101
|
+
--color-primary-hover
|
|
102
|
+
--color-primary-active
|
|
103
|
+
--color-on-primary
|
|
104
|
+
--color-neutral-200
|
|
105
|
+
--color-neutral-300
|
|
106
|
+
--color-text-primary
|
|
107
|
+
--color-error
|
|
108
|
+
--color-error-hover
|
|
109
|
+
--color-success
|
|
110
|
+
--color-warning
|
|
111
|
+
--color-focus-ring
|
|
112
|
+
--space-md
|
|
113
|
+
--space-sm
|
|
114
|
+
--space-lg
|
|
115
|
+
--radius-md
|
|
116
|
+
--font-size-sm
|
|
117
|
+
--font-size-base
|
|
118
|
+
--font-size-lg
|
|
119
|
+
--font-weight-medium
|
|
120
|
+
--transition-fast
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
If any of these don't exist in your token system, **stop and add them before implementing the Button** — don't inline values.
|
|
124
|
+
|
|
125
|
+
## Accessibility
|
|
126
|
+
|
|
127
|
+
- **Semantic**: `<button type="button">` by default. `<a>` if `href` is set. Never `<div onClick>`.
|
|
128
|
+
- **Accessible name**: from `children` (text content). If icon-only, **must** provide `aria-label` (e.g., `aria-label="Close"`).
|
|
129
|
+
- **`aria-disabled="true"`** when `disabled` (in addition to native `disabled` attribute, which removes from tab order and prevents events).
|
|
130
|
+
- **`aria-busy="true"`** when `loading`.
|
|
131
|
+
- **`aria-pressed`** is **not** for regular buttons — that's for toggle buttons. Don't add.
|
|
132
|
+
- **Keyboard**:
|
|
133
|
+
- `Tab` reaches.
|
|
134
|
+
- `Enter` activates.
|
|
135
|
+
- `Space` activates (when rendered as `<button>`, not when rendered as `<a>` — `Space` scrolls anchors).
|
|
136
|
+
- `Escape` does nothing on a button (escapes apply to overlays containing the button).
|
|
137
|
+
- **Focus indicator**: 2px ring with `--color-focus-ring`, 2px offset. Must clear 3:1 against the button's resting background AND against the page background. Cite [knowledge/a11y/contrast.md](../knowledge/a11y/contrast.md).
|
|
138
|
+
- **Touch target**: minimum 44×44 hit area on mobile. If the visual height is `sm` (32px), extend hit area via padding or invisible expanded area.
|
|
139
|
+
- **High contrast mode (Windows)**: ensure border or fill remains visible. Test with `forced-colors: active`.
|
|
140
|
+
- **Reduced motion**: omit fade/scale transitions on hover/active. State changes still happen, just instant.
|
|
141
|
+
- **Screen reader on loading**: announcing "loading" on every Button activation is noisy. Prefer toast/live-region for "Saving…" instead, with the button just becoming `disabled` + visually showing spinner.
|
|
142
|
+
|
|
143
|
+
## Code example
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
// Default — primary CTA
|
|
147
|
+
<Button onClick={handleSave}>
|
|
148
|
+
Save changes
|
|
149
|
+
</Button>
|
|
150
|
+
|
|
151
|
+
// Loading mid-action
|
|
152
|
+
<Button onClick={handleSave} loading={isPending} disabled={isPending}>
|
|
153
|
+
Save changes
|
|
154
|
+
</Button>
|
|
155
|
+
|
|
156
|
+
// Destructive
|
|
157
|
+
<Button intent="danger" onClick={handleDelete}>
|
|
158
|
+
Delete project
|
|
159
|
+
</Button>
|
|
160
|
+
|
|
161
|
+
// Icon-only — REQUIRES aria-label
|
|
162
|
+
<Button variant="ghost" size="sm" aria-label="Close dialog">
|
|
163
|
+
<CloseIcon />
|
|
164
|
+
</Button>
|
|
165
|
+
|
|
166
|
+
// As link (renders <a>, not <button>)
|
|
167
|
+
<Button asChild variant="link">
|
|
168
|
+
<Link to="/pricing">See pricing</Link>
|
|
169
|
+
</Button>
|
|
170
|
+
|
|
171
|
+
// Outline secondary paired with solid primary
|
|
172
|
+
<div className="flex gap-2">
|
|
173
|
+
<Button variant="outline">Cancel</Button>
|
|
174
|
+
<Button>Confirm</Button>
|
|
175
|
+
</div>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Edge cases
|
|
179
|
+
|
|
180
|
+
- **Empty label**: renders nothing visible. Treat as a bug — log warning in dev.
|
|
181
|
+
- **Long label**: by default, the button grows to fit. If the parent constrains width, the label truncates with `…`. Provide `title` attribute for the full text.
|
|
182
|
+
- **`disabled` and `loading` both true**: precedence is `disabled` (no spinner). Document this — surprises if not specified.
|
|
183
|
+
- **Submit form with `Enter`**: the form's first `<button type="submit">` (or first `<button>` if no type) handles it. Always set `type="button"` on non-submit buttons in forms.
|
|
184
|
+
- **Inside a `<a>` parent (don't)**: invalid HTML. Use `asChild` to compose.
|
|
185
|
+
- **RTL**: `iconStart` mirrors to the right, `iconEnd` to the left, padding swaps. CSS logical properties (`padding-inline-start`, etc.) handle this automatically with `dir="rtl"`.
|
|
186
|
+
- **Print**: hidden by default (`@media print { display: none; }`).
|
|
187
|
+
|
|
188
|
+
## Don't
|
|
189
|
+
|
|
190
|
+
- Don't use `intent="primary"` for more than **one** button on a surface.
|
|
191
|
+
- Don't pass an icon as children when also using `iconStart` — pick one approach.
|
|
192
|
+
- Don't disable the only path forward without offering an alternative ("submit" can't just be disabled with no error explanation).
|
|
193
|
+
- Don't use `onClick` to navigate when `href` is appropriate — middle-click and right-click expectations break.
|
|
194
|
+
- Don't put `onClick` on `<a>` — use `<Button>` or wire the link properly.
|
|
195
|
+
- Don't put two solid + primary buttons next to each other. If both are essential, make one `outline`.
|
|
196
|
+
|
|
197
|
+
## References
|
|
198
|
+
|
|
199
|
+
- Ant Design: [`refs/ant-design/components/button/Button.tsx`](../refs/ant-design/components/button/Button.tsx) — most exhaustive prop coverage; uses `type` (legacy) and `variant` (modern) in parallel, with `color` as a separate axis.
|
|
200
|
+
- MUI: [`refs/mui/packages/mui-material/src/Button/Button.d.ts`](../refs/mui/packages/mui-material/src/Button/Button.d.ts) — `variant` (`text`/`outlined`/`contained`), `color` (semantic), `loadingPosition`. The most thoroughly documented.
|
|
201
|
+
- shadcn-ui: [`refs/shadcn-ui/apps/v4/registry/new-york-v4/ui/button.tsx`](../refs/shadcn-ui/apps/v4/registry/new-york-v4/ui/button.tsx) — Tailwind `cva` pattern, `asChild` via Radix Slot, simplest API surface. Inspired the `iconStart`/`iconEnd` and `asChild` choices in this spec.
|
|
202
|
+
|
|
203
|
+
API choices made:
|
|
204
|
+
- **`variant` names**: `solid`/`outline`/`ghost`/`link` over MUI's `text`/`outlined`/`contained` (clearer for non-Material teams) and over Ant's `default`/`dashed`/`text`/`link` (`default` is uninformative).
|
|
205
|
+
- **`intent` over `color`**: `intent` reads as semantic (purpose), `color` reads as visual (which can clash with theme tokens).
|
|
206
|
+
- **`asChild` adopted from shadcn**: cleaner composition with router `<Link>` than MUI's `component` prop.
|
|
207
|
+
- **`loadingPosition` adopted from MUI**: covers a real ergonomic need (don't always want spinner at start).
|
|
208
|
+
|
|
209
|
+
## Cross-reference
|
|
210
|
+
|
|
211
|
+
- [knowledge/components/INDEX.md](../knowledge/components/INDEX.md) — cross-library component index
|
|
212
|
+
- [knowledge/a11y/keyboard-and-focus.md](../knowledge/a11y/keyboard-and-focus.md) — keyboard contract
|
|
213
|
+
- [knowledge/a11y/contrast.md](../knowledge/a11y/contrast.md) — WCAG ratios
|