@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,106 @@
1
+ /**
2
+ * Floating git-branch indicator — pinned to the bottom-right viewport
3
+ * corner. Collapsed shows only the git-branch icon (36px circle); on
4
+ * hover/focus the pill expands rightward to reveal the branch name.
5
+ *
6
+ * `right`-anchored so the expansion grows leftward and never clips off the
7
+ * right edge regardless of branch-name length.
8
+ */
9
+
10
+ .cp-floating-branch {
11
+ position: fixed;
12
+ bottom: 16px;
13
+ right: 16px;
14
+ z-index: 50;
15
+
16
+ display: inline-flex;
17
+ align-items: center;
18
+ gap: 0;
19
+
20
+ height: 36px;
21
+ width: 36px;
22
+ padding: 0;
23
+ border-radius: 18px;
24
+
25
+ background: var(--cp-c-bg-soft);
26
+ border: 1px solid var(--cp-c-divider);
27
+ color: var(--cp-c-text-3);
28
+
29
+ font-family: var(--cp-font-family-mono);
30
+ font-size: 12px;
31
+ font-weight: 600;
32
+ line-height: 1;
33
+ white-space: nowrap;
34
+ overflow: hidden;
35
+ text-decoration: none !important;
36
+
37
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
38
+ backdrop-filter: blur(8px);
39
+
40
+ transition:
41
+ width 0.2s ease,
42
+ padding 0.2s ease,
43
+ gap 0.2s ease,
44
+ border-color 0.2s,
45
+ color 0.2s,
46
+ background 0.2s;
47
+ }
48
+
49
+ .cp-floating-branch:hover,
50
+ .cp-floating-branch:focus-visible {
51
+ width: auto;
52
+ max-width: 240px;
53
+ padding: 0 12px 0 10px;
54
+ gap: 6px;
55
+
56
+ border-color: var(--cp-c-brand-1);
57
+ color: var(--cp-c-brand-1);
58
+ background: var(--cp-c-bg);
59
+ text-decoration: none !important;
60
+ }
61
+
62
+ .cp-floating-branch:focus-visible {
63
+ outline: 2px solid var(--rp-c-brand);
64
+ outline-offset: 2px;
65
+ }
66
+
67
+ .cp-floating-branch__icon {
68
+ flex-shrink: 0;
69
+ width: 16px;
70
+ height: 16px;
71
+ margin: 0 auto;
72
+ transition: margin 0.2s ease;
73
+ }
74
+
75
+ .cp-floating-branch:hover .cp-floating-branch__icon,
76
+ .cp-floating-branch:focus-visible .cp-floating-branch__icon {
77
+ margin: 0;
78
+ }
79
+
80
+ .cp-floating-branch__text {
81
+ display: inline-block;
82
+ max-width: 0;
83
+ opacity: 0;
84
+ overflow: hidden;
85
+ text-overflow: ellipsis;
86
+
87
+ transition:
88
+ max-width 0.2s ease,
89
+ opacity 0.15s ease;
90
+ }
91
+
92
+ .cp-floating-branch:hover .cp-floating-branch__text,
93
+ .cp-floating-branch:focus-visible .cp-floating-branch__text {
94
+ max-width: 200px;
95
+ opacity: 1;
96
+ }
97
+
98
+ /* ── Responsive ──────────────────────────────────────────── */
99
+ /* Mobile: hide the floating branch indicator entirely. The hamburger
100
+ drawer surfaces the same chrome, and a corner-anchored chip
101
+ competes with the on-screen keyboard / browser UI on small viewports. */
102
+ @media (max-width: 768px) {
103
+ .cp-floating-branch {
104
+ display: none;
105
+ }
106
+ }
@@ -0,0 +1,109 @@
1
+ import type { SiteConfig } 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
+
7
+ import './floating-branch-indicator.css'
8
+ import { Icon } from '../shared/icon.tsx'
9
+
10
+ declare const __CIDERPRESS_GIT_BRANCH__: string | undefined
11
+
12
+ /**
13
+ * Floating git-branch indicator pinned to the bottom-right corner of the
14
+ * viewport. Collapsed: a small circular icon. On hover: expands to reveal
15
+ * the branch name. Click anywhere on the pill opens the branch on GitHub.
16
+ *
17
+ * Hidden when on default branches (`main` / `master`), when the
18
+ * build-time branch global is undefined, or when `site.edit.repo` is
19
+ * not configured.
20
+ *
21
+ * @returns React element or null when hidden
22
+ */
23
+ export function FloatingBranchIndicator(): React.ReactElement | null {
24
+ const { site } = useCiderpress()
25
+ const branch = resolveBranch()
26
+
27
+ if (!branch || branch === 'main' || branch === 'master') {
28
+ return null
29
+ }
30
+
31
+ const href = buildBranchHref({ repo: resolveRepo(site), branch })
32
+ if (href === null) {
33
+ return null
34
+ }
35
+
36
+ return (
37
+ <a
38
+ className="cp-floating-branch"
39
+ href={href}
40
+ target="_blank"
41
+ rel="noopener noreferrer"
42
+ title={`Branch: ${branch}`}
43
+ >
44
+ <Icon
45
+ icon="pixelarticons:git-branch"
46
+ width={16}
47
+ height={16}
48
+ className="cp-floating-branch__icon"
49
+ />
50
+ <span className="cp-floating-branch__text">{branch}</span>
51
+ </a>
52
+ )
53
+ }
54
+
55
+ export { FloatingBranchIndicator as default }
56
+
57
+ /**
58
+ * Resolves the current git branch name from the build-time global,
59
+ * returning an empty string when undefined.
60
+ *
61
+ * @private
62
+ * @returns Current git branch name or empty string
63
+ */
64
+ function resolveBranch(): string {
65
+ if (__CIDERPRESS_GIT_BRANCH__ !== undefined) {
66
+ return __CIDERPRESS_GIT_BRANCH__
67
+ }
68
+ return ''
69
+ }
70
+
71
+ /**
72
+ * Build a GitHub `/tree/<branch>` URL from the configured `site.edit.repo`.
73
+ *
74
+ * Accepts either a full URL (used as-is) or an `org/repo` slug
75
+ * (prefixed with `https://github.com/`). Returns `null` when `repo` is
76
+ * missing so the caller can omit the component entirely.
77
+ *
78
+ * @private
79
+ * @param params - The configured repo and the current branch.
80
+ * @returns Fully-qualified URL string, or `null` when unconfigured.
81
+ */
82
+ function buildBranchHref(params: {
83
+ readonly repo: string | undefined
84
+ readonly branch: string
85
+ }): string | null {
86
+ return match(params.repo)
87
+ .with(undefined, () => null)
88
+ .with('', () => null)
89
+ .with(P.string.startsWith('http'), (full) => `${full}/tree/${params.branch}`)
90
+ .otherwise((slug) => `https://github.com/${slug}/tree/${params.branch}`)
91
+ }
92
+
93
+ /**
94
+ * Pull the configured edit-repo slug off the site config, expressed
95
+ * with explicit null checks rather than optional chaining.
96
+ *
97
+ * @private
98
+ * @param site - The ciderpress site config (may be undefined).
99
+ * @returns The configured `edit.repo` value or `undefined`.
100
+ */
101
+ function resolveRepo(site: SiteConfig | undefined): string | undefined {
102
+ if (site === undefined) {
103
+ return undefined
104
+ }
105
+ if (site.edit === undefined) {
106
+ return undefined
107
+ }
108
+ return site.edit.repo
109
+ }
@@ -0,0 +1,268 @@
1
+ import type { SiteEditConfig, SiteReportConfig } from '@ciderpress/config'
2
+ import { useFrontmatter, useSite } from '@rspress/core/runtime'
3
+ import { Layout as OriginalLayout } from '@rspress/core/theme-original'
4
+ import { match, P } from 'massaman/match'
5
+ import type React from 'react'
6
+ import { useEffect } from 'react'
7
+
8
+ import { useCiderpress } from '../../hooks/use-ciderpress'
9
+ import { useNavItems } from '../../hooks/use-nav-items'
10
+ import { readSocialLinks } from '../../lib/read-social-links'
11
+ import { AnnouncementBar } from '../announcement/announcement-bar'
12
+ import { ContentFooterPortal } from '../content-footer/content-footer-portal'
13
+ import { Feedback } from '../content-footer/feedback'
14
+ import type { MetaAction } from '../content-footer/meta-actions'
15
+ import { MetaActions } from '../content-footer/meta-actions'
16
+ import { SiteFooter } from '../footer/site-footer'
17
+ import { SidebarLinks } from '../sidebar/sidebar-links'
18
+ import { SidebarPromo } from '../sidebar/sidebar-promo'
19
+ import { CiderpressDocsBar } from './ciderpress-docs-bar'
20
+ import { CiderpressHeader } from './ciderpress-header'
21
+ import type { CiderpressNavMenuItem } from './ciderpress-nav-menu'
22
+ import { FloatingBranchIndicator } from './floating-branch-indicator'
23
+
24
+ /**
25
+ * Custom Layout override for ciderpress.
26
+ *
27
+ * Renders `<CiderpressHeader />` as the entire site header chrome
28
+ * (Rspress's `.rp-nav` is hidden via CSS in `ciderpress-header.css`).
29
+ * `<OriginalLayout />` is kept around purely to render Rspress's
30
+ * sidebar + article body + footer; every nav-related slot is fed
31
+ * `null` so Rspress doesn't render its own chrome.
32
+ *
33
+ * Slots still in use:
34
+ * - `beforeSidebar`: SidebarLinks (above) and the `.cp-sidebar-top` band
35
+ * - `afterSidebar`: SidebarLinks (below) plus SidebarPromo
36
+ * - `afterDoc`: Feedback + MetaActions portalled into the doc footer
37
+ * - `bottom`: SiteFooter on doc pages
38
+ *
39
+ * @returns React element with the custom layout
40
+ */
41
+ export function Layout(): React.ReactElement {
42
+ // Rspress's `.rp-nav` is visually hidden via `ciderpress-header.css`
43
+ // but stays in the a11y tree, producing duplicate `banner` landmarks
44
+ // alongside our `<CiderpressHeader>`. Mark it aria-hidden after mount
45
+ // so screen readers ignore it. The element lives for the layout's
46
+ // lifetime, so no cleanup is required.
47
+ useEffect(() => {
48
+ const rpNav = document.querySelector('.rp-nav')
49
+ if (rpNav !== null) {
50
+ rpNav.setAttribute('aria-hidden', 'true')
51
+ }
52
+ }, [])
53
+
54
+ const { sidebarAbove, sidebarBelow, site } = useCiderpress()
55
+ const { site: rspressSite } = useSite()
56
+ const configNavItems = readNavItems(rspressSite)
57
+ const scrapedNavItems = useNavItems()
58
+ const navItems = match(configNavItems.length > 0)
59
+ .with(true, () => configNavItems)
60
+ .otherwise(() => scrapedNavItems)
61
+ const socialLinks = readSocialLinks(rspressSite)
62
+ const { announcement, topbarCta, sidebarPromo: sidebarPromoConfig, edit, report } = site ?? {}
63
+ const { frontmatter } = useFrontmatter()
64
+ const fmRecord = frontmatter as Record<string, unknown>
65
+ const isHome = fmRecord.pageType === 'home'
66
+ const isBlank = fmRecord.pageType === 'blank'
67
+ const filepathValue = fmRecord.__filepath
68
+ const pagePath = match(filepathValue)
69
+ .with(P.string, (v) => v)
70
+ .otherwise(() => '')
71
+
72
+ const announcementSlot = match(announcement)
73
+ .with(undefined, () => null)
74
+ .otherwise((a) => (
75
+ <AnnouncementBar id={a.id} lead={a.lead} cta={a.cta} persistent={a.persistent}>
76
+ {a.message}
77
+ </AnnouncementBar>
78
+ ))
79
+
80
+ const aboveItems = sidebarAbove ?? []
81
+ const belowItems = sidebarBelow ?? []
82
+
83
+ const beforeSidebar = match(aboveItems.length > 0)
84
+ .with(true, () => (
85
+ <div className="cp-sidebar-top">
86
+ <SidebarLinks items={aboveItems} position="above" />
87
+ </div>
88
+ ))
89
+ .otherwise(() => null)
90
+
91
+ const sidebarPromo = match(sidebarPromoConfig)
92
+ .with(undefined, () => null)
93
+ .otherwise((p) => (
94
+ <SidebarPromo title={p.title} body={p.body} ctaText={p.cta.text} ctaHref={p.cta.href} />
95
+ ))
96
+
97
+ const belowLinks = match(belowItems.length > 0)
98
+ .with(true, () => <SidebarLinks items={belowItems} position="below" />)
99
+ .otherwise(() => null)
100
+
101
+ const afterSidebar = match(belowLinks === null && sidebarPromo === null)
102
+ .with(true, () => null)
103
+ .otherwise(() => (
104
+ <div className="cp-sidebar-bottom">
105
+ {belowLinks}
106
+ {sidebarPromo}
107
+ </div>
108
+ ))
109
+
110
+ const bottomSlot = match(isHome || isBlank)
111
+ .with(true, () => null)
112
+ .otherwise(() => <SiteFooter />)
113
+
114
+ const metaActions = collectMetaActions({ edit, report, pagePath })
115
+
116
+ const afterDocSlot = (
117
+ <ContentFooterPortal>
118
+ <Feedback />
119
+ <MetaActions actions={metaActions} />
120
+ </ContentFooterPortal>
121
+ )
122
+
123
+ return (
124
+ <>
125
+ <CiderpressHeader
126
+ announcement={announcementSlot}
127
+ navItems={navItems}
128
+ socialLinks={socialLinks}
129
+ topbarCta={topbarCta}
130
+ isHome={isHome}
131
+ />
132
+ <OriginalLayout
133
+ top={null}
134
+ beforeNavMenu={null}
135
+ afterNavMenu={null}
136
+ beforeSidebar={beforeSidebar}
137
+ afterSidebar={afterSidebar}
138
+ beforeDoc={<CiderpressDocsBar />}
139
+ afterDoc={afterDocSlot}
140
+ bottom={bottomSlot}
141
+ />
142
+ <FloatingBranchIndicator />
143
+ </>
144
+ )
145
+ }
146
+
147
+ /**
148
+ * Pull the primary nav menu items off Rspress's `site` shape. The
149
+ * Rspress `SiteData` type doesn't expose `nav` at compile time, so we
150
+ * read through an indexed access and validate the shape at runtime.
151
+ *
152
+ * @private
153
+ * @param site - Rspress site data
154
+ * @returns Array of nav items (empty array when not configured)
155
+ */
156
+ function readNavItems(site: unknown): readonly CiderpressNavMenuItem[] {
157
+ const candidate = (site as { readonly nav?: unknown }).nav
158
+ if (!Array.isArray(candidate)) {
159
+ return []
160
+ }
161
+ return candidate.filter(
162
+ (item): item is CiderpressNavMenuItem =>
163
+ typeof item === 'object' &&
164
+ item !== null &&
165
+ typeof (item as { text?: unknown }).text === 'string' &&
166
+ typeof (item as { link?: unknown }).link === 'string'
167
+ )
168
+ }
169
+
170
+ /**
171
+ * Build the list of `MetaAction`s to render under each doc page,
172
+ * derived from `site.edit` and `site.report`. Returns an empty array
173
+ * when neither is configured.
174
+ *
175
+ * @private
176
+ * @param params - Site edit/report config plus current page path
177
+ * @returns Ordered list of meta actions
178
+ */
179
+ function collectMetaActions(params: {
180
+ readonly edit: SiteEditConfig | undefined
181
+ readonly report: SiteReportConfig | undefined
182
+ readonly pagePath: string
183
+ }): readonly MetaAction[] {
184
+ const { edit, report, pagePath } = params
185
+ const editAction = match(edit)
186
+ .with(undefined, () => null)
187
+ .otherwise(
188
+ (e): MetaAction => ({
189
+ label: e.label ?? 'Edit this page on GitHub',
190
+ href: buildEditUrl(e, pagePath),
191
+ icon: <EditIcon />,
192
+ })
193
+ )
194
+ const reportAction = match(report)
195
+ .with(undefined, () => null)
196
+ .otherwise(
197
+ (r): MetaAction => ({
198
+ label: r.label ?? 'Report an issue',
199
+ href: buildReportUrl(r),
200
+ icon: <AlertIcon />,
201
+ })
202
+ )
203
+ return [editAction, reportAction].filter((a): a is MetaAction => a !== null)
204
+ }
205
+
206
+ /**
207
+ * @private
208
+ */
209
+ function buildEditUrl(edit: SiteEditConfig, pagePath: string): string {
210
+ if (edit.repo.startsWith('http')) {
211
+ return edit.repo
212
+ }
213
+ const branch = edit.branch ?? 'main'
214
+ const directory = match(edit.directory)
215
+ .with(undefined, () => '')
216
+ .otherwise((d) => `${d.replaceAll(/^\/+|\/+$/g, '')}/`)
217
+ const path = pagePath.replace(/^\/+/, '')
218
+ return `https://github.com/${edit.repo}/edit/${branch}/${directory}${path}`
219
+ }
220
+
221
+ /**
222
+ * @private
223
+ */
224
+ function buildReportUrl(report: SiteReportConfig): string {
225
+ if (report.repo.startsWith('http')) {
226
+ return report.repo
227
+ }
228
+ return `https://github.com/${report.repo}/issues/new`
229
+ }
230
+
231
+ /**
232
+ * @private
233
+ */
234
+ function EditIcon(): React.ReactElement {
235
+ return (
236
+ <svg
237
+ width="11"
238
+ height="11"
239
+ viewBox="0 0 24 24"
240
+ fill="none"
241
+ stroke="currentColor"
242
+ strokeWidth="2"
243
+ >
244
+ <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
245
+ <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
246
+ </svg>
247
+ )
248
+ }
249
+
250
+ /**
251
+ * @private
252
+ */
253
+ function AlertIcon(): React.ReactElement {
254
+ return (
255
+ <svg
256
+ width="11"
257
+ height="11"
258
+ viewBox="0 0 24 24"
259
+ fill="none"
260
+ stroke="currentColor"
261
+ strokeWidth="2"
262
+ >
263
+ <circle cx="12" cy="12" r="10" />
264
+ <line x1="12" y1="8" x2="12" y2="12" />
265
+ <line x1="12" y1="16" x2="12.01" y2="16" />
266
+ </svg>
267
+ )
268
+ }
@@ -0,0 +1,79 @@
1
+ import React, { useEffect, useState } from 'react'
2
+ import { createPortal } from 'react-dom'
3
+
4
+ import { TopbarCTA } from './topbar-cta'
5
+
6
+ export interface MobileNavCTAProps {
7
+ /**
8
+ * CTA button text.
9
+ */
10
+ readonly text: string
11
+ /**
12
+ * CTA destination href.
13
+ */
14
+ readonly href: string
15
+ }
16
+
17
+ const HOST_ATTR = 'data-cp-mobile-nav-cta-host'
18
+
19
+ /**
20
+ * MobileNavCTA — portals a primary CTA button into Rspress's mobile
21
+ * nav-screen (`.rp-nav-screen__container`) so users can still reach
22
+ * the get-started action when the topbar CTA is hidden on narrow
23
+ * viewports. Inserts the CTA right before the trailing social-links
24
+ * block so the existing dividers wrap it naturally.
25
+ *
26
+ * Watches DOM mutations because Rspress mounts the nav-screen
27
+ * lazily on first hamburger click and re-mounts on route changes.
28
+ *
29
+ * @param props - CTA configuration.
30
+ * @returns React element.
31
+ */
32
+ export function MobileNavCTA(props: MobileNavCTAProps): React.ReactElement | null {
33
+ const [host, setHost] = useState<HTMLElement | null>(null)
34
+
35
+ useEffect(() => {
36
+ function ensureHost(): HTMLElement | null {
37
+ const container = globalThis.document.querySelector(
38
+ '.rp-nav-screen__container'
39
+ ) as HTMLElement | null
40
+ if (container === null) {
41
+ return null
42
+ }
43
+ const existing = container.querySelector(`[${HOST_ATTR}]`) as HTMLElement | null
44
+ if (existing !== null) {
45
+ return existing
46
+ }
47
+ const node = globalThis.document.createElement('div')
48
+ node.setAttribute(HOST_ATTR, '')
49
+ node.className = 'cp-mobile-nav-cta'
50
+ const socials = container.querySelector('.rp-social-links')
51
+ if (socials === null) {
52
+ container.append(node)
53
+ } else {
54
+ socials.before(node)
55
+ }
56
+ return node
57
+ }
58
+
59
+ setHost(ensureHost())
60
+
61
+ const observer = new globalThis.MutationObserver(() => {
62
+ const next = ensureHost()
63
+ setHost((prev) => {
64
+ if (prev !== null && prev.isConnected) {
65
+ return prev
66
+ }
67
+ return next
68
+ })
69
+ })
70
+ observer.observe(globalThis.document.body, { childList: true, subtree: true })
71
+
72
+ return () => observer.disconnect()
73
+ }, [])
74
+
75
+ if (host === null) {
76
+ return null
77
+ }
78
+ return createPortal(<TopbarCTA text={props.text} href={props.href} />, host)
79
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Vertical nav divider — used inline between groups of topbar elements.
3
+ *
4
+ * Theme-customisable via:
5
+ * --cp-c-divider colour (defaults via the active theme's --cp-c-divider)
6
+ * --cp-nav-divider-height height of the line (default 18px)
7
+ * --cp-nav-divider-width width of the line (default 1px)
8
+ */
9
+ .cp-nav-divider {
10
+ display: inline-block;
11
+ flex-shrink: 0;
12
+ width: var(--cp-nav-divider-width, 1px);
13
+ height: var(--cp-nav-divider-height, 18px);
14
+ background: var(--cp-c-divider);
15
+ }
@@ -0,0 +1,19 @@
1
+ import type React from 'react'
2
+
3
+ import './nav-divider.css'
4
+
5
+ /**
6
+ * Thin vertical divider used to separate adjacent groups of nav items
7
+ * in the topbar (logo / search / menu / icons / CTA).
8
+ *
9
+ * Themable via the `--cp-c-divider` CSS custom property and the
10
+ * `.cp-nav-divider` class. The divider is `aria-hidden` so it does not
11
+ * pollute the accessibility tree.
12
+ *
13
+ * @returns Inline-flex divider element
14
+ */
15
+ export function NavDivider(): React.ReactElement {
16
+ return <span className="cp-nav-divider" aria-hidden="true" />
17
+ }
18
+
19
+ export { NavDivider as default }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * NavLogo slot — portaled into `.rp-nav__title__link` to render ciderpress's
3
+ * theme-aware `<CiderpressLogo />` SVG or the user's function-form logo.
4
+ *
5
+ * Render pipeline:
6
+ * 1. Initial paint: Rspress emits its native `<img src="/logo.svg">`
7
+ * (the auto-generated static SVG with hardcoded brand color).
8
+ * 2. After hydration: NavLogo's portal mounts a `<span class="cp-nav-logo">`
9
+ * child with an inline SVG that reads `var(--rp-c-brand)` via
10
+ * `currentColor`, giving us theme-aware color switching.
11
+ * 3. CSS below hides the native img + fallback span when our portal mounts
12
+ * so only the theme-aware version shows.
13
+ *
14
+ * The `:has(.cp-nav-logo)` guard means CSS only hides Rspress's native logo
15
+ * when our slot actually mounted — if NavLogo fails for any reason, the
16
+ * static `/logo.svg` stays visible as a graceful fallback.
17
+ */
18
+
19
+ .cp-nav-logo {
20
+ display: inline-flex;
21
+ align-items: center;
22
+ line-height: 0;
23
+ }
24
+
25
+ .cp-nav-logo > svg {
26
+ display: block;
27
+ height: 1.75rem;
28
+ width: auto;
29
+ }
30
+
31
+ /* When our theme-aware portal mounts, hide Rspress's stock title elements
32
+ so we don't double-render. Covers both:
33
+ - the fallback `<span>title</span>` (rendered when no logo string)
34
+ - the native `<img class="rspress-logo">` (rendered for string logos
35
+ including our `/logo.svg` default).
36
+ The `:not(.cp-nav-logo)` guard is critical — our portal IS a span, so
37
+ a bare `> span` selector would hide it too. */
38
+ .rp-nav__title__link:has(.cp-nav-logo) > span:not(.cp-nav-logo),
39
+ .rp-nav__title__link:has(.cp-nav-logo) > .rp-nav__title__logo,
40
+ .rp-nav__title__link:has(.cp-nav-logo) > img.rspress-logo {
41
+ display: none;
42
+ }