@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,426 @@
1
+ import { useFrontmatter, useLocation } from '@rspress/core/runtime'
2
+ import {
3
+ LlmsContainer,
4
+ LlmsCopyButton,
5
+ LlmsViewOptions,
6
+ ReadPercent,
7
+ renderInlineMarkdown,
8
+ Toc,
9
+ useActiveAnchor,
10
+ useDynamicToc,
11
+ } from '@rspress/core/theme'
12
+ import { match, P } from 'massaman/match'
13
+ import { useCallback, useEffect, useRef, useState } from 'react'
14
+ import type React from 'react'
15
+
16
+ import { RouteLink } from '../../lib/route-link.tsx'
17
+ import { Icon } from '../shared/icon.tsx'
18
+ import { useCiderpressLayout } from './ciderpress-layout-context'
19
+
20
+ import './ciderpress-docs-bar.css'
21
+
22
+ const SIDEBAR_STORAGE_KEY = 'ciderpress-sidebar-collapsed'
23
+ const SIDEBAR_HTML_ATTR = 'cpSidebarCollapsed'
24
+ const OUTLINE_STORAGE_KEY = 'ciderpress-outline-collapsed'
25
+ const OUTLINE_HTML_ATTR = 'cpOutlineCollapsed'
26
+ /**
27
+ * Below this viewport width, the sidebar behaves as a fixed overlay
28
+ * drawer (drawer-base rules ship in `sidebar/sidebar-toggle.css` —
29
+ * Rspress only provides the rules natively at <=768px, so the same
30
+ * stylesheet extends them up to 1279px to keep this threshold). Above,
31
+ * the sidebar is a sticky rail — `data-cp-sidebar-collapsed` is the
32
+ * right toggle. Matches `OUTLINE_DRAWER_MAX_WIDTH` so Menu and "On
33
+ * this page" flip to mobile behaviour in lockstep — and matches the
34
+ * CSS half (`sidebar-toggle.css`) so clicks fire the right state on
35
+ * either side of the threshold.
36
+ */
37
+ const SIDEBAR_DRAWER_MAX_WIDTH = 1279
38
+ /**
39
+ * Below this viewport width, Rspress styles `.rp-doc-layout__outline`
40
+ * as a fixed overlay drawer (DocLayout/index.css `@media (width <= 1279px)`).
41
+ * Above, the outline is a sticky rail — `data-cp-outline-collapsed`
42
+ * hides it. Same caveat: must match Rspress's media query exactly.
43
+ */
44
+ const OUTLINE_DRAWER_MAX_WIDTH = 1279
45
+
46
+ /**
47
+ * Sticky bar below the site header that replaces Rspress's built-in
48
+ * `.rp-doc-layout__menu` (which Ciderpress hides via CSS in `rail.css`).
49
+ *
50
+ * Left cluster: sidebar toggle + breadcrumbs (Section › Page).
51
+ * - Desktop (>= 960px): the toggle collapses/expands the docs sidebar
52
+ * via `html[data-cp-sidebar-collapsed]`, persisted to localStorage.
53
+ * - Narrow viewports: the toggle programmatically clicks Rspress's
54
+ * hidden `.rp-sidebar-menu__left` so the native sidebar drawer
55
+ * opens (overlay slide-in).
56
+ *
57
+ * Right cluster: "On this page" label + `<ReadPercent />` progress
58
+ * ring + chevron toggle for the outline rail.
59
+ *
60
+ * Mounted from `<Layout />` via `<OriginalLayout>`'s `beforeDoc` slot
61
+ * so it sits between the header and the doc-layout container — outside
62
+ * the sidebar, so it stays reachable even when the sidebar collapses.
63
+ *
64
+ * @returns Sticky docs sub-header.
65
+ */
66
+ export function CiderpressDocsBar(): React.ReactElement | null {
67
+ const { pathname } = useLocation()
68
+ const { frontmatter } = useFrontmatter()
69
+ const headers = useDynamicToc()
70
+ const { scrolledHeader } = useActiveAnchor(headers)
71
+ const { isOutlineOpen, setIsSidebarOpen, setIsOutlineOpen } = useCiderpressLayout()
72
+ const [sidebarCollapsed, setSidebarCollapsed] = useState(readSidebarCollapsed)
73
+ const [outlineCollapsed, setOutlineCollapsed] = useState(readOutlineCollapsed)
74
+ const outlineWrapRef = useRef<HTMLDivElement | null>(null)
75
+
76
+ // Close the outline dropdown when the user clicks anywhere outside
77
+ // it. Cheaper than a transparent backdrop element, and means clicks
78
+ // *inside* the dropdown (notably on TOC `<a>` links) still bubble
79
+ // up to React-Router's link handler and actually navigate. Only
80
+ // arms while the dropdown is open.
81
+ useEffect(() => {
82
+ if (!isOutlineOpen) {
83
+ return
84
+ }
85
+ // Use `click` not `mousedown` — on touch devices `mousedown`
86
+ // fires at the START of a touch-scroll gesture, which would
87
+ // close the dropdown the moment the user tries to scroll the
88
+ // page. `click` only fires on a completed tap (no drag), so
89
+ // touch-scrolling outside the dropdown leaves it alone.
90
+ function handleDocumentClick(event: MouseEvent): void {
91
+ const wrap = outlineWrapRef.current
92
+ if (wrap === null) {
93
+ return
94
+ }
95
+ if (event.target instanceof Node && wrap.contains(event.target)) {
96
+ return
97
+ }
98
+ setIsOutlineOpen(false)
99
+ }
100
+ globalThis.document.addEventListener('click', handleDocumentClick)
101
+ return () => {
102
+ globalThis.document.removeEventListener('click', handleDocumentClick)
103
+ }
104
+ }, [isOutlineOpen, setIsOutlineOpen])
105
+
106
+ useEffect(() => {
107
+ applyAttr(SIDEBAR_HTML_ATTR, sidebarCollapsed)
108
+ }, [sidebarCollapsed])
109
+
110
+ useEffect(() => {
111
+ applyAttr(OUTLINE_HTML_ATTR, outlineCollapsed)
112
+ }, [outlineCollapsed])
113
+
114
+ const fmRecord = frontmatter as Record<string, unknown>
115
+ const isHome = fmRecord.pageType === 'home'
116
+ const isBlank = fmRecord.pageType === 'blank'
117
+
118
+ const pageTitle = readStringField(fmRecord.title)
119
+
120
+ const breadcrumbs = buildBreadcrumbs(pathname, pageTitle)
121
+ const outlineEnabled = match(fmRecord.outline)
122
+ .with(false, () => false)
123
+ .otherwise(() => true)
124
+
125
+ const handleMenuClick = useCallback(() => {
126
+ if (globalThis.innerWidth <= SIDEBAR_DRAWER_MAX_WIDTH) {
127
+ setIsSidebarOpen((prev) => !prev)
128
+ return
129
+ }
130
+ setSidebarCollapsed((prev) => {
131
+ const next = !prev
132
+ writeStorage(SIDEBAR_STORAGE_KEY, next)
133
+ return next
134
+ })
135
+ }, [setIsSidebarOpen])
136
+
137
+ const handleOutlineClick = useCallback(() => {
138
+ if (globalThis.innerWidth <= OUTLINE_DRAWER_MAX_WIDTH) {
139
+ setIsOutlineOpen((prev) => !prev)
140
+ return
141
+ }
142
+ setOutlineCollapsed((prev) => {
143
+ const next = !prev
144
+ writeStorage(OUTLINE_STORAGE_KEY, next)
145
+ return next
146
+ })
147
+ }, [setIsOutlineOpen])
148
+
149
+ if (isHome || isBlank) {
150
+ return null
151
+ }
152
+
153
+ return (
154
+ <div className="cp-docs-bar">
155
+ <div className="cp-docs-bar__menu">
156
+ <button
157
+ type="button"
158
+ className="cp-docs-bar__menu-btn"
159
+ onClick={handleMenuClick}
160
+ aria-label="Toggle sidebar"
161
+ >
162
+ <Icon icon="pixelarticons:layout-sidebar-left" width={14} height={14} />
163
+ <span>Menu</span>
164
+ </button>
165
+ </div>
166
+ <div className="cp-docs-bar__center">
167
+ {breadcrumbs.length > 0 && (
168
+ <nav className="cp-docs-bar__crumbs" aria-label="Breadcrumb">
169
+ <RouteLink href="/" className="cp-docs-bar__crumb-home" aria-label="Home">
170
+ <Icon icon="pixelarticons:home" width={14} height={14} />
171
+ </RouteLink>
172
+ {breadcrumbs.map((crumb) => (
173
+ <span key={crumb.href} className="cp-docs-bar__crumb-wrap">
174
+ <span className="cp-docs-bar__sep">›</span>
175
+ {match(crumb.current)
176
+ .with(true, () => (
177
+ <span className="cp-docs-bar__crumb" aria-current="page">
178
+ {crumb.label}
179
+ </span>
180
+ ))
181
+ .otherwise(() => (
182
+ <RouteLink href={crumb.href} className="cp-docs-bar__crumb">
183
+ {crumb.label}
184
+ </RouteLink>
185
+ ))}
186
+ </span>
187
+ ))}
188
+ </nav>
189
+ )}
190
+ <div className="cp-docs-bar__llms">
191
+ <LlmsContainer>
192
+ <LlmsCopyButton />
193
+ <LlmsViewOptions />
194
+ </LlmsContainer>
195
+ </div>
196
+ </div>
197
+ {outlineEnabled && (
198
+ <div className="cp-docs-bar__outline-wrap" ref={outlineWrapRef}>
199
+ <button
200
+ type="button"
201
+ className="cp-docs-bar__outline"
202
+ onClick={handleOutlineClick}
203
+ aria-label="Toggle outline"
204
+ aria-expanded={isOutlineOpen}
205
+ >
206
+ <span className="cp-docs-bar__label">On this page</span>
207
+ {match(scrolledHeader)
208
+ .with(P.nullish, () => null)
209
+ .with({ text: P.string }, (header) => (
210
+ <span className="cp-docs-bar__section" {...renderInlineMarkdown(header.text)} />
211
+ ))
212
+ .otherwise(() => null)}
213
+ <ReadPercent size={14} strokeWidth={2} />
214
+ <Icon
215
+ icon="pixelarticons:chevron-down"
216
+ width={14}
217
+ height={14}
218
+ className="cp-docs-bar__chev"
219
+ />
220
+ </button>
221
+ {isOutlineOpen && (
222
+ <nav
223
+ /* `rp-doc-layout__outline` is here ONLY so Rspress's
224
+ `<TocItem>` auto-scroll-into-view boundary check stops
225
+ at this element (its boundary returns false for
226
+ elements with that class). Without it the library walks
227
+ up past our dropdown and scrolls the WHOLE PAGE every
228
+ time the active section changes — which felt like the
229
+ page was jumping every time you opened the menu or
230
+ scrolled past a heading. The `cp-docs-bar__outline-dropdown`
231
+ styles below override every Rspress outline rule we
232
+ don't want (position, visibility, layout). */
233
+ className="cp-docs-bar__outline-dropdown rp-doc-layout__outline"
234
+ aria-label="On this page"
235
+ onClick={makeLinkClickCloser(setIsOutlineOpen)}
236
+ >
237
+ <Toc />
238
+ </nav>
239
+ )}
240
+ </div>
241
+ )}
242
+ </div>
243
+ )
244
+ }
245
+
246
+ /**
247
+ * Single rendered breadcrumb — its display label, the route it links to,
248
+ * and whether it represents the current page (the last crumb, which
249
+ * renders as a non-link span with `aria-current="page"`).
250
+ */
251
+ interface Crumb {
252
+ readonly label: string
253
+ readonly href: string
254
+ readonly current: boolean
255
+ }
256
+
257
+ /**
258
+ * Build a 1- or 2-level breadcrumb trail from the current path and the
259
+ * page's frontmatter title. The section label comes from titlecasing
260
+ * the first path segment (e.g. `framework` → `Framework`) and links to
261
+ * that section's index page (`/framework/`). The page crumb links to
262
+ * the current pathname and is marked `current` so the renderer skips
263
+ * the anchor (you don't link to where you already are).
264
+ *
265
+ * @private
266
+ * @param pathname - The current location pathname.
267
+ * @param pageTitle - The page's frontmatter `title`, if defined.
268
+ * @returns Ordered breadcrumb entries (section first).
269
+ */
270
+ function buildBreadcrumbs(pathname: string, pageTitle: string | undefined): readonly Crumb[] {
271
+ const segments = pathname.split('/').filter((s) => s !== '')
272
+ if (segments.length === 0) {
273
+ return []
274
+ }
275
+ const section = titleCase(segments[0])
276
+ const sectionHref = `/${segments[0]}/`
277
+ const pageLabel = match(pageTitle)
278
+ .with(P.string, (t) => t)
279
+ .otherwise(() =>
280
+ match(segments.length > 1)
281
+ .with(true, () => titleCase(segments.at(-1) ?? ''))
282
+ .otherwise(() => '')
283
+ )
284
+ return match(pageLabel === '' || pageLabel === section)
285
+ .with(true, () => [{ label: section, href: sectionHref, current: true }])
286
+ .otherwise(() => [
287
+ { label: section, href: sectionHref, current: false },
288
+ { label: pageLabel, href: pathname, current: true },
289
+ ])
290
+ }
291
+
292
+ /**
293
+ * Build an onClick handler for the outline TOC dropdown that closes
294
+ * it whenever the user clicks an `<a>` (or anything nested under
295
+ * one). Hash-only navigation doesn't trigger React Router's pathname
296
+ * effect, so the drawer-close useEffect in `<CiderpressDocLayout />`
297
+ * never fires for TOC clicks — this handler is what actually closes
298
+ * the dropdown.
299
+ *
300
+ * @private
301
+ * @param setIsOutlineOpen - Outline open-state setter from the layout context.
302
+ * @returns Click handler suitable for the dropdown root element.
303
+ */
304
+ function makeLinkClickCloser(
305
+ setIsOutlineOpen: React.Dispatch<React.SetStateAction<boolean>>
306
+ ): React.MouseEventHandler<HTMLElement> {
307
+ return (event) => {
308
+ const { target } = event
309
+ if (!(target instanceof HTMLElement)) {
310
+ return
311
+ }
312
+ if (target.closest('a') !== null) {
313
+ setIsOutlineOpen(false)
314
+ }
315
+ }
316
+ }
317
+
318
+ /**
319
+ * Convert a kebab-case path segment into Title Case.
320
+ *
321
+ * @private
322
+ * @param segment - A single path segment (e.g. `getting-started`).
323
+ * @returns Title-cased label (e.g. `Getting Started`).
324
+ */
325
+ function titleCase(segment: string): string {
326
+ return segment
327
+ .split('-')
328
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
329
+ .join(' ')
330
+ }
331
+
332
+ /**
333
+ * Narrow an `unknown` frontmatter field to `string`, returning a bare
334
+ * (no explicit `undefined`) absent value when the field is missing or
335
+ * non-string. Used to coerce gray-matter's loose typing into the
336
+ * `string | undefined` shape downstream helpers expect.
337
+ *
338
+ * @private
339
+ * @param value - Frontmatter field value.
340
+ * @returns The string when typed as such, otherwise an absent value.
341
+ */
342
+ function readStringField(value: unknown): string | undefined {
343
+ if (typeof value === 'string') {
344
+ return value
345
+ }
346
+ }
347
+
348
+ /**
349
+ * Read the persisted sidebar-collapsed state from localStorage.
350
+ *
351
+ * @private
352
+ * @returns true when the sidebar should start collapsed.
353
+ */
354
+ function readSidebarCollapsed(): boolean {
355
+ return readStorage(SIDEBAR_STORAGE_KEY)
356
+ }
357
+
358
+ /**
359
+ * Read the persisted outline-collapsed state from localStorage.
360
+ *
361
+ * @private
362
+ * @returns true when the outline should start collapsed.
363
+ */
364
+ function readOutlineCollapsed(): boolean {
365
+ return readStorage(OUTLINE_STORAGE_KEY)
366
+ }
367
+
368
+ /**
369
+ * Read a boolean flag from localStorage.
370
+ *
371
+ * @private
372
+ * @param key - localStorage key.
373
+ * @returns true when the stored value is `'1'`.
374
+ */
375
+ function readStorage(key: string): boolean {
376
+ if (globalThis.window === undefined) {
377
+ return false
378
+ }
379
+ try {
380
+ return globalThis.localStorage.getItem(key) === '1'
381
+ } catch {
382
+ return false
383
+ }
384
+ }
385
+
386
+ /**
387
+ * Persist a boolean flag to localStorage. Removes the entry when
388
+ * `value` is false so the key is absent rather than `'0'`.
389
+ *
390
+ * @private
391
+ * @param key - localStorage key.
392
+ * @param value - true to write `'1'`, false to delete the key.
393
+ */
394
+ function writeStorage(key: string, value: boolean): void {
395
+ if (globalThis.window === undefined) {
396
+ return
397
+ }
398
+ try {
399
+ match(value)
400
+ .with(true, () => globalThis.localStorage.setItem(key, '1'))
401
+ .otherwise(() => globalThis.localStorage.removeItem(key))
402
+ } catch {
403
+ // ignore — storage may be unavailable
404
+ }
405
+ }
406
+
407
+ /**
408
+ * Apply a boolean flag to the html dataset for CSS targeting.
409
+ *
410
+ * @private
411
+ * @param attr - Dataset key (camelCase, mapped to `data-*` by React).
412
+ * @param value - true to write `'true'`, false to delete the attribute.
413
+ */
414
+ function applyAttr(attr: string, value: boolean): void {
415
+ if (globalThis.document === undefined) {
416
+ return
417
+ }
418
+ const html = globalThis.document.documentElement
419
+ match(value)
420
+ .with(true, () => {
421
+ html.dataset[attr] = 'true'
422
+ })
423
+ .otherwise(() => {
424
+ delete html.dataset[attr]
425
+ })
426
+ }
@@ -0,0 +1,172 @@
1
+ /**
2
+ * CiderpressHeader — sticky site header that fully replaces Rspress's
3
+ * built-in `.rp-nav` chrome. All visual properties are themable via
4
+ * `--cp-*` custom properties.
5
+ *
6
+ * Theme-author API:
7
+ * --cp-header-bg background colour
8
+ * --cp-header-border bottom border colour
9
+ * --cp-header-height total row height (default 56px)
10
+ * --cp-header-pad-x inline padding (default 16px)
11
+ * --cp-header-max-width inner content max width (default 1280px)
12
+ * --cp-header-gap flex gap between header items (default 8px)
13
+ * --cp-header-z stacking index (default 60 — matches the
14
+ * Rspress nav slot it replaces and sits
15
+ * above `--rp-z-index-sidebar: 50` so the
16
+ * sidebar doesn't punch through when the
17
+ * page is scrolled)
18
+ */
19
+ .cp-header {
20
+ position: sticky;
21
+ top: 0;
22
+ z-index: var(--cp-header-z, 60);
23
+ width: 100%;
24
+ background: var(--cp-header-bg, var(--cp-c-bg));
25
+ backdrop-filter: blur(8px);
26
+ }
27
+
28
+ .cp-header-inner {
29
+ display: flex;
30
+ align-items: center;
31
+ gap: var(--cp-header-gap, 8px);
32
+ height: var(--cp-header-height, 56px);
33
+ padding: 0 var(--cp-header-pad-x, 16px);
34
+ margin: 0 auto;
35
+ /* Border lives on the inner so it stays aligned with the constrained
36
+ container, not the full viewport. Docs pages keep the bottom edge
37
+ (full-width inner). Landing also picks up left + right edges to
38
+ match `.cp-page-rail`'s box treatment. */
39
+ border-bottom: 1px solid var(--cp-header-border, var(--cp-c-border));
40
+ /* Allow `.cp-nav-menu__overflow-popover` to escape vertically; the
41
+ CiderpressNavMenu owns horizontal overflow via its own measure +
42
+ collapse logic. */
43
+ overflow: visible;
44
+ }
45
+
46
+ /* Landing / home pages: align edge-for-edge with `.cp-page-rail` so
47
+ the header sits inside the same outer frame as the hero. We mirror
48
+ page-rail's positioning rules (margin gutter under 1248px, centered
49
+ margin auto above) and use the same `--cp-landing-max-width` token
50
+ so both move together when a theme overrides the width. */
51
+ .cp-header--landing .cp-header-inner {
52
+ max-width: var(--cp-landing-max-width, 1200px);
53
+ margin: 0 var(--cp-frame-gutter);
54
+ padding: 0 16px;
55
+ border-left: 1px solid var(--cp-header-border, var(--cp-c-border));
56
+ border-right: 1px solid var(--cp-header-border, var(--cp-c-border));
57
+ }
58
+
59
+ @media (min-width: 1248px) {
60
+ .cp-header--landing .cp-header-inner {
61
+ margin: 0 auto;
62
+ }
63
+ }
64
+
65
+ /* Doc pages: span the full viewport, matching Rspress's sidebar + main
66
+ layout which already stretches edge-to-edge. */
67
+ .cp-header--docs .cp-header-inner {
68
+ max-width: none;
69
+ }
70
+
71
+ .cp-header-logo {
72
+ display: inline-flex;
73
+ align-items: center;
74
+ flex-shrink: 0;
75
+ color: inherit;
76
+ text-decoration: none;
77
+ }
78
+
79
+ .cp-header-logo > svg {
80
+ height: var(--cp-header-logo-height, 28px);
81
+ width: auto;
82
+ }
83
+
84
+ /* `.cp-sidebar-toggle` ships with `position: absolute; left: 16px` so it
85
+ pins to the far-left of its container — fine inside Rspress's own
86
+ `.rp-nav`, but inside our header it overlaps the logo. Restore inline
87
+ flex positioning so it flows alongside the other items. */
88
+ .cp-header-inner .cp-sidebar-toggle {
89
+ position: static;
90
+ transform: none;
91
+ margin: 0;
92
+ }
93
+
94
+ /* Menu wrapper claims every pixel between the left cluster (logo) and
95
+ the trailing chrome (theme / socials / CTA). `justify-content:
96
+ flex-end` pushes both children (search + menu) to the right edge of
97
+ the wrapper, putting them side-by-side as a single right-anchored
98
+ cluster. CiderpressNavMenu observes this wrapper (not its own width)
99
+ to decide how many items fit — see ciderpress-nav-menu.tsx. */
100
+ .cp-header-menu-wrap {
101
+ flex: 1 1 0;
102
+ min-width: 0;
103
+ display: flex;
104
+ align-items: center;
105
+ gap: 8px;
106
+ justify-content: flex-end;
107
+ }
108
+
109
+ .cp-header-menu-wrap > .cp-nav-search {
110
+ flex-shrink: 0;
111
+ }
112
+
113
+ .cp-header-menu-wrap > .cp-nav-menu {
114
+ /* Reset the `width: 100%` baked into ciderpress-nav-menu.css; in the
115
+ header context we want the menu to size to its content so the wrap's
116
+ `justify-content: flex-end` cleanly pushes both search and the menu
117
+ items to the right edge as a single right-anchored cluster. */
118
+ flex: 0 1 auto;
119
+ width: auto;
120
+ min-width: 0;
121
+ }
122
+
123
+ /* ── Mobile collapse ───────────────────────────────────────────────
124
+ At <=1024px the desktop chrome (inline menu, variant toggle,
125
+ socials, CTA, dividers) collapses into the slide-out drawer
126
+ surfaced by `<CiderpressNavHamburger />`. Each of the hidden
127
+ elements is still in the React tree — the drawer renders its own
128
+ copies so nothing is actually lost from the mobile UX. The
129
+ threshold matches `.cp-nav-hamburger`'s show breakpoint and the
130
+ docs bar's mobile layout (`@media (max-width: 1024px)` everywhere)
131
+ so the three pieces flip to mobile in lockstep. */
132
+ @media (max-width: 1024px) {
133
+ /* Hide the chrome that the drawer surfaces. Keep the menu wrap (it
134
+ still holds the search button), but hide the inline menu items
135
+ and right-anchor the search to the viewport edge. */
136
+ .cp-header-inner > .cp-nav-divider,
137
+ .cp-header-inner > .cp-nav-social,
138
+ .cp-header-inner > .cp-topbar-cta,
139
+ .cp-header-inner > .rp-switch-appearance,
140
+ .cp-header-inner > .cp-variant-toggle,
141
+ .cp-header-inner > .cp-sidebar-toggle {
142
+ display: none;
143
+ }
144
+ .cp-header-menu-wrap > .cp-nav-menu,
145
+ .cp-header-menu-wrap > .cp-nav-divider {
146
+ display: none;
147
+ }
148
+ .cp-header-menu-wrap > .cp-nav-search {
149
+ margin-left: auto;
150
+ }
151
+ }
152
+
153
+ /* Hide Rspress's built-in nav entirely. Its DOM stays mounted (so the
154
+ keyboard-driven search modal still wires up) but it claims zero
155
+ visual space and zero interaction surface. */
156
+ html .rp-nav {
157
+ position: absolute !important;
158
+ width: 1px !important;
159
+ height: 1px !important;
160
+ padding: 0 !important;
161
+ border: 0 !important;
162
+ opacity: 0 !important;
163
+ pointer-events: none !important;
164
+ overflow: hidden !important;
165
+ clip: rect(0, 0, 0, 0) !important;
166
+ }
167
+
168
+ /* `--rp-nav-height` is defined at `html:root` in
169
+ `styles/overrides/rail.css` to clear the announcement + header +
170
+ docs bar stack. Rspress 2.x dropped the `.rp-doc-container` /
171
+ `.rspress-doc-container` wrapper, so a scoped override here would
172
+ never match anything. */