@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,224 @@
|
|
|
1
|
+
# `Toast` (Snackbar) — spec
|
|
2
|
+
|
|
3
|
+
> Status: example artifact for `component-spec-writer` skill
|
|
4
|
+
> Generated by: `skills/component-spec-writer`, citing Ant Design `message`/`notification`, MUI `Snackbar`, shadcn-ui `sonner`
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
A toast is **transient feedback** about an action — "Saved", "Failed to send", "Copied to clipboard". It doesn't interrupt; it appears, optionally auto-dismisses, doesn't require user input.
|
|
9
|
+
|
|
10
|
+
For interruption requiring decision → use `Modal` / `AlertDialog`.
|
|
11
|
+
For persistent in-page status → use `Alert` / `Banner`.
|
|
12
|
+
|
|
13
|
+
## Anatomy
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
ToastContainer (singleton, portal-mounted, fixed position)
|
|
17
|
+
└── Toast[] (stacked)
|
|
18
|
+
└── Toast
|
|
19
|
+
├── [iconStart]? (status icon by intent: ✓, !, ⚠, ⊘)
|
|
20
|
+
├── Body
|
|
21
|
+
│ ├── Title
|
|
22
|
+
│ └── [Description]?
|
|
23
|
+
├── [Action]? (button — undo, retry, view)
|
|
24
|
+
└── [CloseButton]? (✕, optional)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
| Part | Required | Notes |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| Title | yes | the message; ≤ 60 chars ideal |
|
|
30
|
+
| Description | optional | second line for detail |
|
|
31
|
+
| iconStart | usually | matches intent — provides redundant cue beyond color |
|
|
32
|
+
| Action | optional | one button max ("Undo", "Retry", "View") |
|
|
33
|
+
| CloseButton | optional | always provide for `intent="error"` and persistent toasts |
|
|
34
|
+
|
|
35
|
+
## API
|
|
36
|
+
|
|
37
|
+
| Prop | Type | Default | Description |
|
|
38
|
+
| --- | --- | --- | --- |
|
|
39
|
+
| `title` | `string \| ReactNode` | — | Primary message. Required. |
|
|
40
|
+
| `description` | `string \| ReactNode` | — | Secondary detail line. |
|
|
41
|
+
| `intent` | `"info" \| "success" \| "warning" \| "error"` | `"info"` | Sets icon, color, and ARIA role. |
|
|
42
|
+
| `duration` | `number` | varies by intent (see below) | Auto-dismiss in ms. `0` or `Infinity` = persistent. |
|
|
43
|
+
| `action` | `{ label: string, onClick: () => void }` | — | One action button. |
|
|
44
|
+
| `dismissible` | `boolean` | `true` (always for `error`) | Show ✕ close button. |
|
|
45
|
+
| `position` | `"top-right" \| "top-center" \| "bottom-right" \| "bottom-center" \| "bottom-left" \| "top-left"` | `"bottom-right"` (desktop) / `"top-center"` (mobile) | Container position. |
|
|
46
|
+
| `id` | `string` | auto | For programmatic control (update/dismiss). |
|
|
47
|
+
|
|
48
|
+
Imperative API (canonical):
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
toast(title, options?)
|
|
52
|
+
toast.success(title, options?)
|
|
53
|
+
toast.error(title, options?)
|
|
54
|
+
toast.warning(title, options?)
|
|
55
|
+
toast.info(title, options?)
|
|
56
|
+
toast.loading(title, options?) // returns id
|
|
57
|
+
toast.dismiss(id?) // dismisses one or all
|
|
58
|
+
toast.update(id, options) // updates content (e.g., loading → success)
|
|
59
|
+
|
|
60
|
+
// Promise wrapper — common pattern for async actions
|
|
61
|
+
toast.promise(
|
|
62
|
+
fetchData(),
|
|
63
|
+
{
|
|
64
|
+
loading: 'Saving…',
|
|
65
|
+
success: 'Saved',
|
|
66
|
+
error: 'Could not save',
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This imperative API is **the** convention (sonner, react-hot-toast, ant `message`, MUI `useSnackbar`). Composition-style toasts (`<Toast>...</Toast>` rendered inline) are an anti-pattern — toasts come from any code path, not just JSX.
|
|
72
|
+
|
|
73
|
+
## Default duration by intent
|
|
74
|
+
|
|
75
|
+
| Intent | Duration | Reasoning |
|
|
76
|
+
| --- | --- | --- |
|
|
77
|
+
| `info` | 4000ms | Brief acknowledgement |
|
|
78
|
+
| `success` | 3000ms | Slightly faster — confirms completion, less to read |
|
|
79
|
+
| `warning` | 5000ms | More content typical, give time to absorb |
|
|
80
|
+
| `error` | **Persistent** (`duration: Infinity`) | User must see and dismiss. Never auto-hide errors. |
|
|
81
|
+
| `loading` | Persistent | Updated to success/error via `toast.update`. |
|
|
82
|
+
|
|
83
|
+
Hovering pauses the timer. Resumes when mouse leaves.
|
|
84
|
+
|
|
85
|
+
## States
|
|
86
|
+
|
|
87
|
+
| State | Trigger | Behavior |
|
|
88
|
+
| --- | --- | --- |
|
|
89
|
+
| Entering | toast triggered | slide-in 250ms ease-out from edge, opacity 0→1 |
|
|
90
|
+
| Visible | settled | duration timer ticks; pauses on hover/focus |
|
|
91
|
+
| Action triggered | user clicks action button | optionally auto-dismiss after click |
|
|
92
|
+
| Exiting | timer or click ✕ | slide-out 200ms ease-in, opacity 1→0 |
|
|
93
|
+
| Hidden | unmounted | removed from DOM after exit transition |
|
|
94
|
+
|
|
95
|
+
## Stacking and limits
|
|
96
|
+
|
|
97
|
+
- New toasts stack on top of existing.
|
|
98
|
+
- Max simultaneous: 3–5 (most systems cap at 3). Beyond that, oldest auto-dismisses.
|
|
99
|
+
- Same `id` re-toasted: replaces in place rather than stacking. Useful for "still saving…" updates.
|
|
100
|
+
|
|
101
|
+
## Position behavior
|
|
102
|
+
|
|
103
|
+
- **Desktop**: bottom-right is conventional (least intrusive). Top-right for important info that must be seen.
|
|
104
|
+
- **Mobile**: top-center, full-width minus 16px margin. Avoid bottom-anchored toasts on mobile — fingers cover them when toasting from a tap.
|
|
105
|
+
- **Account for safe-area-inset** on iOS: `padding-bottom: max(16px, env(safe-area-inset-bottom))`.
|
|
106
|
+
|
|
107
|
+
## Tokens consumed
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
--color-bg-elevated
|
|
111
|
+
--color-text-primary
|
|
112
|
+
--color-text-secondary
|
|
113
|
+
--color-success (intent="success")
|
|
114
|
+
--color-warning (intent="warning")
|
|
115
|
+
--color-error (intent="error")
|
|
116
|
+
--color-info (intent="info")
|
|
117
|
+
--color-border-default
|
|
118
|
+
--space-md
|
|
119
|
+
--space-sm
|
|
120
|
+
--radius-md
|
|
121
|
+
--shadow-2
|
|
122
|
+
--motion-default
|
|
123
|
+
--easing-out
|
|
124
|
+
--easing-in
|
|
125
|
+
--z-toast (above modals: typically z-modal + 100)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Accessibility
|
|
129
|
+
|
|
130
|
+
- **Role**:
|
|
131
|
+
- `role="status"` for `info` / `success` (polite — does not interrupt screen reader).
|
|
132
|
+
- `role="alert"` for `warning` / `error` (assertive — interrupts).
|
|
133
|
+
- **`aria-live`** corresponding (`polite` / `assertive`) on the container.
|
|
134
|
+
- **Don't auto-focus** the toast. It's transient feedback, not a modal.
|
|
135
|
+
- **Action button** in the toast: keyboard-reachable when focus is in the page; tab order includes it.
|
|
136
|
+
- **Pause on focus** as well as on hover — for keyboard users tabbing through the page, the toast shouldn't disappear before they reach it.
|
|
137
|
+
- **Close button** must have `aria-label="Dismiss notification"`.
|
|
138
|
+
- **Color is not the only signal**: every toast has an intent icon (`✓` `!` `⚠` `⊘`) — color-blind users see the icon.
|
|
139
|
+
- **Don't put critical info only in toasts**: a toast that auto-dismisses is the wrong place for "Your file failed to save — re-upload required." Make `error` persistent and provide an action.
|
|
140
|
+
|
|
141
|
+
## Code example
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
// Setup at app root
|
|
145
|
+
<ToastContainer position="bottom-right" />
|
|
146
|
+
|
|
147
|
+
// Anywhere in code
|
|
148
|
+
import { toast } from "@/components/toast";
|
|
149
|
+
|
|
150
|
+
// Simple confirmation
|
|
151
|
+
toast.success("Saved");
|
|
152
|
+
|
|
153
|
+
// With description and action
|
|
154
|
+
toast.success("Project deleted", {
|
|
155
|
+
description: "All project data has been removed.",
|
|
156
|
+
action: {
|
|
157
|
+
label: "Undo",
|
|
158
|
+
onClick: () => restoreProject(id),
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Persistent error with action
|
|
163
|
+
toast.error("Could not save", {
|
|
164
|
+
description: "Check your network connection.",
|
|
165
|
+
action: {
|
|
166
|
+
label: "Retry",
|
|
167
|
+
onClick: () => save(),
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Promise wrapper (canonical async pattern)
|
|
172
|
+
toast.promise(saveProject(data), {
|
|
173
|
+
loading: "Saving…",
|
|
174
|
+
success: "Saved",
|
|
175
|
+
error: (err) => `Could not save: ${err.message}`,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Programmatic update (loading → success/error)
|
|
179
|
+
const id = toast.loading("Uploading…");
|
|
180
|
+
upload().then(
|
|
181
|
+
() => toast.success("Uploaded", { id }),
|
|
182
|
+
() => toast.error("Upload failed", { id }),
|
|
183
|
+
);
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Edge cases
|
|
187
|
+
|
|
188
|
+
- **Many toasts at once** (e.g., 10 errors fire in a row from a failed batch operation): collapse to one summary toast — "10 items failed to save. View errors." Don't blast 10 toasts.
|
|
189
|
+
- **User navigates away** mid-toast: toast follows the user (lives in portal at root, persists across routes). Cancel only on full app exit.
|
|
190
|
+
- **Network offline**: don't toast for every retry. One persistent "Connection lost" + auto-resolve when back online.
|
|
191
|
+
- **Toast obscures the action that triggered it**: if user clicks "Save" at the bottom-right, a bottom-right toast covers their next click. Position to the opposite edge of the user's likely next interaction.
|
|
192
|
+
- **Reduced motion**: skip slide-in/out, use opacity-only transition.
|
|
193
|
+
- **Long text**: wrap, don't truncate. Keep on screen until dismissed.
|
|
194
|
+
- **Action and dismissible together**: action button on left of body, ✕ on right. Don't stack actions.
|
|
195
|
+
|
|
196
|
+
## Don't
|
|
197
|
+
|
|
198
|
+
- Don't auto-dismiss errors. Ever. User must acknowledge.
|
|
199
|
+
- Don't use toasts for **decisions**. "Are you sure?" → modal, not toast.
|
|
200
|
+
- Don't show login/signup prompts as toasts.
|
|
201
|
+
- Don't cover the bottom of the screen on mobile with persistent toasts — top-center.
|
|
202
|
+
- Don't make the entire toast clickable. Click target should be the explicit action button, not the toast body — accidental dismissal is otherwise easy.
|
|
203
|
+
- Don't combine `success` and `error` in the same `intent="info"` color — the intent is the cue, not just the message.
|
|
204
|
+
- Don't toast on app load ("Welcome back!"). Friction with no value.
|
|
205
|
+
|
|
206
|
+
## References
|
|
207
|
+
|
|
208
|
+
- Ant Design:
|
|
209
|
+
- [`refs/ant-design/components/message/`](../refs/ant-design/components/message/) — single-line transient messages (closest to "toast").
|
|
210
|
+
- [`refs/ant-design/components/notification/`](../refs/ant-design/components/notification/) — multi-line, with title and description (closest to this spec's full toast). Ant separates these by line count — most other systems combine.
|
|
211
|
+
- MUI: [`refs/mui/packages/mui-material/src/Snackbar/Snackbar.tsx`](../refs/mui/packages/mui-material/src/Snackbar/) — composition-style React component. The least ergonomic of the three for the imperative pattern; pair with `useSnackbar` hook from notistack or build a custom queue.
|
|
212
|
+
- shadcn-ui: [`refs/shadcn-ui/apps/v4/registry/new-york-v4/ui/sonner.tsx`](../refs/shadcn-ui/apps/v4/registry/new-york-v4/ui/sonner.tsx) — wraps `sonner` library. Sonner is the modern de-facto standard; its API (this spec mirrors it) is the cleanest of the three.
|
|
213
|
+
|
|
214
|
+
API choices made:
|
|
215
|
+
- **Imperative API as primary** (`toast.success(...)`) — matches user mental model. Composition (`<Toast>` JSX) is rejected — toasts come from any code path, not from render.
|
|
216
|
+
- **Single component for `info` / `success` / `warning` / `error`** rather than separate `Notification` and `Message` (Ant's split): the line-count distinction is implementation, not interface.
|
|
217
|
+
- **Default-persistent error**: deviates from MUI/Ant defaults but matches user need. Errors auto-hiding silently are how bugs go unnoticed.
|
|
218
|
+
- **`toast.promise` adopted from sonner**: canonical async pattern. Saves consumers from writing the `.then(success).catch(error)` boilerplate.
|
|
219
|
+
|
|
220
|
+
## Cross-reference
|
|
221
|
+
|
|
222
|
+
- [knowledge/motion/principles.md](../knowledge/motion/principles.md) — toast enter/exit timing
|
|
223
|
+
- [knowledge/a11y/keyboard-and-focus.md](../knowledge/a11y/keyboard-and-focus.md) — `role="status"` vs `role="alert"`
|
|
224
|
+
- [WAI-ARIA Live Region documentation](https://www.w3.org/WAI/ARIA/apg/practices/notifications/)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# `ToggleButton` — spec
|
|
2
|
+
|
|
3
|
+
> Synthesized from MUI `ToggleButton`. A button that stays in a "pressed" state when activated, like the formatting buttons in a rich-text editor (B / I / U). Used inside `ToggleButtonGroup` for related options.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
- Single binary toggle (e.g., "show grid").
|
|
8
|
+
- Set of mutually exclusive options (text alignment: left / center / right) — use inside `ToggleButtonGroup` with `exclusive`.
|
|
9
|
+
- Set of multi-select options (text style: bold + italic) — `ToggleButtonGroup` without `exclusive`.
|
|
10
|
+
|
|
11
|
+
## When NOT to use
|
|
12
|
+
|
|
13
|
+
- For two states with text labels (filter chips), use `Chip` with `clickable`.
|
|
14
|
+
- For toggling a setting on/off in a form, use `Switch` (more standard).
|
|
15
|
+
|
|
16
|
+
## Anatomy
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
┌──────┬──────┬──────┐
|
|
20
|
+
│ B │ I │ U │ (pressed = filled bg)
|
|
21
|
+
└──────┴──────┴──────┘
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## API
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
<ToggleButtonGroup
|
|
28
|
+
value={align}
|
|
29
|
+
exclusive
|
|
30
|
+
onChange={(_, v) => v && setAlign(v)}
|
|
31
|
+
aria-label="text alignment"
|
|
32
|
+
>
|
|
33
|
+
<ToggleButton value="left" aria-label="왼쪽 정렬">
|
|
34
|
+
<FormatAlignLeftIcon />
|
|
35
|
+
</ToggleButton>
|
|
36
|
+
<ToggleButton value="center" aria-label="가운데 정렬">
|
|
37
|
+
<FormatAlignCenterIcon />
|
|
38
|
+
</ToggleButton>
|
|
39
|
+
<ToggleButton value="right" aria-label="오른쪽 정렬">
|
|
40
|
+
<FormatAlignRightIcon />
|
|
41
|
+
</ToggleButton>
|
|
42
|
+
</ToggleButtonGroup>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
| Prop | Type | Default | Description |
|
|
46
|
+
| --- | --- | --- | --- |
|
|
47
|
+
| `value` | `any` | required | Identifies this button to the parent group |
|
|
48
|
+
| `selected` | `boolean` | derived | Whether this button is pressed (auto when inside group) |
|
|
49
|
+
| `disabled` | `boolean` | `false` | Non-interactive; greyed |
|
|
50
|
+
| `onChange` | `(e, value) => void` | — | Standalone use; group manages otherwise |
|
|
51
|
+
| `color` | `'standard' \| 'primary' \| 'secondary' \| ...` | `'standard'` | Pressed color |
|
|
52
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | |
|
|
53
|
+
| `aria-label` | `string` | — | Required for icon-only buttons |
|
|
54
|
+
|
|
55
|
+
## States
|
|
56
|
+
|
|
57
|
+
| State | Visual |
|
|
58
|
+
| --- | --- |
|
|
59
|
+
| Default | transparent bg, fg-default border |
|
|
60
|
+
| Hover | bg-subtle |
|
|
61
|
+
| Focus-visible | 2px focus ring |
|
|
62
|
+
| Pressed (selected) | bg-pressed (brand-tinted), fg-on-pressed |
|
|
63
|
+
| Disabled | reduced opacity |
|
|
64
|
+
|
|
65
|
+
## Tokens consumed
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
--toggle-bg-default
|
|
69
|
+
--toggle-bg-hover
|
|
70
|
+
--toggle-bg-pressed /* brand-50 light, brand-900-30 dark */
|
|
71
|
+
--toggle-fg-default
|
|
72
|
+
--toggle-fg-on-pressed
|
|
73
|
+
--toggle-border
|
|
74
|
+
--toggle-min-height-32 /* small */
|
|
75
|
+
--toggle-min-height-40 /* medium — touch-friendly */
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Accessibility
|
|
79
|
+
|
|
80
|
+
- For icon-only: `aria-label` MUST be set ("왼쪽 정렬", not "Left").
|
|
81
|
+
- `aria-pressed` on the button reflects selected state (MUI handles this).
|
|
82
|
+
- Inside `ToggleButtonGroup` with `aria-label`, the group becomes a toolbar; arrow keys navigate between buttons.
|
|
83
|
+
- For exclusive groups, `aria-pressed` shouldn't be all unset — at least one should be pressed (or set `value=null` explicitly).
|
|
84
|
+
|
|
85
|
+
## Edge cases
|
|
86
|
+
|
|
87
|
+
- **Exclusive group with no selection** — possible if `value=null`; user can deselect by clicking the active button. Decide if that's intentional (alignment: probably no — always have one).
|
|
88
|
+
- **Long labels** — switch to text labels with icons. Avoid mixing icon-only and text-only in the same group.
|
|
89
|
+
- **Disabled subset** — possible per-button, but visually confusing if scattered. Prefer disabling the entire group.
|
|
90
|
+
|
|
91
|
+
## Code example
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
function TextStyleToolbar({ formats, onChange }) {
|
|
95
|
+
return (
|
|
96
|
+
<ToggleButtonGroup
|
|
97
|
+
value={formats}
|
|
98
|
+
onChange={(_, next) => onChange(next)}
|
|
99
|
+
aria-label="텍스트 스타일"
|
|
100
|
+
>
|
|
101
|
+
<ToggleButton value="bold" aria-label="굵게">
|
|
102
|
+
<FormatBoldIcon />
|
|
103
|
+
</ToggleButton>
|
|
104
|
+
<ToggleButton value="italic" aria-label="기울임">
|
|
105
|
+
<FormatItalicIcon />
|
|
106
|
+
</ToggleButton>
|
|
107
|
+
<ToggleButton value="underline" aria-label="밑줄">
|
|
108
|
+
<FormatUnderlinedIcon />
|
|
109
|
+
</ToggleButton>
|
|
110
|
+
</ToggleButtonGroup>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Don't
|
|
116
|
+
|
|
117
|
+
- Don't put 6+ ToggleButtons in a row — overflow into a menu.
|
|
118
|
+
- Don't use as a primary CTA — it's a setting control, not an action.
|
|
119
|
+
- Don't omit `aria-label` for icon-only.
|
|
120
|
+
|
|
121
|
+
## References
|
|
122
|
+
|
|
123
|
+
- MUI: [`ToggleButton`](../refs/mui/packages/mui-material/src/ToggleButton/) + [`ToggleButtonGroup`](../refs/mui/packages/mui-material/src/ToggleButtonGroup/)
|
|
124
|
+
|
|
125
|
+
## Cross-reference
|
|
126
|
+
|
|
127
|
+
- [`component-button.md`](component-button.md)
|
|
128
|
+
- [`component-toggle.md`](component-toggle.md)
|
|
129
|
+
- [`component-switch.md`](component-switch.md)
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# `Toggle` and `ToggleGroup` — spec
|
|
2
|
+
|
|
3
|
+
> Synthesized from shadcn-ui `toggle` + `toggle-group` (Radix). A two-state pressable button. `Toggle` is single; `ToggleGroup` is a set of mutually exclusive (radio) or independent (checkbox) toggles.
|
|
4
|
+
|
|
5
|
+
## Toggle vs Switch vs Checkbox
|
|
6
|
+
|
|
7
|
+
| | Toggle | Switch | Checkbox |
|
|
8
|
+
| --- | --- | --- | --- |
|
|
9
|
+
| Visual | Button-like | iOS slider | Square box + check |
|
|
10
|
+
| Use | Bold/italic in editor; pressable filter chips | On/off setting | Form selection / accept |
|
|
11
|
+
| Affordance | "Press" | "Slide" | "Check" |
|
|
12
|
+
| State | Pressed / unpressed | On / off | Checked / unchecked |
|
|
13
|
+
| Form? | No | Yes (input semantics) | Yes (input semantics) |
|
|
14
|
+
|
|
15
|
+
Toggle is for **interactive controls** in toolbars and editors. Switch is for **settings**. Checkbox is for **forms**.
|
|
16
|
+
|
|
17
|
+
## Toggle anatomy
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
[ B ] [ I ] [ U ] <- toolbar with 3 toggles
|
|
21
|
+
↑ pressed (B is bold-toggled on)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## API — Toggle
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
<Toggle
|
|
28
|
+
pressed={isBold}
|
|
29
|
+
onPressedChange={setIsBold}
|
|
30
|
+
aria-label="Toggle bold"
|
|
31
|
+
>
|
|
32
|
+
<BoldIcon />
|
|
33
|
+
</Toggle>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
| Prop | Type | Default | Description |
|
|
37
|
+
| --- | --- | --- | --- |
|
|
38
|
+
| `pressed` | `boolean` | controlled | Pressed state |
|
|
39
|
+
| `defaultPressed` | `boolean` | `false` | Uncontrolled initial |
|
|
40
|
+
| `onPressedChange` | `(pressed: boolean) => void` | — | Callback |
|
|
41
|
+
| `disabled` | `boolean` | `false` | Disabled |
|
|
42
|
+
| `variant` | `"default" \| "outline"` | `"default"` | Visual style |
|
|
43
|
+
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size |
|
|
44
|
+
| `aria-label` | `string` | required (for icon-only) | Accessible label |
|
|
45
|
+
|
|
46
|
+
## ToggleGroup anatomy
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
[ Left | Center | Right ] ← single-select (one active)
|
|
50
|
+
↑ Center pressed
|
|
51
|
+
|
|
52
|
+
[ B ] [ I ] [ U ] ← multi-select (multiple can be pressed)
|
|
53
|
+
↑ B and I both pressed
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## API — ToggleGroup
|
|
57
|
+
|
|
58
|
+
### Single
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
<ToggleGroup type="single" value={align} onValueChange={setAlign}>
|
|
62
|
+
<ToggleGroup.Item value="left" aria-label="Align left"><AlignLeftIcon /></ToggleGroup.Item>
|
|
63
|
+
<ToggleGroup.Item value="center" aria-label="Align center"><AlignCenterIcon /></ToggleGroup.Item>
|
|
64
|
+
<ToggleGroup.Item value="right" aria-label="Align right"><AlignRightIcon /></ToggleGroup.Item>
|
|
65
|
+
</ToggleGroup>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Multiple
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
<ToggleGroup type="multiple" value={formatting} onValueChange={setFormatting}>
|
|
72
|
+
<ToggleGroup.Item value="bold" aria-label="Bold"><BoldIcon /></ToggleGroup.Item>
|
|
73
|
+
<ToggleGroup.Item value="italic" aria-label="Italic"><ItalicIcon /></ToggleGroup.Item>
|
|
74
|
+
<ToggleGroup.Item value="underline" aria-label="Underline"><UnderlineIcon /></ToggleGroup.Item>
|
|
75
|
+
</ToggleGroup>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
| Prop | Type | Default | Description |
|
|
79
|
+
| --- | --- | --- | --- |
|
|
80
|
+
| `type` | `"single" \| "multiple"` | required | Selection model |
|
|
81
|
+
| `value` | `string \| string[]` | controlled | Selected values |
|
|
82
|
+
| `onValueChange` | function | — | Callback (signature depends on type) |
|
|
83
|
+
| `disabled` | `boolean` | `false` | Disable all items |
|
|
84
|
+
| `variant` | `"default" \| "outline"` | `"default"` | Visual style |
|
|
85
|
+
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size |
|
|
86
|
+
|
|
87
|
+
## Variants
|
|
88
|
+
|
|
89
|
+
### `default`
|
|
90
|
+
|
|
91
|
+
Filled when pressed; transparent when not.
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
Idle: [ B ] (transparent)
|
|
95
|
+
Pressed: [ B ] (brand-colored bg)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### `outline`
|
|
99
|
+
|
|
100
|
+
Bordered when not pressed; bordered + filled when pressed.
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
Idle: [ B ] (border + bg-secondary)
|
|
104
|
+
Pressed: [ B ] (border + brand-bg)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## States
|
|
108
|
+
|
|
109
|
+
| State | Visual |
|
|
110
|
+
| --- | --- |
|
|
111
|
+
| Idle | Per variant |
|
|
112
|
+
| Hover | Bg shifts subtly |
|
|
113
|
+
| Focus-visible | 2px focus ring |
|
|
114
|
+
| Pressed (active) | Persistent visual indicating "on" state |
|
|
115
|
+
| Disabled | Reduced opacity, no events |
|
|
116
|
+
|
|
117
|
+
Don't confuse "active" (pressed-on) with "active" (mid-press). They're different states.
|
|
118
|
+
|
|
119
|
+
## Tokens consumed
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
--color-bg-default
|
|
123
|
+
--color-bg-secondary (outline idle bg)
|
|
124
|
+
--color-bg-hover
|
|
125
|
+
--color-bg-pressed (when toggled-on)
|
|
126
|
+
--color-fg-default
|
|
127
|
+
--color-fg-on-pressed
|
|
128
|
+
--color-border-default (outline)
|
|
129
|
+
--radius-md
|
|
130
|
+
--space-xs, --space-sm
|
|
131
|
+
--font-size-sm
|
|
132
|
+
--motion-fast
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Accessibility
|
|
136
|
+
|
|
137
|
+
### Toggle
|
|
138
|
+
|
|
139
|
+
- `<button>` with `aria-pressed="true|false"`.
|
|
140
|
+
- Icon-only: `aria-label` required.
|
|
141
|
+
- Touch target ≥ 24×24 (web) / 44×44 (mobile primary).
|
|
142
|
+
- Focus-visible ring.
|
|
143
|
+
|
|
144
|
+
### ToggleGroup
|
|
145
|
+
|
|
146
|
+
- `role="group"` with `aria-label="<purpose>"`.
|
|
147
|
+
- For `type="single"`: items use `role="radio"` + `aria-checked`. Treat as radio group.
|
|
148
|
+
- For `type="multiple"`: items use `role="button"` + `aria-pressed`.
|
|
149
|
+
- Keyboard:
|
|
150
|
+
- Tab into group focuses first.
|
|
151
|
+
- Arrow keys navigate (single-select moves selection; multi-select moves focus).
|
|
152
|
+
- Space / Enter toggles.
|
|
153
|
+
|
|
154
|
+
## Code example — Editor toolbar
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
function EditorToolbar({ editor }: Props) {
|
|
158
|
+
return (
|
|
159
|
+
<div className="toolbar">
|
|
160
|
+
<ToggleGroup type="multiple" value={editor.activeFormats} onValueChange={editor.setFormats}>
|
|
161
|
+
<ToggleGroup.Item value="bold" aria-label="굵게">
|
|
162
|
+
<BoldIcon />
|
|
163
|
+
</ToggleGroup.Item>
|
|
164
|
+
<ToggleGroup.Item value="italic" aria-label="기울임">
|
|
165
|
+
<ItalicIcon />
|
|
166
|
+
</ToggleGroup.Item>
|
|
167
|
+
<ToggleGroup.Item value="underline" aria-label="밑줄">
|
|
168
|
+
<UnderlineIcon />
|
|
169
|
+
</ToggleGroup.Item>
|
|
170
|
+
</ToggleGroup>
|
|
171
|
+
|
|
172
|
+
<Separator orientation="vertical" />
|
|
173
|
+
|
|
174
|
+
<ToggleGroup type="single" value={editor.alignment} onValueChange={editor.setAlignment}>
|
|
175
|
+
<ToggleGroup.Item value="left" aria-label="왼쪽 정렬"><AlignLeftIcon /></ToggleGroup.Item>
|
|
176
|
+
<ToggleGroup.Item value="center" aria-label="가운데 정렬"><AlignCenterIcon /></ToggleGroup.Item>
|
|
177
|
+
<ToggleGroup.Item value="right" aria-label="오른쪽 정렬"><AlignRightIcon /></ToggleGroup.Item>
|
|
178
|
+
</ToggleGroup>
|
|
179
|
+
</div>
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Korean labels
|
|
185
|
+
|
|
186
|
+
For toolbar icons:
|
|
187
|
+
- 굵게 (bold) / 기울임 (italic) / 밑줄 (underline) / 취소선 (strikethrough)
|
|
188
|
+
- 왼쪽 / 가운데 / 오른쪽 / 양쪽 정렬
|
|
189
|
+
- 글머리 기호 (bullet list) / 번호 매기기 (numbered list)
|
|
190
|
+
|
|
191
|
+
Pretendard for label / Korean text in `aria-label`.
|
|
192
|
+
|
|
193
|
+
## Edge cases
|
|
194
|
+
|
|
195
|
+
- **No selection in single-select**: allow empty value (no item pressed). Some UIs require always-one — set initial value.
|
|
196
|
+
- **All items disabled**: group still rendered for layout; aria-label communicates state.
|
|
197
|
+
- **Loading state**: typically disable while async toggle pending; show spinner inside.
|
|
198
|
+
- **Confirmation needed for destructive toggle**: don't fire on click; open confirmation dialog first.
|
|
199
|
+
- **Tooltip integration**: pair Toggle with Tooltip for icon-only buttons.
|
|
200
|
+
- **RTL**: text-direction-aware alignment toggles flip meaning (left ↔ right) but keep visual order.
|
|
201
|
+
|
|
202
|
+
## Don't
|
|
203
|
+
|
|
204
|
+
- Don't use Toggle for form submission state. That's Switch.
|
|
205
|
+
- Don't omit `aria-label` on icon-only Toggle.
|
|
206
|
+
- Don't make the pressed state too subtle (need clear visual difference).
|
|
207
|
+
- Don't put 10+ items in a single ToggleGroup. Split or use a dropdown.
|
|
208
|
+
- Don't conflate Toggle with Button — Toggle has persistent state.
|
|
209
|
+
- Don't disable focus outline.
|
|
210
|
+
|
|
211
|
+
## References
|
|
212
|
+
|
|
213
|
+
- shadcn-ui: [`toggle`](../refs/shadcn-ui/apps/v4/registry/new-york-v4/ui/toggle.tsx), [`toggle-group`](../refs/shadcn-ui/apps/v4/registry/new-york-v4/ui/toggle-group.tsx) (Radix)
|
|
214
|
+
- WAI-ARIA: [Toggle button](https://www.w3.org/WAI/ARIA/apg/patterns/button/) + [Radio group](https://www.w3.org/WAI/ARIA/apg/patterns/radio/)
|
|
215
|
+
|
|
216
|
+
## Cross-reference
|
|
217
|
+
|
|
218
|
+
- [`examples/component-form-controls.md`](component-form-controls.md) — Switch + Checkbox + Radio
|
|
219
|
+
- [`examples/component-segmented.md`](component-segmented.md) — segmented control variant
|
|
220
|
+
- [`examples/component-button.md`](component-button.md) — non-toggle variant
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# `Toolbar` — spec
|
|
2
|
+
|
|
3
|
+
> Synthesized from MUI `Toolbar`. A horizontal container for buttons + controls — the action row in app bars, editors, dialog footers.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
- Top-bar toolbar in app shells (next to logo).
|
|
8
|
+
- Editor / canvas toolbar (formatting buttons, tools).
|
|
9
|
+
- Dialog action footers (Confirm / Cancel buttons).
|
|
10
|
+
- Anywhere a horizontal cluster of related controls lives.
|
|
11
|
+
|
|
12
|
+
When NOT to use:
|
|
13
|
+
- Single button (use Button alone).
|
|
14
|
+
- Navigation menus (use NavigationMenu / Menubar).
|
|
15
|
+
|
|
16
|
+
## Anatomy
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
[Logo] [⚙][↶][↷][·][B][I][U][·][🔗] [Save] [Close]
|
|
20
|
+
left center right
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Three slots: leading / main / trailing. Items spaced via gap or `space-between` justification.
|
|
24
|
+
|
|
25
|
+
## API
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
<Toolbar>
|
|
29
|
+
<IconButton aria-label="설정"><SettingsIcon /></IconButton>
|
|
30
|
+
<IconButton aria-label="실행 취소"><UndoIcon /></IconButton>
|
|
31
|
+
<Separator orientation="vertical" />
|
|
32
|
+
<ToggleGroup type="multiple">
|
|
33
|
+
<ToggleGroup.Item value="bold"><BoldIcon /></ToggleGroup.Item>
|
|
34
|
+
<ToggleGroup.Item value="italic"><ItalicIcon /></ToggleGroup.Item>
|
|
35
|
+
</ToggleGroup>
|
|
36
|
+
<Box flex={1} /> {/* push right */}
|
|
37
|
+
<Button>Save</Button>
|
|
38
|
+
</Toolbar>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
| Prop | Type | Default | Description |
|
|
42
|
+
| --- | --- | --- | --- |
|
|
43
|
+
| `variant` | `"default" \| "compact" \| "dense"` | `"default"` | Padding density |
|
|
44
|
+
| `disableGutters` | `boolean` | `false` | Remove horizontal padding |
|
|
45
|
+
| `as` | element | `"div"` | Render as |
|
|
46
|
+
|
|
47
|
+
## States
|
|
48
|
+
|
|
49
|
+
Stateless. Children carry their own states.
|
|
50
|
+
|
|
51
|
+
## Tokens consumed
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
--toolbar-bg
|
|
55
|
+
--toolbar-fg
|
|
56
|
+
--toolbar-border-bottom (when used as app bar)
|
|
57
|
+
--toolbar-min-height (typically 56-64px)
|
|
58
|
+
--space-sm (item gap)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Accessibility
|
|
62
|
+
|
|
63
|
+
- `role="toolbar" aria-label="..."` on the Toolbar wrapper. Required.
|
|
64
|
+
- Each child remains independently focusable.
|
|
65
|
+
- Roving tabindex (optional): only one child tabbable at a time; arrow keys move focus among children. Standard for editor toolbars.
|
|
66
|
+
- Touch target ≥ 44pt for primary mobile.
|
|
67
|
+
|
|
68
|
+
## Korean labels
|
|
69
|
+
|
|
70
|
+
- 도구 모음 (toolbar) — Korean term, rarely user-visible
|
|
71
|
+
- 편집 / 보기 / 삽입 — typical menu / toolbar action names
|
|
72
|
+
- aria-label in Korean for icon-only buttons
|
|
73
|
+
|
|
74
|
+
## Code example — editor toolbar
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
<Toolbar role="toolbar" aria-label="텍스트 서식">
|
|
78
|
+
<IconButton aria-label="실행 취소" onClick={undo}><UndoIcon /></IconButton>
|
|
79
|
+
<IconButton aria-label="다시 실행" onClick={redo}><RedoIcon /></IconButton>
|
|
80
|
+
<Separator orientation="vertical" />
|
|
81
|
+
<ToggleGroup type="multiple" value={formats} onValueChange={setFormats}>
|
|
82
|
+
<ToggleGroup.Item value="bold" aria-label="굵게"><BoldIcon /></ToggleGroup.Item>
|
|
83
|
+
<ToggleGroup.Item value="italic" aria-label="기울임"><ItalicIcon /></ToggleGroup.Item>
|
|
84
|
+
<ToggleGroup.Item value="underline" aria-label="밑줄"><UnderlineIcon /></ToggleGroup.Item>
|
|
85
|
+
</ToggleGroup>
|
|
86
|
+
</Toolbar>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Don't
|
|
90
|
+
|
|
91
|
+
- Don't omit `role="toolbar"` for accessibility.
|
|
92
|
+
- Don't pile up 20+ controls — group via overflow menu.
|
|
93
|
+
- Don't make Toolbar height inconsistent across pages.
|
|
94
|
+
|
|
95
|
+
## References
|
|
96
|
+
|
|
97
|
+
- MUI: [`Toolbar`](../refs/mui/packages/mui-material/src/Toolbar)
|
|
98
|
+
- WAI-ARIA: [Toolbar pattern](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/)
|
|
99
|
+
|
|
100
|
+
## Cross-reference
|
|
101
|
+
|
|
102
|
+
- [`examples/component-app-bar.md`](component-app-bar.md) — top app bar pattern
|
|
103
|
+
- [`examples/component-button-group.md`](component-button-group.md) — joined button cluster
|
|
104
|
+
- [`examples/component-toggle.md`](component-toggle.md) — formatting toggles
|