@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.
Files changed (529) hide show
  1. package/.claude-plugin/plugin.json +164 -0
  2. package/AGENTS.ko.md +126 -0
  3. package/AGENTS.md +182 -0
  4. package/CHANGELOG.md +6883 -0
  5. package/CLAUDE.md +39 -0
  6. package/LICENSE +21 -0
  7. package/README.ko.md +245 -0
  8. package/README.md +277 -0
  9. package/agents/README.md +14 -0
  10. package/agents/a11y-reviewer.md +121 -0
  11. package/agents/component-architect.md +57 -0
  12. package/agents/design-critic.md +46 -0
  13. package/agents/token-extractor.md +63 -0
  14. package/cli/bin/design-ai-mcp.mjs +6 -0
  15. package/cli/bin/design-ai.mjs +40 -0
  16. package/cli/commands/audit.mjs +111 -0
  17. package/cli/commands/check.mjs +226 -0
  18. package/cli/commands/doctor.mjs +141 -0
  19. package/cli/commands/examples.mjs +58 -0
  20. package/cli/commands/help.mjs +271 -0
  21. package/cli/commands/install.mjs +161 -0
  22. package/cli/commands/learn.mjs +1871 -0
  23. package/cli/commands/list.mjs +143 -0
  24. package/cli/commands/mcp.mjs +27 -0
  25. package/cli/commands/pack.mjs +211 -0
  26. package/cli/commands/prompt.mjs +199 -0
  27. package/cli/commands/route.mjs +247 -0
  28. package/cli/commands/search.mjs +60 -0
  29. package/cli/commands/show.mjs +52 -0
  30. package/cli/commands/site.mjs +558 -0
  31. package/cli/commands/status.mjs +161 -0
  32. package/cli/commands/uninstall.mjs +119 -0
  33. package/cli/commands/update.mjs +184 -0
  34. package/cli/commands/version.mjs +94 -0
  35. package/cli/commands/workspace.mjs +176 -0
  36. package/cli/lib/brief.mjs +52 -0
  37. package/cli/lib/check.mjs +642 -0
  38. package/cli/lib/dispatch.mjs +109 -0
  39. package/cli/lib/doctor.mjs +505 -0
  40. package/cli/lib/examples.mjs +258 -0
  41. package/cli/lib/exec.mjs +63 -0
  42. package/cli/lib/help-flags.mjs +5 -0
  43. package/cli/lib/learn.mjs +3694 -0
  44. package/cli/lib/log.mjs +47 -0
  45. package/cli/lib/mcp-server.mjs +426 -0
  46. package/cli/lib/output.mjs +101 -0
  47. package/cli/lib/pack.mjs +599 -0
  48. package/cli/lib/paths.mjs +63 -0
  49. package/cli/lib/prompt.mjs +603 -0
  50. package/cli/lib/route.mjs +740 -0
  51. package/cli/lib/search.mjs +158 -0
  52. package/cli/lib/show.mjs +161 -0
  53. package/cli/lib/signals.mjs +2337 -0
  54. package/cli/lib/site.mjs +6617 -0
  55. package/cli/lib/skill-proposals.mjs +2046 -0
  56. package/cli/lib/suggest.mjs +66 -0
  57. package/cli/lib/workspace.mjs +1056 -0
  58. package/commands/README.md +25 -0
  59. package/commands/component-spec.md +34 -0
  60. package/commands/conversational.md +44 -0
  61. package/commands/design-from-brief.md +141 -0
  62. package/commands/design-review.md +62 -0
  63. package/commands/document-from-brief.md +47 -0
  64. package/commands/extract-tokens.md +38 -0
  65. package/commands/game-ui.md +40 -0
  66. package/commands/illustration.md +37 -0
  67. package/commands/iterate.md +167 -0
  68. package/commands/motion-design.md +54 -0
  69. package/commands/palette-from-brand.md +50 -0
  70. package/commands/print.md +49 -0
  71. package/commands/slide-deck.md +46 -0
  72. package/commands/spatial.md +47 -0
  73. package/commands/stability-review.md +74 -0
  74. package/commands/video.md +42 -0
  75. package/commands/website-improvement.md +77 -0
  76. package/docs/AGENT-DEVELOPMENT.md +658 -0
  77. package/docs/AI-LEARNING.md +429 -0
  78. package/docs/AIDER-INTEGRATION.md +224 -0
  79. package/docs/ARCHITECTURE.ko.md +183 -0
  80. package/docs/ARCHITECTURE.md +105 -0
  81. package/docs/CODEX-INTEGRATION.md +311 -0
  82. package/docs/COMPANY-WEBSITE-DOGFOOD.ko.md +144 -0
  83. package/docs/COMPANY-WEBSITE-DOGFOOD.md +150 -0
  84. package/docs/COMPANY-WEBSITE-INTAKE-TEMPLATE.ko.md +153 -0
  85. package/docs/COMPANY-WEBSITE-INTAKE-TEMPLATE.md +154 -0
  86. package/docs/CONTRIBUTING.ko.md +203 -0
  87. package/docs/CONTRIBUTING.md +242 -0
  88. package/docs/CURSOR-INTEGRATION.md +220 -0
  89. package/docs/DISTRIBUTION.ko.md +248 -0
  90. package/docs/DISTRIBUTION.md +253 -0
  91. package/docs/DOGFOOD-FINDINGS.md +180 -0
  92. package/docs/DOGFOOD-V4-FINDINGS.md +139 -0
  93. package/docs/DOGFOOD-V4-MKDOCS-FINDINGS.md +233 -0
  94. package/docs/DOGFOOD-V4-NPM-FINDINGS.md +157 -0
  95. package/docs/DOGFOOD-V4-VSCODE-FINDINGS.md +135 -0
  96. package/docs/FIGMA-INTEGRATION.md +222 -0
  97. package/docs/MCP-INTEGRATION.md +243 -0
  98. package/docs/MIGRATION-v4.md +121 -0
  99. package/docs/PLUGIN-PACKAGING.md +240 -0
  100. package/docs/PRODUCT-READINESS.md +66 -0
  101. package/docs/QUICKSTART.ko.md +178 -0
  102. package/docs/QUICKSTART.md +179 -0
  103. package/docs/RELEASE-CHECKLIST.md +292 -0
  104. package/docs/ROADMAP.md +19495 -0
  105. package/docs/SESSION-LOG.md +940 -0
  106. package/docs/TOKEN-SYNC.md +237 -0
  107. package/docs/USING.ko.md +206 -0
  108. package/docs/USING.md +218 -0
  109. package/docs/WEBSITE-IMPROVEMENT.ko.md +75 -0
  110. package/docs/WEBSITE-IMPROVEMENT.md +89 -0
  111. package/docs/announcements/README.md +56 -0
  112. package/docs/announcements/dev-to-korea.md +206 -0
  113. package/docs/announcements/hashnode-post.ko.md +232 -0
  114. package/docs/announcements/okky-post.ko.md +158 -0
  115. package/docs/announcements/press-kit.md +101 -0
  116. package/docs/announcements/reddit-r-korea.md +196 -0
  117. package/docs/announcements/show-hn.md +114 -0
  118. package/docs/announcements/twitter-thread.md +255 -0
  119. package/docs/external-status.md +34 -0
  120. package/docs/integrations/aider-walkthrough.ko.md +275 -0
  121. package/docs/integrations/aider-walkthrough.md +274 -0
  122. package/docs/integrations/codex-walkthrough.ko.md +297 -0
  123. package/docs/integrations/codex-walkthrough.md +297 -0
  124. package/docs/integrations/cursor-walkthrough.ko.md +281 -0
  125. package/docs/integrations/cursor-walkthrough.md +284 -0
  126. package/docs/integrations/design-ai-mcp-server.md +169 -0
  127. package/docs/integrations/figma-mcp.md +149 -0
  128. package/docs/integrations/github-mcp.md +178 -0
  129. package/docs/integrations/linear-mcp.md +215 -0
  130. package/docs/integrations/notion-mcp.md +174 -0
  131. package/docs/integrations/sdk-walkthrough.ko.md +375 -0
  132. package/docs/integrations/sdk-walkthrough.md +375 -0
  133. package/docs/integrations/slack-mcp.md +208 -0
  134. package/docs/integrations/vscode-walkthrough.ko.md +202 -0
  135. package/docs/integrations/vscode-walkthrough.md +205 -0
  136. package/docs/requirements.txt +16 -0
  137. package/docs/site-overrides/extra.css +83 -0
  138. package/docs/site-overrides/favicon.svg +4 -0
  139. package/docs/site-overrides/logo.svg +10 -0
  140. package/docs/site-overrides/main.html +18 -0
  141. package/docs/website-console/app.js +2540 -0
  142. package/docs/website-console/index.html +24 -0
  143. package/docs/website-console/styles.css +975 -0
  144. package/examples/README.md +252 -0
  145. package/examples/cases/dogfood-v4-korean-hr-onboarding.md +356 -0
  146. package/examples/component-accordion-actions.md +153 -0
  147. package/examples/component-accordion-details.md +147 -0
  148. package/examples/component-accordion-summary.md +180 -0
  149. package/examples/component-accordion.md +229 -0
  150. package/examples/component-account-card.md +284 -0
  151. package/examples/component-address-input.md +260 -0
  152. package/examples/component-affix.md +190 -0
  153. package/examples/component-alert-dialog.md +210 -0
  154. package/examples/component-alert-title.md +77 -0
  155. package/examples/component-alert.md +192 -0
  156. package/examples/component-amount-input.md +278 -0
  157. package/examples/component-anchor.md +198 -0
  158. package/examples/component-app-bar.md +249 -0
  159. package/examples/component-aspect-ratio.md +156 -0
  160. package/examples/component-auto-complete.md +199 -0
  161. package/examples/component-avatar-group.md +170 -0
  162. package/examples/component-avatar.md +191 -0
  163. package/examples/component-back-top.md +123 -0
  164. package/examples/component-backdrop.md +148 -0
  165. package/examples/component-badge.md +181 -0
  166. package/examples/component-banner.md +237 -0
  167. package/examples/component-biometric-gate.md +281 -0
  168. package/examples/component-blockquote.md +153 -0
  169. package/examples/component-border-beam.md +207 -0
  170. package/examples/component-bottom-navigation.md +226 -0
  171. package/examples/component-box.md +112 -0
  172. package/examples/component-breadcrumb.md +222 -0
  173. package/examples/component-button-base.md +190 -0
  174. package/examples/component-button-group.md +117 -0
  175. package/examples/component-button.md +213 -0
  176. package/examples/component-calendar.md +280 -0
  177. package/examples/component-callout.md +131 -0
  178. package/examples/component-card-actions.md +101 -0
  179. package/examples/component-card-content.md +90 -0
  180. package/examples/component-card-header.md +122 -0
  181. package/examples/component-card-media.md +79 -0
  182. package/examples/component-card.md +233 -0
  183. package/examples/component-carousel.md +266 -0
  184. package/examples/component-cascader.md +135 -0
  185. package/examples/component-category-picker.md +271 -0
  186. package/examples/component-chart.md +237 -0
  187. package/examples/component-chat-interface.md +399 -0
  188. package/examples/component-checkbox.md +149 -0
  189. package/examples/component-click-away-listener.md +87 -0
  190. package/examples/component-code.md +213 -0
  191. package/examples/component-collapsible.md +219 -0
  192. package/examples/component-color-picker.md +110 -0
  193. package/examples/component-combobox.md +267 -0
  194. package/examples/component-command.md +299 -0
  195. package/examples/component-config-provider.md +190 -0
  196. package/examples/component-context-menu.md +179 -0
  197. package/examples/component-css-baseline.md +148 -0
  198. package/examples/component-date-picker.md +249 -0
  199. package/examples/component-descriptions.md +242 -0
  200. package/examples/component-dialog-actions.md +111 -0
  201. package/examples/component-dialog-content-text.md +76 -0
  202. package/examples/component-dialog-content.md +105 -0
  203. package/examples/component-dialog-title.md +104 -0
  204. package/examples/component-dialog.md +176 -0
  205. package/examples/component-divider.md +182 -0
  206. package/examples/component-doc-page.md +217 -0
  207. package/examples/component-drawer.md +257 -0
  208. package/examples/component-dropdown.md +220 -0
  209. package/examples/component-email-layout.md +253 -0
  210. package/examples/component-empty-state.md +269 -0
  211. package/examples/component-empty.md +172 -0
  212. package/examples/component-fade.md +87 -0
  213. package/examples/component-feature-grid.md +201 -0
  214. package/examples/component-field.md +266 -0
  215. package/examples/component-filled-input.md +114 -0
  216. package/examples/component-flex.md +117 -0
  217. package/examples/component-float-button.md +214 -0
  218. package/examples/component-form-control-label.md +134 -0
  219. package/examples/component-form-control.md +113 -0
  220. package/examples/component-form-controls.md +251 -0
  221. package/examples/component-form-group.md +86 -0
  222. package/examples/component-form-helper-text.md +95 -0
  223. package/examples/component-form-label.md +98 -0
  224. package/examples/component-form.md +291 -0
  225. package/examples/component-game-hud.md +362 -0
  226. package/examples/component-game-menu.md +327 -0
  227. package/examples/component-grid.md +140 -0
  228. package/examples/component-grow.md +79 -0
  229. package/examples/component-hero-block.md +252 -0
  230. package/examples/component-hover-card.md +211 -0
  231. package/examples/component-icon-button.md +142 -0
  232. package/examples/component-icon.md +102 -0
  233. package/examples/component-illustration.md +280 -0
  234. package/examples/component-image-list.md +107 -0
  235. package/examples/component-image.md +282 -0
  236. package/examples/component-input-adornment.md +101 -0
  237. package/examples/component-input-base.md +134 -0
  238. package/examples/component-input-number.md +141 -0
  239. package/examples/component-input-otp.md +271 -0
  240. package/examples/component-input.md +213 -0
  241. package/examples/component-item.md +243 -0
  242. package/examples/component-kbd.md +197 -0
  243. package/examples/component-krw-amount.md +219 -0
  244. package/examples/component-label.md +118 -0
  245. package/examples/component-layout.md +217 -0
  246. package/examples/component-link.md +223 -0
  247. package/examples/component-list-item-avatar.md +72 -0
  248. package/examples/component-list-item-button.md +139 -0
  249. package/examples/component-list-item-icon.md +82 -0
  250. package/examples/component-list-item-text.md +98 -0
  251. package/examples/component-list-item.md +116 -0
  252. package/examples/component-list-subheader.md +70 -0
  253. package/examples/component-list.md +198 -0
  254. package/examples/component-loading-button.md +125 -0
  255. package/examples/component-loading-sequence.md +254 -0
  256. package/examples/component-lottie-player.md +279 -0
  257. package/examples/component-masonry.md +191 -0
  258. package/examples/component-mentions.md +189 -0
  259. package/examples/component-menu-item.md +102 -0
  260. package/examples/component-menu-list.md +98 -0
  261. package/examples/component-menu.md +139 -0
  262. package/examples/component-menubar.md +259 -0
  263. package/examples/component-message.md +162 -0
  264. package/examples/component-mobile-stepper.md +155 -0
  265. package/examples/component-modal.md +220 -0
  266. package/examples/component-navigation-menu.md +295 -0
  267. package/examples/component-notification.md +166 -0
  268. package/examples/component-otp-countdown.md +245 -0
  269. package/examples/component-outlined-input.md +145 -0
  270. package/examples/component-page-transition.md +281 -0
  271. package/examples/component-pagination.md +226 -0
  272. package/examples/component-paper.md +199 -0
  273. package/examples/component-pass-auth.md +265 -0
  274. package/examples/component-payment-brand-button.md +253 -0
  275. package/examples/component-payment-method-selector.md +272 -0
  276. package/examples/component-payment-receipt.md +277 -0
  277. package/examples/component-popconfirm.md +144 -0
  278. package/examples/component-popover.md +239 -0
  279. package/examples/component-popper.md +129 -0
  280. package/examples/component-pricing-cards.md +247 -0
  281. package/examples/component-progress.md +195 -0
  282. package/examples/component-qr-code.md +201 -0
  283. package/examples/component-radio.md +167 -0
  284. package/examples/component-rate.md +202 -0
  285. package/examples/component-resizable.md +163 -0
  286. package/examples/component-result.md +270 -0
  287. package/examples/component-scroll-area.md +199 -0
  288. package/examples/component-scroll-reveal.md +320 -0
  289. package/examples/component-segmented.md +178 -0
  290. package/examples/component-select.md +258 -0
  291. package/examples/component-separator.md +177 -0
  292. package/examples/component-sheet.md +277 -0
  293. package/examples/component-sidebar.md +257 -0
  294. package/examples/component-skeleton.md +178 -0
  295. package/examples/component-slide.md +89 -0
  296. package/examples/component-slider.md +208 -0
  297. package/examples/component-snackbar-content.md +92 -0
  298. package/examples/component-snackbar.md +121 -0
  299. package/examples/component-sonner.md +165 -0
  300. package/examples/component-space.md +125 -0
  301. package/examples/component-spatial-locomotion.md +373 -0
  302. package/examples/component-spatial-panel.md +330 -0
  303. package/examples/component-speed-dial-action.md +78 -0
  304. package/examples/component-speed-dial.md +177 -0
  305. package/examples/component-spin.md +173 -0
  306. package/examples/component-spinner.md +204 -0
  307. package/examples/component-splitter.md +210 -0
  308. package/examples/component-stack.md +130 -0
  309. package/examples/component-statistic.md +282 -0
  310. package/examples/component-step-button.md +157 -0
  311. package/examples/component-step-connector.md +157 -0
  312. package/examples/component-step-content.md +121 -0
  313. package/examples/component-step-icon.md +115 -0
  314. package/examples/component-step-label.md +101 -0
  315. package/examples/component-step.md +84 -0
  316. package/examples/component-steps.md +264 -0
  317. package/examples/component-stock-chart.md +251 -0
  318. package/examples/component-swipeable-drawer.md +149 -0
  319. package/examples/component-switch.md +99 -0
  320. package/examples/component-tab-scroll-button.md +180 -0
  321. package/examples/component-tab.md +120 -0
  322. package/examples/component-table-body.md +82 -0
  323. package/examples/component-table-cell.md +118 -0
  324. package/examples/component-table-container.md +75 -0
  325. package/examples/component-table-footer.md +72 -0
  326. package/examples/component-table-head.md +78 -0
  327. package/examples/component-table-pagination.md +137 -0
  328. package/examples/component-table-row.md +113 -0
  329. package/examples/component-table-sort-label.md +109 -0
  330. package/examples/component-table.md +202 -0
  331. package/examples/component-tabs.md +184 -0
  332. package/examples/component-tag-badge.md +309 -0
  333. package/examples/component-tag.md +102 -0
  334. package/examples/component-testimonial-carousel.md +218 -0
  335. package/examples/component-textarea-autosize.md +114 -0
  336. package/examples/component-textarea.md +173 -0
  337. package/examples/component-time-picker.md +205 -0
  338. package/examples/component-timeline.md +170 -0
  339. package/examples/component-toast.md +224 -0
  340. package/examples/component-toggle-button.md +129 -0
  341. package/examples/component-toggle.md +220 -0
  342. package/examples/component-toolbar.md +104 -0
  343. package/examples/component-tooltip.md +178 -0
  344. package/examples/component-tour.md +176 -0
  345. package/examples/component-transaction-list-item.md +243 -0
  346. package/examples/component-transfer.md +156 -0
  347. package/examples/component-tree-select.md +202 -0
  348. package/examples/component-tree.md +297 -0
  349. package/examples/component-typography.md +215 -0
  350. package/examples/component-upload.md +295 -0
  351. package/examples/component-video-hero.md +409 -0
  352. package/examples/component-video-player.md +340 -0
  353. package/examples/component-voice-input.md +408 -0
  354. package/examples/component-watermark.md +217 -0
  355. package/examples/component-zoom.md +92 -0
  356. package/examples/doc-explanation-example.md +196 -0
  357. package/examples/doc-how-to-example.md +205 -0
  358. package/examples/doc-tutorial-example.md +162 -0
  359. package/examples/dogfood-korean-fintech-system.md +433 -0
  360. package/examples/email-transactional-example.md +259 -0
  361. package/examples/palette-saas-violet.md +235 -0
  362. package/examples/print-business-card-spec.md +205 -0
  363. package/examples/print-packaging-spec.md +285 -0
  364. package/examples/report-example.md +228 -0
  365. package/examples/slide-deck-example.md +237 -0
  366. package/examples/website-improvement-report.md +128 -0
  367. package/examples/website-improvement-workspace.json +126 -0
  368. package/install.sh +189 -0
  369. package/knowledge/COVERAGE.md +740 -0
  370. package/knowledge/PRINCIPLES.md +108 -0
  371. package/knowledge/a11y/contrast.md +70 -0
  372. package/knowledge/a11y/keyboard-and-focus.md +108 -0
  373. package/knowledge/colors/color-theory.md +90 -0
  374. package/knowledge/colors/mui-palette-structure.md +105 -0
  375. package/knowledge/colors/palettes-by-product-type.md +876 -0
  376. package/knowledge/components/INDEX.md +231 -0
  377. package/knowledge/components/index.json +1470 -0
  378. package/knowledge/components/shadcn-registry.md +159 -0
  379. package/knowledge/conversational/ai-chat-interfaces.md +323 -0
  380. package/knowledge/conversational/chatbot-design.md +312 -0
  381. package/knowledge/conversational/conversational-ui-fundamentals.md +299 -0
  382. package/knowledge/conversational/korean-voice-conventions.md +281 -0
  383. package/knowledge/conversational/voice-ui-patterns.md +297 -0
  384. package/knowledge/design-tokens/ant-design.md +124 -0
  385. package/knowledge/design-tokens/material-3.md +235 -0
  386. package/knowledge/design-tokens/polaris-and-carbon.md +231 -0
  387. package/knowledge/design-tokens/tailwind-v4.md +284 -0
  388. package/knowledge/game-ui/game-accessibility.md +317 -0
  389. package/knowledge/game-ui/game-ui-fundamentals.md +281 -0
  390. package/knowledge/game-ui/hud-design.md +324 -0
  391. package/knowledge/game-ui/korean-gaming-conventions.md +312 -0
  392. package/knowledge/game-ui/menu-systems.md +388 -0
  393. package/knowledge/i18n/korean-app-store-visual.md +223 -0
  394. package/knowledge/i18n/korean-document-style.md +301 -0
  395. package/knowledge/i18n/korean-payments.md +211 -0
  396. package/knowledge/i18n/korean-product-conventions.md +96 -0
  397. package/knowledge/i18n/korean-publishing.md +139 -0
  398. package/knowledge/i18n/korean-typography.md +123 -0
  399. package/knowledge/icons/curated-sets.md +225 -0
  400. package/knowledge/illustration/hero-illustrations.md +234 -0
  401. package/knowledge/illustration/illustration-systems.md +221 -0
  402. package/knowledge/illustration/mascot-design.md +208 -0
  403. package/knowledge/illustration/spot-illustrations.md +246 -0
  404. package/knowledge/illustration/svg-optimization.md +308 -0
  405. package/knowledge/layout/spacing-and-grid.md +119 -0
  406. package/knowledge/motion/app-loading-sequences.md +277 -0
  407. package/knowledge/motion/choreography-depth.md +297 -0
  408. package/knowledge/motion/marketing-motion.md +223 -0
  409. package/knowledge/motion/micro-interactions.md +266 -0
  410. package/knowledge/motion/motion-tools.md +281 -0
  411. package/knowledge/motion/principles.md +126 -0
  412. package/knowledge/patterns/auth-flow-design.md +316 -0
  413. package/knowledge/patterns/b2b-onboarding-flows.md +182 -0
  414. package/knowledge/patterns/brand-identity.md +238 -0
  415. package/knowledge/patterns/brand-references.md +97 -0
  416. package/knowledge/patterns/chart-color-encoding.md +269 -0
  417. package/knowledge/patterns/chart-types.md +344 -0
  418. package/knowledge/patterns/dashboard-composition.md +299 -0
  419. package/knowledge/patterns/design-system-qa.md +356 -0
  420. package/knowledge/patterns/document-typography.md +248 -0
  421. package/knowledge/patterns/email-design.md +338 -0
  422. package/knowledge/patterns/empty-states.md +263 -0
  423. package/knowledge/patterns/error-states.md +318 -0
  424. package/knowledge/patterns/form-design.md +237 -0
  425. package/knowledge/patterns/information-architecture.md +341 -0
  426. package/knowledge/patterns/landing-hero-design.md +283 -0
  427. package/knowledge/patterns/landing-page-patterns.md +681 -0
  428. package/knowledge/patterns/list-and-feed.md +371 -0
  429. package/knowledge/patterns/mobile-navigation.md +278 -0
  430. package/knowledge/patterns/money-and-amount.md +301 -0
  431. package/knowledge/patterns/onboarding.md +300 -0
  432. package/knowledge/patterns/pricing-page-design.md +261 -0
  433. package/knowledge/patterns/realtime-data.md +280 -0
  434. package/knowledge/patterns/report-design.md +330 -0
  435. package/knowledge/patterns/search-ux.md +373 -0
  436. package/knowledge/patterns/settings-page.md +325 -0
  437. package/knowledge/patterns/slide-deck-design.md +316 -0
  438. package/knowledge/patterns/styles-catalog.md +2599 -0
  439. package/knowledge/patterns/technical-writing.md +306 -0
  440. package/knowledge/patterns/ui-reasoning.md +1853 -0
  441. package/knowledge/patterns/ux-guidelines.md +1454 -0
  442. package/knowledge/platforms/react-native.md +395 -0
  443. package/knowledge/print/brochures-and-flyers.md +276 -0
  444. package/knowledge/print/korean-print-conventions.md +284 -0
  445. package/knowledge/print/packaging.md +321 -0
  446. package/knowledge/print/print-fundamentals.md +238 -0
  447. package/knowledge/print/signage-and-posters.md +235 -0
  448. package/knowledge/print/stationery.md +262 -0
  449. package/knowledge/spatial/ar-patterns.md +253 -0
  450. package/knowledge/spatial/comfort-and-accessibility.md +245 -0
  451. package/knowledge/spatial/spatial-design-fundamentals.md +346 -0
  452. package/knowledge/spatial/spatial-ui-elements.md +343 -0
  453. package/knowledge/spatial/vr-patterns.md +302 -0
  454. package/knowledge/typography/font-pairings.md +332 -0
  455. package/knowledge/typography/mui-type-scale.md +57 -0
  456. package/knowledge/typography/type-scale-fundamentals.md +105 -0
  457. package/knowledge/video/in-product-video.md +277 -0
  458. package/knowledge/video/korean-video-conventions.md +247 -0
  459. package/knowledge/video/marketing-video.md +258 -0
  460. package/knowledge/video/social-and-short-form.md +257 -0
  461. package/knowledge/video/video-fundamentals.md +296 -0
  462. package/package.json +106 -0
  463. package/skills/README.md +39 -0
  464. package/skills/color-palette/PLAYBOOK.md +175 -0
  465. package/skills/color-palette/SKILL.md +6 -0
  466. package/skills/color-palette/TEMPLATE.md +103 -0
  467. package/skills/component-spec-writer/PLAYBOOK.md +169 -0
  468. package/skills/component-spec-writer/SKILL.md +6 -0
  469. package/skills/component-spec-writer/TEMPLATE.md +115 -0
  470. package/skills/conversational-ui-designer/PLAYBOOK.md +231 -0
  471. package/skills/conversational-ui-designer/SKILL.md +6 -0
  472. package/skills/design-broadcast/PLAYBOOK.md +146 -0
  473. package/skills/design-broadcast/SKILL.md +6 -0
  474. package/skills/design-critique/PLAYBOOK.md +137 -0
  475. package/skills/design-critique/SKILL.md +6 -0
  476. package/skills/design-pr-review/PLAYBOOK.md +171 -0
  477. package/skills/design-pr-review/SKILL.md +6 -0
  478. package/skills/design-system-builder/PLAYBOOK.md +218 -0
  479. package/skills/design-system-builder/SKILL.md +6 -0
  480. package/skills/design-system-qa/PLAYBOOK.md +163 -0
  481. package/skills/design-system-qa/SKILL.md +6 -0
  482. package/skills/document-author/PLAYBOOK.md +167 -0
  483. package/skills/document-author/SKILL.md +6 -0
  484. package/skills/figma-token-sync/PLAYBOOK.md +149 -0
  485. package/skills/figma-token-sync/SKILL.md +6 -0
  486. package/skills/game-ui-designer/PLAYBOOK.md +209 -0
  487. package/skills/game-ui-designer/SKILL.md +6 -0
  488. package/skills/handoff-spec/PLAYBOOK.md +170 -0
  489. package/skills/handoff-spec/SKILL.md +6 -0
  490. package/skills/illustration-designer/PLAYBOOK.md +166 -0
  491. package/skills/illustration-designer/SKILL.md +6 -0
  492. package/skills/motion-designer/PLAYBOOK.md +223 -0
  493. package/skills/motion-designer/SKILL.md +6 -0
  494. package/skills/print-designer/PLAYBOOK.md +209 -0
  495. package/skills/print-designer/SKILL.md +6 -0
  496. package/skills/slide-deck-author/PLAYBOOK.md +198 -0
  497. package/skills/slide-deck-author/SKILL.md +6 -0
  498. package/skills/spatial-designer/PLAYBOOK.md +238 -0
  499. package/skills/spatial-designer/SKILL.md +6 -0
  500. package/skills/ux-audit/PLAYBOOK.md +142 -0
  501. package/skills/ux-audit/SKILL.md +6 -0
  502. package/skills/video-designer/PLAYBOOK.md +240 -0
  503. package/skills/video-designer/SKILL.md +6 -0
  504. package/skills/website-improvement/PLAYBOOK.md +118 -0
  505. package/skills/website-improvement/SKILL.md +6 -0
  506. package/skills/website-improvement/TEMPLATE.md +103 -0
  507. package/tools/audit/changelog-generate.py +176 -0
  508. package/tools/audit/check-coverage.py +483 -0
  509. package/tools/audit/doctor_assertions.py +256 -0
  510. package/tools/audit/example-qa.py +108 -0
  511. package/tools/audit/frontmatter-check.py +199 -0
  512. package/tools/audit/integration-check.py +95 -0
  513. package/tools/audit/korean-copy-check.py +161 -0
  514. package/tools/audit/link-check.py +146 -0
  515. package/tools/audit/local-ci.py +558 -0
  516. package/tools/audit/package-contents.py +723 -0
  517. package/tools/audit/package-smoke.py +22443 -0
  518. package/tools/audit/raw-hex-check.py +252 -0
  519. package/tools/audit/registry-smoke.py +8188 -0
  520. package/tools/audit/release-metadata.py +9832 -0
  521. package/tools/audit/run-all.py +351 -0
  522. package/tools/audit/smoke_assertions.py +12742 -0
  523. package/tools/audit/stability-review.py +332 -0
  524. package/tools/audit/stale-check.py +156 -0
  525. package/tools/migrations/add-version-frontmatter.py +132 -0
  526. package/tools/migrations/bump-last-updated.py +131 -0
  527. package/tools/migrations/promote-stability.py +172 -0
  528. package/tools/preview/README.md +58 -0
  529. package/tools/preview/render-tokens.py +454 -0
