@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.
- package/LICENSE +21 -0
- package/README.md +23 -0
- package/dist/0~142.js +2 -0
- package/dist/0~164.js +2 -0
- package/dist/0~2.js +2 -0
- package/dist/0~225.js +2 -0
- package/dist/0~288.js +2 -0
- package/dist/0~299.js +2 -0
- package/dist/0~3.js +2 -0
- package/dist/0~301.js +2 -0
- package/dist/0~311.js +2 -0
- package/dist/0~326.js +2 -0
- package/dist/0~40.js +2 -0
- package/dist/0~43.js +2 -0
- package/dist/0~433.js +2 -0
- package/dist/0~453.js +2 -0
- package/dist/0~457.js +2 -0
- package/dist/0~497.js +2 -0
- package/dist/0~511.js +2 -0
- package/dist/0~603.js +2 -0
- package/dist/0~616.js +2 -0
- package/dist/0~659.js +2 -0
- package/dist/0~670.js +2 -0
- package/dist/0~687.js +2 -0
- package/dist/0~706.js +2 -0
- package/dist/0~729.js +2 -0
- package/dist/0~768.js +2 -0
- package/dist/0~819.js +2 -0
- package/dist/0~830.js +2 -0
- package/dist/0~854.js +2 -0
- package/dist/0~863.js +2 -0
- package/dist/0~879.js +2 -0
- package/dist/0~96.js +2 -0
- package/dist/0~97.js +2 -0
- package/dist/components/FileTree/FileTree.css +90 -0
- package/dist/components/FileTree/FileTree.d.ts +7 -0
- package/dist/components/FileTree/FileTree.js +531 -0
- package/dist/components/FileTree/FileTreeItem.d.ts +8 -0
- package/dist/components/FileTree/RemoteSvgIcon.d.ts +11 -0
- package/dist/components/FileTree/index.d.ts +4 -0
- package/dist/components/folder-icons.d.ts +32 -0
- package/dist/components/languages.d.ts +7 -0
- package/dist/components/tree-parser/tree-parser.d.ts +12 -0
- package/dist/components/tree-parser/types.d.ts +11 -0
- package/dist/head/css/loader-apple.css +1 -0
- package/dist/head/css/loader-backdrop.css +1 -0
- package/dist/head/css/loader-dots.css +1 -0
- package/dist/head/css/themes/amber.css +1 -0
- package/dist/head/css/themes/arcade.css +1 -0
- package/dist/head/css/themes/grannysmith.css +1 -0
- package/dist/head/css/themes/honeycrisp.css +1 -0
- package/dist/head/css/themes/midnight.css +1 -0
- package/dist/head/css/themes/mulled.css +1 -0
- package/dist/head/js/loader-dots.js +1 -0
- package/dist/head/js/vscode-nav.js +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.mjs +40 -0
- package/dist/node.d.ts +81 -0
- package/dist/node.mjs +17762 -0
- package/dist/plugins/mermaid/MermaidRenderer.tsx +480 -0
- package/dist/plugins/mermaid/mermaid.css +199 -0
- package/dist/theme/components/announcement/announcement-bar.css +103 -0
- package/dist/theme/components/announcement/announcement-bar.tsx +173 -0
- package/dist/theme/components/ask-ai/ask-ai-button.css +52 -0
- package/dist/theme/components/ask-ai/ask-ai-button.tsx +56 -0
- package/dist/theme/components/content-footer/content-footer-portal.tsx +70 -0
- package/dist/theme/components/content-footer/feedback.css +47 -0
- package/dist/theme/components/content-footer/feedback.tsx +96 -0
- package/dist/theme/components/content-footer/meta-actions.css +25 -0
- package/dist/theme/components/content-footer/meta-actions.tsx +57 -0
- package/dist/theme/components/content-footer/page-pager.css +61 -0
- package/dist/theme/components/content-footer/page-pager.tsx +110 -0
- package/dist/theme/components/edit-source-button.tsx +97 -0
- package/dist/theme/components/footer/site-footer.css +179 -0
- package/dist/theme/components/footer/site-footer.tsx +115 -0
- package/dist/theme/components/home/cta.css +67 -0
- package/dist/theme/components/home/cta.tsx +77 -0
- package/dist/theme/components/home/feature-card.css +52 -0
- package/dist/theme/components/home/feature-card.tsx +131 -0
- package/dist/theme/components/home/feature.tsx +79 -0
- package/dist/theme/components/home/hero-demo.css +66 -0
- package/dist/theme/components/home/hero-demo.tsx +46 -0
- package/dist/theme/components/home/hero.css +96 -0
- package/dist/theme/components/home/hero.tsx +111 -0
- package/dist/theme/components/home/layout.tsx +183 -0
- package/dist/theme/components/home/page-rail.css +21 -0
- package/dist/theme/components/home/page-rail.tsx +19 -0
- package/dist/theme/components/home/split.css +148 -0
- package/dist/theme/components/home/split.tsx +120 -0
- package/dist/theme/components/home/trust-strip.css +33 -0
- package/dist/theme/components/home/trust-strip.tsx +43 -0
- package/dist/theme/components/home/workspaces.tsx +71 -0
- package/dist/theme/components/nav/branch-tag.css +54 -0
- package/dist/theme/components/nav/branch-tag.tsx +101 -0
- package/dist/theme/components/nav/ciderpress-doc-layout.tsx +247 -0
- package/dist/theme/components/nav/ciderpress-docs-bar.css +505 -0
- package/dist/theme/components/nav/ciderpress-docs-bar.tsx +426 -0
- package/dist/theme/components/nav/ciderpress-header.css +172 -0
- package/dist/theme/components/nav/ciderpress-header.tsx +113 -0
- package/dist/theme/components/nav/ciderpress-layout-context.tsx +49 -0
- package/dist/theme/components/nav/ciderpress-nav-hamburger.css +193 -0
- package/dist/theme/components/nav/ciderpress-nav-hamburger.tsx +112 -0
- package/dist/theme/components/nav/ciderpress-nav-menu.css +130 -0
- package/dist/theme/components/nav/ciderpress-nav-menu.tsx +372 -0
- package/dist/theme/components/nav/ciderpress-nav-search.css +73 -0
- package/dist/theme/components/nav/ciderpress-nav-search.tsx +55 -0
- package/dist/theme/components/nav/ciderpress-nav-social-links.css +35 -0
- package/dist/theme/components/nav/ciderpress-nav-social-links.tsx +87 -0
- package/dist/theme/components/nav/floating-branch-indicator.css +106 -0
- package/dist/theme/components/nav/floating-branch-indicator.tsx +109 -0
- package/dist/theme/components/nav/layout.tsx +268 -0
- package/dist/theme/components/nav/mobile-nav-cta.tsx +79 -0
- package/dist/theme/components/nav/nav-divider.css +15 -0
- package/dist/theme/components/nav/nav-divider.tsx +19 -0
- package/dist/theme/components/nav/nav-logo.css +42 -0
- package/dist/theme/components/nav/nav-logo.tsx +262 -0
- package/dist/theme/components/nav/theme-switcher.css +92 -0
- package/dist/theme/components/nav/theme-switcher.tsx +298 -0
- package/dist/theme/components/nav/topbar-cta.css +45 -0
- package/dist/theme/components/nav/topbar-cta.tsx +39 -0
- package/dist/theme/components/nav/variant-toggle.css +70 -0
- package/dist/theme/components/nav/variant-toggle.tsx +83 -0
- package/dist/theme/components/nav/version-chip.css +31 -0
- package/dist/theme/components/nav/version-chip.tsx +45 -0
- package/dist/theme/components/nav/vscode-tag.css +32 -0
- package/dist/theme/components/nav/vscode-tag.tsx +20 -0
- package/dist/theme/components/openapi/code-sample.tsx +341 -0
- package/dist/theme/components/openapi/copy-markdown-button.tsx +41 -0
- package/dist/theme/components/openapi/icons.tsx +45 -0
- package/dist/theme/components/openapi/index.ts +6 -0
- package/dist/theme/components/openapi/method-badge.tsx +24 -0
- package/dist/theme/components/openapi/openapi.css +665 -0
- package/dist/theme/components/openapi/operation.tsx +200 -0
- package/dist/theme/components/openapi/overview.tsx +207 -0
- package/dist/theme/components/openapi/parameters-table.tsx +149 -0
- package/dist/theme/components/openapi/request-body.tsx +90 -0
- package/dist/theme/components/openapi/response-list.tsx +112 -0
- package/dist/theme/components/openapi/schema-viewer.tsx +277 -0
- package/dist/theme/components/openapi/security-badges.tsx +63 -0
- package/dist/theme/components/openapi/spec-utils.ts +122 -0
- package/dist/theme/components/shared/accordion.css +118 -0
- package/dist/theme/components/shared/accordion.stories.tsx +96 -0
- package/dist/theme/components/shared/accordion.tsx +191 -0
- package/dist/theme/components/shared/brand-logo.stories.tsx +49 -0
- package/dist/theme/components/shared/brand-mark.stories.tsx +53 -0
- package/dist/theme/components/shared/browser-window.css +1 -0
- package/dist/theme/components/shared/browser-window.stories.tsx +100 -0
- package/dist/theme/components/shared/browser-window.tsx +2 -0
- package/dist/theme/components/shared/card.stories.tsx +50 -0
- package/dist/theme/components/shared/card.tsx +35 -0
- package/dist/theme/components/shared/ciderpress-logo.tsx +93 -0
- package/dist/theme/components/shared/ciderpress-mark.tsx +77 -0
- package/dist/theme/components/shared/color.css +56 -0
- package/dist/theme/components/shared/color.stories.tsx +47 -0
- package/dist/theme/components/shared/color.tsx +69 -0
- package/dist/theme/components/shared/columns.css +37 -0
- package/dist/theme/components/shared/columns.stories.tsx +91 -0
- package/dist/theme/components/shared/columns.tsx +50 -0
- package/dist/theme/components/shared/desktop-window.css +339 -0
- package/dist/theme/components/shared/desktop-window.tsx +535 -0
- package/dist/theme/components/shared/field.css +158 -0
- package/dist/theme/components/shared/field.stories.tsx +100 -0
- package/dist/theme/components/shared/field.tsx +186 -0
- package/dist/theme/components/shared/frame.css +39 -0
- package/dist/theme/components/shared/frame.stories.tsx +49 -0
- package/dist/theme/components/shared/frame.tsx +76 -0
- package/dist/theme/components/shared/icon.stories.tsx +90 -0
- package/dist/theme/components/shared/icon.tsx +41 -0
- package/dist/theme/components/shared/prompt.css +178 -0
- package/dist/theme/components/shared/prompt.stories.tsx +57 -0
- package/dist/theme/components/shared/prompt.tsx +369 -0
- package/dist/theme/components/shared/resolve-card-icon.ts +28 -0
- package/dist/theme/components/shared/section-card.stories.tsx +51 -0
- package/dist/theme/components/shared/section-card.tsx +44 -0
- package/dist/theme/components/shared/section-grid.stories.tsx +46 -0
- package/dist/theme/components/shared/section-grid.tsx +15 -0
- package/dist/theme/components/shared/status-badge.css +37 -0
- package/dist/theme/components/shared/status-badge.stories.tsx +61 -0
- package/dist/theme/components/shared/status-badge.tsx +74 -0
- package/dist/theme/components/shared/steps.css +88 -0
- package/dist/theme/components/shared/steps.stories.tsx +68 -0
- package/dist/theme/components/shared/steps.tsx +100 -0
- package/dist/theme/components/shared/tech-icon-table.stories.tsx +29 -0
- package/dist/theme/components/shared/tech-icon-table.tsx +71 -0
- package/dist/theme/components/shared/tech-tag.stories.tsx +40 -0
- package/dist/theme/components/shared/tech-tag.tsx +31 -0
- package/dist/theme/components/shared/theme-color-palette.css +80 -0
- package/dist/theme/components/shared/theme-color-palette.stories.tsx +52 -0
- package/dist/theme/components/shared/theme-color-palette.tsx +275 -0
- package/dist/theme/components/shared/tooltip.css +69 -0
- package/dist/theme/components/shared/tooltip.stories.tsx +72 -0
- package/dist/theme/components/shared/tooltip.tsx +77 -0
- package/dist/theme/components/sidebar/framework-picker.css +77 -0
- package/dist/theme/components/sidebar/framework-picker.tsx +78 -0
- package/dist/theme/components/sidebar/sidebar-filter.test.ts +140 -0
- package/dist/theme/components/sidebar/sidebar-filter.ts +79 -0
- package/dist/theme/components/sidebar/sidebar-links.css +102 -0
- package/dist/theme/components/sidebar/sidebar-links.tsx +122 -0
- package/dist/theme/components/sidebar/sidebar-promo.css +42 -0
- package/dist/theme/components/sidebar/sidebar-promo.tsx +52 -0
- package/dist/theme/components/sidebar/sidebar-scope.tsx +151 -0
- package/dist/theme/components/sidebar/sidebar-toggle.css +181 -0
- package/dist/theme/components/sidebar/sidebar-toggle.tsx +127 -0
- package/dist/theme/components/theme-provider.tsx +637 -0
- package/dist/theme/components/workspaces/card.css +151 -0
- package/dist/theme/components/workspaces/card.tsx +166 -0
- package/dist/theme/components/workspaces/grid.tsx +62 -0
- package/dist/theme/css.d.ts +1 -0
- package/dist/theme/env.d.ts +12 -0
- package/dist/theme/fonts/GeistMono-Variable.woff2 +0 -0
- package/dist/theme/fonts/GeistPixel-Square.woff2 +0 -0
- package/dist/theme/fonts/GeistSans-Variable.woff2 +0 -0
- package/dist/theme/hooks/use-ciderpress.ts +61 -0
- package/dist/theme/hooks/use-nav-items.ts +76 -0
- package/dist/theme/icons/index.ts +2 -0
- package/dist/theme/icons/tech-map.ts +228 -0
- package/dist/theme/index.tsx +180 -0
- package/dist/theme/lib/read-social-links.ts +27 -0
- package/dist/theme/lib/route-link.tsx +126 -0
- package/dist/theme/lib/safe-url.test.ts +0 -0
- package/dist/theme/lib/safe-url.ts +68 -0
- package/dist/theme/lib/theme-favicon.ts +125 -0
- package/dist/theme/lib/user-config-stub.ts +12 -0
- package/dist/theme/styles/layers.css +32 -0
- package/dist/theme/styles/overrides/badge.css +26 -0
- package/dist/theme/styles/overrides/content-footer.css +80 -0
- package/dist/theme/styles/overrides/details.css +61 -0
- package/dist/theme/styles/overrides/fonts.css +32 -0
- package/dist/theme/styles/overrides/home-card.css +133 -0
- package/dist/theme/styles/overrides/home.css +243 -0
- package/dist/theme/styles/overrides/rail.css +337 -0
- package/dist/theme/styles/overrides/rspress.css +62 -0
- package/dist/theme/styles/overrides/scrollbar.css +25 -0
- package/dist/theme/styles/overrides/section-card.css +114 -0
- package/dist/theme/styles/overrides/sidebar.css +144 -0
- package/dist/theme/styles/overrides/tokens.css +288 -0
- package/dist/theme/styles/overrides/vscode.css +88 -0
- package/dist/theme/styles/themes/amber.css +545 -0
- package/dist/theme/styles/themes/arcade-fx.css +366 -0
- package/dist/theme/styles/themes/arcade.css +273 -0
- package/dist/theme/styles/themes/grannysmith.css +545 -0
- package/dist/theme/styles/themes/honeycrisp.css +545 -0
- package/dist/theme/styles/themes/midnight.css +273 -0
- package/dist/theme/styles/themes/mulled.css +817 -0
- package/package.json +103 -0
- package/src/theme/components/announcement/announcement-bar.css +103 -0
- package/src/theme/components/announcement/announcement-bar.tsx +173 -0
- package/src/theme/components/ask-ai/ask-ai-button.css +52 -0
- package/src/theme/components/ask-ai/ask-ai-button.tsx +56 -0
- package/src/theme/components/content-footer/content-footer-portal.tsx +70 -0
- package/src/theme/components/content-footer/feedback.css +47 -0
- package/src/theme/components/content-footer/feedback.tsx +96 -0
- package/src/theme/components/content-footer/meta-actions.css +25 -0
- package/src/theme/components/content-footer/meta-actions.tsx +57 -0
- package/src/theme/components/content-footer/page-pager.css +61 -0
- package/src/theme/components/content-footer/page-pager.tsx +110 -0
- package/src/theme/components/edit-source-button.tsx +97 -0
- package/src/theme/components/footer/site-footer.css +179 -0
- package/src/theme/components/footer/site-footer.tsx +115 -0
- package/src/theme/components/home/cta.css +67 -0
- package/src/theme/components/home/cta.tsx +77 -0
- package/src/theme/components/home/feature-card.css +52 -0
- package/src/theme/components/home/feature-card.tsx +131 -0
- package/src/theme/components/home/feature.tsx +79 -0
- package/src/theme/components/home/hero-demo.css +66 -0
- package/src/theme/components/home/hero-demo.tsx +46 -0
- package/src/theme/components/home/hero.css +96 -0
- package/src/theme/components/home/hero.tsx +111 -0
- package/src/theme/components/home/layout.tsx +183 -0
- package/src/theme/components/home/page-rail.css +21 -0
- package/src/theme/components/home/page-rail.tsx +19 -0
- package/src/theme/components/home/split.css +148 -0
- package/src/theme/components/home/split.tsx +120 -0
- package/src/theme/components/home/trust-strip.css +33 -0
- package/src/theme/components/home/trust-strip.tsx +43 -0
- package/src/theme/components/home/workspaces.tsx +71 -0
- package/src/theme/components/nav/branch-tag.css +54 -0
- package/src/theme/components/nav/branch-tag.tsx +101 -0
- package/src/theme/components/nav/ciderpress-doc-layout.tsx +247 -0
- package/src/theme/components/nav/ciderpress-docs-bar.css +505 -0
- package/src/theme/components/nav/ciderpress-docs-bar.tsx +426 -0
- package/src/theme/components/nav/ciderpress-header.css +172 -0
- package/src/theme/components/nav/ciderpress-header.tsx +113 -0
- package/src/theme/components/nav/ciderpress-layout-context.tsx +49 -0
- package/src/theme/components/nav/ciderpress-nav-hamburger.css +193 -0
- package/src/theme/components/nav/ciderpress-nav-hamburger.tsx +112 -0
- package/src/theme/components/nav/ciderpress-nav-menu.css +130 -0
- package/src/theme/components/nav/ciderpress-nav-menu.tsx +372 -0
- package/src/theme/components/nav/ciderpress-nav-search.css +73 -0
- package/src/theme/components/nav/ciderpress-nav-search.tsx +55 -0
- package/src/theme/components/nav/ciderpress-nav-social-links.css +35 -0
- package/src/theme/components/nav/ciderpress-nav-social-links.tsx +87 -0
- package/src/theme/components/nav/floating-branch-indicator.css +106 -0
- package/src/theme/components/nav/floating-branch-indicator.tsx +109 -0
- package/src/theme/components/nav/layout.tsx +268 -0
- package/src/theme/components/nav/mobile-nav-cta.tsx +79 -0
- package/src/theme/components/nav/nav-divider.css +15 -0
- package/src/theme/components/nav/nav-divider.tsx +19 -0
- package/src/theme/components/nav/nav-logo.css +42 -0
- package/src/theme/components/nav/nav-logo.tsx +262 -0
- package/src/theme/components/nav/theme-switcher.css +92 -0
- package/src/theme/components/nav/theme-switcher.tsx +298 -0
- package/src/theme/components/nav/topbar-cta.css +45 -0
- package/src/theme/components/nav/topbar-cta.tsx +39 -0
- package/src/theme/components/nav/variant-toggle.css +70 -0
- package/src/theme/components/nav/variant-toggle.tsx +83 -0
- package/src/theme/components/nav/version-chip.css +31 -0
- package/src/theme/components/nav/version-chip.tsx +45 -0
- package/src/theme/components/nav/vscode-tag.css +32 -0
- package/src/theme/components/nav/vscode-tag.tsx +20 -0
- package/src/theme/components/openapi/code-sample.tsx +341 -0
- package/src/theme/components/openapi/copy-markdown-button.tsx +41 -0
- package/src/theme/components/openapi/icons.tsx +45 -0
- package/src/theme/components/openapi/index.ts +6 -0
- package/src/theme/components/openapi/method-badge.tsx +24 -0
- package/src/theme/components/openapi/openapi.css +665 -0
- package/src/theme/components/openapi/operation.tsx +200 -0
- package/src/theme/components/openapi/overview.tsx +207 -0
- package/src/theme/components/openapi/parameters-table.tsx +149 -0
- package/src/theme/components/openapi/request-body.tsx +90 -0
- package/src/theme/components/openapi/response-list.tsx +112 -0
- package/src/theme/components/openapi/schema-viewer.tsx +277 -0
- package/src/theme/components/openapi/security-badges.tsx +63 -0
- package/src/theme/components/openapi/spec-utils.ts +122 -0
- package/src/theme/components/shared/accordion.css +118 -0
- package/src/theme/components/shared/accordion.stories.tsx +96 -0
- package/src/theme/components/shared/accordion.tsx +191 -0
- package/src/theme/components/shared/brand-logo.stories.tsx +49 -0
- package/src/theme/components/shared/brand-mark.stories.tsx +53 -0
- package/src/theme/components/shared/browser-window.css +1 -0
- package/src/theme/components/shared/browser-window.stories.tsx +100 -0
- package/src/theme/components/shared/browser-window.tsx +2 -0
- package/src/theme/components/shared/card.stories.tsx +50 -0
- package/src/theme/components/shared/card.tsx +35 -0
- package/src/theme/components/shared/ciderpress-logo.tsx +93 -0
- package/src/theme/components/shared/ciderpress-mark.tsx +77 -0
- package/src/theme/components/shared/color.css +56 -0
- package/src/theme/components/shared/color.stories.tsx +47 -0
- package/src/theme/components/shared/color.tsx +69 -0
- package/src/theme/components/shared/columns.css +37 -0
- package/src/theme/components/shared/columns.stories.tsx +91 -0
- package/src/theme/components/shared/columns.tsx +50 -0
- package/src/theme/components/shared/desktop-window.css +339 -0
- package/src/theme/components/shared/desktop-window.tsx +535 -0
- package/src/theme/components/shared/field.css +158 -0
- package/src/theme/components/shared/field.stories.tsx +100 -0
- package/src/theme/components/shared/field.tsx +186 -0
- package/src/theme/components/shared/frame.css +39 -0
- package/src/theme/components/shared/frame.stories.tsx +49 -0
- package/src/theme/components/shared/frame.tsx +76 -0
- package/src/theme/components/shared/icon.stories.tsx +90 -0
- package/src/theme/components/shared/icon.tsx +41 -0
- package/src/theme/components/shared/prompt.css +178 -0
- package/src/theme/components/shared/prompt.stories.tsx +57 -0
- package/src/theme/components/shared/prompt.tsx +369 -0
- package/src/theme/components/shared/resolve-card-icon.ts +28 -0
- package/src/theme/components/shared/section-card.stories.tsx +51 -0
- package/src/theme/components/shared/section-card.tsx +44 -0
- package/src/theme/components/shared/section-grid.stories.tsx +46 -0
- package/src/theme/components/shared/section-grid.tsx +15 -0
- package/src/theme/components/shared/status-badge.css +37 -0
- package/src/theme/components/shared/status-badge.stories.tsx +61 -0
- package/src/theme/components/shared/status-badge.tsx +74 -0
- package/src/theme/components/shared/steps.css +88 -0
- package/src/theme/components/shared/steps.stories.tsx +68 -0
- package/src/theme/components/shared/steps.tsx +100 -0
- package/src/theme/components/shared/tech-icon-table.stories.tsx +29 -0
- package/src/theme/components/shared/tech-icon-table.tsx +71 -0
- package/src/theme/components/shared/tech-tag.stories.tsx +40 -0
- package/src/theme/components/shared/tech-tag.tsx +31 -0
- package/src/theme/components/shared/theme-color-palette.css +80 -0
- package/src/theme/components/shared/theme-color-palette.stories.tsx +52 -0
- package/src/theme/components/shared/theme-color-palette.tsx +275 -0
- package/src/theme/components/shared/tooltip.css +69 -0
- package/src/theme/components/shared/tooltip.stories.tsx +72 -0
- package/src/theme/components/shared/tooltip.tsx +77 -0
- package/src/theme/components/sidebar/framework-picker.css +77 -0
- package/src/theme/components/sidebar/framework-picker.tsx +78 -0
- package/src/theme/components/sidebar/sidebar-filter.test.ts +140 -0
- package/src/theme/components/sidebar/sidebar-filter.ts +79 -0
- package/src/theme/components/sidebar/sidebar-links.css +102 -0
- package/src/theme/components/sidebar/sidebar-links.tsx +122 -0
- package/src/theme/components/sidebar/sidebar-promo.css +42 -0
- package/src/theme/components/sidebar/sidebar-promo.tsx +52 -0
- package/src/theme/components/sidebar/sidebar-scope.tsx +151 -0
- package/src/theme/components/sidebar/sidebar-toggle.css +181 -0
- package/src/theme/components/sidebar/sidebar-toggle.tsx +127 -0
- package/src/theme/components/theme-provider.tsx +637 -0
- package/src/theme/components/workspaces/card.css +151 -0
- package/src/theme/components/workspaces/card.tsx +166 -0
- package/src/theme/components/workspaces/grid.tsx +62 -0
- package/src/theme/css.d.ts +1 -0
- package/src/theme/env.d.ts +12 -0
- package/src/theme/fonts/GeistMono-Variable.woff2 +0 -0
- package/src/theme/fonts/GeistPixel-Square.woff2 +0 -0
- package/src/theme/fonts/GeistSans-Variable.woff2 +0 -0
- package/src/theme/hooks/use-ciderpress.ts +61 -0
- package/src/theme/hooks/use-nav-items.ts +76 -0
- package/src/theme/icons/index.ts +2 -0
- package/src/theme/icons/tech-map.ts +228 -0
- package/src/theme/index.tsx +180 -0
- package/src/theme/lib/read-social-links.ts +27 -0
- package/src/theme/lib/route-link.tsx +126 -0
- package/src/theme/lib/safe-url.test.ts +0 -0
- package/src/theme/lib/safe-url.ts +68 -0
- package/src/theme/lib/theme-favicon.ts +125 -0
- package/src/theme/lib/user-config-stub.ts +12 -0
- package/src/theme/styles/layers.css +32 -0
- package/src/theme/styles/overrides/badge.css +26 -0
- package/src/theme/styles/overrides/content-footer.css +80 -0
- package/src/theme/styles/overrides/details.css +61 -0
- package/src/theme/styles/overrides/fonts.css +32 -0
- package/src/theme/styles/overrides/home-card.css +133 -0
- package/src/theme/styles/overrides/home.css +243 -0
- package/src/theme/styles/overrides/rail.css +337 -0
- package/src/theme/styles/overrides/rspress.css +62 -0
- package/src/theme/styles/overrides/scrollbar.css +25 -0
- package/src/theme/styles/overrides/section-card.css +114 -0
- package/src/theme/styles/overrides/sidebar.css +144 -0
- package/src/theme/styles/overrides/tokens.css +288 -0
- package/src/theme/styles/overrides/vscode.css +88 -0
- package/src/theme/styles/themes/amber.css +545 -0
- package/src/theme/styles/themes/arcade-fx.css +366 -0
- package/src/theme/styles/themes/arcade.css +273 -0
- package/src/theme/styles/themes/grannysmith.css +545 -0
- package/src/theme/styles/themes/honeycrisp.css +545 -0
- package/src/theme/styles/themes/midnight.css +273 -0
- package/src/theme/styles/themes/mulled.css +817 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature Card — layout and typography (base card styles from home-card.css).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/* ── Feature card layout ───────────────────────────────────── */
|
|
6
|
+
.cp-feature-card {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
gap: var(--cp-s-10);
|
|
10
|
+
height: 100%;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* Row 1: icon + title */
|
|
14
|
+
.cp-feature-card__header {
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
gap: var(--cp-s-12);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.cp-feature-card__title {
|
|
21
|
+
font-family: 'Geist Pixel Square', var(--rp-font-family-base, sans-serif);
|
|
22
|
+
font-size: var(--cp-fs-feature-title);
|
|
23
|
+
font-weight: var(--cp-fw-bold);
|
|
24
|
+
color: var(--rp-c-text-1, var(--cp-c-text-1));
|
|
25
|
+
line-height: var(--cp-lh-tight);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Row 2: description */
|
|
29
|
+
.cp-feature-card__desc {
|
|
30
|
+
font-size: var(--cp-fs-feature-desc);
|
|
31
|
+
color: var(--rp-c-text-2, var(--cp-c-text-2));
|
|
32
|
+
line-height: var(--cp-lh-base);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* ── Truncation ────────────────────────────────────────────── */
|
|
36
|
+
.cp-feature-card__title.cp-clamp,
|
|
37
|
+
.cp-feature-card__desc.cp-clamp {
|
|
38
|
+
display: -webkit-box;
|
|
39
|
+
-webkit-box-orient: vertical;
|
|
40
|
+
overflow: hidden;
|
|
41
|
+
text-overflow: ellipsis;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* Row 3: link tail (mockup pattern) */
|
|
45
|
+
.cp-feature-card__link {
|
|
46
|
+
margin-top: auto;
|
|
47
|
+
padding-top: var(--cp-s-16);
|
|
48
|
+
font-family: var(--cp-font-family-mono);
|
|
49
|
+
font-size: var(--cp-fs-feature-link);
|
|
50
|
+
color: var(--cp-c-brand-1);
|
|
51
|
+
font-weight: 500;
|
|
52
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { match, P } from 'massaman/match'
|
|
2
|
+
import type React from 'react'
|
|
3
|
+
|
|
4
|
+
import './feature-card.css'
|
|
5
|
+
import { Card } from '../shared/card'
|
|
6
|
+
import { Icon } from '../shared/icon'
|
|
7
|
+
import { resolveCardIcon } from '../shared/resolve-card-icon'
|
|
8
|
+
|
|
9
|
+
export interface FeatureCardProps {
|
|
10
|
+
readonly title: string
|
|
11
|
+
readonly description: string
|
|
12
|
+
readonly href?: string
|
|
13
|
+
readonly icon?: string | { readonly id: string; readonly color: string }
|
|
14
|
+
readonly span?: 2 | 3 | 4 | 6
|
|
15
|
+
readonly titleLines?: number
|
|
16
|
+
readonly descriptionLines?: number
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Frontmatter-shaped data for consumers to map from.
|
|
21
|
+
*/
|
|
22
|
+
export interface FeatureItem {
|
|
23
|
+
readonly title: string
|
|
24
|
+
readonly details: string
|
|
25
|
+
readonly link?: string
|
|
26
|
+
readonly icon?: string | { readonly id: string; readonly color: string }
|
|
27
|
+
readonly span?: 2 | 3 | 4 | 6
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Feature card for landing pages — matches the workspace/section card design.
|
|
32
|
+
* Renders as `<a>` when `href` is provided, `<div>` otherwise.
|
|
33
|
+
*
|
|
34
|
+
* @param props - Feature card props including title, description, href, icon, span, titleLines, descriptionLines
|
|
35
|
+
* @returns React element with feature card layout
|
|
36
|
+
*/
|
|
37
|
+
export function FeatureCard({
|
|
38
|
+
title,
|
|
39
|
+
description,
|
|
40
|
+
href,
|
|
41
|
+
icon,
|
|
42
|
+
span = 4,
|
|
43
|
+
titleLines,
|
|
44
|
+
descriptionLines,
|
|
45
|
+
}: FeatureCardProps): React.ReactElement {
|
|
46
|
+
const resolved = resolveCardIcon(icon)
|
|
47
|
+
|
|
48
|
+
const iconEl = match(resolved)
|
|
49
|
+
.with(P.nonNullable, (r) => (
|
|
50
|
+
<span className={`cp-card__icon cp-card__icon--${r.color}`}>
|
|
51
|
+
<Icon icon={r.id} />
|
|
52
|
+
</span>
|
|
53
|
+
))
|
|
54
|
+
.otherwise(() => null)
|
|
55
|
+
|
|
56
|
+
const linkTail = match(href)
|
|
57
|
+
.with(P.nonNullable, () => <span className="cp-feature-card__link">Learn more →</span>)
|
|
58
|
+
.otherwise(() => null)
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div className={`cp-feature-grid__item cp-feature-grid__item--span-${span}`}>
|
|
62
|
+
<div className="cp-feature-grid__item-wrap">
|
|
63
|
+
<Card href={href} className="cp-feature-card">
|
|
64
|
+
<div className="cp-feature-card__header">
|
|
65
|
+
{iconEl}
|
|
66
|
+
<span
|
|
67
|
+
className={clampClass('cp-feature-card__title', titleLines)}
|
|
68
|
+
style={clampStyle(titleLines)}
|
|
69
|
+
>
|
|
70
|
+
{title}
|
|
71
|
+
</span>
|
|
72
|
+
</div>
|
|
73
|
+
<span
|
|
74
|
+
className={clampClass('cp-feature-card__desc', descriptionLines)}
|
|
75
|
+
style={clampStyle(descriptionLines)}
|
|
76
|
+
>
|
|
77
|
+
{description}
|
|
78
|
+
</span>
|
|
79
|
+
{linkTail}
|
|
80
|
+
</Card>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
interface FeatureGridProps {
|
|
87
|
+
readonly children: React.ReactNode
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Flex-wrap layout container for feature cards.
|
|
92
|
+
*
|
|
93
|
+
* @param props - Props with children to render inside the grid
|
|
94
|
+
* @returns React element wrapping children in a feature grid
|
|
95
|
+
*/
|
|
96
|
+
export function FeatureGrid({ children }: FeatureGridProps): React.ReactElement {
|
|
97
|
+
return (
|
|
98
|
+
<div className="cp-feature-section">
|
|
99
|
+
<div className="cp-feature-grid">{children}</div>
|
|
100
|
+
</div>
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Build a className string with optional `cp-clamp` suffix.
|
|
106
|
+
*
|
|
107
|
+
* @private
|
|
108
|
+
* @param base - Base CSS class name
|
|
109
|
+
* @param lines - Optional line clamp value
|
|
110
|
+
* @returns Class string with or without cp-clamp
|
|
111
|
+
*/
|
|
112
|
+
function clampClass(base: string, lines: number | undefined): string {
|
|
113
|
+
if (lines) {
|
|
114
|
+
return `${base} cp-clamp`
|
|
115
|
+
}
|
|
116
|
+
return base
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Build an inline style object for line clamping.
|
|
121
|
+
*
|
|
122
|
+
* @private
|
|
123
|
+
* @param lines - Optional line clamp value
|
|
124
|
+
* @returns Style object with WebkitLineClamp or undefined
|
|
125
|
+
*/
|
|
126
|
+
function clampStyle(lines: number | undefined): React.CSSProperties | undefined {
|
|
127
|
+
if (lines) {
|
|
128
|
+
return { WebkitLineClamp: lines }
|
|
129
|
+
}
|
|
130
|
+
return undefined
|
|
131
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { HomeGridConfig } from '@ciderpress/config'
|
|
2
|
+
import { useFrontmatter } from '@rspress/core/runtime'
|
|
3
|
+
import { match, P } from 'massaman/match'
|
|
4
|
+
import type React from 'react'
|
|
5
|
+
|
|
6
|
+
import { useCiderpress } from '../../hooks/use-ciderpress'
|
|
7
|
+
import { FeatureCard } from './feature-card'
|
|
8
|
+
import type { FeatureItem } from './feature-card'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Custom HomeFeature override for ciderpress.
|
|
12
|
+
* Uses useFrontmatter() hook to read features and renders with FeatureCard/FeatureGrid styling.
|
|
13
|
+
*
|
|
14
|
+
* @returns React element with feature grid or null
|
|
15
|
+
*/
|
|
16
|
+
export function HomeFeature(): React.ReactElement | null {
|
|
17
|
+
const { frontmatter } = useFrontmatter()
|
|
18
|
+
const { home } = useCiderpress()
|
|
19
|
+
const gridConfig = home && home.features
|
|
20
|
+
|
|
21
|
+
// Rspress types frontmatter as its own FrontMatterMeta shape which does not
|
|
22
|
+
// include ciderpress-specific `features`. The double cast is necessary because
|
|
23
|
+
// no shared Zod schema exists for frontmatter validation at runtime.
|
|
24
|
+
const features = (frontmatter as Record<string, unknown>).features as
|
|
25
|
+
| readonly FeatureItem[]
|
|
26
|
+
| undefined
|
|
27
|
+
|
|
28
|
+
return match(features)
|
|
29
|
+
.with(
|
|
30
|
+
P.when((f): f is readonly FeatureItem[] => Array.isArray(f) && f.length > 0),
|
|
31
|
+
(items) => (
|
|
32
|
+
<div className="cp-feature-section">
|
|
33
|
+
<div className="cp-feature-section-head">
|
|
34
|
+
<div className="cp-feature-section-head__eyebrow">Features</div>
|
|
35
|
+
<h2 className="cp-feature-section-head__title">Built for the way you ship.</h2>
|
|
36
|
+
<p className="cp-feature-section-head__sub">
|
|
37
|
+
Everything you need, nothing you don't. Configured in TypeScript, validated at
|
|
38
|
+
boot.
|
|
39
|
+
</p>
|
|
40
|
+
</div>
|
|
41
|
+
<div className="cp-feature-grid">
|
|
42
|
+
{items.map((f, i) => renderFeature(f, i, gridConfig))}
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
.otherwise(() => null)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Render a single feature as a FeatureCard element.
|
|
52
|
+
* Accepts the array index from `.map()` to guarantee unique keys.
|
|
53
|
+
*
|
|
54
|
+
* @private
|
|
55
|
+
* @param feature - Feature item data
|
|
56
|
+
* @param index - Array index for key generation
|
|
57
|
+
* @param gridConfig - Optional grid config for truncation
|
|
58
|
+
* @returns Feature card element
|
|
59
|
+
*/
|
|
60
|
+
function renderFeature(
|
|
61
|
+
feature: FeatureItem,
|
|
62
|
+
index: number,
|
|
63
|
+
gridConfig: HomeGridConfig | undefined
|
|
64
|
+
): React.ReactElement {
|
|
65
|
+
const titleLines = gridConfig && gridConfig.truncate && gridConfig.truncate.title
|
|
66
|
+
const descLines = gridConfig && gridConfig.truncate && gridConfig.truncate.description
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<FeatureCard
|
|
70
|
+
key={`${feature.title}-${index}`}
|
|
71
|
+
title={feature.title}
|
|
72
|
+
description={feature.details}
|
|
73
|
+
href={feature.link}
|
|
74
|
+
icon={feature.icon}
|
|
75
|
+
titleLines={titleLines}
|
|
76
|
+
descriptionLines={descLines}
|
|
77
|
+
/>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
.cp-hero-demo {
|
|
2
|
+
max-width: var(--cp-size-demo-max);
|
|
3
|
+
margin: 0 auto;
|
|
4
|
+
border: 1px solid var(--cp-c-border);
|
|
5
|
+
border-radius: var(--cp-radius-lg);
|
|
6
|
+
background: var(--cp-code-block-bg);
|
|
7
|
+
overflow: hidden;
|
|
8
|
+
box-shadow: var(--cp-shadow-hero-demo);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.cp-hero-demo__bar {
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
gap: var(--cp-s-8);
|
|
15
|
+
padding: var(--cp-s-10) var(--cp-s-14);
|
|
16
|
+
background: var(--cp-c-bg-elv);
|
|
17
|
+
border-bottom: 1px solid var(--cp-c-border);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.cp-hero-demo__dot {
|
|
21
|
+
width: var(--cp-size-window-dot);
|
|
22
|
+
height: var(--cp-size-window-dot);
|
|
23
|
+
border-radius: 50%;
|
|
24
|
+
background: var(--cp-c-bg-soft);
|
|
25
|
+
border: 1px solid var(--cp-c-border);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.cp-hero-demo__title {
|
|
29
|
+
font-family: var(--cp-font-family-mono);
|
|
30
|
+
font-size: var(--cp-fs-demo-title);
|
|
31
|
+
color: var(--cp-c-text-3);
|
|
32
|
+
margin-left: var(--cp-s-8);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.cp-hero-demo__title em {
|
|
36
|
+
color: var(--cp-c-text-2);
|
|
37
|
+
font-style: normal;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.cp-hero-demo__body {
|
|
41
|
+
margin: 0;
|
|
42
|
+
padding: var(--cp-s-20) var(--cp-s-24);
|
|
43
|
+
font-family: var(--cp-font-family-mono);
|
|
44
|
+
font-size: var(--cp-fs-demo-body);
|
|
45
|
+
line-height: var(--cp-lh-demo);
|
|
46
|
+
white-space: pre;
|
|
47
|
+
overflow-x: auto;
|
|
48
|
+
color: var(--cp-c-text-1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.cp-hero-demo__prompt,
|
|
52
|
+
.cp-hero-demo__ok {
|
|
53
|
+
color: var(--cp-c-brand-1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.cp-hero-demo__cmt {
|
|
57
|
+
color: var(--cp-c-text-3);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.cp-hero-demo__info {
|
|
61
|
+
color: var(--cp-c-tint-blue-fg);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.cp-hero-demo__file {
|
|
65
|
+
color: var(--cp-c-tint-amber-bright-fg);
|
|
66
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type React from 'react'
|
|
2
|
+
|
|
3
|
+
import './hero-demo.css'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* HeroDemo — default terminal-style demo block used inside Hero.
|
|
7
|
+
*
|
|
8
|
+
* Renders a fake macOS window with `pnpm ciderpress dev` output. Self-contained
|
|
9
|
+
* so consumers can render it directly in MDX or via HomeLayout.
|
|
10
|
+
*
|
|
11
|
+
* @returns React element.
|
|
12
|
+
*/
|
|
13
|
+
export function HeroDemo(): React.ReactElement {
|
|
14
|
+
return (
|
|
15
|
+
<div className="cp-hero-demo">
|
|
16
|
+
<div className="cp-hero-demo__bar">
|
|
17
|
+
<span className="cp-hero-demo__dot" />
|
|
18
|
+
<span className="cp-hero-demo__dot" />
|
|
19
|
+
<span className="cp-hero-demo__dot" />
|
|
20
|
+
<span className="cp-hero-demo__title">
|
|
21
|
+
<em>~/code/acme</em> — pnpm ciderpress dev
|
|
22
|
+
</span>
|
|
23
|
+
</div>
|
|
24
|
+
<pre className="cp-hero-demo__body">
|
|
25
|
+
<span className="cp-hero-demo__prompt">$ </span>pnpm ciderpress dev
|
|
26
|
+
{'\n\n'}
|
|
27
|
+
<span className="cp-hero-demo__ok"> ▸</span> ciderpress 0.5 — Rspress 2.0
|
|
28
|
+
{'\n'}
|
|
29
|
+
<span className="cp-hero-demo__ok"> ▸</span> watching{' '}
|
|
30
|
+
<span className="cp-hero-demo__file">./docs</span>,{' '}
|
|
31
|
+
<span className="cp-hero-demo__file">./openapi.yaml</span>
|
|
32
|
+
{'\n'}
|
|
33
|
+
<span className="cp-hero-demo__ok"> ▸</span> sidebar synced from 24 files
|
|
34
|
+
{'\n'}
|
|
35
|
+
<span className="cp-hero-demo__info"> ▸</span> openapi spec parsed — 18 endpoints
|
|
36
|
+
{'\n'}
|
|
37
|
+
<span className="cp-hero-demo__ok"> ✓</span> ready on{' '}
|
|
38
|
+
<span className="cp-hero-demo__file">http://localhost:4321</span> in 412ms
|
|
39
|
+
{'\n\n'}
|
|
40
|
+
<span className="cp-hero-demo__cmt"> ↻ docs/guides/openapi.md changed</span>
|
|
41
|
+
{'\n'}
|
|
42
|
+
<span className="cp-hero-demo__cmt"> ↻ rebuilt sidebar in 8ms</span>
|
|
43
|
+
</pre>
|
|
44
|
+
</div>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
.cp-hero {
|
|
2
|
+
position: relative;
|
|
3
|
+
padding: 96px 0 72px;
|
|
4
|
+
text-align: center;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.cp-hero__inner {
|
|
8
|
+
max-width: 1100px;
|
|
9
|
+
margin: 0 auto;
|
|
10
|
+
padding: 0 32px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.cp-hero__eyebrow {
|
|
14
|
+
display: inline-flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
gap: 8px;
|
|
17
|
+
padding: 6px 12px;
|
|
18
|
+
border: 1px solid var(--cp-c-border);
|
|
19
|
+
border-radius: var(--cp-radius-pill);
|
|
20
|
+
background: var(--cp-c-bg-elv);
|
|
21
|
+
font-family: var(--cp-font-family-mono);
|
|
22
|
+
font-size: 11px;
|
|
23
|
+
color: var(--cp-c-text-2);
|
|
24
|
+
text-transform: uppercase;
|
|
25
|
+
letter-spacing: 0.06em;
|
|
26
|
+
margin-bottom: 28px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.cp-hero__title {
|
|
30
|
+
font-size: clamp(40px, 6.5vw, 76px);
|
|
31
|
+
font-weight: 600;
|
|
32
|
+
letter-spacing: -0.04em;
|
|
33
|
+
line-height: 1;
|
|
34
|
+
margin: 0 0 24px;
|
|
35
|
+
color: var(--cp-c-text-1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.cp-hero__title .cp-hero__grad {
|
|
39
|
+
color: var(--cp-c-brand-1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.cp-hero__tagline {
|
|
43
|
+
max-width: 640px;
|
|
44
|
+
margin: 0 auto 40px;
|
|
45
|
+
font-size: 18px;
|
|
46
|
+
line-height: 1.6;
|
|
47
|
+
color: var(--cp-c-text-2);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.cp-hero__cta {
|
|
51
|
+
display: flex;
|
|
52
|
+
gap: 12px;
|
|
53
|
+
justify-content: center;
|
|
54
|
+
flex-wrap: wrap;
|
|
55
|
+
margin-bottom: 56px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.cp-hero__btn {
|
|
59
|
+
display: inline-flex;
|
|
60
|
+
align-items: center;
|
|
61
|
+
gap: 8px;
|
|
62
|
+
padding: 10px 18px;
|
|
63
|
+
font-size: 14px;
|
|
64
|
+
font-weight: 500;
|
|
65
|
+
border-radius: var(--cp-radius-pill);
|
|
66
|
+
border: 1px solid var(--cp-c-border);
|
|
67
|
+
background: transparent;
|
|
68
|
+
color: var(--cp-c-text-1);
|
|
69
|
+
cursor: pointer;
|
|
70
|
+
transition: all 0.15s ease;
|
|
71
|
+
white-space: nowrap;
|
|
72
|
+
text-decoration: none;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.cp-hero__btn:hover {
|
|
76
|
+
background: var(--cp-c-bg-soft);
|
|
77
|
+
border-color: var(--cp-c-border);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.cp-hero__btn--primary {
|
|
81
|
+
background: var(--cp-c-brand-1);
|
|
82
|
+
color: var(--cp-c-brand-fg);
|
|
83
|
+
border-color: var(--cp-c-brand-1);
|
|
84
|
+
font-weight: 600;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.cp-hero__btn--primary:hover {
|
|
88
|
+
background: var(--cp-c-brand-2);
|
|
89
|
+
border-color: var(--cp-c-brand-2);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.cp-hero__demo {
|
|
93
|
+
max-width: 920px;
|
|
94
|
+
margin: 0 auto;
|
|
95
|
+
text-align: left;
|
|
96
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { match } from 'massaman/match'
|
|
2
|
+
import type React from 'react'
|
|
3
|
+
|
|
4
|
+
import { RouteLink } from '../../lib/route-link.tsx'
|
|
5
|
+
import { safeUrl } from '../../lib/safe-url.ts'
|
|
6
|
+
|
|
7
|
+
import './hero.css'
|
|
8
|
+
|
|
9
|
+
export interface HeroAction {
|
|
10
|
+
/**
|
|
11
|
+
* Visible label.
|
|
12
|
+
*/
|
|
13
|
+
readonly text: string
|
|
14
|
+
/**
|
|
15
|
+
* Destination URL.
|
|
16
|
+
*/
|
|
17
|
+
readonly link: string
|
|
18
|
+
/**
|
|
19
|
+
* Visual style — `brand` is the filled primary, `alt` is the outline.
|
|
20
|
+
*/
|
|
21
|
+
readonly theme?: 'brand' | 'alt'
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface HeroProps {
|
|
25
|
+
/**
|
|
26
|
+
* Optional eyebrow chip (e.g. "★ 2.1k stars · v0.4.2").
|
|
27
|
+
*/
|
|
28
|
+
readonly eyebrow?: React.ReactNode
|
|
29
|
+
/**
|
|
30
|
+
* Main heading. Wrap a fragment in `<span className="cp-hero__grad">…</span>`
|
|
31
|
+
* for the gradient phrase.
|
|
32
|
+
*/
|
|
33
|
+
readonly title: React.ReactNode
|
|
34
|
+
/**
|
|
35
|
+
* Sub-text shown below the headline.
|
|
36
|
+
*/
|
|
37
|
+
readonly tagline?: React.ReactNode
|
|
38
|
+
/**
|
|
39
|
+
* Two CTAs at most for visual balance.
|
|
40
|
+
*/
|
|
41
|
+
readonly actions?: readonly HeroAction[]
|
|
42
|
+
/**
|
|
43
|
+
* Optional visual block beneath the CTAs (terminal demo, screenshot, etc).
|
|
44
|
+
*/
|
|
45
|
+
readonly demo?: React.ReactNode
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Hero — landing-page hero with eyebrow chip, gradient-friendly headline,
|
|
50
|
+
* tagline, CTAs, and an optional demo slot. The radial accent glow + dotted
|
|
51
|
+
* grid backdrop are baked in via CSS and adapt to the active theme.
|
|
52
|
+
*
|
|
53
|
+
* @param props - Hero configuration.
|
|
54
|
+
* @returns React element.
|
|
55
|
+
*/
|
|
56
|
+
export function Hero(props: HeroProps): React.ReactElement {
|
|
57
|
+
const { eyebrow, title, tagline, actions, demo } = props
|
|
58
|
+
const list = actions ?? []
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<section className="cp-hero">
|
|
62
|
+
<div className="cp-hero__inner">
|
|
63
|
+
{match(eyebrow)
|
|
64
|
+
.with(undefined, () => null)
|
|
65
|
+
.otherwise((e) => (
|
|
66
|
+
<div className="cp-hero__eyebrow">{e}</div>
|
|
67
|
+
))}
|
|
68
|
+
<h1 className="cp-hero__title">{title}</h1>
|
|
69
|
+
{match(tagline)
|
|
70
|
+
.with(undefined, () => null)
|
|
71
|
+
.otherwise((t) => (
|
|
72
|
+
<p className="cp-hero__tagline">{t}</p>
|
|
73
|
+
))}
|
|
74
|
+
{match(list.length === 0)
|
|
75
|
+
.with(true, () => null)
|
|
76
|
+
.otherwise(() => (
|
|
77
|
+
<div className="cp-hero__cta">{list.map(renderAction)}</div>
|
|
78
|
+
))}
|
|
79
|
+
{match(demo)
|
|
80
|
+
.with(undefined, () => null)
|
|
81
|
+
.otherwise((d) => (
|
|
82
|
+
<div className="cp-hero__demo">{d}</div>
|
|
83
|
+
))}
|
|
84
|
+
</div>
|
|
85
|
+
</section>
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Render a single hero CTA action.
|
|
91
|
+
*
|
|
92
|
+
* @private
|
|
93
|
+
* @param action - Hero action.
|
|
94
|
+
* @param index - Array index for key generation.
|
|
95
|
+
* @returns Anchor element.
|
|
96
|
+
*/
|
|
97
|
+
function renderAction(action: HeroAction, index: number): React.ReactElement | null {
|
|
98
|
+
const href = safeUrl(action.link)
|
|
99
|
+
if (href === null) {
|
|
100
|
+
return null
|
|
101
|
+
}
|
|
102
|
+
const className = match(action.theme ?? 'brand')
|
|
103
|
+
.with('brand', () => 'cp-hero__btn cp-hero__btn--primary')
|
|
104
|
+
.otherwise(() => 'cp-hero__btn')
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<RouteLink key={`${href}:${index}`} href={href} className={className}>
|
|
108
|
+
{action.text}
|
|
109
|
+
</RouteLink>
|
|
110
|
+
)
|
|
111
|
+
}
|