From e875ff0255853b7ef0f4952cf717c18fd59ee301 Mon Sep 17 00:00:00 2001 From: "liuzhao@meicai.cn" Date: Thu, 24 Sep 2026 18:16:36 +0800 Subject: [PATCH 01/12] feat(theme): restyle docs UI to SandBase pixel-poster design Match the sandbase /docs reference design and copy the sandbase.ai main-site header and footer: - Adopt the SandBase palette (canvas/ink/violet-lime accent), Clash Grotesk typeface, hairline borders, near-square radii, and monospace uppercase micro-labels, all mapped onto VitePress core tokens. - Header: Clash Grotesk wordmark, ink nav links with accent hover, and a solid 'Start building' CTA button; add a Pricing link to the main site. - Footer: brand + tagline, Store/Solutions/Build/Learn columns, social row, and a bottom rule with copyright and service status (mirrors sandbase.ai). - Render code on the signature dark 'panel' surface in both appearances (pin syntax theme to github-dark) with a monospace language label. - Add pixel-square accent list bullets for prose. --- .vitepress/config.ts | 11 +- .vitepress/theme/ContactFooter.vue | 163 +++++----- .vitepress/theme/custom.css | 506 ++++++++++++++++++++++++++--- public/ClashGrotesk-Variable.woff2 | Bin 0 -> 47224 bytes 4 files changed, 566 insertions(+), 114 deletions(-) create mode 100644 public/ClashGrotesk-Variable.woff2 diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 6e72d6c5..d39972d4 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -237,6 +237,13 @@ export default defineConfig({ ignoreDeadLinks: true, appearance: true, cleanUrls: true, + + // The SandBase design presents code on a dark "panel" surface in both light + // and dark appearance. Pin the syntax theme to a dark palette so code blocks + // read as the signature dark panels on every background. + markdown: { + theme: { light: 'github-dark', dark: 'github-dark' }, + }, // Frontmatter titles are already curated for SEO; avoid appending a second // brand suffix that can push rendered titles beyond search-result limits. titleTemplate: false, @@ -295,7 +302,9 @@ export default defineConfig({ { text: 'Docs', link: '/', activeMatch: '^/(?!api-reference/|model-api-reference/)' }, { text: 'Model API Reference', link: '/model-api-reference/', activeMatch: '^/model-api-reference/' }, { text: 'Platform API', link: '/api-reference/', activeMatch: '^/api-reference/' }, - { text: 'Console', link: 'https://www.sandbase.ai/console', target: '_blank', rel: 'noopener noreferrer' }, + { text: 'Pricing', link: 'https://www.sandbase.ai/pricing', target: '_blank', rel: 'noopener noreferrer' }, + // Rendered as the primary "Start building" CTA button (see custom.css). + { text: 'Start building', link: 'https://www.sandbase.ai/console', target: '_blank', rel: 'noopener noreferrer' }, ], sidebar: { diff --git a/.vitepress/theme/ContactFooter.vue b/.vitepress/theme/ContactFooter.vue index 782f8dd3..eefa0001 100644 --- a/.vitepress/theme/ContactFooter.vue +++ b/.vitepress/theme/ContactFooter.vue @@ -15,52 +15,53 @@ type FooterColumn = { }> } +const site = 'https://www.sandbase.ai' +const statusPageUrl = 'https://status.sandbase.ai/' +const tagline = + 'Build your Agent, give it real-world tools, and run it inside your AI app, product, or schedule.' + const socialLinks: SocialLink[] = [ { href: 'https://github.com/sandbaseai', label: 'GitHub', icon: 'github' }, { href: 'https://discord.com/invite/4hXv2f5Q9f', label: 'Discord', icon: 'discord' }, - { href: 'https://x.com/SandbaseAI', label: 'X', icon: 'x' }, - { href: 'https://www.linkedin.com/company/sandbaseai/', label: 'LinkedIn', icon: 'linkedin' }, + { href: 'https://x.com/sandbaseai', label: 'X', icon: 'x' }, + { href: 'https://www.linkedin.com/company/sandbaseai', label: 'LinkedIn', icon: 'linkedin' }, ] +// Mirrors the sandbase.ai site footer navigation (Store · Solutions · Build · Learn). const footerColumns: FooterColumn[] = [ { - title: 'Product', + title: 'Store', links: [ - { href: '/docs/store/', label: 'Store' }, - { href: '/docs/models/', label: 'Models' }, - { href: '/docs/model-api-reference/', label: 'Model API Reference' }, - { href: '/docs/api-reference/', label: 'Platform API' }, - { href: 'https://www.sandbase.ai/console', label: 'Console' }, + { href: `${site}/agents`, label: 'Agents' }, + { href: `${site}/models`, label: 'Models' }, + { href: `${site}/apis`, label: 'APIs' }, + { href: `${site}/skills`, label: 'Skills' }, ], }, { - title: 'Resources', + title: 'Solutions', links: [ - { href: '/docs/', label: 'Docs' }, - { href: '/docs/getting-started/quickstart', label: 'Quickstart' }, - { href: '/docs/getting-started/first-call', label: 'First API call' }, - { href: 'https://www.sandbase.ai/blog', label: 'Blog' }, - { href: 'https://status.sandbase.ai', label: 'Status' }, + { href: `${site}/solutions`, label: 'All Solutions' }, + { href: `${site}/solutions/build-agent`, label: 'Build Agent' }, + { href: `${site}/solutions/service`, label: 'Service' }, + { href: `${site}/solutions/schedule`, label: 'Schedule' }, ], }, { - title: 'Company', + title: 'Build', links: [ - { href: 'https://www.sandbase.ai/about', label: 'About' }, - { href: 'https://www.sandbase.ai/pricing', label: 'Pricing' }, - { href: 'https://www.sandbase.ai/contact', label: 'Contact' }, - { href: 'https://github.com/sandbaseai', label: 'GitHub' }, - { href: 'https://x.com/SandbaseAI', label: 'X' }, + { href: `${site}/console/agents`, label: 'Build Agent' }, + { href: `${site}/console/endpoints`, label: 'Published Agents' }, + { href: `${site}/console/deployments`, label: 'Schedules' }, + { href: `${site}/console/sessions`, label: 'Runs' }, ], }, { - title: 'Help and security', + title: 'Learn', links: [ - { href: 'mailto:support@sandbase.ai', label: 'Support' }, - { href: 'https://discord.com/invite/4hXv2f5Q9f', label: 'Discord' }, - { href: '/docs/api-reference/errors', label: 'Errors' }, - { href: '/docs/admin/rate-limits', label: 'Rate limits' }, - { href: 'https://www.sandbase.ai/privacy', label: 'Privacy policy' }, + { href: '/docs/', label: 'Docs' }, + { href: `${site}/pricing`, label: 'Pricing' }, + { href: `${site}/blog/`, label: 'Blog' }, ], }, ] @@ -68,61 +69,73 @@ const footerColumns: FooterColumn[] = [ diff --git a/.vitepress/theme/custom.css b/.vitepress/theme/custom.css index 3b75b94c..569d3689 100644 --- a/.vitepress/theme/custom.css +++ b/.vitepress/theme/custom.css @@ -1,39 +1,105 @@ -/* SandBase docs palette — documentation-first neutrals. Brand green is a - semantic accent, never the default text or surface color. */ +/* Clash Grotesk — the SandBase brand typeface, shared with the main site. */ +@font-face { + font-family: 'Clash Grotesk'; + src: url('/docs/ClashGrotesk-Variable.woff2') format('woff2'); + font-weight: 200 700; + font-display: swap; + font-style: normal; +} + +/* ─── SandBase design system ─────────────────────────────────────────────── + Ported from the sandbase /docs reference design and the sandbase.ai main + site. The whole theme is token-driven: change these values and the palette + cascades through VitePress's own `--vp-c-*` variables. The look is an + editorial "pixel poster": near-zero radius, hairline borders, a violet + (light) / lime (dark) accent, and monospace uppercase micro-labels. */ :root { - --vp-c-brand-1: #303238; - --vp-c-brand-2: #1f2126; - --vp-c-brand-3: #15171b; - --vp-c-brand-soft: rgba(31, 33, 38, 0.065); - --sb-accent-green: #16815b; - - --sb-code-text: #344054; - --sb-code-bg: #f1f3f5; - --sb-code-border: #e4e7ec; - --sb-code-block-bg: #f8f9fa; - - /* Fonts — unified Inter stack (matches platform.claude.com) */ - --vp-font-family-base: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', Roboto, sans-serif; + --sb-canvas: #f2f0f3; + --sb-surface: #ffffff; + --sb-surface-alt: #e7e4ea; + --sb-line: #dbd8df; + --sb-line-strong: #0e0b1a; + --sb-ink: #0e0b1a; + --sb-ink-muted: #5d5969; + --sb-ink-subtle: #757183; + --sb-accent: #5e3fff; + --sb-accent-hover: #4a2fe0; + --sb-accent-contrast: #ffffff; + --sb-tint: #d9ff43; /* pixel accent / corner marks / CTA hover */ + --sb-tint-fg: #0e0b1a; + --sb-panel: #0e0b1a; /* dark code panel */ + --sb-panel-fg: #f2f0f3; + --sb-panel-label: #8a8698; + + /* Map onto VitePress core tokens so the palette propagates everywhere. */ + --vp-c-bg: var(--sb-canvas); + --vp-c-bg-alt: var(--sb-canvas); + --vp-c-bg-soft: var(--sb-surface-alt); + --vp-c-bg-elv: var(--sb-surface); + --vp-c-text-1: var(--sb-ink); + --vp-c-text-2: var(--sb-ink-muted); + --vp-c-text-3: var(--sb-ink-subtle); + --vp-c-divider: var(--sb-line); + --vp-c-border: var(--sb-line); + --vp-c-gutter: var(--sb-line); + --vp-c-brand-1: var(--sb-accent); + --vp-c-brand-2: var(--sb-accent-hover); + --vp-c-brand-3: var(--sb-accent); + --vp-c-brand-soft: color-mix(in srgb, var(--sb-accent) 12%, transparent); + --sb-accent-green: var(--sb-accent); /* legacy alias reused across this file */ + + --sb-code-text: var(--sb-ink); /* inline code chips read on surface-alt */ + --sb-code-bg: var(--sb-surface-alt); /* inline code chips */ + --sb-code-border: var(--sb-line); + --sb-code-block-bg: var(--sb-panel); /* fenced code = dark panel */ + --vp-code-block-bg: var(--sb-panel); + --vp-code-copy-code-bg: rgba(255, 255, 255, 0.09); + --vp-code-copy-code-hover-bg: rgba(255, 255, 255, 0.18); + --vp-code-copy-code-active-text: var(--sb-panel-fg); + + --vp-font-family-base: 'Clash Grotesk', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', Roboto, sans-serif; --vp-font-family-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', Consolas, monospace; } .dark { - --vp-c-brand-1: #e3e5e8; - --vp-c-brand-2: #f1f2f4; - --vp-c-brand-3: #ffffff; - --vp-c-brand-soft: rgba(255, 255, 255, 0.08); - --sb-accent-green: #68d6a8; - - --sb-code-text: #d6dce5; - --sb-code-bg: #232832; - --sb-code-border: #343b48; - --sb-code-block-bg: #171b22; - - /* Dark background matching main site */ - --vp-c-bg: #0f1117; - --vp-c-bg-alt: #161922; - --vp-c-bg-elv: #1c1f2b; - --vp-c-bg-soft: #1c1f2b; + --sb-canvas: #0e0b1a; + --sb-surface: #241d44; + --sb-surface-alt: #2e2656; + --sb-line: #332d4f; + --sb-line-strong: #f2f0f3; + --sb-ink: #f2f0f3; + --sb-ink-muted: #a29ea9; + --sb-ink-subtle: #8a8698; + --sb-accent: #d9ff43; + --sb-accent-hover: #e6ff70; + --sb-accent-contrast: #0e0b1a; + --sb-tint: #8b6fff; + --sb-tint-fg: #ffffff; + --sb-panel: #1e1936; + --sb-panel-fg: #f2f0f3; + --sb-panel-label: #a9a5b8; + + --vp-c-bg: var(--sb-canvas); + --vp-c-bg-alt: var(--sb-canvas); + --vp-c-bg-soft: var(--sb-surface); + --vp-c-bg-elv: var(--sb-surface); + --vp-c-text-1: var(--sb-ink); + --vp-c-text-2: var(--sb-ink-muted); + --vp-c-text-3: var(--sb-ink-subtle); + --vp-c-divider: var(--sb-line); + --vp-c-border: var(--sb-line); + --vp-c-gutter: var(--sb-line); + --vp-c-brand-1: var(--sb-accent); + --vp-c-brand-2: var(--sb-accent-hover); + --vp-c-brand-3: var(--sb-accent); + --vp-c-brand-soft: color-mix(in srgb, var(--sb-accent) 16%, transparent); + --sb-accent-green: var(--sb-accent); + + --sb-code-text: var(--sb-ink); + --sb-code-bg: var(--sb-surface-alt); + --sb-code-border: var(--sb-line); + --sb-code-block-bg: var(--sb-panel); + --vp-code-block-bg: var(--sb-panel); } /* ─── Developer-doc sidebar: compact, structured, keyboard friendly ─── */ @@ -459,9 +525,9 @@ /* Custom container (tip, warning, danger) colors */ :root { - --vp-custom-block-tip-border: #cfd3d8; - --vp-custom-block-tip-bg: rgba(31, 33, 38, 0.035); - --vp-custom-block-tip-text: #303238; + --vp-custom-block-tip-border: var(--sb-line); + --vp-custom-block-tip-bg: var(--sb-surface); + --vp-custom-block-tip-text: var(--sb-ink); --vp-custom-block-warning-border: #e5a50a; --vp-custom-block-warning-bg: rgba(229, 165, 10, 0.08); @@ -581,10 +647,10 @@ html { /* ─── Reference-document layout: dense, quiet, and scan-first ─── */ :root { - --vp-nav-height: 64px; + --vp-nav-height: 72px; --vp-sidebar-width: 244px; --vp-layout-max-width: 1680px; - --sb-doc-rule: color-mix(in srgb, var(--vp-c-divider) 72%, transparent); + --sb-doc-rule: var(--sb-line); } /* Light-only surface tints. These MUST stay scoped to `:not(.dark)`: a bare @@ -592,8 +658,8 @@ html { it would clobber the dark surfaces and tint the sidebar, table rows, and inline code light while in dark mode. */ :root:not(.dark) { - --vp-c-bg-alt: #f8f9f8; - --vp-c-bg-soft: #f4f6f5; + --vp-c-bg-alt: var(--sb-canvas); + --vp-c-bg-soft: var(--sb-surface-alt); } .VPNav { @@ -1412,3 +1478,367 @@ html { margin: 24px 0 32px; border-radius: 2px; } + +/* ══════════════════════════════════════════════════════════════════════════ + SandBase design layer + Header, footer, code panels, and pixel-poster typography ported from the + sandbase.ai main site and the sandbase /docs reference design. Appended last + so these rules win over the earlier documentation-neutral defaults. + ══════════════════════════════════════════════════════════════════════════ */ + +/* ─── Header / top navigation (mirrors the sandbase.ai site header) ─────── */ +.VPNav { + border-bottom: 1px solid var(--sb-line); +} + +.VPNavBar { + background: color-mix(in srgb, var(--sb-canvas) 92%, transparent) !important; + backdrop-filter: saturate(1.1) blur(12px); +} + +/* Brand: logo mark + Clash Grotesk wordmark. */ +.VPNavBarTitle .title { + gap: 0.6rem !important; + color: var(--sb-ink) !important; + font-family: var(--vp-font-family-base); + font-size: 1.5rem !important; + font-weight: 550 !important; + letter-spacing: -0.018em !important; + line-height: 1.1 !important; +} + +.dark .VPNavBarTitle .title { + color: var(--sb-ink) !important; +} + +.VPNavBar .VPImage.logo { + width: 22px; + height: 27px; + border-radius: 0; +} + +/* Primary nav links: ink by default, accent on hover / when active. */ +.VPNavBarMenuLink, +.VPNavBarMenuGroup .text { + color: var(--sb-ink) !important; + font-family: var(--vp-font-family-base); + font-size: 15px !important; + font-weight: 450 !important; + letter-spacing: 0.005em; +} + +.VPNavBarMenuLink:hover, +.VPNavBarMenuLink.active, +.VPNavBarMenuGroup:hover .text, +.VPNavBarMenuGroup.active .text { + color: var(--sb-accent) !important; +} + +/* The final nav item ("Start building") reads as the primary CTA button. */ +.VPNavBarMenu .VPNavBarMenuLink[href*="/console"] { + align-self: center; + margin-left: 8px; + padding: 9px 18px !important; + line-height: 1 !important; + border-radius: 4px; + background: var(--sb-ink); + color: var(--sb-canvas) !important; + font-weight: 500 !important; + transition: background-color 0.16s ease, color 0.16s ease; +} + +.VPNavBarMenu .VPNavBarMenuLink[href*="/console"]:hover { + background: var(--sb-tint); + color: var(--sb-tint-fg) !important; +} + +/* No external-link arrow on the solid CTA button. */ +.VPNavBarMenu .VPNavBarMenuLink[href*="/console"].vp-external-link-icon::after, +.VPNavBarMenu .VPNavBarMenuLink[href*="/console"] .vpi-external-link-icon { + display: none !important; +} + +/* Search trigger + appearance toggle: hairline, square-ish, on-canvas. */ +.VPNavBarSearch .DocSearch-Button, +.VPNavBarSearchButton { + border-radius: 4px; +} + +/* ─── Sidebar: on-canvas rail with monospace section labels ─────────────── */ +.VPSidebar { + background: var(--sb-canvas) !important; + border-right: 1px solid var(--sb-line); +} + +.VPSidebar .curtain { + background: var(--sb-canvas) !important; +} + +/* Top-level section headers become uppercase monospace micro-labels. */ +.VPSidebarItem.level-0 > .item .text { + font-family: var(--vp-font-family-mono); + font-size: 11px !important; + font-weight: 500 !important; + letter-spacing: 0.08em !important; + text-transform: uppercase; + color: var(--sb-ink-subtle) !important; +} + +.VPSidebarItem.level-0 + .VPSidebarItem.level-0 { + border-top: 1px solid var(--sb-line); +} + +/* Active leaf link: accent left rule + ink text (no heavy pill). */ +.VPSidebarItem.is-active > .item .link { + background: transparent; + color: var(--sb-ink) !important; + font-weight: 550; +} + +.VPSidebarItem.is-active > .item .link::before { + background: var(--sb-accent); +} + +/* ─── "On this page" outline: monospace label ───────────────────────────── */ +.VPDocAsideOutline .outline-title { + font-family: var(--vp-font-family-mono); + font-size: 11px; + font-weight: 500; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--sb-ink-subtle); +} + +.VPDocAsideOutline .outline-link.active { + color: var(--sb-accent); +} + +/* ─── Fenced code: dark panel with a monospace language label ───────────── */ +.vp-doc div[class*='language-'], +.vp-doc:not(:has(.api-reference-page)) div[class*='language-'] { + border: 1px solid var(--sb-line); + border-radius: 4px; + background: var(--sb-panel); +} + +.vp-doc [class*='language-'] .lang { + color: var(--sb-panel-label); + font-family: var(--vp-font-family-mono); + font-size: 11px; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.vp-doc [class*='language-'] code { + color: var(--sb-panel-fg); +} + +/* Keep code readable at all widths (undo the hover-to-reveal scroll trick). */ +.vp-doc div[class*="language-"] pre { + overflow-x: auto; +} + +/* ─── Inline code chips ─────────────────────────────────────────────────── */ +.vp-doc p > code, +.vp-doc li > code, +.vp-doc td > code, +.vp-doc dd > code { + border-radius: 4px; +} + +/* ─── Custom blocks: hairline, near-square ──────────────────────────────── */ +.vp-doc .custom-block, +.vp-doc:not(:has(.api-reference-page)) .custom-block { + border-radius: 4px; +} + +/* ─── Pixel-square list bullets in the accent colour (prose only) ───────── */ +.vp-doc:not(:has(.api-reference-page)) ul { + list-style: none; + padding-left: 1.2rem; +} + +.vp-doc:not(:has(.api-reference-page)) ul > li { + position: relative; +} + +.vp-doc:not(:has(.api-reference-page)) ul > li:not(.task-list-item)::before { + content: ''; + position: absolute; + left: -1.05rem; + top: 0.62em; + width: 7px; + height: 7px; + background: var(--sb-accent); +} + +/* ─── Tables: monospace uppercase headers ───────────────────────────────── */ +.vp-doc table th { + font-family: var(--vp-font-family-mono); + font-size: 11px; + font-weight: 500; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--sb-ink-subtle); +} + +/* ─── Focus ring uses the accent, matching the reference design ─────────── */ +:root { + --vp-c-brand-1: var(--sb-accent); +} +*:focus-visible { + outline-color: var(--sb-accent); +} + +/* ══════════════════════════════════════════════════════════════════════════ + Footer (mirrors the sandbase.ai site footer) + Brand + tagline + social row · four navigation columns · bottom rule with + copyright and service status. + ══════════════════════════════════════════════════════════════════════════ */ +.sb-contact-footer { + display: block; + gap: 0; + margin-top: 64px; + padding: 48px 0 28px; + border-top: 1px solid var(--sb-line); +} + +.sb-contact-main { + display: grid; + grid-template-columns: minmax(240px, 1fr) minmax(0, 2.1fr); + gap: 56px; + align-items: start; +} + +.sb-contact-brand { + display: flex; + flex-direction: column; + gap: 20px; + max-width: 22rem; + min-width: 0; +} + +.sb-contact-logo { + display: inline-flex; + align-items: center; + gap: 0.6rem; + color: var(--sb-ink); + text-decoration: none; +} + +.dark .sb-contact-logo { + color: var(--sb-ink); +} + +.sb-contact-mark { + display: grid; + width: 22px; + height: 27px; + flex: none; + overflow: visible; + border-radius: 0; + color: inherit; +} + +.sb-contact-wordmark { + font-family: var(--vp-font-family-base); + font-size: 1.4rem; + font-weight: 550; + letter-spacing: -0.018em; + line-height: 1; +} + +.sb-contact-tagline { + margin: 0; + max-width: 24rem; + color: var(--sb-ink-muted); + font-size: 14.5px; + line-height: 1.6; +} + +.sb-contact-links { + display: flex; + align-items: center; + gap: 18px; + margin-top: 2px; +} + +.sb-contact-link { + color: var(--sb-ink-muted); +} + +.sb-contact-link:hover { + color: var(--sb-accent); + transform: translateY(-1px); +} + +.sb-footer-column h2 { + font-family: var(--vp-font-family-mono); + font-size: 11px; + font-weight: 500; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--sb-ink-subtle); +} + +.sb-footer-column a { + color: var(--sb-ink-muted); + font-size: 14px; + font-weight: 450; +} + +.sb-footer-column a:hover { + color: var(--sb-accent); +} + +.sb-footer-bottom { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + gap: 16px; + margin-top: 48px; + padding-top: 24px; + border-top: 1px solid var(--sb-line); +} + +.sb-footer-copy { + margin: 0; + color: var(--sb-ink-subtle); + font-size: 13px; +} + +.sb-footer-status { + display: inline-flex; + align-items: center; + gap: 8px; + color: var(--sb-ink-muted); + font-size: 13px; + text-decoration: none; +} + +.sb-footer-status:hover { + color: var(--sb-ink); +} + +.sb-footer-status-dot { + width: 7px; + height: 7px; + border-radius: 999px; + background: light-dark(#3f7a1a, #d9ff43); +} + +:root:not(.dark) .sb-footer-status-dot { + background: #3f7a1a; +} + +.dark .sb-footer-status-dot { + background: #d9ff43; +} + +@media (max-width: 959px) { + .sb-contact-main { + grid-template-columns: 1fr; + gap: 32px; + } +} diff --git a/public/ClashGrotesk-Variable.woff2 b/public/ClashGrotesk-Variable.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..d5b13d07ee6cf13a21e6cd1ee317ccfb69b5db3b GIT binary patch literal 47224 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 literal 0 HcmV?d00001 From 8e6e2de2d5c988282efb54fccf0898c564e9a90e Mon Sep 17 00:00:00 2001 From: "liuzhao@meicai.cn" Date: Thu, 24 Sep 2026 19:27:50 +0800 Subject: [PATCH 02/12] feat(theme): replace nav+footer with 1:1 sandbase.ai header and footer The previous pass only restyled VitePress's own nav. Make the chrome a true replica of the main site instead: - Add SiteHeader.vue: exact port of sandbase-fe site-header (logo + wordmark, Explore and Solutions mega-menus, Agents/Docs/Pricing, GitHub, Sign in, Start building CTA, mobile drawer). Rendered fixed via the layout-top slot. - Add SiteFooter.vue: exact port of sandbase-fe site-footer (brand + tagline, Store/Solutions/Build/Learn columns, text socials, copyright, status) plus an inline colour-theme switch (the appearance toggle moved off the nav). - Hide the default .VPNav (kept mounted so its search hotkey and the mobile sidebar plumbing still work); content is already offset by --vp-nav-height, which the fixed header fills. VPLocalNav keeps the mobile docs sidebar. - Add --color-* aliases mapping to the --sb-* tokens so the ported main-site stylesheets apply verbatim. Render both in layout-top/layout-bottom. - Remove the now-unused ContactFooter.vue. --- .vitepress/theme/ContactFooter.vue | 141 ------ .vitepress/theme/SiteFooter.vue | 319 ++++++++++++++ .vitepress/theme/SiteHeader.vue | 662 +++++++++++++++++++++++++++++ .vitepress/theme/custom.css | 41 ++ .vitepress/theme/index.ts | 10 +- 5 files changed, 1030 insertions(+), 143 deletions(-) delete mode 100644 .vitepress/theme/ContactFooter.vue create mode 100644 .vitepress/theme/SiteFooter.vue create mode 100644 .vitepress/theme/SiteHeader.vue diff --git a/.vitepress/theme/ContactFooter.vue b/.vitepress/theme/ContactFooter.vue deleted file mode 100644 index eefa0001..00000000 --- a/.vitepress/theme/ContactFooter.vue +++ /dev/null @@ -1,141 +0,0 @@ - - - diff --git a/.vitepress/theme/SiteFooter.vue b/.vitepress/theme/SiteFooter.vue new file mode 100644 index 00000000..72933b01 --- /dev/null +++ b/.vitepress/theme/SiteFooter.vue @@ -0,0 +1,319 @@ + + + + + diff --git a/.vitepress/theme/SiteHeader.vue b/.vitepress/theme/SiteHeader.vue new file mode 100644 index 00000000..ff118590 --- /dev/null +++ b/.vitepress/theme/SiteHeader.vue @@ -0,0 +1,662 @@ + + + + + diff --git a/.vitepress/theme/custom.css b/.vitepress/theme/custom.css index 569d3689..5dc2ddb7 100644 --- a/.vitepress/theme/custom.css +++ b/.vitepress/theme/custom.css @@ -59,6 +59,27 @@ --vp-font-family-base: 'Clash Grotesk', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', Roboto, sans-serif; --vp-font-family-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', Consolas, monospace; + + /* Aliases matching the sandbase.ai main site so the ported header/footer + stylesheets work verbatim. These resolve to the --sb-* tokens above and + therefore switch automatically between light and dark. */ + --color-canvas: var(--sb-canvas); + --color-surface: var(--sb-surface); + --color-surface-alt: var(--sb-surface-alt); + --color-line: var(--sb-line); + --color-ink: var(--sb-ink); + --color-ink-muted: var(--sb-ink-muted); + --color-ink-subtle: var(--sb-ink-subtle); + --color-accent: var(--sb-accent); + --color-panel: var(--sb-panel); + --color-panel-fg: var(--sb-panel-fg); + --color-tint-cyan: var(--sb-tint); + --color-positive: #3f7a1a; + --font-family-heading: var(--vp-font-family-base); + --font-family-body: var(--vp-font-family-base); + --font-family-mono: var(--vp-font-family-mono); + --shadow-lg: 0 12px 28px rgba(15, 12, 26, 0.14); + --page-inset: max(clamp(1.25rem, 5.5556vw, 5rem), calc((100% - 90rem) / 2 + 5rem)); } .dark { @@ -100,6 +121,9 @@ --sb-code-border: var(--sb-line); --sb-code-block-bg: var(--sb-panel); --vp-code-block-bg: var(--sb-panel); + + --color-positive: #d9ff43; + --shadow-lg: 0 12px 24px rgba(0, 0, 0, 0.6); } /* ─── Developer-doc sidebar: compact, structured, keyboard friendly ─── */ @@ -1842,3 +1866,20 @@ html { gap: 32px; } } + +/* ══════════════════════════════════════════════════════════════════════════ + Replace the default VitePress nav with the custom SandBase site header + (rendered via the layout-top slot). The default nav stays in the component + tree (so its search hotkey and the mobile sidebar plumbing keep working) but + is hidden; content is already offset by --vp-nav-height, which the fixed + custom header fills. The mobile docs-sidebar toggle lives in VPLocalNav, + which is independent of VPNav and remains visible. + ══════════════════════════════════════════════════════════════════════════ */ +.VPNav { + display: none !important; +} + +/* VPLocalNav (mobile sidebar + outline bar) sits directly below the header. */ +.VPLocalNav { + border-bottom: 1px solid var(--sb-line); +} diff --git a/.vitepress/theme/index.ts b/.vitepress/theme/index.ts index 36b58d28..489d41b9 100644 --- a/.vitepress/theme/index.ts +++ b/.vitepress/theme/index.ts @@ -2,20 +2,26 @@ import DefaultTheme from 'vitepress/theme' import { h } from 'vue' import HomePage from './HomePage.vue' import ApiReferencePage from './ApiReferencePage.vue' -import ContactFooter from './ContactFooter.vue' import QuickstartOnboard from './QuickstartOnboard.vue' import QuickstartResources from './QuickstartResources.vue' import PlatformApiSidebar from './PlatformApiSidebar.vue' import OfficialNativeApiSidebar from './OfficialNativeApiSidebar.vue' import PlatformApiLanding from './PlatformApiLanding.vue' +import SiteHeader from './SiteHeader.vue' +import SiteFooter from './SiteFooter.vue' import './custom.css' export default { ...DefaultTheme, Layout() { return h(DefaultTheme.Layout, null, { + // Replace VitePress's default top nav with a 1:1 replica of the + // sandbase.ai site header, and render the site footer full-width at the + // bottom. The default nav is hidden via custom.css but stays mounted so + // its search hotkey and mobile sidebar plumbing keep working. 'sidebar-nav-after': () => [h(PlatformApiSidebar), h(OfficialNativeApiSidebar)], - 'doc-after': () => h(ContactFooter), + 'layout-top': () => h(SiteHeader), + 'layout-bottom': () => h(SiteFooter), }) }, enhanceApp({ app }) { From 350a39666c5d225eb668728d221367e0763140b0 Mon Sep 17 00:00:00 2001 From: "liuzhao@meicai.cn" Date: Thu, 24 Sep 2026 22:09:47 +0800 Subject: [PATCH 03/12] fix(theme): keep the site footer clear of the fixed docs sidebar Moving the footer into the layout-bottom slot made it span the full width at the bottom of the layout, where the persistent fixed left sidebar covered its left (brand) column and made it look missing. From >=960px, inset the footer content past the sidebar so it aligns with the content column and is fully visible. --- .vitepress/theme/SiteFooter.vue | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.vitepress/theme/SiteFooter.vue b/.vitepress/theme/SiteFooter.vue index 72933b01..ee8bda70 100644 --- a/.vitepress/theme/SiteFooter.vue +++ b/.vitepress/theme/SiteFooter.vue @@ -310,6 +310,18 @@ function toggleTheme() { justify-self: end; } } + +/* The docs keep a persistent fixed sidebar on the left. A full-width footer at + the bottom of the layout would sit partly behind it, so from >=960px inset + the footer content to clear the sidebar and align with the content column + (mirrors the .VPContent.has-sidebar padding math in custom.css). */ +@media (min-width: 960px) { + .sf-container { + margin-inline: 0; + padding-left: calc(var(--vp-sidebar-width, 272px) + var(--sb-layout-gutter, 0px) + 32px); + padding-right: max(48px, var(--sb-layout-gutter, 0px)); + } +} @media (prefers-reduced-motion: reduce) { .sf-link, .sf-theme { From 28e0933575ab14837f882a52e28485b503866fca Mon Sep 17 00:00:00 2001 From: "liuzhao@meicai.cn" Date: Thu, 24 Sep 2026 22:52:49 +0800 Subject: [PATCH 04/12] fix(theme): make the site footer full-width edge-to-edge Instead of insetting the footer to the right of the fixed sidebar, keep it full-width (margin-inline: page-inset, like the main site) and raise its z-index above the desktop sidebar (25) so it paints edge-to-edge over the sidebar's lower portion at the bottom of the page. Stays below the mobile sidebar drawer/backdrop. --- .vitepress/theme/SiteFooter.vue | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/.vitepress/theme/SiteFooter.vue b/.vitepress/theme/SiteFooter.vue index ee8bda70..509ec004 100644 --- a/.vitepress/theme/SiteFooter.vue +++ b/.vitepress/theme/SiteFooter.vue @@ -120,7 +120,11 @@ function toggleTheme() { diff --git a/.vitepress/theme/custom.css b/.vitepress/theme/custom.css index 5dc2ddb7..caa733d7 100644 --- a/.vitepress/theme/custom.css +++ b/.vitepress/theme/custom.css @@ -1883,3 +1883,68 @@ html { .VPLocalNav { border-bottom: 1px solid var(--sb-line); } + +/* ══════════════════════════════════════════════════════════════════════════ + Docs sidebar — match the sandbase /docs reference design's link rail. + Group titles are uppercase monospace micro-labels; leaf links form a + vertical hairline rail with an accent segment when active and a stronger + segment on hover (no pills, no radius). Appended last to win over the + earlier documentation-neutral sidebar rules. + ══════════════════════════════════════════════════════════════════════════ */ +.VPSidebarItem.level-0 > .item .text { + font-family: var(--font-family-mono) !important; + font-size: 11px !important; + font-weight: 500 !important; + letter-spacing: 0.08em !important; + text-transform: uppercase; + color: var(--color-ink-subtle) !important; +} + +/* Separate top-level groups by space only (the reference has no dividers). */ +.VPSidebarItem.level-0 + .VPSidebarItem.level-0 { + margin-top: 1.5rem; + padding-top: 0; + border-top: 0; +} + +/* Leaf links: hairline rail on the left. */ +.VPSidebarItem.level-1 > .item .link, +.VPSidebarItem.level-2 > .item .link, +.VPSidebarItem.level-3 > .item .link { + border-left: 1px solid var(--color-line); + border-radius: 0 !important; + background: transparent !important; + color: var(--color-ink-muted); + transition: border-color 150ms ease, color 150ms ease; +} +.VPSidebarItem.level-1 > .item .link:hover, +.VPSidebarItem.level-2 > .item .link:hover, +.VPSidebarItem.level-3 > .item .link:hover { + border-left-color: var(--color-ink) !important; + background: transparent !important; + color: var(--color-ink) !important; +} +.VPSidebarItem.level-1 > .item .link:hover > .text, +.VPSidebarItem.level-2 > .item .link:hover > .text, +.VPSidebarItem.level-3 > .item .link:hover > .text { + color: var(--color-ink) !important; +} + +/* Active leaf link: accent rail segment, ink text, medium weight. */ +.VPSidebarItem.is-active > .item .link { + border-left-color: var(--color-accent) !important; + background: transparent !important; + color: var(--color-ink) !important; + font-weight: 500; +} +.VPSidebarItem.is-active > .item .link > .text { + color: var(--color-ink) !important; +} +.VPSidebarItem.is-active > .item .link::before { + display: none !important; +} +.VPSidebarItem > .item .link:focus-visible { + outline: 2px solid var(--color-accent); + outline-offset: -2px; + background: transparent !important; +} diff --git a/.vitepress/theme/index.ts b/.vitepress/theme/index.ts index 489d41b9..40e0a8e5 100644 --- a/.vitepress/theme/index.ts +++ b/.vitepress/theme/index.ts @@ -9,6 +9,7 @@ import OfficialNativeApiSidebar from './OfficialNativeApiSidebar.vue' import PlatformApiLanding from './PlatformApiLanding.vue' import SiteHeader from './SiteHeader.vue' import SiteFooter from './SiteFooter.vue' +import DocsSearch from './DocsSearch.vue' import './custom.css' export default { @@ -19,6 +20,9 @@ export default { // sandbase.ai site header, and render the site footer full-width at the // bottom. The default nav is hidden via custom.css but stays mounted so // its search hotkey and mobile sidebar plumbing keep working. + // The docs sidebar leads with a "Search docs" button (matching the + // reference design) that triggers VitePress's local search. + 'sidebar-nav-before': () => h(DocsSearch), 'sidebar-nav-after': () => [h(PlatformApiSidebar), h(OfficialNativeApiSidebar)], 'layout-top': () => h(SiteHeader), 'layout-bottom': () => h(SiteFooter), From dc1d6f087e7971d298dea0ed16cf4c7677873436 Mon Sep 17 00:00:00 2001 From: "liuzhao@meicai.cn" Date: Fri, 25 Sep 2026 00:34:23 +0800 Subject: [PATCH 06/12] =?UTF-8?q?fix(theme):=20match=20reference=20sidebar?= =?UTF-8?q?=20=E2=80=94=20no=20rail=20lines,=20filled=20search=20box?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the reference screenshot: - Sidebar links are plain text (ink-muted, ink on hover, ink + medium when active); remove the left hairline rail, the accent bar, pills, and radius. - Remove the divider between sidebar and content. - Search box is a filled, borderless, slightly-rounded box (surface-alt, 8px) rather than a bordered one. --- .vitepress/theme/DocsSearch.vue | 10 +++++----- .vitepress/theme/custom.css | 28 ++++++++++++++-------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.vitepress/theme/DocsSearch.vue b/.vitepress/theme/DocsSearch.vue index ee50bb18..aa61e95d 100644 --- a/.vitepress/theme/DocsSearch.vue +++ b/.vitepress/theme/DocsSearch.vue @@ -41,19 +41,19 @@ function openSearch() { gap: 0.625rem; margin-bottom: 1.5rem; padding: 0.5rem 0.75rem; - border: 1px solid var(--color-line); - border-radius: 0; - background: var(--color-surface); + border: 0; + border-radius: 8px; + background: var(--color-surface-alt); color: var(--color-ink-subtle); font-family: var(--font-family-body); font-size: 0.9375rem; line-height: 1.4375rem; text-align: left; cursor: pointer; - transition: border-color 150ms ease, color 150ms ease; + transition: background-color 150ms ease, color 150ms ease; } .docs-search:hover { - border-color: var(--color-ink); + background: color-mix(in srgb, var(--color-surface-alt) 82%, var(--color-ink)); color: var(--color-ink); } .docs-search:focus-visible { diff --git a/.vitepress/theme/custom.css b/.vitepress/theme/custom.css index caa733d7..f0901a14 100644 --- a/.vitepress/theme/custom.css +++ b/.vitepress/theme/custom.css @@ -1907,39 +1907,34 @@ html { border-top: 0; } -/* Leaf links: hairline rail on the left. */ +/* Leaf links: plain text, no rail, no pills, no radius (matches the + reference, which has no border lines beside the links). */ .VPSidebarItem.level-1 > .item .link, .VPSidebarItem.level-2 > .item .link, .VPSidebarItem.level-3 > .item .link { - border-left: 1px solid var(--color-line); + border: 0 !important; border-radius: 0 !important; background: transparent !important; color: var(--color-ink-muted); - transition: border-color 150ms ease, color 150ms ease; + transition: color 150ms ease; } .VPSidebarItem.level-1 > .item .link:hover, .VPSidebarItem.level-2 > .item .link:hover, -.VPSidebarItem.level-3 > .item .link:hover { - border-left-color: var(--color-ink) !important; - background: transparent !important; - color: var(--color-ink) !important; -} +.VPSidebarItem.level-3 > .item .link:hover, .VPSidebarItem.level-1 > .item .link:hover > .text, .VPSidebarItem.level-2 > .item .link:hover > .text, .VPSidebarItem.level-3 > .item .link:hover > .text { + background: transparent !important; color: var(--color-ink) !important; } -/* Active leaf link: accent rail segment, ink text, medium weight. */ -.VPSidebarItem.is-active > .item .link { - border-left-color: var(--color-accent) !important; +/* Active leaf link: ink text, medium weight — no bar, no border, no pill. */ +.VPSidebarItem.is-active > .item .link, +.VPSidebarItem.is-active > .item .link > .text { background: transparent !important; color: var(--color-ink) !important; font-weight: 500; } -.VPSidebarItem.is-active > .item .link > .text { - color: var(--color-ink) !important; -} .VPSidebarItem.is-active > .item .link::before { display: none !important; } @@ -1948,3 +1943,8 @@ html { outline-offset: -2px; background: transparent !important; } + +/* The reference has no divider between the sidebar and the content. */ +.VPSidebar { + border-right: 0 !important; +} From be823c7677d8970f8b0ef6ea02ebd116016d6c76 Mon Sep 17 00:00:00 2001 From: "liuzhao@meicai.cn" Date: Fri, 25 Sep 2026 00:43:08 +0800 Subject: [PATCH 07/12] fix(theme): sidebar has only the vertical rail; no horizontal lines Per the reference comparison: - Restore the single subtle vertical rail beside each menu link list (border on the .items container), with the active link showing an accent segment. - Remove all horizontal lines in the sidebar (no group dividers, no top/bottom borders) and the sidebar/content divider. - Search box uses the muted surface fill (not the brighter surface-alt). --- .vitepress/theme/DocsSearch.vue | 4 +-- .vitepress/theme/custom.css | 47 ++++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/.vitepress/theme/DocsSearch.vue b/.vitepress/theme/DocsSearch.vue index aa61e95d..1345b96f 100644 --- a/.vitepress/theme/DocsSearch.vue +++ b/.vitepress/theme/DocsSearch.vue @@ -43,7 +43,7 @@ function openSearch() { padding: 0.5rem 0.75rem; border: 0; border-radius: 8px; - background: var(--color-surface-alt); + background: var(--color-surface); color: var(--color-ink-subtle); font-family: var(--font-family-body); font-size: 0.9375rem; @@ -53,7 +53,7 @@ function openSearch() { transition: background-color 150ms ease, color 150ms ease; } .docs-search:hover { - background: color-mix(in srgb, var(--color-surface-alt) 82%, var(--color-ink)); + background: var(--color-surface-alt); color: var(--color-ink); } .docs-search:focus-visible { diff --git a/.vitepress/theme/custom.css b/.vitepress/theme/custom.css index f0901a14..88b461db 100644 --- a/.vitepress/theme/custom.css +++ b/.vitepress/theme/custom.css @@ -1907,34 +1907,48 @@ html { border-top: 0; } -/* Leaf links: plain text, no rail, no pills, no radius (matches the - reference, which has no border lines beside the links). */ +/* Menu rail: a single subtle vertical line beside each link list (the ONLY + lines in the sidebar). The active link shows an accent segment over it. */ +.VPSidebarItem .items { + border-left: 1px solid var(--color-line); +} .VPSidebarItem.level-1 > .item .link, .VPSidebarItem.level-2 > .item .link, .VPSidebarItem.level-3 > .item .link { - border: 0 !important; + margin-left: -1px; + border-left: 1px solid transparent; + border-top: 0 !important; + border-right: 0 !important; + border-bottom: 0 !important; border-radius: 0 !important; background: transparent !important; color: var(--color-ink-muted); - transition: color 150ms ease; + transition: color 150ms ease, border-color 150ms ease; } .VPSidebarItem.level-1 > .item .link:hover, .VPSidebarItem.level-2 > .item .link:hover, -.VPSidebarItem.level-3 > .item .link:hover, +.VPSidebarItem.level-3 > .item .link:hover { + border-left-color: var(--sb-line-strong) !important; + background: transparent !important; + color: var(--color-ink) !important; +} .VPSidebarItem.level-1 > .item .link:hover > .text, .VPSidebarItem.level-2 > .item .link:hover > .text, .VPSidebarItem.level-3 > .item .link:hover > .text { - background: transparent !important; color: var(--color-ink) !important; } -/* Active leaf link: ink text, medium weight — no bar, no border, no pill. */ -.VPSidebarItem.is-active > .item .link, -.VPSidebarItem.is-active > .item .link > .text { +/* Active leaf link: accent rail segment, ink text, medium weight. */ +.VPSidebarItem.is-active > .item .link { + margin-left: -1px; + border-left: 1px solid var(--color-accent) !important; background: transparent !important; color: var(--color-ink) !important; font-weight: 500; } +.VPSidebarItem.is-active > .item .link > .text { + color: var(--color-ink) !important; +} .VPSidebarItem.is-active > .item .link::before { display: none !important; } @@ -1944,7 +1958,20 @@ html { background: transparent !important; } -/* The reference has no divider between the sidebar and the content. */ +/* No horizontal lines anywhere in the sidebar (groups are spaced, not ruled), + and no divider between the sidebar and content. */ +.VPSidebar, +.VPSidebarItem, +.VPSidebarItem > .item, +.VPSidebarItem.level-0, +.VPSidebarItem.level-0 + .VPSidebarItem.level-0 { + border-top: 0 !important; + border-bottom: 0 !important; +} +.VPSidebarItem.level-0 + .VPSidebarItem.level-0 { + margin-top: 1.5rem; + padding-top: 0 !important; +} .VPSidebar { border-right: 0 !important; } From c9e7a0bbc6ba7ad593b975c0cef28028a0d7b9dc Mon Sep 17 00:00:00 2001 From: "liuzhao@meicai.cn" Date: Fri, 25 Sep 2026 00:46:46 +0800 Subject: [PATCH 08/12] fix(theme): square, bordered search box to match the reference design The reference 'Search docs' control is a squared box with a subtle 1px border (border-line) on the surface fill, not a rounded borderless box. Restore the border + square corners; brighten the border on hover. --- .vitepress/theme/DocsSearch.vue | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.vitepress/theme/DocsSearch.vue b/.vitepress/theme/DocsSearch.vue index 1345b96f..c89209ce 100644 --- a/.vitepress/theme/DocsSearch.vue +++ b/.vitepress/theme/DocsSearch.vue @@ -24,7 +24,7 @@ function openSearch() {