@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,173 @@
|
|
|
1
|
+
# `Spin` (Spinner) — spec
|
|
2
|
+
|
|
3
|
+
> Citing Ant Design `Spin`, MUI `CircularProgress` (used as spinner), shadcn-ui (composition)
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
A simple loading indicator. **Indeterminate spinner** for "something is happening, no progress %." Different from `Progress` (percentage-based) and `Skeleton` (content-shape).
|
|
8
|
+
|
|
9
|
+
## When Spin vs Skeleton vs Progress
|
|
10
|
+
|
|
11
|
+
| Use Spin | Use Skeleton | Use Progress |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| Async action with no shape (button submit, modal opening) | Page/list initial load (you know the shape) | Determinate operation (upload %, multi-step) |
|
|
14
|
+
| Brief (< 2s) waiting | Longer (1s+) load | Any duration with % known |
|
|
15
|
+
|
|
16
|
+
## Anatomy
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Standalone: With overlay:
|
|
20
|
+
⟳ ┌─────────────────┐
|
|
21
|
+
│ ⟳ │
|
|
22
|
+
│ "로딩 중..." │
|
|
23
|
+
│ │
|
|
24
|
+
└─────────────────┘
|
|
25
|
+
(content faded behind)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
| Slot | Required | Notes |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| Spinner | yes | Rotating circular indicator |
|
|
31
|
+
| Tip / label | optional | "로딩 중..." text |
|
|
32
|
+
| Overlay | optional | Fades the wrapped content |
|
|
33
|
+
| Children | optional | Wrapped element (Spin can wrap content to overlay loading) |
|
|
34
|
+
|
|
35
|
+
## API
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
// Standalone
|
|
39
|
+
<Spin size="md" />
|
|
40
|
+
<Spin tip="로딩 중..." />
|
|
41
|
+
|
|
42
|
+
// Wrapping content
|
|
43
|
+
<Spin spinning={isLoading}>
|
|
44
|
+
<DataTable data={data} />
|
|
45
|
+
</Spin>
|
|
46
|
+
|
|
47
|
+
// Inside a button (rare — buttons have their own loading)
|
|
48
|
+
<Button loading><Spin size="sm" /></Button>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
| Prop | Type | Default | Description |
|
|
52
|
+
| --- | --- | --- | --- |
|
|
53
|
+
| `spinning` | `boolean` | `true` | Whether to show |
|
|
54
|
+
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Spinner size |
|
|
55
|
+
| `tip` | `string` | — | Optional label |
|
|
56
|
+
| `delay` | `number` | `0` | Show only after N ms (avoids flash for fast loads) |
|
|
57
|
+
| `children` | `ReactNode` | — | Wrapped content (gets overlay) |
|
|
58
|
+
| `indicator` | `ReactNode` | default circular | Custom spinner |
|
|
59
|
+
|
|
60
|
+
## Sizes
|
|
61
|
+
|
|
62
|
+
| Size | Diameter | Use |
|
|
63
|
+
| --- | --- | --- |
|
|
64
|
+
| `sm` | 16px | Inline (button, badge) |
|
|
65
|
+
| `md` (default) | 24px | Standard inline |
|
|
66
|
+
| `lg` | 40px | Page-level loading |
|
|
67
|
+
|
|
68
|
+
## Animation
|
|
69
|
+
|
|
70
|
+
Standard spinner: `360°` rotation, 1000ms loop, linear easing.
|
|
71
|
+
|
|
72
|
+
```css
|
|
73
|
+
@keyframes spin {
|
|
74
|
+
from { transform: rotate(0deg); }
|
|
75
|
+
to { transform: rotate(360deg); }
|
|
76
|
+
}
|
|
77
|
+
.spinner {
|
|
78
|
+
animation: spin 1000ms linear infinite;
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
For Material 3 style: arc length also varies (10–80%) for a "pulsing" feel. More expensive; default static-arc spinner is fine.
|
|
83
|
+
|
|
84
|
+
## States
|
|
85
|
+
|
|
86
|
+
| State | Visual |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| Spinning (active) | Animated rotation |
|
|
89
|
+
| Stopped (`spinning={false}`) | Hidden (or unmounted) |
|
|
90
|
+
| Delayed (`delay > 0`) | Hidden until delay elapses |
|
|
91
|
+
|
|
92
|
+
## Accessibility
|
|
93
|
+
|
|
94
|
+
- Wrap with `aria-busy="true"` on the loading container.
|
|
95
|
+
- The spinner itself: `aria-hidden="true"` (decorative).
|
|
96
|
+
- Provide `aria-label` on the wrapper if tip is missing: "Loading...".
|
|
97
|
+
- Don't announce "Loading" repeatedly via `aria-live` — single announcement at start of load.
|
|
98
|
+
|
|
99
|
+
```html
|
|
100
|
+
<div aria-busy="true" aria-live="polite" aria-label="데이터 로딩 중">
|
|
101
|
+
<span class="spin" aria-hidden="true">⟳</span>
|
|
102
|
+
</div>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
For `delay` > 0: don't show the spinner OR announce until the delay elapses. Avoids flash for fast loads.
|
|
106
|
+
|
|
107
|
+
## Reduced motion
|
|
108
|
+
|
|
109
|
+
```css
|
|
110
|
+
@media (prefers-reduced-motion: reduce) {
|
|
111
|
+
.spinner { animation: none; }
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
When motion disabled: spinner is static. Provide a text label or different non-animated indicator (dots fading, etc.). Don't leave a static rotated icon — looks broken.
|
|
116
|
+
|
|
117
|
+
## Tokens consumed
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
--color-primary-default (default spinner color)
|
|
121
|
+
--color-text-secondary (tip text)
|
|
122
|
+
--color-bg-overlay (overlay when wrapping content)
|
|
123
|
+
--space-sm
|
|
124
|
+
--motion-default (rotation period; though linear loop ignores easing)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Code example
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
// Inline spinner
|
|
131
|
+
<div>
|
|
132
|
+
<Spin /> 데이터를 불러오는 중...
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
// Wrapping a list
|
|
136
|
+
<Spin spinning={isLoading} tip="저장하는 중...">
|
|
137
|
+
<Form>
|
|
138
|
+
{/* form content */}
|
|
139
|
+
</Form>
|
|
140
|
+
</Spin>
|
|
141
|
+
|
|
142
|
+
// With delay (avoid flash)
|
|
143
|
+
<Spin spinning={isLoading} delay={200} />
|
|
144
|
+
{/* Spinner appears only if loading takes > 200ms */}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Edge cases
|
|
148
|
+
|
|
149
|
+
- **Delay vs no delay**: for sub-200ms loads, don't show spinner at all (avoid flicker). Use `delay: 200` to gate.
|
|
150
|
+
- **Spin wrapping a tall scrollable**: overlay covers visible viewport; spinner centered. Don't anchor to top.
|
|
151
|
+
- **Multiple Spin on screen**: collapse into one spinner if they all represent the same operation.
|
|
152
|
+
- **Reduced motion**: spinner is static; text "로딩 중..." carries the meaning.
|
|
153
|
+
- **Custom indicator** (animated logo, etc.): provide via `indicator` prop. Don't violate reduced-motion preference.
|
|
154
|
+
|
|
155
|
+
## Don't
|
|
156
|
+
|
|
157
|
+
- Don't use Spin for known-shape content. Use Skeleton.
|
|
158
|
+
- Don't use Spin for known-percentage operation. Use Progress.
|
|
159
|
+
- Don't show Spin without context. Pair with text or place it where the content will land.
|
|
160
|
+
- Don't auto-show spinner on every interaction. Sub-200ms loads don't need spinner.
|
|
161
|
+
- Don't omit reduced-motion handling.
|
|
162
|
+
|
|
163
|
+
## References
|
|
164
|
+
|
|
165
|
+
- Ant Design: [`refs/ant-design/components/spin/`](../refs/ant-design/components/spin/) — `Spin`. Standard spinner with `tip`, `delay`, `wrapperClassName`.
|
|
166
|
+
- MUI: [`CircularProgress`](../refs/mui/packages/mui-material/src/CircularProgress/) (Material's equivalent). Same role.
|
|
167
|
+
- shadcn-ui: no built-in. Use Lucide's `Loader2` icon with CSS spin.
|
|
168
|
+
|
|
169
|
+
## Cross-reference
|
|
170
|
+
|
|
171
|
+
- [`examples/component-skeleton.md`](component-skeleton.md) — for known-shape loading
|
|
172
|
+
- [`examples/component-progress.md`](component-progress.md) — for percentage operations
|
|
173
|
+
- [`knowledge/motion/principles.md`](../knowledge/motion/principles.md) — reduced motion
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# `Spinner` — spec
|
|
2
|
+
|
|
3
|
+
> Synthesized from MUI `CircularProgress` (indeterminate variant) and shadcn-ui's spinner pattern. Indeterminate loading indicator — a small rotating circle / ring used inline or as a centered loading state.
|
|
4
|
+
|
|
5
|
+
## Spinner vs Progress vs Skeleton
|
|
6
|
+
|
|
7
|
+
> Pick the right loading affordance for the situation.
|
|
8
|
+
|
|
9
|
+
| | Spinner | Progress | Skeleton |
|
|
10
|
+
| --- | --- | --- | --- |
|
|
11
|
+
| Determinate? | No | Yes | No |
|
|
12
|
+
| Use | Brief loads; intermediate state | Long operations with measurable progress | Layout-aware "content is coming" |
|
|
13
|
+
| Where | Buttons, inline within content | Section / page-level, file uploads | Cards, lists, full pages |
|
|
14
|
+
| Duration | < 1-2s typical | 1-30s+ | Until content arrives |
|
|
15
|
+
|
|
16
|
+
For "I'm doing something briefly" → Spinner. For "X% done" → Progress. For "preserve layout while loading" → Skeleton.
|
|
17
|
+
|
|
18
|
+
## Anatomy
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
◜◝
|
|
22
|
+
◟◞ ← rotating partial-arc
|
|
23
|
+
|
|
24
|
+
[Loading...] ← optional adjacent text
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## API
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
<Spinner />
|
|
31
|
+
<Spinner size="sm" />
|
|
32
|
+
<Spinner size="lg" />
|
|
33
|
+
|
|
34
|
+
<Spinner aria-label="Loading data" />
|
|
35
|
+
|
|
36
|
+
<Spinner color="brand" />
|
|
37
|
+
<Spinner color="muted" />
|
|
38
|
+
|
|
39
|
+
<Button loading>Save</Button> {/* Spinner inside button */}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
| Prop | Type | Default | Description |
|
|
43
|
+
| --- | --- | --- | --- |
|
|
44
|
+
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Diameter |
|
|
45
|
+
| `color` | `"brand" \| "muted" \| "current" \| "white"` | `"current"` | Color |
|
|
46
|
+
| `aria-label` | `string` | `"Loading"` | Screen-reader label |
|
|
47
|
+
| `speed` | `"slow" \| "normal" \| "fast"` | `"normal"` | Rotation duration |
|
|
48
|
+
|
|
49
|
+
## Sizes
|
|
50
|
+
|
|
51
|
+
| Size | Diameter | Use |
|
|
52
|
+
| --- | --- | --- |
|
|
53
|
+
| `xs` | 12px | Inline within text, very compact |
|
|
54
|
+
| `sm` | 16px | Inside small buttons, beside text |
|
|
55
|
+
| `md` (default) | 24px | Inline within content, default buttons |
|
|
56
|
+
| `lg` | 32px | Section-level loading |
|
|
57
|
+
| `xl` | 48px | Page-level loading |
|
|
58
|
+
|
|
59
|
+
For most cases: `sm` for inline, `md` for component-level, `lg` for full-section. Avoid going larger — use Skeleton instead.
|
|
60
|
+
|
|
61
|
+
## Variants
|
|
62
|
+
|
|
63
|
+
### Color
|
|
64
|
+
|
|
65
|
+
- `current` (default): inherits from text color (`color: currentColor`).
|
|
66
|
+
- `brand`: brand color.
|
|
67
|
+
- `muted`: gray.
|
|
68
|
+
- `white`: explicit white (for use on dark / colored backgrounds, e.g., inside primary button).
|
|
69
|
+
|
|
70
|
+
### Speed
|
|
71
|
+
|
|
72
|
+
- `slow`: 1.5s rotation (calm; for premium / luxury feel).
|
|
73
|
+
- `normal` (default): 0.8-1s rotation.
|
|
74
|
+
- `fast`: 0.5s rotation (urgent, snappy feedback).
|
|
75
|
+
|
|
76
|
+
## States
|
|
77
|
+
|
|
78
|
+
Stateless. Spinner is always animating (when rendered).
|
|
79
|
+
|
|
80
|
+
For "stop spinning + show success": un-render the Spinner; render a check icon instead. Don't try to morph the spinner.
|
|
81
|
+
|
|
82
|
+
## Tokens consumed
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
--color-fg-default (current)
|
|
86
|
+
--color-brand-default (brand variant)
|
|
87
|
+
--color-fg-muted (muted)
|
|
88
|
+
--motion-spinner-duration (typically 1s)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## CSS
|
|
92
|
+
|
|
93
|
+
```css
|
|
94
|
+
@keyframes spin {
|
|
95
|
+
from { transform: rotate(0deg); }
|
|
96
|
+
to { transform: rotate(360deg); }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.spinner {
|
|
100
|
+
display: inline-block;
|
|
101
|
+
width: var(--spinner-size);
|
|
102
|
+
height: var(--spinner-size);
|
|
103
|
+
border: 2px solid currentColor;
|
|
104
|
+
border-top-color: transparent;
|
|
105
|
+
border-radius: 50%;
|
|
106
|
+
animation: spin 1s linear infinite;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@media (prefers-reduced-motion: reduce) {
|
|
110
|
+
.spinner {
|
|
111
|
+
animation: spin 2s linear infinite; /* Slower; or none entirely */
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
For SVG-based spinner (more flexible coloring / variants):
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
<svg className="spinner" viewBox="0 0 24 24" fill="none">
|
|
120
|
+
<circle cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="2" opacity="0.25" />
|
|
121
|
+
<path d="M2 12 a10 10 0 0 1 10-10" stroke="currentColor" strokeWidth="2" />
|
|
122
|
+
</svg>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Accessibility
|
|
126
|
+
|
|
127
|
+
- `role="status"` (preferred) OR `role="progressbar" aria-valuenow="0"` (less common for indeterminate).
|
|
128
|
+
- `aria-label` (default "Loading") for screen readers.
|
|
129
|
+
- For very brief loads (< 500ms): consider hiding the Spinner from screen readers (`aria-hidden`) — repeated "Loading" announcements are noise.
|
|
130
|
+
- For longer loads: include text content adjacent ("Loading data...") so users with reduced-motion who don't see spinning still get feedback.
|
|
131
|
+
- Reduced motion: slow the rotation OR replace with static dots.
|
|
132
|
+
|
|
133
|
+
## Inside buttons
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
<Button loading>
|
|
137
|
+
{loading && <Spinner size="sm" color="current" />}
|
|
138
|
+
Save
|
|
139
|
+
</Button>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
When button is loading:
|
|
143
|
+
- Spinner replaces (or sits beside) the icon.
|
|
144
|
+
- Button is disabled (`aria-disabled`).
|
|
145
|
+
- Label may be replaced ("Saving...") OR kept (with spinner before it).
|
|
146
|
+
|
|
147
|
+
## Code example
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
function SaveButton() {
|
|
151
|
+
const [saving, setSaving] = useState(false);
|
|
152
|
+
|
|
153
|
+
return (
|
|
154
|
+
<Button onClick={async () => { setSaving(true); await save(); setSaving(false); }} disabled={saving}>
|
|
155
|
+
{saving && <Spinner size="sm" />}
|
|
156
|
+
{saving ? "저장 중..." : "저장"}
|
|
157
|
+
</Button>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function DataTable() {
|
|
162
|
+
if (loading) {
|
|
163
|
+
return (
|
|
164
|
+
<div className="table-loading">
|
|
165
|
+
<Spinner size="lg" />
|
|
166
|
+
<p>데이터를 불러오는 중...</p>
|
|
167
|
+
</div>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
// ...
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
For longer waits, Korean: "잠시만 기다려 주세요...".
|
|
175
|
+
|
|
176
|
+
## Edge cases
|
|
177
|
+
|
|
178
|
+
- **Spinner shown for < 200ms**: skip it. Brief flicker = bad UX. Use a debounced reveal.
|
|
179
|
+
- **Spinner stuck for > 10s**: show timeout UI ("This is taking longer than expected. Retry?").
|
|
180
|
+
- **Multiple concurrent spinners on a page**: coordinate so one section settles, others reveal staggered.
|
|
181
|
+
- **Spinner inside disabled button + button gets focus**: `aria-disabled` prevents click but allows focus. Spinner inside is purely visual.
|
|
182
|
+
- **Reduced motion**: per CSS above; can also replace with static "Loading" text.
|
|
183
|
+
- **RTL**: no impact (rotation is symmetric).
|
|
184
|
+
|
|
185
|
+
## Don't
|
|
186
|
+
|
|
187
|
+
- Don't show Spinner for sub-200ms operations. Flickers; do nothing instead.
|
|
188
|
+
- Don't use Spinner where progress is measurable. Use Progress.
|
|
189
|
+
- Don't use Spinner to fill large empty regions. Use Skeleton.
|
|
190
|
+
- Don't show multiple spinners in one button — confusing. One per loading control.
|
|
191
|
+
- Don't rotate via JS — use CSS animation.
|
|
192
|
+
- Don't omit reduced-motion handling.
|
|
193
|
+
|
|
194
|
+
## References
|
|
195
|
+
|
|
196
|
+
- MUI: [`CircularProgress`](../refs/mui/packages/mui-material/src/CircularProgress) (indeterminate variant)
|
|
197
|
+
- Patterns: standard SVG spinner
|
|
198
|
+
|
|
199
|
+
## Cross-reference
|
|
200
|
+
|
|
201
|
+
- [`examples/component-progress.md`](component-progress.md) — determinate progress
|
|
202
|
+
- [`examples/component-skeleton.md`](component-skeleton.md) — layout-aware loading
|
|
203
|
+
- [`examples/component-button.md`](component-button.md) — Spinner inside loading button
|
|
204
|
+
- [`knowledge/motion/principles.md`](../knowledge/motion/principles.md) — duration tiers
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# `Splitter` (resizable panel) — spec
|
|
2
|
+
|
|
3
|
+
> Citing Ant Design `Splitter`, MUI (no built-in), shadcn-ui `resizable`
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
Two or more panels separated by draggable handles. User resizes by dragging the handle. Used for: IDE/editor layouts, three-pane email apps, dashboard with sidebar, side-by-side editors.
|
|
8
|
+
|
|
9
|
+
## When Splitter vs alternatives
|
|
10
|
+
|
|
11
|
+
| Pattern | Use |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| **Splitter** | User-driven resize between persistent panels |
|
|
14
|
+
| **Collapsible drawer** | Show/hide a panel (binary, not gradient resize) |
|
|
15
|
+
| **Tabs** | Switch between mutually exclusive views |
|
|
16
|
+
| **Grid** | Static layout |
|
|
17
|
+
|
|
18
|
+
Splitter is a desktop-first pattern. Mobile rarely uses it (small screens, touch resize is awkward).
|
|
19
|
+
|
|
20
|
+
## Anatomy
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
Horizontal split:
|
|
24
|
+
┌────────────┬┊┬─────────────────────────────┐
|
|
25
|
+
│ │┊│ │
|
|
26
|
+
│ Panel A │┊│ Panel B │
|
|
27
|
+
│ │┊│ │
|
|
28
|
+
└────────────┴┊┴─────────────────────────────┘
|
|
29
|
+
↑ draggable handle
|
|
30
|
+
|
|
31
|
+
Vertical split:
|
|
32
|
+
┌──────────────────────────────────────────────┐
|
|
33
|
+
│ │
|
|
34
|
+
│ Panel A │
|
|
35
|
+
│ │
|
|
36
|
+
├╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┤ ← drag handle
|
|
37
|
+
│ │
|
|
38
|
+
│ Panel B │
|
|
39
|
+
│ │
|
|
40
|
+
└──────────────────────────────────────────────┘
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## API
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
<Splitter direction="horizontal">
|
|
47
|
+
<Splitter.Panel size={240} minSize={200} maxSize={400}>
|
|
48
|
+
<Sidebar />
|
|
49
|
+
</Splitter.Panel>
|
|
50
|
+
<Splitter.Panel size="auto">
|
|
51
|
+
<MainContent />
|
|
52
|
+
</Splitter.Panel>
|
|
53
|
+
</Splitter>
|
|
54
|
+
|
|
55
|
+
<Splitter direction="horizontal">
|
|
56
|
+
<Splitter.Panel size={240}>{nav}</Splitter.Panel>
|
|
57
|
+
<Splitter.Panel size="40%">{listing}</Splitter.Panel>
|
|
58
|
+
<Splitter.Panel size="auto">{detail}</Splitter.Panel>
|
|
59
|
+
</Splitter>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
| Prop (root) | Type | Default | Description |
|
|
63
|
+
| --- | --- | --- | --- |
|
|
64
|
+
| `direction` | `"horizontal" \| "vertical"` | `"horizontal"` | |
|
|
65
|
+
| `lazy` | `boolean` | `false` | Defer panel rendering during drag (perf) |
|
|
66
|
+
| `onResizeEnd` | `(sizes: number[]) => void` | — | Persist sizes |
|
|
67
|
+
|
|
68
|
+
| Prop (Panel) | Type | Description |
|
|
69
|
+
| --- | --- | --- |
|
|
70
|
+
| `size` | `number \| string \| "auto"` | px, %, "auto" (consume remaining) |
|
|
71
|
+
| `minSize` | `number` | Minimum size when dragging |
|
|
72
|
+
| `maxSize` | `number` | Maximum size |
|
|
73
|
+
| `collapsible` | `boolean` | Collapse to 0 when dragged below minSize |
|
|
74
|
+
| `defaultSize` | `number \| string` | Initial (uncontrolled) |
|
|
75
|
+
|
|
76
|
+
## Behavior
|
|
77
|
+
|
|
78
|
+
- User drags handle: adjacent panels resize.
|
|
79
|
+
- Constraints: min/max enforced.
|
|
80
|
+
- Collapsible: dragging below `minSize` snaps to 0; clicking handle restores to `minSize`.
|
|
81
|
+
- Total: panels share the parent's space; resizing one redistributes.
|
|
82
|
+
|
|
83
|
+
## Persistence
|
|
84
|
+
|
|
85
|
+
Common pattern: persist sizes to localStorage:
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
const [sizes, setSizes] = useLocalStorage("splitter-sizes", [240, 400, 800]);
|
|
89
|
+
|
|
90
|
+
<Splitter onResizeEnd={setSizes}>
|
|
91
|
+
<Splitter.Panel size={sizes[0]}>{...}</Splitter.Panel>
|
|
92
|
+
<Splitter.Panel size={sizes[1]}>{...}</Splitter.Panel>
|
|
93
|
+
<Splitter.Panel size={sizes[2]}>{...}</Splitter.Panel>
|
|
94
|
+
</Splitter>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
User's preference survives refresh.
|
|
98
|
+
|
|
99
|
+
## States
|
|
100
|
+
|
|
101
|
+
| State | Visual |
|
|
102
|
+
| --- | --- |
|
|
103
|
+
| Default handle | Subtle 2-4px line, neutral color |
|
|
104
|
+
| Hover handle | Border color changes, cursor `col-resize` (or `row-resize`) |
|
|
105
|
+
| Dragging | Handle highlighted, panels shrink/grow live |
|
|
106
|
+
| Focus-visible (keyboard) | 2px ring around handle |
|
|
107
|
+
| Panel collapsed | Width/height 0; expand affordance visible |
|
|
108
|
+
|
|
109
|
+
## Tokens consumed
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
--color-border-default (handle line)
|
|
113
|
+
--color-border-strong (hover)
|
|
114
|
+
--color-primary-default (drag-active or focus)
|
|
115
|
+
--color-bg-default
|
|
116
|
+
--color-focus-ring
|
|
117
|
+
--space-xs (handle thickness)
|
|
118
|
+
--motion-fast (resize transitions)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Sizes
|
|
122
|
+
|
|
123
|
+
| Direction | Handle thickness |
|
|
124
|
+
| --- | --- |
|
|
125
|
+
| Horizontal | 4–6px width |
|
|
126
|
+
| Vertical | 4–6px height |
|
|
127
|
+
|
|
128
|
+
For touch devices: increase hit area to 12–16px around the visual line via padding.
|
|
129
|
+
|
|
130
|
+
## Accessibility
|
|
131
|
+
|
|
132
|
+
- Each handle: `role="separator"`, `aria-orientation`, `aria-valuenow`, `aria-valuemin`, `aria-valuemax`.
|
|
133
|
+
- Handle is keyboard-reachable: `tabIndex="0"`.
|
|
134
|
+
- Resize via keyboard: `←` / `→` (horizontal) or `↑` / `↓` (vertical) — increment/decrement by 10px.
|
|
135
|
+
|
|
136
|
+
```html
|
|
137
|
+
<div role="separator"
|
|
138
|
+
aria-orientation="vertical"
|
|
139
|
+
aria-valuenow="240"
|
|
140
|
+
aria-valuemin="200"
|
|
141
|
+
aria-valuemax="400"
|
|
142
|
+
tabindex="0"
|
|
143
|
+
aria-label="Resize navigation panel">
|
|
144
|
+
</div>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Mobile
|
|
148
|
+
|
|
149
|
+
For mobile: usually replace with stacked panels, or a single-pane experience with drill-in. Splitter at narrow widths is awkward.
|
|
150
|
+
|
|
151
|
+
If Splitter is needed on mobile (rare, e.g., for tablet apps): handle width should be 16+ px for touch.
|
|
152
|
+
|
|
153
|
+
## Code example
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
// IDE-style 3-pane layout
|
|
157
|
+
function CodeEditor() {
|
|
158
|
+
const [sizes, setSizes] = useLocalStorage("editor-sizes", [240, 50, 50]);
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<Splitter direction="horizontal" onResizeEnd={setSizes}>
|
|
162
|
+
<Splitter.Panel size={sizes[0]} minSize={180} maxSize={400} collapsible>
|
|
163
|
+
<FileTree />
|
|
164
|
+
</Splitter.Panel>
|
|
165
|
+
<Splitter.Panel size={`${sizes[1]}%`} minSize={20}>
|
|
166
|
+
<Editor />
|
|
167
|
+
</Splitter.Panel>
|
|
168
|
+
<Splitter.Panel size="auto">
|
|
169
|
+
<Preview />
|
|
170
|
+
</Splitter.Panel>
|
|
171
|
+
</Splitter>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Vertical: editor + console
|
|
176
|
+
<Splitter direction="vertical">
|
|
177
|
+
<Splitter.Panel size="70%">
|
|
178
|
+
<Editor />
|
|
179
|
+
</Splitter.Panel>
|
|
180
|
+
<Splitter.Panel size="30%" minSize={100}>
|
|
181
|
+
<Console />
|
|
182
|
+
</Splitter.Panel>
|
|
183
|
+
</Splitter>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Edge cases
|
|
187
|
+
|
|
188
|
+
- **All panels at minSize and total < parent**: leftover space shows; consider extending the last panel or showing a fallback.
|
|
189
|
+
- **Window resize**: panels redistribute proportionally if percentage-based; clamp to absolute mins.
|
|
190
|
+
- **Nested Splitters**: works but heavy. Avoid 3+ nested levels — UX gets confusing.
|
|
191
|
+
- **Panels with text content**: ensure text wraps when narrow; otherwise, splitter becomes a horizontal-scroll trap.
|
|
192
|
+
|
|
193
|
+
## Don't
|
|
194
|
+
|
|
195
|
+
- Don't use Splitter for content that doesn't benefit from user-driven resize.
|
|
196
|
+
- Don't remember the user's resize *globally* across all instances — be context-specific.
|
|
197
|
+
- Don't allow collapse to 0 without an obvious "expand" affordance somewhere visible.
|
|
198
|
+
- Don't render the handle without a clear cursor change (col-resize / row-resize) — users won't know it's draggable.
|
|
199
|
+
- Don't omit aria-valuenow on the separator — keyboard users need feedback.
|
|
200
|
+
|
|
201
|
+
## References
|
|
202
|
+
|
|
203
|
+
- Ant Design: [`refs/ant-design/components/splitter/`](../refs/ant-design/components/splitter/) — `Splitter` + `Splitter.Panel`. Modern Ant addition.
|
|
204
|
+
- MUI: no built-in. Use `react-resizable-panels` or `allotment`.
|
|
205
|
+
- shadcn-ui: [`resizable.tsx`](../refs/shadcn-ui/apps/v4/registry/new-york-v4/ui/resizable.tsx) — wraps `react-resizable-panels`. Cleanest impl.
|
|
206
|
+
|
|
207
|
+
## Cross-reference
|
|
208
|
+
|
|
209
|
+
- [`examples/component-drawer.md`](component-drawer.md) — collapsible alternative
|
|
210
|
+
- [`knowledge/layout/spacing-and-grid.md`](../knowledge/layout/spacing-and-grid.md) — broader layout context
|