@ciderpress/ui 1.0.0-rc.1

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 (428) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -0
  3. package/dist/0~142.js +2 -0
  4. package/dist/0~164.js +2 -0
  5. package/dist/0~2.js +2 -0
  6. package/dist/0~225.js +2 -0
  7. package/dist/0~288.js +2 -0
  8. package/dist/0~299.js +2 -0
  9. package/dist/0~3.js +2 -0
  10. package/dist/0~301.js +2 -0
  11. package/dist/0~311.js +2 -0
  12. package/dist/0~326.js +2 -0
  13. package/dist/0~40.js +2 -0
  14. package/dist/0~43.js +2 -0
  15. package/dist/0~433.js +2 -0
  16. package/dist/0~453.js +2 -0
  17. package/dist/0~457.js +2 -0
  18. package/dist/0~497.js +2 -0
  19. package/dist/0~511.js +2 -0
  20. package/dist/0~603.js +2 -0
  21. package/dist/0~616.js +2 -0
  22. package/dist/0~659.js +2 -0
  23. package/dist/0~670.js +2 -0
  24. package/dist/0~687.js +2 -0
  25. package/dist/0~706.js +2 -0
  26. package/dist/0~729.js +2 -0
  27. package/dist/0~768.js +2 -0
  28. package/dist/0~819.js +2 -0
  29. package/dist/0~830.js +2 -0
  30. package/dist/0~854.js +2 -0
  31. package/dist/0~863.js +2 -0
  32. package/dist/0~879.js +2 -0
  33. package/dist/0~96.js +2 -0
  34. package/dist/0~97.js +2 -0
  35. package/dist/components/FileTree/FileTree.css +90 -0
  36. package/dist/components/FileTree/FileTree.d.ts +7 -0
  37. package/dist/components/FileTree/FileTree.js +531 -0
  38. package/dist/components/FileTree/FileTreeItem.d.ts +8 -0
  39. package/dist/components/FileTree/RemoteSvgIcon.d.ts +11 -0
  40. package/dist/components/FileTree/index.d.ts +4 -0
  41. package/dist/components/folder-icons.d.ts +32 -0
  42. package/dist/components/languages.d.ts +7 -0
  43. package/dist/components/tree-parser/tree-parser.d.ts +12 -0
  44. package/dist/components/tree-parser/types.d.ts +11 -0
  45. package/dist/head/css/loader-apple.css +1 -0
  46. package/dist/head/css/loader-backdrop.css +1 -0
  47. package/dist/head/css/loader-dots.css +1 -0
  48. package/dist/head/css/themes/amber.css +1 -0
  49. package/dist/head/css/themes/arcade.css +1 -0
  50. package/dist/head/css/themes/grannysmith.css +1 -0
  51. package/dist/head/css/themes/honeycrisp.css +1 -0
  52. package/dist/head/css/themes/midnight.css +1 -0
  53. package/dist/head/css/themes/mulled.css +1 -0
  54. package/dist/head/js/loader-dots.js +1 -0
  55. package/dist/head/js/vscode-nav.js +1 -0
  56. package/dist/index.d.ts +43 -0
  57. package/dist/index.mjs +40 -0
  58. package/dist/node.d.ts +81 -0
  59. package/dist/node.mjs +17762 -0
  60. package/dist/plugins/mermaid/MermaidRenderer.tsx +480 -0
  61. package/dist/plugins/mermaid/mermaid.css +199 -0
  62. package/dist/theme/components/announcement/announcement-bar.css +103 -0
  63. package/dist/theme/components/announcement/announcement-bar.tsx +173 -0
  64. package/dist/theme/components/ask-ai/ask-ai-button.css +52 -0
  65. package/dist/theme/components/ask-ai/ask-ai-button.tsx +56 -0
  66. package/dist/theme/components/content-footer/content-footer-portal.tsx +70 -0
  67. package/dist/theme/components/content-footer/feedback.css +47 -0
  68. package/dist/theme/components/content-footer/feedback.tsx +96 -0
  69. package/dist/theme/components/content-footer/meta-actions.css +25 -0
  70. package/dist/theme/components/content-footer/meta-actions.tsx +57 -0
  71. package/dist/theme/components/content-footer/page-pager.css +61 -0
  72. package/dist/theme/components/content-footer/page-pager.tsx +110 -0
  73. package/dist/theme/components/edit-source-button.tsx +97 -0
  74. package/dist/theme/components/footer/site-footer.css +179 -0
  75. package/dist/theme/components/footer/site-footer.tsx +115 -0
  76. package/dist/theme/components/home/cta.css +67 -0
  77. package/dist/theme/components/home/cta.tsx +77 -0
  78. package/dist/theme/components/home/feature-card.css +52 -0
  79. package/dist/theme/components/home/feature-card.tsx +131 -0
  80. package/dist/theme/components/home/feature.tsx +79 -0
  81. package/dist/theme/components/home/hero-demo.css +66 -0
  82. package/dist/theme/components/home/hero-demo.tsx +46 -0
  83. package/dist/theme/components/home/hero.css +96 -0
  84. package/dist/theme/components/home/hero.tsx +111 -0
  85. package/dist/theme/components/home/layout.tsx +183 -0
  86. package/dist/theme/components/home/page-rail.css +21 -0
  87. package/dist/theme/components/home/page-rail.tsx +19 -0
  88. package/dist/theme/components/home/split.css +148 -0
  89. package/dist/theme/components/home/split.tsx +120 -0
  90. package/dist/theme/components/home/trust-strip.css +33 -0
  91. package/dist/theme/components/home/trust-strip.tsx +43 -0
  92. package/dist/theme/components/home/workspaces.tsx +71 -0
  93. package/dist/theme/components/nav/branch-tag.css +54 -0
  94. package/dist/theme/components/nav/branch-tag.tsx +101 -0
  95. package/dist/theme/components/nav/ciderpress-doc-layout.tsx +247 -0
  96. package/dist/theme/components/nav/ciderpress-docs-bar.css +505 -0
  97. package/dist/theme/components/nav/ciderpress-docs-bar.tsx +426 -0
  98. package/dist/theme/components/nav/ciderpress-header.css +172 -0
  99. package/dist/theme/components/nav/ciderpress-header.tsx +113 -0
  100. package/dist/theme/components/nav/ciderpress-layout-context.tsx +49 -0
  101. package/dist/theme/components/nav/ciderpress-nav-hamburger.css +193 -0
  102. package/dist/theme/components/nav/ciderpress-nav-hamburger.tsx +112 -0
  103. package/dist/theme/components/nav/ciderpress-nav-menu.css +130 -0
  104. package/dist/theme/components/nav/ciderpress-nav-menu.tsx +372 -0
  105. package/dist/theme/components/nav/ciderpress-nav-search.css +73 -0
  106. package/dist/theme/components/nav/ciderpress-nav-search.tsx +55 -0
  107. package/dist/theme/components/nav/ciderpress-nav-social-links.css +35 -0
  108. package/dist/theme/components/nav/ciderpress-nav-social-links.tsx +87 -0
  109. package/dist/theme/components/nav/floating-branch-indicator.css +106 -0
  110. package/dist/theme/components/nav/floating-branch-indicator.tsx +109 -0
  111. package/dist/theme/components/nav/layout.tsx +268 -0
  112. package/dist/theme/components/nav/mobile-nav-cta.tsx +79 -0
  113. package/dist/theme/components/nav/nav-divider.css +15 -0
  114. package/dist/theme/components/nav/nav-divider.tsx +19 -0
  115. package/dist/theme/components/nav/nav-logo.css +42 -0
  116. package/dist/theme/components/nav/nav-logo.tsx +262 -0
  117. package/dist/theme/components/nav/theme-switcher.css +92 -0
  118. package/dist/theme/components/nav/theme-switcher.tsx +298 -0
  119. package/dist/theme/components/nav/topbar-cta.css +45 -0
  120. package/dist/theme/components/nav/topbar-cta.tsx +39 -0
  121. package/dist/theme/components/nav/variant-toggle.css +70 -0
  122. package/dist/theme/components/nav/variant-toggle.tsx +83 -0
  123. package/dist/theme/components/nav/version-chip.css +31 -0
  124. package/dist/theme/components/nav/version-chip.tsx +45 -0
  125. package/dist/theme/components/nav/vscode-tag.css +32 -0
  126. package/dist/theme/components/nav/vscode-tag.tsx +20 -0
  127. package/dist/theme/components/openapi/code-sample.tsx +341 -0
  128. package/dist/theme/components/openapi/copy-markdown-button.tsx +41 -0
  129. package/dist/theme/components/openapi/icons.tsx +45 -0
  130. package/dist/theme/components/openapi/index.ts +6 -0
  131. package/dist/theme/components/openapi/method-badge.tsx +24 -0
  132. package/dist/theme/components/openapi/openapi.css +665 -0
  133. package/dist/theme/components/openapi/operation.tsx +200 -0
  134. package/dist/theme/components/openapi/overview.tsx +207 -0
  135. package/dist/theme/components/openapi/parameters-table.tsx +149 -0
  136. package/dist/theme/components/openapi/request-body.tsx +90 -0
  137. package/dist/theme/components/openapi/response-list.tsx +112 -0
  138. package/dist/theme/components/openapi/schema-viewer.tsx +277 -0
  139. package/dist/theme/components/openapi/security-badges.tsx +63 -0
  140. package/dist/theme/components/openapi/spec-utils.ts +122 -0
  141. package/dist/theme/components/shared/accordion.css +118 -0
  142. package/dist/theme/components/shared/accordion.stories.tsx +96 -0
  143. package/dist/theme/components/shared/accordion.tsx +191 -0
  144. package/dist/theme/components/shared/brand-logo.stories.tsx +49 -0
  145. package/dist/theme/components/shared/brand-mark.stories.tsx +53 -0
  146. package/dist/theme/components/shared/browser-window.css +1 -0
  147. package/dist/theme/components/shared/browser-window.stories.tsx +100 -0
  148. package/dist/theme/components/shared/browser-window.tsx +2 -0
  149. package/dist/theme/components/shared/card.stories.tsx +50 -0
  150. package/dist/theme/components/shared/card.tsx +35 -0
  151. package/dist/theme/components/shared/ciderpress-logo.tsx +93 -0
  152. package/dist/theme/components/shared/ciderpress-mark.tsx +77 -0
  153. package/dist/theme/components/shared/color.css +56 -0
  154. package/dist/theme/components/shared/color.stories.tsx +47 -0
  155. package/dist/theme/components/shared/color.tsx +69 -0
  156. package/dist/theme/components/shared/columns.css +37 -0
  157. package/dist/theme/components/shared/columns.stories.tsx +91 -0
  158. package/dist/theme/components/shared/columns.tsx +50 -0
  159. package/dist/theme/components/shared/desktop-window.css +339 -0
  160. package/dist/theme/components/shared/desktop-window.tsx +535 -0
  161. package/dist/theme/components/shared/field.css +158 -0
  162. package/dist/theme/components/shared/field.stories.tsx +100 -0
  163. package/dist/theme/components/shared/field.tsx +186 -0
  164. package/dist/theme/components/shared/frame.css +39 -0
  165. package/dist/theme/components/shared/frame.stories.tsx +49 -0
  166. package/dist/theme/components/shared/frame.tsx +76 -0
  167. package/dist/theme/components/shared/icon.stories.tsx +90 -0
  168. package/dist/theme/components/shared/icon.tsx +41 -0
  169. package/dist/theme/components/shared/prompt.css +178 -0
  170. package/dist/theme/components/shared/prompt.stories.tsx +57 -0
  171. package/dist/theme/components/shared/prompt.tsx +369 -0
  172. package/dist/theme/components/shared/resolve-card-icon.ts +28 -0
  173. package/dist/theme/components/shared/section-card.stories.tsx +51 -0
  174. package/dist/theme/components/shared/section-card.tsx +44 -0
  175. package/dist/theme/components/shared/section-grid.stories.tsx +46 -0
  176. package/dist/theme/components/shared/section-grid.tsx +15 -0
  177. package/dist/theme/components/shared/status-badge.css +37 -0
  178. package/dist/theme/components/shared/status-badge.stories.tsx +61 -0
  179. package/dist/theme/components/shared/status-badge.tsx +74 -0
  180. package/dist/theme/components/shared/steps.css +88 -0
  181. package/dist/theme/components/shared/steps.stories.tsx +68 -0
  182. package/dist/theme/components/shared/steps.tsx +100 -0
  183. package/dist/theme/components/shared/tech-icon-table.stories.tsx +29 -0
  184. package/dist/theme/components/shared/tech-icon-table.tsx +71 -0
  185. package/dist/theme/components/shared/tech-tag.stories.tsx +40 -0
  186. package/dist/theme/components/shared/tech-tag.tsx +31 -0
  187. package/dist/theme/components/shared/theme-color-palette.css +80 -0
  188. package/dist/theme/components/shared/theme-color-palette.stories.tsx +52 -0
  189. package/dist/theme/components/shared/theme-color-palette.tsx +275 -0
  190. package/dist/theme/components/shared/tooltip.css +69 -0
  191. package/dist/theme/components/shared/tooltip.stories.tsx +72 -0
  192. package/dist/theme/components/shared/tooltip.tsx +77 -0
  193. package/dist/theme/components/sidebar/framework-picker.css +77 -0
  194. package/dist/theme/components/sidebar/framework-picker.tsx +78 -0
  195. package/dist/theme/components/sidebar/sidebar-filter.test.ts +140 -0
  196. package/dist/theme/components/sidebar/sidebar-filter.ts +79 -0
  197. package/dist/theme/components/sidebar/sidebar-links.css +102 -0
  198. package/dist/theme/components/sidebar/sidebar-links.tsx +122 -0
  199. package/dist/theme/components/sidebar/sidebar-promo.css +42 -0
  200. package/dist/theme/components/sidebar/sidebar-promo.tsx +52 -0
  201. package/dist/theme/components/sidebar/sidebar-scope.tsx +151 -0
  202. package/dist/theme/components/sidebar/sidebar-toggle.css +181 -0
  203. package/dist/theme/components/sidebar/sidebar-toggle.tsx +127 -0
  204. package/dist/theme/components/theme-provider.tsx +637 -0
  205. package/dist/theme/components/workspaces/card.css +151 -0
  206. package/dist/theme/components/workspaces/card.tsx +166 -0
  207. package/dist/theme/components/workspaces/grid.tsx +62 -0
  208. package/dist/theme/css.d.ts +1 -0
  209. package/dist/theme/env.d.ts +12 -0
  210. package/dist/theme/fonts/GeistMono-Variable.woff2 +0 -0
  211. package/dist/theme/fonts/GeistPixel-Square.woff2 +0 -0
  212. package/dist/theme/fonts/GeistSans-Variable.woff2 +0 -0
  213. package/dist/theme/hooks/use-ciderpress.ts +61 -0
  214. package/dist/theme/hooks/use-nav-items.ts +76 -0
  215. package/dist/theme/icons/index.ts +2 -0
  216. package/dist/theme/icons/tech-map.ts +228 -0
  217. package/dist/theme/index.tsx +180 -0
  218. package/dist/theme/lib/read-social-links.ts +27 -0
  219. package/dist/theme/lib/route-link.tsx +126 -0
  220. package/dist/theme/lib/safe-url.test.ts +0 -0
  221. package/dist/theme/lib/safe-url.ts +68 -0
  222. package/dist/theme/lib/theme-favicon.ts +125 -0
  223. package/dist/theme/lib/user-config-stub.ts +12 -0
  224. package/dist/theme/styles/layers.css +32 -0
  225. package/dist/theme/styles/overrides/badge.css +26 -0
  226. package/dist/theme/styles/overrides/content-footer.css +80 -0
  227. package/dist/theme/styles/overrides/details.css +61 -0
  228. package/dist/theme/styles/overrides/fonts.css +32 -0
  229. package/dist/theme/styles/overrides/home-card.css +133 -0
  230. package/dist/theme/styles/overrides/home.css +243 -0
  231. package/dist/theme/styles/overrides/rail.css +337 -0
  232. package/dist/theme/styles/overrides/rspress.css +62 -0
  233. package/dist/theme/styles/overrides/scrollbar.css +25 -0
  234. package/dist/theme/styles/overrides/section-card.css +114 -0
  235. package/dist/theme/styles/overrides/sidebar.css +144 -0
  236. package/dist/theme/styles/overrides/tokens.css +288 -0
  237. package/dist/theme/styles/overrides/vscode.css +88 -0
  238. package/dist/theme/styles/themes/amber.css +545 -0
  239. package/dist/theme/styles/themes/arcade-fx.css +366 -0
  240. package/dist/theme/styles/themes/arcade.css +273 -0
  241. package/dist/theme/styles/themes/grannysmith.css +545 -0
  242. package/dist/theme/styles/themes/honeycrisp.css +545 -0
  243. package/dist/theme/styles/themes/midnight.css +273 -0
  244. package/dist/theme/styles/themes/mulled.css +817 -0
  245. package/package.json +103 -0
  246. package/src/theme/components/announcement/announcement-bar.css +103 -0
  247. package/src/theme/components/announcement/announcement-bar.tsx +173 -0
  248. package/src/theme/components/ask-ai/ask-ai-button.css +52 -0
  249. package/src/theme/components/ask-ai/ask-ai-button.tsx +56 -0
  250. package/src/theme/components/content-footer/content-footer-portal.tsx +70 -0
  251. package/src/theme/components/content-footer/feedback.css +47 -0
  252. package/src/theme/components/content-footer/feedback.tsx +96 -0
  253. package/src/theme/components/content-footer/meta-actions.css +25 -0
  254. package/src/theme/components/content-footer/meta-actions.tsx +57 -0
  255. package/src/theme/components/content-footer/page-pager.css +61 -0
  256. package/src/theme/components/content-footer/page-pager.tsx +110 -0
  257. package/src/theme/components/edit-source-button.tsx +97 -0
  258. package/src/theme/components/footer/site-footer.css +179 -0
  259. package/src/theme/components/footer/site-footer.tsx +115 -0
  260. package/src/theme/components/home/cta.css +67 -0
  261. package/src/theme/components/home/cta.tsx +77 -0
  262. package/src/theme/components/home/feature-card.css +52 -0
  263. package/src/theme/components/home/feature-card.tsx +131 -0
  264. package/src/theme/components/home/feature.tsx +79 -0
  265. package/src/theme/components/home/hero-demo.css +66 -0
  266. package/src/theme/components/home/hero-demo.tsx +46 -0
  267. package/src/theme/components/home/hero.css +96 -0
  268. package/src/theme/components/home/hero.tsx +111 -0
  269. package/src/theme/components/home/layout.tsx +183 -0
  270. package/src/theme/components/home/page-rail.css +21 -0
  271. package/src/theme/components/home/page-rail.tsx +19 -0
  272. package/src/theme/components/home/split.css +148 -0
  273. package/src/theme/components/home/split.tsx +120 -0
  274. package/src/theme/components/home/trust-strip.css +33 -0
  275. package/src/theme/components/home/trust-strip.tsx +43 -0
  276. package/src/theme/components/home/workspaces.tsx +71 -0
  277. package/src/theme/components/nav/branch-tag.css +54 -0
  278. package/src/theme/components/nav/branch-tag.tsx +101 -0
  279. package/src/theme/components/nav/ciderpress-doc-layout.tsx +247 -0
  280. package/src/theme/components/nav/ciderpress-docs-bar.css +505 -0
  281. package/src/theme/components/nav/ciderpress-docs-bar.tsx +426 -0
  282. package/src/theme/components/nav/ciderpress-header.css +172 -0
  283. package/src/theme/components/nav/ciderpress-header.tsx +113 -0
  284. package/src/theme/components/nav/ciderpress-layout-context.tsx +49 -0
  285. package/src/theme/components/nav/ciderpress-nav-hamburger.css +193 -0
  286. package/src/theme/components/nav/ciderpress-nav-hamburger.tsx +112 -0
  287. package/src/theme/components/nav/ciderpress-nav-menu.css +130 -0
  288. package/src/theme/components/nav/ciderpress-nav-menu.tsx +372 -0
  289. package/src/theme/components/nav/ciderpress-nav-search.css +73 -0
  290. package/src/theme/components/nav/ciderpress-nav-search.tsx +55 -0
  291. package/src/theme/components/nav/ciderpress-nav-social-links.css +35 -0
  292. package/src/theme/components/nav/ciderpress-nav-social-links.tsx +87 -0
  293. package/src/theme/components/nav/floating-branch-indicator.css +106 -0
  294. package/src/theme/components/nav/floating-branch-indicator.tsx +109 -0
  295. package/src/theme/components/nav/layout.tsx +268 -0
  296. package/src/theme/components/nav/mobile-nav-cta.tsx +79 -0
  297. package/src/theme/components/nav/nav-divider.css +15 -0
  298. package/src/theme/components/nav/nav-divider.tsx +19 -0
  299. package/src/theme/components/nav/nav-logo.css +42 -0
  300. package/src/theme/components/nav/nav-logo.tsx +262 -0
  301. package/src/theme/components/nav/theme-switcher.css +92 -0
  302. package/src/theme/components/nav/theme-switcher.tsx +298 -0
  303. package/src/theme/components/nav/topbar-cta.css +45 -0
  304. package/src/theme/components/nav/topbar-cta.tsx +39 -0
  305. package/src/theme/components/nav/variant-toggle.css +70 -0
  306. package/src/theme/components/nav/variant-toggle.tsx +83 -0
  307. package/src/theme/components/nav/version-chip.css +31 -0
  308. package/src/theme/components/nav/version-chip.tsx +45 -0
  309. package/src/theme/components/nav/vscode-tag.css +32 -0
  310. package/src/theme/components/nav/vscode-tag.tsx +20 -0
  311. package/src/theme/components/openapi/code-sample.tsx +341 -0
  312. package/src/theme/components/openapi/copy-markdown-button.tsx +41 -0
  313. package/src/theme/components/openapi/icons.tsx +45 -0
  314. package/src/theme/components/openapi/index.ts +6 -0
  315. package/src/theme/components/openapi/method-badge.tsx +24 -0
  316. package/src/theme/components/openapi/openapi.css +665 -0
  317. package/src/theme/components/openapi/operation.tsx +200 -0
  318. package/src/theme/components/openapi/overview.tsx +207 -0
  319. package/src/theme/components/openapi/parameters-table.tsx +149 -0
  320. package/src/theme/components/openapi/request-body.tsx +90 -0
  321. package/src/theme/components/openapi/response-list.tsx +112 -0
  322. package/src/theme/components/openapi/schema-viewer.tsx +277 -0
  323. package/src/theme/components/openapi/security-badges.tsx +63 -0
  324. package/src/theme/components/openapi/spec-utils.ts +122 -0
  325. package/src/theme/components/shared/accordion.css +118 -0
  326. package/src/theme/components/shared/accordion.stories.tsx +96 -0
  327. package/src/theme/components/shared/accordion.tsx +191 -0
  328. package/src/theme/components/shared/brand-logo.stories.tsx +49 -0
  329. package/src/theme/components/shared/brand-mark.stories.tsx +53 -0
  330. package/src/theme/components/shared/browser-window.css +1 -0
  331. package/src/theme/components/shared/browser-window.stories.tsx +100 -0
  332. package/src/theme/components/shared/browser-window.tsx +2 -0
  333. package/src/theme/components/shared/card.stories.tsx +50 -0
  334. package/src/theme/components/shared/card.tsx +35 -0
  335. package/src/theme/components/shared/ciderpress-logo.tsx +93 -0
  336. package/src/theme/components/shared/ciderpress-mark.tsx +77 -0
  337. package/src/theme/components/shared/color.css +56 -0
  338. package/src/theme/components/shared/color.stories.tsx +47 -0
  339. package/src/theme/components/shared/color.tsx +69 -0
  340. package/src/theme/components/shared/columns.css +37 -0
  341. package/src/theme/components/shared/columns.stories.tsx +91 -0
  342. package/src/theme/components/shared/columns.tsx +50 -0
  343. package/src/theme/components/shared/desktop-window.css +339 -0
  344. package/src/theme/components/shared/desktop-window.tsx +535 -0
  345. package/src/theme/components/shared/field.css +158 -0
  346. package/src/theme/components/shared/field.stories.tsx +100 -0
  347. package/src/theme/components/shared/field.tsx +186 -0
  348. package/src/theme/components/shared/frame.css +39 -0
  349. package/src/theme/components/shared/frame.stories.tsx +49 -0
  350. package/src/theme/components/shared/frame.tsx +76 -0
  351. package/src/theme/components/shared/icon.stories.tsx +90 -0
  352. package/src/theme/components/shared/icon.tsx +41 -0
  353. package/src/theme/components/shared/prompt.css +178 -0
  354. package/src/theme/components/shared/prompt.stories.tsx +57 -0
  355. package/src/theme/components/shared/prompt.tsx +369 -0
  356. package/src/theme/components/shared/resolve-card-icon.ts +28 -0
  357. package/src/theme/components/shared/section-card.stories.tsx +51 -0
  358. package/src/theme/components/shared/section-card.tsx +44 -0
  359. package/src/theme/components/shared/section-grid.stories.tsx +46 -0
  360. package/src/theme/components/shared/section-grid.tsx +15 -0
  361. package/src/theme/components/shared/status-badge.css +37 -0
  362. package/src/theme/components/shared/status-badge.stories.tsx +61 -0
  363. package/src/theme/components/shared/status-badge.tsx +74 -0
  364. package/src/theme/components/shared/steps.css +88 -0
  365. package/src/theme/components/shared/steps.stories.tsx +68 -0
  366. package/src/theme/components/shared/steps.tsx +100 -0
  367. package/src/theme/components/shared/tech-icon-table.stories.tsx +29 -0
  368. package/src/theme/components/shared/tech-icon-table.tsx +71 -0
  369. package/src/theme/components/shared/tech-tag.stories.tsx +40 -0
  370. package/src/theme/components/shared/tech-tag.tsx +31 -0
  371. package/src/theme/components/shared/theme-color-palette.css +80 -0
  372. package/src/theme/components/shared/theme-color-palette.stories.tsx +52 -0
  373. package/src/theme/components/shared/theme-color-palette.tsx +275 -0
  374. package/src/theme/components/shared/tooltip.css +69 -0
  375. package/src/theme/components/shared/tooltip.stories.tsx +72 -0
  376. package/src/theme/components/shared/tooltip.tsx +77 -0
  377. package/src/theme/components/sidebar/framework-picker.css +77 -0
  378. package/src/theme/components/sidebar/framework-picker.tsx +78 -0
  379. package/src/theme/components/sidebar/sidebar-filter.test.ts +140 -0
  380. package/src/theme/components/sidebar/sidebar-filter.ts +79 -0
  381. package/src/theme/components/sidebar/sidebar-links.css +102 -0
  382. package/src/theme/components/sidebar/sidebar-links.tsx +122 -0
  383. package/src/theme/components/sidebar/sidebar-promo.css +42 -0
  384. package/src/theme/components/sidebar/sidebar-promo.tsx +52 -0
  385. package/src/theme/components/sidebar/sidebar-scope.tsx +151 -0
  386. package/src/theme/components/sidebar/sidebar-toggle.css +181 -0
  387. package/src/theme/components/sidebar/sidebar-toggle.tsx +127 -0
  388. package/src/theme/components/theme-provider.tsx +637 -0
  389. package/src/theme/components/workspaces/card.css +151 -0
  390. package/src/theme/components/workspaces/card.tsx +166 -0
  391. package/src/theme/components/workspaces/grid.tsx +62 -0
  392. package/src/theme/css.d.ts +1 -0
  393. package/src/theme/env.d.ts +12 -0
  394. package/src/theme/fonts/GeistMono-Variable.woff2 +0 -0
  395. package/src/theme/fonts/GeistPixel-Square.woff2 +0 -0
  396. package/src/theme/fonts/GeistSans-Variable.woff2 +0 -0
  397. package/src/theme/hooks/use-ciderpress.ts +61 -0
  398. package/src/theme/hooks/use-nav-items.ts +76 -0
  399. package/src/theme/icons/index.ts +2 -0
  400. package/src/theme/icons/tech-map.ts +228 -0
  401. package/src/theme/index.tsx +180 -0
  402. package/src/theme/lib/read-social-links.ts +27 -0
  403. package/src/theme/lib/route-link.tsx +126 -0
  404. package/src/theme/lib/safe-url.test.ts +0 -0
  405. package/src/theme/lib/safe-url.ts +68 -0
  406. package/src/theme/lib/theme-favicon.ts +125 -0
  407. package/src/theme/lib/user-config-stub.ts +12 -0
  408. package/src/theme/styles/layers.css +32 -0
  409. package/src/theme/styles/overrides/badge.css +26 -0
  410. package/src/theme/styles/overrides/content-footer.css +80 -0
  411. package/src/theme/styles/overrides/details.css +61 -0
  412. package/src/theme/styles/overrides/fonts.css +32 -0
  413. package/src/theme/styles/overrides/home-card.css +133 -0
  414. package/src/theme/styles/overrides/home.css +243 -0
  415. package/src/theme/styles/overrides/rail.css +337 -0
  416. package/src/theme/styles/overrides/rspress.css +62 -0
  417. package/src/theme/styles/overrides/scrollbar.css +25 -0
  418. package/src/theme/styles/overrides/section-card.css +114 -0
  419. package/src/theme/styles/overrides/sidebar.css +144 -0
  420. package/src/theme/styles/overrides/tokens.css +288 -0
  421. package/src/theme/styles/overrides/vscode.css +88 -0
  422. package/src/theme/styles/themes/amber.css +545 -0
  423. package/src/theme/styles/themes/arcade-fx.css +366 -0
  424. package/src/theme/styles/themes/arcade.css +273 -0
  425. package/src/theme/styles/themes/grannysmith.css +545 -0
  426. package/src/theme/styles/themes/honeycrisp.css +545 -0
  427. package/src/theme/styles/themes/midnight.css +273 -0
  428. package/src/theme/styles/themes/mulled.css +817 -0