@@ -0,0 +1,295 @@
1
+ # `NavigationMenu` — spec
2
+
3
+ > Synthesized from shadcn-ui `navigation-menu` (Radix) and patterns from MUI / Ant menu primitives. Top-of-page horizontal navigation with optional megamenu / dropdown panels. Common in marketing sites and B2B SaaS app headers.
4
+
5
+ ## When to use
6
+
7
+ - **Marketing site top nav** with Product / Solutions / Resources mega-panels.
8
+ - **SaaS app header** for top-level sections.
9
+ - **Documentation site** primary nav.
10
+
11
+ When NOT to use:
12
+ - Vertical nav contexts → `Sidebar`.
13
+ - Action menus → `DropdownMenu`.
14
+ - Mobile-only contexts → `MobileNavigation` (separate component).
15
+
16
+ ## Anatomy
17
+
18
+ ```
19
+ [Logo] Product ▾ Solutions ▾ Pricing Docs [Sign in]
20
+
21
+ ┌────────────────────────────────────┐
22
+ │ Product overview [→] │
23
+ │ A platform for... │
24
+ │ │
25
+ │ Components Themes │
26
+ │ Templates Pricing │
27
+ │ │
28
+ │ Featured: New design tokens │
29
+ └────────────────────────────────────┘
30
+ (mega-menu panel, hover/click triggered)
31
+ ```
32
+
33
+ ## API
34
+
35
+ ```tsx
36
+ <NavigationMenu>
37
+ <NavigationMenu.List>
38
+ <NavigationMenu.Item>
39
+ <NavigationMenu.Trigger>Product</NavigationMenu.Trigger>
40
+ <NavigationMenu.Content>
41
+ <ul className="grid gap-2 p-4 md:w-[500px] grid-cols-2">
42
+ <li>
43
+ <NavigationMenu.Link href="/components">
44
+ <h3>Components</h3>
45
+ <p>Pre-built primitives.</p>
46
+ </NavigationMenu.Link>
47
+ </li>
48
+ <li>
49
+ <NavigationMenu.Link href="/themes">
50
+ <h3>Themes</h3>
51
+ <p>Beautiful color palettes.</p>
52
+ </NavigationMenu.Link>
53
+ </li>
54
+ </ul>
55
+ </NavigationMenu.Content>
56
+ </NavigationMenu.Item>
57
+
58
+ <NavigationMenu.Item>
59
+ <NavigationMenu.Link href="/pricing">Pricing</NavigationMenu.Link>
60
+ </NavigationMenu.Item>
61
+
62
+ <NavigationMenu.Item>
63
+ <NavigationMenu.Link href="/docs">Docs</NavigationMenu.Link>
64
+ </NavigationMenu.Item>
65
+ </NavigationMenu.List>
66
+
67
+ <NavigationMenu.Indicator /> {/* Animated underline */}
68
+ <NavigationMenu.Viewport /> {/* Container for active panel */}
69
+ </NavigationMenu>
70
+ ```
71
+
72
+ ## Composition
73
+
74
+ | Part | Purpose |
75
+ | --- | --- |
76
+ | `NavigationMenu` | Wrapper |
77
+ | `List` | Horizontal list of top-level items |
78
+ | `Item` | Wrapper for a top-level entry |
79
+ | `Trigger` | Hover/click target that opens a panel |
80
+ | `Content` | Mega-menu panel content |
81
+ | `Link` | A direct navigation link (no panel) |
82
+ | `Indicator` | Animated underline / arrow pointing at active item |
83
+ | `Viewport` | Single shared container that panels animate into |
84
+
85
+ ## Trigger modes
86
+
87
+ ### Hover (marketing default)
88
+
89
+ Hover trigger → panel opens after 200ms. Mouse-leave → closes after 300ms (graceful).
90
+
91
+ ### Click (for product apps)
92
+
93
+ Tap-or-click only. More predictable; preferred when nav has many panels.
94
+
95
+ ### Mobile
96
+
97
+ NavigationMenu doesn't translate to mobile directly. On small screens:
98
+ - Collapse to a hamburger menu that opens a `Sheet`.
99
+ - Or use `MobileNavigation` (separate component).
100
+
101
+ ## Mega-menu layouts
102
+
103
+ ### List
104
+
105
+ ```
106
+ ┌─────────────────────────┐
107
+ │ Item 1 │
108
+ │ Item 2 │
109
+ │ Item 3 │
110
+ │ ───── │
111
+ │ Featured: ... │
112
+ └─────────────────────────┘
113
+ ```
114
+
115
+ ### Grid (most common)
116
+
117
+ ```
118
+ ┌──────────────┬──────────────┐
119
+ │ Components │ Themes │
120
+ │ Pre-built... │ Color... │
121
+ ├──────────────┼──────────────┤
122
+ │ Templates │ Pricing │
123
+ │ Starter... │ Plans... │
124
+ └──────────────┴──────────────┘
125
+ ```
126
+
127
+ ### Featured + grid
128
+
129
+ ```
130
+ ┌─────────────┬───────────────────┐
131
+ │ │ Components │
132
+ │ Hero │ Themes │
133
+ │ Promo │ Templates │
134
+ │ + image │ Pricing │
135
+ │ │ │
136
+ └─────────────┴───────────────────┘
137
+ ```
138
+
139
+ ## States
140
+
141
+ | State | Visual |
142
+ | --- | --- |
143
+ | Resting | All triggers visible, no panel |
144
+ | Trigger hover | Underline indicator slides under hovered item |
145
+ | Panel open | Content visible below; Indicator points at active trigger |
146
+ | Switching panels | Indicator slides; Content cross-fades |
147
+ | Closing | Indicator hides; Content fades |
148
+
149
+ ## Animations
150
+
151
+ ```
152
+ Indicator: 200ms slide between triggers (transform: translateX)
153
+ Panel: 250ms cross-fade + slight slide (translateY -4px → 0)
154
+ Reduced motion: instant
155
+ ```
156
+
157
+ ## Tokens consumed
158
+
159
+ ```
160
+ --color-bg-default
161
+ --color-fg-default
162
+ --color-fg-muted (panel description text)
163
+ --color-bg-overlay (panel bg)
164
+ --color-bg-overlay-hover (panel item hover)
165
+ --color-brand-default (active indicator)
166
+ --color-border-default
167
+ --radius-md
168
+ --shadow-overlay
169
+ --space-md, --space-lg
170
+ --font-size-base
171
+ --font-weight-medium
172
+ --motion-medium (panel transition)
173
+ --ease-out
174
+ --z-overlay
175
+ ```
176
+
177
+ ## Accessibility
178
+
179
+ - Wrapper: `<nav aria-label="Main">`.
180
+ - List: `<ul role="menubar">`.
181
+ - Item: `<li>` containing either `<NavigationMenu.Trigger>` or `<NavigationMenu.Link>`.
182
+ - Trigger: `<button aria-haspopup="true" aria-expanded="...">`.
183
+ - Content: `role="menu"` (or just rendered list).
184
+ - Active page: `aria-current="page"` on the corresponding link.
185
+ - Keyboard:
186
+ - Tab moves between top-level items.
187
+ - Enter / Space on Trigger opens panel; arrows navigate within panel.
188
+ - Esc closes panel.
189
+ - For touch: hover doesn't fire; panels open on tap (close on second tap of same trigger or outside).
190
+
191
+ ## Mobile fallback pattern
192
+
193
+ ```tsx
194
+ function ResponsiveNav() {
195
+ const isDesktop = useMediaQuery("(min-width: 1024px)");
196
+
197
+ if (isDesktop) {
198
+ return <NavigationMenu>...</NavigationMenu>;
199
+ }
200
+
201
+ return (
202
+ <Sheet>
203
+ <Sheet.Trigger asChild>
204
+ <Button variant="ghost"><MenuIcon /></Button>
205
+ </Sheet.Trigger>
206
+ <Sheet.Content side="right">
207
+ <MobileNavList items={navItems} />
208
+ </Sheet.Content>
209
+ </Sheet>
210
+ );
211
+ }
212
+ ```
213
+
214
+ ## Code example (marketing site)
215
+
216
+ ```tsx
217
+ function MarketingHeader() {
218
+ return (
219
+ <header className="site-header">
220
+ <Logo />
221
+
222
+ <NavigationMenu>
223
+ <NavigationMenu.List>
224
+ <NavigationMenu.Item>
225
+ <NavigationMenu.Trigger>Product</NavigationMenu.Trigger>
226
+ <NavigationMenu.Content>
227
+ <div className="mega-grid">
228
+ <div className="featured">
229
+ <Image src="/hero.jpg" alt="" />
230
+ <h3>What's new</h3>
231
+ <p>v3.2 just shipped — explore the spatial design domain.</p>
232
+ <a href="/changelog">See changelog →</a>
233
+ </div>
234
+ <ul className="links">
235
+ <li><a href="/components">Components</a></li>
236
+ <li><a href="/themes">Themes</a></li>
237
+ <li><a href="/templates">Templates</a></li>
238
+ </ul>
239
+ </div>
240
+ </NavigationMenu.Content>
241
+ </NavigationMenu.Item>
242
+
243
+ <NavigationMenu.Item>
244
+ <NavigationMenu.Link href="/pricing">Pricing</NavigationMenu.Link>
245
+ </NavigationMenu.Item>
246
+
247
+ <NavigationMenu.Item>
248
+ <NavigationMenu.Link href="/docs">Docs</NavigationMenu.Link>
249
+ </NavigationMenu.Item>
250
+ </NavigationMenu.List>
251
+
252
+ <NavigationMenu.Indicator />
253
+ <NavigationMenu.Viewport />
254
+ </NavigationMenu>
255
+
256
+ <div className="actions">
257
+ <a href="/login">Sign in</a>
258
+ <Button asChild><a href="/signup">Sign up</a></Button>
259
+ </div>
260
+ </header>
261
+ );
262
+ }
263
+ ```
264
+
265
+ ## Edge cases
266
+
267
+ - **Single-item nav** (only one trigger): NavigationMenu is overkill. Just use a button.
268
+ - **Trigger with active sub-route**: highlight Trigger when child route active (`aria-current="true"` if any descendant link matches current URL).
269
+ - **Mega-panel taller than viewport**: cap height; scroll inside panel.
270
+ - **Panel with images**: lazy-load; image-loading shouldn't block panel paint.
271
+ - **Hover into panel from trigger**: panel must remain open during hover-traversal; use `closeDelay`.
272
+ - **Mobile breakpoint switch mid-session**: re-render with appropriate component.
273
+ - **RTL**: flip indicator direction + alignment.
274
+
275
+ ## Don't
276
+
277
+ - Don't use NavigationMenu for in-app navigation when a Sidebar is more appropriate. Top nav for marketing-feel + flat sites; sidebar for app-shell.
278
+ - Don't pack 7+ top-level items. Group via mega-menu or rethink IA.
279
+ - Don't ship without a mobile fallback. Top nav doesn't work on phones.
280
+ - Don't omit `aria-current` on active links.
281
+ - Don't have hover-only triggers on touch devices.
282
+ - Don't disable Esc to close panels.
283
+
284
+ ## References
285
+
286
+ - shadcn-ui: [`navigation-menu`](../refs/shadcn-ui/apps/v4/registry/new-york-v4/ui/navigation-menu.tsx) (Radix)
287
+ - Patterns: Stripe, Linear, Vercel marketing nav
288
+
289
+ ## Cross-reference
290
+
291
+ - [`examples/component-sidebar.md`](component-sidebar.md) — vertical nav
292
+ - [`examples/component-app-bar.md`](component-app-bar.md) — top app bar
293
+ - [`examples/component-sheet.md`](component-sheet.md) — mobile fallback
294
+ - [`knowledge/patterns/mobile-navigation.md`](../knowledge/patterns/mobile-navigation.md)
295
+ - [`knowledge/patterns/landing-hero-design.md`](../knowledge/patterns/landing-hero-design.md)
@@ -0,0 +1,166 @@
1
+ # `Notification` — spec
2
+
3
+ > Synthesized from Ant Design `Notification`. Richer card-style notification — title + description + optional actions, anchored to a screen corner. Distinct from `Toast` (smaller, action-focused), `Message` (top thin pill), and `Banner` (persistent in-page).
4
+
5
+ ## When to use
6
+
7
+ - **System-level events** that need title + body description.
8
+ - **Multi-action notifications** ("New message from John" with Reply / Mark read buttons).
9
+ - **Push-notification surface** for in-app-only events.
10
+
11
+ When NOT to use:
12
+ - Brief result confirmation (use Message or Toast).
13
+ - Critical actions blocking workflow (use Modal / AlertDialog).
14
+ - In-page persistent strip (use Banner).
15
+
16
+ ## Anatomy
17
+
18
+ ```
19
+ ┌───────────────────────────┐
20
+ │ ⓘ 새 알림 │
21
+ │ @sungjin이 댓글을 │
22
+ │ 남겼어요. │
23
+ │ │
24
+ │ [답장] [읽음 처리] [×] │
25
+ └───────────────────────────┘
26
+ ↑ top-right corner
27
+ ```
28
+
29
+ ## API
30
+
31
+ ```tsx
32
+ import { notification } from "antd";
33
+
34
+ notification.open({
35
+ message: "새 알림",
36
+ description: "@sungjin이 댓글을 남겼어요.",
37
+ placement: "topRight",
38
+ duration: 4.5,
39
+ btn: <Button onClick={reply}>답장</Button>,
40
+ onClose: handleClose,
41
+ });
42
+
43
+ notification.success({ message: "성공", description: "저장됐어요." });
44
+ notification.error({ message: "실패", description: "저장에 실패했어요." });
45
+ notification.info({ message: "알림", description: "..." });
46
+ notification.warning({ message: "경고", description: "..." });
47
+ ```
48
+
49
+ | Config field | Description |
50
+ | --- | --- |
51
+ | `message` | Title (bold) |
52
+ | `description` | Body (multiple lines OK) |
53
+ | `placement` | `"top" \| "topLeft" \| "topRight" \| "bottom" \| "bottomLeft" \| "bottomRight"` |
54
+ | `duration` | Seconds; 0 = persistent until dismissed |
55
+ | `key` | Unique key (replace existing) |
56
+ | `btn` | Custom action button(s) |
57
+ | `onClose` | Dismiss callback |
58
+ | `onClick` | Click on notification (optional) |
59
+ | `icon` | Custom icon override |
60
+ | `closable` | Show × dismiss button |
61
+
62
+ ## States
63
+
64
+ | Severity | Visual |
65
+ | --- | --- |
66
+ | `open` (neutral) | Generic info icon |
67
+ | `success` | Green check |
68
+ | `error` | Red X |
69
+ | `info` | Blue info |
70
+ | `warning` | Amber triangle |
71
+
72
+ ## Animation
73
+
74
+ ```
75
+ Enter: slide-in from corner (250ms)
76
+ Hold: full opacity for `duration` seconds
77
+ Exit: fade + slide-out (200ms)
78
+ ```
79
+
80
+ Reduced motion: fade only.
81
+
82
+ ## Stacking
83
+
84
+ Multiple Notifications stack vertically in their corner. Newest on top (or bottom — configurable).
85
+
86
+ Cap visible: 3-5. Beyond that, oldest collapse to "+ N more" indicator.
87
+
88
+ ## Tokens consumed
89
+
90
+ ```
91
+ --notification-bg
92
+ --notification-fg
93
+ --notification-fg-muted (description)
94
+ --notification-success-icon
95
+ --notification-error-icon
96
+ --notification-warning-icon
97
+ --notification-info-icon
98
+ --notification-shadow
99
+ --radius-md
100
+ --space-md, --space-lg
101
+ --font-size-sm (description)
102
+ --font-weight-medium (title)
103
+ --motion-medium
104
+ --z-notification (above modals OR below; pick consciously)
105
+ ```
106
+
107
+ ## Accessibility
108
+
109
+ - `role="alert"` for time-sensitive (errors, warnings).
110
+ - `role="status"` for non-urgent.
111
+ - `aria-live="polite"` (status) or `assertive` (alert) — be sparing with assertive.
112
+ - Focus management: Notification doesn't steal focus by default. For action-required: persistent + focus the first button.
113
+ - Touch target ≥ 44pt for action buttons.
114
+
115
+ ## Korean conventions
116
+
117
+ ```
118
+ 새 메시지
119
+ @sungjin이 메시지를 보냈어요.
120
+ [답장] [확인]
121
+ ```
122
+
123
+ - 해요체 for casual brands; 합쇼체 for formal / banking.
124
+ - Title: 20자 이내; Body: 50자 이내.
125
+ - For 카카오톡 / KakaoTalk-style notifications: avatar + title + preview.
126
+
127
+ ## Code example
128
+
129
+ ```tsx
130
+ function NewMessageNotification({ message }: Props) {
131
+ return (
132
+ notification.info({
133
+ message: `새 메시지 — ${message.from}`,
134
+ description: message.preview,
135
+ placement: "topRight",
136
+ duration: 4.5,
137
+ icon: <Avatar src={message.fromAvatar} size="sm" />,
138
+ btn: (
139
+ <Button size="sm" onClick={() => navigate(`/messages/${message.id}`)}>
140
+ 확인
141
+ </Button>
142
+ ),
143
+ })
144
+ );
145
+ }
146
+ ```
147
+
148
+ ## Don't
149
+
150
+ - Don't use Notification for fleeting confirmation. Use Message or Toast.
151
+ - Don't show 6+ Notifications stacked. Cap visible.
152
+ - Don't auto-show on page load — feels like spam. Triggered by user action only.
153
+ - Don't put long body text. Description ≤ 2 lines; longer = open a Modal or page.
154
+ - Don't omit dismiss button on persistent notifications.
155
+
156
+ ## References
157
+
158
+ - Ant: [`Notification`](../refs/ant-design/components/notification)
159
+ - Native browser Notification API (different — uses OS-level notifications)
160
+ - iOS / Android notification card patterns
161
+
162
+ ## Cross-reference
163
+
164
+ - [`examples/component-toast.md`](component-toast.md) — smaller corner variant with Undo
165
+ - [`examples/component-message.md`](component-message.md) — top thin pill
166
+ - [`examples/component-banner.md`](component-banner.md) — persistent in-page strip
@@ -0,0 +1,245 @@
1
+ # `OTPCountdown` (custom — Korean SMS verification timer) — spec
2
+
3
+ > Korean fintech custom component. Pairs with `InputOTP` to manage SMS code resend cooldown + expiration timer. Shipped in every Korean SMS-auth flow.
4
+
5
+ ## Purpose
6
+
7
+ Show:
8
+ 1. **Time until code expires** (typically 3 minutes for SMS verification).
9
+ 2. **Time until resend allowed** (typically 30–60 seconds cooldown).
10
+ 3. **Resend button** when cooldown completes.
11
+
12
+ Without this: users frustrate themselves by tapping "재전송" repeatedly OR don't know when they can re-request.
13
+
14
+ ## Anatomy
15
+
16
+ ```
17
+ ┌─────────────────────────────────────┐
18
+ │ 인증번호 입력 │
19
+ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │
20
+ │ │ 1│ │ 2│ │ 3│ │ 4│ │ 5│ │ 6│ │ ← InputOTP
21
+ │ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ │
22
+ │ │
23
+ │ 남은 시간: 02:47 │ ← code expiration
24
+ │ [재전송하기] │ ← becomes active after cooldown
25
+ │ (30초 후 재전송 가능) │ ← cooldown indicator (alternates with button)
26
+ └─────────────────────────────────────┘
27
+ ```
28
+
29
+ ## API
30
+
31
+ ```tsx
32
+ <>
33
+ <InputOTP length={6} value={code} onValueChange={setCode} onComplete={verify} />
34
+ <OTPCountdown
35
+ expiresAt={codeExpiresAt} // 3 min from issue
36
+ cooldownSeconds={30} // resend cooldown
37
+ onResend={requestNewCode}
38
+ onExpired={() => setError("인증번호가 만료되었습니다.")}
39
+ />
40
+ </>
41
+ ```
42
+
43
+ | Prop | Type | Default | Description |
44
+ | --- | --- | --- | --- |
45
+ | `expiresAt` | `Date \| number` | — | When the code expires (Date or unix ms) |
46
+ | `cooldownSeconds` | `number` | `30` | Seconds before resend allowed |
47
+ | `onResend` | `() => void \| Promise<void>` | — | Trigger new code request |
48
+ | `onExpired` | `() => void` | — | Fired when expiresAt reached |
49
+ | `expiredMessage` | `string` | `"인증번호가 만료되었습니다"` | When code expires |
50
+ | `disabled` | `boolean` | `false` | Disable both timer + resend |
51
+
52
+ ## Behavior
53
+
54
+ ### Expiration timer
55
+
56
+ - Counts down from now to `expiresAt`.
57
+ - Format: `mm:ss` for typical 3-min window. `0:30` when under 1 min.
58
+ - Color shift to warning when < 30s remaining.
59
+ - At 0: fires `onExpired`, shows expired message, disables InputOTP.
60
+
61
+ ### Resend cooldown
62
+
63
+ - Starts at `cooldownSeconds` after component mount (or after each resend).
64
+ - Shows "30초 후 재전송 가능" while counting down.
65
+ - At 0: replaces with active "재전송하기" button.
66
+ - Tapping resend: triggers `onResend`, restarts both timers (cooldown + expiration).
67
+
68
+ ### State machine
69
+
70
+ ```
71
+ ┌──────────┐
72
+ │ initial │ ← timer starts, cooldown counts down
73
+ └─────┬────┘
74
+ │ cooldown reaches 0
75
+
76
+ ┌──────────────┐
77
+ │ resend ready │ ← button visible + active
78
+ └─────┬────────┘
79
+ │ user taps resend
80
+
81
+ ┌──────────┐
82
+ │ resending│ ← spinner; new request to server
83
+ └─────┬────┘
84
+ │ server returns new code expiry
85
+ ▼ (loop back to initial with new timers)
86
+
87
+ OR (independent):
88
+ │ expiresAt reached
89
+
90
+ ┌──────────┐
91
+ │ expired │ ← onExpired fires; ui shows message
92
+ └──────────┘
93
+ ```
94
+
95
+ ## States
96
+
97
+ | State | Visual |
98
+ | --- | --- |
99
+ | Initial — counting down | "남은 시간 02:47" + cooldown indicator |
100
+ | Cooldown done | "재전송하기" button active |
101
+ | Expiration warning (<30s) | Timer text in `--color-warning` |
102
+ | Expired | "인증번호가 만료되었습니다" + reload button |
103
+ | Resending | Button shows spinner; cooldown restarts after success |
104
+ | Disabled | All elements muted |
105
+
106
+ ## Tokens consumed
107
+
108
+ ```
109
+ --color-text-primary (timer)
110
+ --color-text-secondary (cooldown indicator)
111
+ --color-warning (timer warning <30s)
112
+ --color-error (expired)
113
+ --color-primary-default (active resend button)
114
+ --color-text-tertiary (disabled cooldown)
115
+ --space-sm, --space-md
116
+ --font-feature-amount: 'tnum' (digits align)
117
+ --font-size-sm, --font-size-base
118
+ --motion-fast
119
+ ```
120
+
121
+ ## Tabular numerals (critical)
122
+
123
+ Timer "02:47" → "02:46" → "02:45" must not visually shift width. Use `font-feature-settings: 'tnum'` so digits are equal-width.
124
+
125
+ ## Korean copy
126
+
127
+ | State | Copy |
128
+ | --- | --- |
129
+ | Time remaining | "남은 시간 mm:ss" or "유효시간 mm:ss" |
130
+ | Cooldown | "N초 후 재전송 가능" |
131
+ | Resend ready | "재전송하기" |
132
+ | Resending | "재전송 중..." |
133
+ | Expired | "인증번호가 만료되었습니다. 다시 발급받아 주세요." |
134
+ | Re-issue button | "인증번호 재발급" |
135
+
136
+ ## Accessibility
137
+
138
+ - Timer in `<span aria-live="off">` — don't announce every second (chatter).
139
+ - Update `aria-label` at milestones: "1분 남음", "30초 남음", "만료됨".
140
+ - Resend button: standard a11y, `aria-disabled` when in cooldown.
141
+ - Screen reader on expiration: announce once via `role="alert"`.
142
+
143
+ ## Implementation hints
144
+
145
+ ```tsx
146
+ function OTPCountdown({ expiresAt, cooldownSeconds, onResend, ... }: Props) {
147
+ const [now, setNow] = useState(Date.now());
148
+ const [cooldownEnd, setCooldownEnd] = useState(Date.now() + cooldownSeconds * 1000);
149
+ const [resending, setResending] = useState(false);
150
+
151
+ useEffect(() => {
152
+ const id = setInterval(() => setNow(Date.now()), 500); // 500ms is enough; UI shows seconds
153
+ return () => clearInterval(id);
154
+ }, []);
155
+
156
+ const expiresMs = Math.max(0, expiresAt - now);
157
+ const cooldownMs = Math.max(0, cooldownEnd - now);
158
+
159
+ // ... render based on state
160
+ }
161
+ ```
162
+
163
+ For server clock skew: pair `expiresAt` from server with a periodic time-sync. For 3-min SMS windows, ±5 seconds skew is tolerable.
164
+
165
+ ## Code example
166
+
167
+ ```tsx
168
+ function VerifyPhoneScreen({ phone }: Props) {
169
+ const [code, setCode] = useState("");
170
+ const [codeIssue, setCodeIssue] = useState({
171
+ expiresAt: Date.now() + 3 * 60 * 1000,
172
+ issuedAt: Date.now(),
173
+ });
174
+ const [error, setError] = useState<string>();
175
+
176
+ const handleResend = async () => {
177
+ const result = await api.resendCode({ phone });
178
+ setCodeIssue({
179
+ expiresAt: result.expiresAt,
180
+ issuedAt: Date.now(),
181
+ });
182
+ setCode(""); // clear input
183
+ };
184
+
185
+ const handleVerify = async (otpCode: string) => {
186
+ try {
187
+ await api.verifyCode({ phone, code: otpCode });
188
+ navigate("/success");
189
+ } catch (err) {
190
+ setError(err.message);
191
+ setCode("");
192
+ }
193
+ };
194
+
195
+ return (
196
+ <Page>
197
+ <Heading>인증번호 입력</Heading>
198
+ <p>{phone}로 보낸 6자리 인증번호를 입력해 주세요.</p>
199
+
200
+ <InputOTP
201
+ length={6}
202
+ value={code}
203
+ onValueChange={setCode}
204
+ onComplete={handleVerify}
205
+ autoFocus
206
+ errorText={error}
207
+ />
208
+
209
+ <OTPCountdown
210
+ expiresAt={codeIssue.expiresAt}
211
+ cooldownSeconds={30}
212
+ onResend={handleResend}
213
+ onExpired={() => setError("인증번호가 만료되었습니다. 재발급 받아주세요.")}
214
+ />
215
+ </Page>
216
+ );
217
+ }
218
+ ```
219
+
220
+ ## Edge cases
221
+
222
+ - **User backgrounds the app, returns minutes later**: timer continues based on real time (not React Time). On return: re-render with current diff.
223
+ - **Server-issued expiry slightly off from client clock**: tolerate ±5s.
224
+ - **Multiple rapid resends**: rate-limit via cooldown. If user spams tap: button stays cooldown.
225
+ - **Page navigation away + back**: timer state should persist (URL search params or shared store) — otherwise re-issuing on every nav is annoying.
226
+ - **Slow network on resend**: button stays in "재전송 중..." state until response. Don't allow second tap.
227
+
228
+ ## Don't
229
+
230
+ - Don't restart the expiration timer on resend without re-issuing a new code from server.
231
+ - Don't omit cooldown — users will spam-resend, server-side rate-limit will kick in confusingly.
232
+ - Don't update timer every 100ms (60Hz updates are wasteful for a 1-second display).
233
+ - Don't expire silently — user must know.
234
+ - Don't allow more than 3-5 resends per session (typical Korean carrier limit).
235
+
236
+ ## References
237
+
238
+ No upstream component matches exactly. This is a Korean-market-specific composition over `InputOTP` + countdown logic.
239
+
240
+ ## Cross-reference
241
+
242
+ - [`examples/component-input-otp.md`](component-input-otp.md) — pairs with this
243
+ - [`knowledge/i18n/korean-product-conventions.md`](../knowledge/i18n/korean-product-conventions.md) — Korean phone-auth conventions
244
+ - [`knowledge/i18n/korean-payments.md`](../knowledge/i18n/korean-payments.md) — broader 본인인증
245
+ - [`examples/component-pass-auth.md`](component-pass-auth.md) — full PASS / 본인인증 wrapper