@@ -0,0 +1,183 @@
1
+ import { useFrontmatter } from '@rspress/core/runtime'
2
+ import { match } from 'massaman/match'
3
+ import type React from 'react'
4
+
5
+ import { SiteFooter } from '../footer/site-footer'
6
+ import { CTA } from './cta'
7
+ import { HomeFeature } from './feature'
8
+ import { Hero } from './hero'
9
+ import type { HeroAction } from './hero'
10
+ import { HeroDemo } from './hero-demo'
11
+ import { PageRail } from './page-rail'
12
+ import { HomeSplit } from './split'
13
+ import { TrustStrip } from './trust-strip'
14
+ import { HomeWorkspaces } from './workspaces'
15
+
16
+ interface HomeLayoutProps {
17
+ readonly beforeHero?: React.ReactNode
18
+ readonly afterHero?: React.ReactNode
19
+ readonly beforeFeatures?: React.ReactNode
20
+ readonly afterFeatures?: React.ReactNode
21
+ }
22
+
23
+ interface FrontmatterHero {
24
+ readonly name?: string
25
+ readonly text?: string
26
+ readonly tagline?: string
27
+ readonly actions?: readonly HeroAction[]
28
+ readonly eyebrow?: string
29
+ }
30
+
31
+ interface FrontmatterTrust {
32
+ readonly lead?: string
33
+ readonly names?: readonly string[]
34
+ }
35
+
36
+ interface FrontmatterCTA {
37
+ readonly title?: string
38
+ readonly subtitle?: string
39
+ readonly actions?: readonly HeroAction[]
40
+ }
41
+
42
+ /**
43
+ * Custom HomeLayout for ciderpress.
44
+ *
45
+ * Renders the approved mockup landing surface inside a continuous PageRail:
46
+ * Hero → TrustStrip → Features → Workspaces → CTA → SiteFooter. Sections
47
+ * render only when their data is present in frontmatter, so consumers opt
48
+ * in to each band individually.
49
+ *
50
+ * @param props - Slot props (kept for API compatibility with Rspress's HomeLayout).
51
+ * @returns React element with the home page.
52
+ */
53
+ export function HomeLayout(props: HomeLayoutProps): React.ReactElement {
54
+ const { frontmatter } = useFrontmatter()
55
+ const fm = frontmatter as Record<string, unknown>
56
+
57
+ const hero = fm.hero as FrontmatterHero | undefined
58
+ const trust = fm.trust as FrontmatterTrust | undefined
59
+ const cta = fm.cta as FrontmatterCTA | undefined
60
+
61
+ const heroSection = match(hero)
62
+ .with(undefined, () => null)
63
+ .otherwise((h) => (
64
+ <Hero
65
+ eyebrow={h.eyebrow}
66
+ title={renderTitle(h.text ?? h.name ?? '')}
67
+ tagline={h.tagline}
68
+ actions={h.actions}
69
+ demo={<HeroDemo />}
70
+ />
71
+ ))
72
+
73
+ const trustSection = match(trust)
74
+ .with(undefined, () => null)
75
+ .otherwise((t) => {
76
+ const names = t.names ?? []
77
+ return match(names.length === 0)
78
+ .with(true, () => null)
79
+ .otherwise(() => <TrustStrip lead={t.lead} names={names} />)
80
+ })
81
+
82
+ const ctaSection = match(cta)
83
+ .with(undefined, () => null)
84
+ .otherwise((c) =>
85
+ match(c.title === undefined)
86
+ .with(true, () => null)
87
+ .otherwise(() => <CTA title={c.title ?? ''} subtitle={c.subtitle} actions={c.actions} />)
88
+ )
89
+
90
+ return (
91
+ <PageRail>
92
+ {props.beforeHero}
93
+ {heroSection}
94
+ {props.afterHero}
95
+ {trustSection}
96
+ {props.beforeFeatures}
97
+ <HomeFeature />
98
+ {props.afterFeatures}
99
+ <HomeSplit
100
+ eyebrow="Configuration"
101
+ title="One file. Validated. Type-safe."
102
+ body="Define your docs site in ciderpress.config.ts. Zod validates at boot — no surprises in prod."
103
+ bullets={[
104
+ 'Type-safe config with full IntelliSense',
105
+ 'Hot-reloads on every save',
106
+ 'Composable presets for OpenAPI, blog, changelog',
107
+ 'First-class i18n out of the box',
108
+ ]}
109
+ action={{ theme: 'brand', text: 'Read the docs', link: '/getting-started/quick-start' }}
110
+ visual={<ConfigPreview />}
111
+ />
112
+ <HomeWorkspaces />
113
+ {ctaSection}
114
+ <SiteFooter />
115
+ </PageRail>
116
+ )
117
+ }
118
+
119
+ /**
120
+ * ConfigPreview — minimal `defineConfig` code preview shown inside the
121
+ * Split section. Imports come exclusively from `ciderpress` so the
122
+ * sample resolves against the published package set.
123
+ *
124
+ * @returns React element.
125
+ */
126
+ function ConfigPreview(): React.ReactElement {
127
+ return (
128
+ <pre>
129
+ <span className="tok-kw">import</span> {'{ defineConfig }'}{' '}
130
+ <span className="tok-kw">from</span> <span className="tok-str">'ciderpress'</span>
131
+ {'\n\n'}
132
+ <span className="tok-kw">export default</span> <span className="tok-fn">defineConfig</span>
133
+ {'({\n'}
134
+ {' title: '}
135
+ <span className="tok-str">'Acme Docs'</span>
136
+ {',\n'}
137
+ {' sections: [\n'}
138
+ {' { title: '}
139
+ <span className="tok-str">'Guides'</span>
140
+ {', include: '}
141
+ <span className="tok-str">'docs/guides/*.md'</span>
142
+ {' },\n'}
143
+ {' ],\n'}
144
+ {' theme: { name: '}
145
+ <span className="tok-str">'mulled'</span>
146
+ {' },\n'}
147
+ {'})'}
148
+ </pre>
149
+ )
150
+ }
151
+
152
+ /**
153
+ * Render a hero title with the trailing segment styled as a gradient.
154
+ *
155
+ * Splits the title on its last word break and wraps the tail in
156
+ * `<span className="cp-hero__grad">`. When the title is a single word
157
+ * (or empty), it renders verbatim.
158
+ *
159
+ * @private
160
+ * @param raw - The raw title string from frontmatter.
161
+ * @returns Title fragment with a gradient tail when applicable.
162
+ */
163
+ function renderTitle(raw: string): React.ReactNode {
164
+ const trimmed = raw.trim()
165
+ return match(trimmed.length === 0)
166
+ .with(true, () => null)
167
+ .otherwise(() => {
168
+ const words = trimmed.split(/\s+/)
169
+ return match(words.length <= 1)
170
+ .with(true, () => trimmed)
171
+ .otherwise(() => {
172
+ const tailCount = Math.max(1, Math.ceil(words.length / 2))
173
+ const headWords = words.slice(0, words.length - tailCount).join(' ')
174
+ const tailWords = words.slice(words.length - tailCount).join(' ')
175
+ return (
176
+ <>
177
+ {headWords}
178
+ <span className="cp-hero__grad"> {tailWords}</span>
179
+ </>
180
+ )
181
+ })
182
+ })
183
+ }
@@ -0,0 +1,21 @@
1
+ .cp-page-rail {
2
+ max-width: var(--cp-landing-max-width);
3
+ margin: 0 var(--cp-frame-gutter);
4
+ background: transparent;
5
+ border-left: 1px solid var(--cp-c-border);
6
+ border-right: 1px solid var(--cp-c-border);
7
+ }
8
+
9
+ .cp-page-rail > * {
10
+ border-bottom: 1px solid var(--cp-c-border);
11
+ }
12
+
13
+ .cp-page-rail > *:last-child {
14
+ border-bottom: 0;
15
+ }
16
+
17
+ @media (min-width: 1248px) {
18
+ .cp-page-rail {
19
+ margin: 0 auto;
20
+ }
21
+ }
@@ -0,0 +1,19 @@
1
+ import type React from 'react'
2
+
3
+ import './page-rail.css'
4
+
5
+ export interface PageRailProps {
6
+ readonly children: React.ReactNode
7
+ }
8
+
9
+ /**
10
+ * PageRail — bounded max-width rail with continuous vertical hairlines on
11
+ * each outer edge. Wraps the entire home/landing surface so every section
12
+ * inside reads as a stack of compartments. Mirrors the mockup landing.
13
+ *
14
+ * @param props - Children to render inside the rail.
15
+ * @returns React element.
16
+ */
17
+ export function PageRail(props: PageRailProps): React.ReactElement {
18
+ return <div className="cp-page-rail">{props.children}</div>
19
+ }
@@ -0,0 +1,148 @@
1
+ .cp-split {
2
+ padding: var(--cp-s-96) var(--cp-s-32);
3
+ }
4
+
5
+ @media (max-width: 720px) {
6
+ .cp-split {
7
+ padding: var(--cp-s-64) var(--cp-s-20);
8
+ }
9
+ }
10
+
11
+ .cp-split__inner {
12
+ display: grid;
13
+ grid-template-columns: 1fr 1fr;
14
+ gap: var(--cp-s-64);
15
+ align-items: center;
16
+ max-width: var(--cp-size-split-max);
17
+ margin: 0 auto;
18
+ }
19
+
20
+ @media (max-width: 880px) {
21
+ .cp-split__inner {
22
+ grid-template-columns: 1fr;
23
+ gap: var(--cp-s-32);
24
+ }
25
+ }
26
+
27
+ .cp-split__copy {
28
+ min-width: 0;
29
+ }
30
+
31
+ .cp-split__eyebrow {
32
+ font-family: var(--cp-font-family-mono);
33
+ font-size: var(--cp-fs-eyebrow);
34
+ text-transform: uppercase;
35
+ letter-spacing: var(--cp-letter-eyebrow);
36
+ color: var(--cp-c-brand-1);
37
+ margin-bottom: var(--cp-s-12);
38
+ }
39
+
40
+ .cp-split__title {
41
+ font-size: var(--cp-fs-split-title);
42
+ font-weight: 600;
43
+ letter-spacing: var(--cp-letter-display);
44
+ line-height: var(--cp-lh-display);
45
+ margin: 0 0 var(--cp-s-16);
46
+ color: var(--cp-c-text-1);
47
+ }
48
+
49
+ .cp-split__body {
50
+ font-size: var(--cp-fs-body);
51
+ line-height: var(--cp-lh-relaxed);
52
+ color: var(--cp-c-text-2);
53
+ margin: 0 0 var(--cp-s-24);
54
+ }
55
+
56
+ .cp-split__bullets {
57
+ list-style: none;
58
+ margin: 0 0 var(--cp-s-24);
59
+ padding: 0;
60
+ display: flex;
61
+ flex-direction: column;
62
+ gap: var(--cp-s-12);
63
+ }
64
+
65
+ .cp-split__bullets li {
66
+ display: flex;
67
+ gap: var(--cp-s-12);
68
+ font-size: var(--cp-fs-bullet);
69
+ color: var(--cp-c-text-1);
70
+ }
71
+
72
+ .cp-split__check {
73
+ width: var(--cp-size-check);
74
+ height: var(--cp-size-check);
75
+ border-radius: 50%;
76
+ background: var(--cp-c-brand-soft);
77
+ color: var(--cp-c-brand-1);
78
+ display: grid;
79
+ place-items: center;
80
+ font-size: var(--cp-fs-check);
81
+ flex-shrink: 0;
82
+ margin-top: var(--cp-s-2);
83
+ }
84
+
85
+ .cp-split__btn {
86
+ display: inline-flex;
87
+ align-items: center;
88
+ gap: var(--cp-s-8);
89
+ padding: var(--cp-s-10) var(--cp-s-18);
90
+ font-size: var(--cp-fs-btn);
91
+ font-weight: 500;
92
+ border-radius: var(--cp-radius-pill);
93
+ border: 1px solid var(--cp-c-border);
94
+ background: transparent;
95
+ color: var(--cp-c-text-1);
96
+ cursor: pointer;
97
+ transition: all var(--cp-duration-fast) var(--cp-ease-base);
98
+ text-decoration: none;
99
+ }
100
+
101
+ .cp-split__btn:hover {
102
+ background: var(--cp-c-bg-soft);
103
+ border-color: var(--cp-c-border);
104
+ }
105
+
106
+ .cp-split__btn--primary {
107
+ background: var(--cp-c-brand-1);
108
+ color: var(--cp-c-brand-fg);
109
+ border-color: var(--cp-c-brand-1);
110
+ font-weight: 600;
111
+ }
112
+
113
+ .cp-split__btn--primary:hover {
114
+ background: var(--cp-c-brand-2);
115
+ border-color: var(--cp-c-brand-2);
116
+ }
117
+
118
+ /* Code visual styling — works for any pre/code or window child */
119
+ .cp-split__visual {
120
+ border: 1px solid var(--cp-c-border);
121
+ border-radius: var(--cp-radius-lg);
122
+ overflow: hidden;
123
+ background: var(--cp-code-block-bg);
124
+ }
125
+
126
+ .cp-split__visual pre {
127
+ margin: 0;
128
+ padding: var(--cp-s-18) var(--cp-s-20);
129
+ font-family: var(--cp-font-family-mono);
130
+ font-size: var(--cp-fs-code);
131
+ line-height: var(--cp-lh-code);
132
+ white-space: pre;
133
+ overflow-x: auto;
134
+ color: var(--cp-c-text-1);
135
+ }
136
+
137
+ .cp-split__visual .tok-kw {
138
+ color: var(--cp-c-syntax-kw);
139
+ }
140
+ .cp-split__visual .tok-str {
141
+ color: var(--cp-c-syntax-str);
142
+ }
143
+ .cp-split__visual .tok-fn {
144
+ color: var(--cp-c-syntax-fn);
145
+ }
146
+ .cp-split__visual .tok-cmt {
147
+ color: var(--cp-c-text-3);
148
+ }
@@ -0,0 +1,120 @@
1
+ import { match } from 'massaman/match'
2
+ import type React from 'react'
3
+
4
+ import { RouteLink } from '../../lib/route-link.tsx'
5
+ import { safeUrl } from '../../lib/safe-url.ts'
6
+
7
+ import './split.css'
8
+
9
+ export interface SplitAction {
10
+ /**
11
+ * Visible label.
12
+ */
13
+ readonly text: string
14
+ /**
15
+ * Destination URL.
16
+ */
17
+ readonly link: string
18
+ /**
19
+ * Visual style — `brand` is the filled primary, `alt` is the outline.
20
+ */
21
+ readonly theme?: 'brand' | 'alt'
22
+ }
23
+
24
+ export interface SplitProps {
25
+ /**
26
+ * Eyebrow label rendered above the headline.
27
+ */
28
+ readonly eyebrow?: string
29
+ /**
30
+ * Section headline.
31
+ */
32
+ readonly title: React.ReactNode
33
+ /**
34
+ * Lead paragraph below the headline.
35
+ */
36
+ readonly body?: React.ReactNode
37
+ /**
38
+ * Optional checkmark bullets rendered under the body.
39
+ */
40
+ readonly bullets?: readonly string[]
41
+ /**
42
+ * Optional CTA action.
43
+ */
44
+ readonly action?: SplitAction
45
+ /**
46
+ * Right-side content — typically a code preview or screenshot.
47
+ */
48
+ readonly visual: React.ReactNode
49
+ }
50
+
51
+ /**
52
+ * HomeSplit — two-column "show and tell" section. Copy + checkmarks on the
53
+ * left, code/screenshot on the right. Mirrors the mockup landing.
54
+ *
55
+ * @param props - Split section configuration.
56
+ * @returns React element.
57
+ */
58
+ export function HomeSplit(props: SplitProps): React.ReactElement {
59
+ const { eyebrow, title, body, bullets, action, visual } = props
60
+ const list = bullets ?? []
61
+
62
+ return (
63
+ <section className="cp-split">
64
+ <div className="cp-split__inner">
65
+ <div className="cp-split__copy">
66
+ {match(eyebrow)
67
+ .with(undefined, () => null)
68
+ .otherwise((e) => (
69
+ <div className="cp-split__eyebrow">{e}</div>
70
+ ))}
71
+ <h2 className="cp-split__title">{title}</h2>
72
+ {match(body)
73
+ .with(undefined, () => null)
74
+ .otherwise((b) => (
75
+ <p className="cp-split__body">{b}</p>
76
+ ))}
77
+ {match(list.length === 0)
78
+ .with(true, () => null)
79
+ .otherwise(() => (
80
+ <ul className="cp-split__bullets">
81
+ {list.map((bullet) => (
82
+ <li key={bullet}>
83
+ <span className="cp-split__check">✓</span>
84
+ <span>{bullet}</span>
85
+ </li>
86
+ ))}
87
+ </ul>
88
+ ))}
89
+ {match(action)
90
+ .with(undefined, () => null)
91
+ .otherwise((a) => {
92
+ const href = safeUrl(a.link)
93
+ if (href === null) {
94
+ return null
95
+ }
96
+ return (
97
+ <RouteLink className={btnClass(a.theme)} href={href}>
98
+ {a.text}
99
+ </RouteLink>
100
+ )
101
+ })}
102
+ </div>
103
+ <div className="cp-split__visual">{visual}</div>
104
+ </div>
105
+ </section>
106
+ )
107
+ }
108
+
109
+ /**
110
+ * Build the CSS class for a split action button.
111
+ *
112
+ * @private
113
+ * @param theme - Action theme.
114
+ * @returns CSS class name string.
115
+ */
116
+ function btnClass(theme: 'brand' | 'alt' | undefined): string {
117
+ return match(theme ?? 'brand')
118
+ .with('brand', () => 'cp-split__btn cp-split__btn--primary')
119
+ .otherwise(() => 'cp-split__btn')
120
+ }
@@ -0,0 +1,33 @@
1
+ .cp-trust {
2
+ padding: 32px 0;
3
+ }
4
+
5
+ .cp-trust__row {
6
+ display: flex;
7
+ align-items: center;
8
+ justify-content: center;
9
+ gap: 12px;
10
+ flex-wrap: wrap;
11
+ font-family: var(--cp-font-family-mono);
12
+ font-size: 12px;
13
+ color: var(--cp-c-text-3);
14
+ }
15
+
16
+ .cp-trust__lead {
17
+ margin-right: 4px;
18
+ }
19
+
20
+ .cp-trust__item {
21
+ display: inline-flex;
22
+ align-items: center;
23
+ gap: 12px;
24
+ }
25
+
26
+ .cp-trust__name {
27
+ color: var(--cp-c-text-1);
28
+ font-weight: 500;
29
+ }
30
+
31
+ .cp-trust__sep {
32
+ color: var(--cp-c-text-3);
33
+ }
@@ -0,0 +1,43 @@
1
+ import { match } from 'massaman/match'
2
+ import type React from 'react'
3
+
4
+ import './trust-strip.css'
5
+
6
+ export interface TrustStripProps {
7
+ /**
8
+ * Lead text shown before the names. Defaults to "used by".
9
+ */
10
+ readonly lead?: string
11
+ /**
12
+ * Names to render, separated by mono dots.
13
+ */
14
+ readonly names: readonly string[]
15
+ }
16
+
17
+ /**
18
+ * TrustStrip — a single-row "used by …" band with mono dots between names.
19
+ * Renders only when at least one name is supplied.
20
+ *
21
+ * @param props - Trust strip configuration.
22
+ * @returns React element, or null when no names are provided.
23
+ */
24
+ export function TrustStrip(props: TrustStripProps): React.ReactElement | null {
25
+ const { lead = 'used by', names } = props
26
+ return match(names.length === 0)
27
+ .with(true, () => null)
28
+ .otherwise(() => (
29
+ <section className="cp-trust">
30
+ <div className="cp-trust__row">
31
+ <span className="cp-trust__lead">{lead}</span>
32
+ {names.map((name, i) => (
33
+ <span key={`${name}:${i}`} className="cp-trust__item">
34
+ <span className="cp-trust__name">{name}</span>
35
+ {match(i < names.length - 1)
36
+ .with(true, () => <span className="cp-trust__sep">·</span>)
37
+ .otherwise(() => null)}
38
+ </span>
39
+ ))}
40
+ </div>
41
+ </section>
42
+ ))
43
+ }
@@ -0,0 +1,71 @@
1
+ import type { HomeGridConfig } from '@ciderpress/config'
2
+ import { match, P } from 'massaman/match'
3
+ import type React from 'react'
4
+
5
+ import { useCiderpress } from '../../hooks/use-ciderpress'
6
+ import type { WorkspaceGroupData } from '../../hooks/use-ciderpress'
7
+ import { WorkspaceCard } from '../workspaces/card'
8
+ import { WorkspaceGrid } from '../workspaces/grid'
9
+
10
+ /**
11
+ * Smart orchestrator that reads workspace data from themeConfig
12
+ * and renders workspace groups with the correct card component per type.
13
+ *
14
+ * @returns React element with workspace groups or null
15
+ */
16
+ export function HomeWorkspaces(): React.ReactElement | null {
17
+ const { workspaces, home } = useCiderpress()
18
+ const gridConfig = home && home.workspaces
19
+
20
+ return match(workspaces)
21
+ .with(
22
+ P.when((w): w is readonly WorkspaceGroupData[] => Array.isArray(w) && w.length > 0),
23
+ (groups) => (
24
+ <div className="cp-workspace-section">
25
+ <hr className="cp-divider" />
26
+ {groups.map((group) => renderGroup(group, gridConfig))}
27
+ </div>
28
+ )
29
+ )
30
+ .otherwise(() => null)
31
+ }
32
+
33
+ /**
34
+ * Render a single workspace group with its cards.
35
+ *
36
+ * @private
37
+ * @param group - Workspace group data with heading, description, and cards
38
+ * @param gridConfig - Optional grid layout config for columns and truncation
39
+ * @returns Workspace grid element
40
+ */
41
+ function renderGroup(
42
+ group: WorkspaceGroupData,
43
+ gridConfig: HomeGridConfig | undefined
44
+ ): React.ReactElement {
45
+ const titleLines = gridConfig && gridConfig.truncate && gridConfig.truncate.title
46
+ const descLines = gridConfig && gridConfig.truncate && gridConfig.truncate.description
47
+
48
+ return (
49
+ <WorkspaceGrid
50
+ key={group.heading}
51
+ heading={group.heading}
52
+ description={group.description}
53
+ columns={gridConfig && gridConfig.columns}
54
+ >
55
+ {group.cards.map((card, i) => (
56
+ <WorkspaceCard
57
+ key={`${card.title}-${i}`}
58
+ title={card.title}
59
+ href={card.href}
60
+ icon={card.icon}
61
+ scope={card.scope}
62
+ description={card.description}
63
+ tags={card.tags}
64
+ badge={card.badge}
65
+ titleLines={titleLines}
66
+ descriptionLines={descLines}
67
+ />
68
+ ))}
69
+ </WorkspaceGrid>
70
+ )
71
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Branch tag pill — git branch badge positioned in the nav bar.
3
+ */
4
+
5
+ .cp-branch-tag {
6
+ display: inline-flex;
7
+ align-items: center;
8
+ gap: 5px;
9
+ margin-left: 8px;
10
+ padding: 3px 10px;
11
+ border-radius: 20px;
12
+ background: var(--cp-c-bg-soft);
13
+ border: 1px solid var(--cp-c-divider);
14
+ color: var(--cp-c-text-3);
15
+ font-family: var(--cp-font-family-mono);
16
+ font-size: 11px;
17
+ font-weight: 600;
18
+ line-height: 1;
19
+ white-space: nowrap;
20
+ max-width: 180px;
21
+ text-decoration: none !important;
22
+ transition:
23
+ border-color 0.2s,
24
+ color 0.2s;
25
+ }
26
+
27
+ .cp-branch-tag:hover {
28
+ border-color: var(--cp-c-brand-1);
29
+ color: var(--cp-c-brand-1);
30
+ text-decoration: none !important;
31
+ }
32
+
33
+ .cp-branch-tag:focus-visible {
34
+ outline: 2px solid var(--rp-c-brand);
35
+ outline-offset: 2px;
36
+ }
37
+
38
+ .cp-branch-tag svg {
39
+ width: 14px;
40
+ height: 14px;
41
+ flex-shrink: 0;
42
+ }
43
+
44
+ .cp-branch-tag__text {
45
+ overflow: hidden;
46
+ text-overflow: ellipsis;
47
+ }
48
+
49
+ /* ── Responsive ──────────────────────────────────────────── */
50
+ @media (max-width: 768px) {
51
+ .cp-branch-tag__text {
52
+ display: none;
53
+ }
54
+ }