Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions cloud/app/components/blog-post-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { ButtonLink } from "@/app/components/ui/button-link";
import { MDXRenderer } from "@/app/components/mdx/renderer";
import { CopyMarkdownButton } from "@/app/components/blocks/copy-markdown-button";
import LoadingContent from "@/app/components/blocks/loading-content";
import { PageTOC } from "@/app/components/page-toc";
import { ContentTOC } from "@/app/components/content-toc";
// import { PagefindMeta } from "@/app/components/pagefind-meta";
import type { BlogContent } from "@/app/lib/content/types";
import PageLayout from "@/app/components/page-layout";
import ContentLayout from "@/app/components/content-layout";
import { useEffect, useState } from "react";

// Reusable component for "Back to Blog" button
Expand Down Expand Up @@ -131,7 +131,7 @@ export function BlogPostPage({

<div className="grow overflow-y-auto pr-4 pb-6 pl-4">
{/* todo(sebastian): Make sure the headings have IDs in the mdx content */}
<PageTOC
<ContentTOC
headings={post.mdx?.tableOfContents || []}
observeHeadings={true}
/>
Expand All @@ -152,23 +152,23 @@ export function BlogPostPage({
author: author,
}}
/> */}
<PageLayout>
<PageLayout.LeftSidebar className="pt-1" collapsible={false}>
<ContentLayout>
<ContentLayout.LeftSidebar className="pt-1" collapsible={false}>
<div className="pr-10">
<BackToBlogLink />
</div>
</PageLayout.LeftSidebar>
</ContentLayout.LeftSidebar>

<PageLayout.Content>{mainContent}</PageLayout.Content>
<ContentLayout.Content>{mainContent}</ContentLayout.Content>

<PageLayout.RightSidebar
<ContentLayout.RightSidebar
className={isLoading ? undefined : "pt-1"}
mobileCollapsible={true}
mobileTitle="Table of Contents"
>
{rightSidebarContent}
</PageLayout.RightSidebar>
</PageLayout>
</ContentLayout.RightSidebar>
</ContentLayout>
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { createContext, useContext, useEffect } from "react";
import { cn } from "@/app/lib/utils";
import { Button } from "@/app/components/ui/button";
import { ChevronLeft, ChevronRight, X, type LucideIcon } from "lucide-react";
import { useSidebar, isMobileView } from "@/app/components/page-sidebar";
import {
useSidebar,
isMobileView,
} from "@/app/components/blocks/navigation/sidebar";

// Shared positioning for sidebar toggle buttons
const SIDEBAR_TOGGLE_POSITION = "calc(var(--header-height) - 1.63rem)";
Expand Down Expand Up @@ -87,7 +90,7 @@ const SidebarToggle = ({
};

/**
* PageLayout - Comprehensive layout component with composable parts
* ContentLayout - Comprehensive layout component with composable parts
*
* Provides a consistent page structure with main content area and
* optional sidebars. Sidebars use fixed positioning for scrolling behavior.
Expand All @@ -96,14 +99,14 @@ const SidebarToggle = ({
*
* Usage example:
* ```tsx
* <PageLayout>
* <PageLayout.LeftSidebar>Left sidebar content</PageLayout.LeftSidebar>
* <PageLayout.Content>Main content</PageLayout.Content>
* <PageLayout.RightSidebar>Right sidebar content</PageLayout.RightSidebar>
* </PageLayout>
* <ContentLayout>
* <ContentLayout.LeftSidebar>Left sidebar content</ContentLayout.LeftSidebar>
* <ContentLayout.Content>Main content</ContentLayout.Content>
* <ContentLayout.RightSidebar>Right sidebar content</ContentLayout.RightSidebar>
* </ContentLayout>
* ```
*/
const PageLayout = ({ children }: { children: ReactNode }) => {
const ContentLayout = ({ children }: { children: ReactNode }) => {
// Create sidebar controllers with coordinated behavior
// The hook now handles only mobile behavior
const leftSidebar = useSidebar({
Expand Down Expand Up @@ -178,7 +181,7 @@ const SidebarBackdrop = ({
* Handles responsive collapsing on small screens with CSS media queries.
* Sidebar content scrolls independently from main content.
*/
PageLayout.LeftSidebar = ({
ContentLayout.LeftSidebar = ({
children,
className,
collapsible = true,
Expand Down Expand Up @@ -295,7 +298,7 @@ PageLayout.LeftSidebar = ({
*
* Expands to fill available space between sidebars and scrolls independently.
*/
PageLayout.Content = ({ children, className }: SidebarProps) => {
ContentLayout.Content = ({ children, className }: SidebarProps) => {
return <div className={cn("min-w-0 flex-1", className)}>{children}</div>;
};

Expand All @@ -308,7 +311,7 @@ PageLayout.Content = ({ children, className }: SidebarProps) => {
* When mobileCollapsible is true, the sidebar will be accessible on mobile
* devices via a toggle button that shows a slide-in panel.
*/
PageLayout.RightSidebar = ({
ContentLayout.RightSidebar = ({
children,
className,
mobileCollapsible = false,
Expand Down Expand Up @@ -389,4 +392,4 @@ PageLayout.RightSidebar = ({
);
};

export default PageLayout;
export default ContentLayout;
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface TableOfContentsProps {
* Takes explicit props instead of extracting content from the DOM.
* Can optionally track which heading is currently active by observing heading elements.
*/
export const PageTOC: React.FC<TableOfContentsProps> = ({
export const ContentTOC: React.FC<TableOfContentsProps> = ({
headings,
activeId: initialActiveId = "",
observeHeadings = false,
Expand Down
35 changes: 17 additions & 18 deletions cloud/app/components/docs-page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from "react";
import PageLayout from "@/app/components/page-layout";
import ContentLayout from "@/app/components/content-layout";
import LoadingContent from "@/app/components/blocks/loading-content";
import { ProviderContextProvider } from "@/app/components/blocks/model-provider-provider";
// import TocSidebar from "@/app/components/toc-sidebar";
import { ModelProviderProvider } from "@/app/components/mdx/elements/model-provider-provider";
import DocsTocSidebar from "@/app/components/docs-toc-sidebar";
import MainContent from "@/app/components/blocks/docs/main-content";
import DocsSidebar from "@/app/components/blocks/docs/sidebar";
import DocsSidebar from "@/app/components/docs-sidebar";
import type { DocContent } from "@/app/lib/content/types";

type DocsPageProps = {
Expand All @@ -21,36 +21,35 @@ type DocsPageProps = {
const DocsPage: React.FC<DocsPageProps> = ({ document, isLoading = false }) => {
return (
<>
<ProviderContextProvider>
<PageLayout>
<PageLayout.LeftSidebar className="pt-1" collapsible={true}>
<ModelProviderProvider>
<ContentLayout>
<ContentLayout.LeftSidebar className="pt-1" collapsible={true}>
<DocsSidebar />
</PageLayout.LeftSidebar>
</ContentLayout.LeftSidebar>

<PageLayout.Content>
<ContentLayout.Content>
{isLoading ? (
<LoadingContent fullHeight={true} />
) : (
document && <MainContent document={document} />
)}
</PageLayout.Content>
</ContentLayout.Content>

<PageLayout.RightSidebar
<ContentLayout.RightSidebar
className="pt-1"
mobileCollapsible={true}
mobileTitle="On this page"
>
Sidebar content
{/* {isLoading ? (
{isLoading ? (
<div className="h-full">
<div className="bg-muted mx-4 mt-16 h-6 animate-pulse rounded-md"></div>
</div>
) : (
document && <TocSidebar document={document} />
)} */}
</PageLayout.RightSidebar>
</PageLayout>
</ProviderContextProvider>
document && <DocsTocSidebar document={document} />
)}
</ContentLayout.RightSidebar>
</ContentLayout>
</ModelProviderProvider>
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { docRegistry } from "@/app/lib/content/doc-registry";
import type { DocSpec, SectionSpec } from "@/app/lib/content/spec";
import { type Provider } from "@/app/components/blocks/model-provider-provider";
import Sidebar from "@/app/components/page-sidebar";
import { type Provider } from "@/app/components/mdx/elements/model-provider-provider";
import Sidebar from "@/app/components/blocks/navigation/sidebar";
import type {
SidebarConfig,
SidebarItem,
SidebarGroup,
SidebarSection,
} from "@/app/components/page-sidebar";
} from "@/app/components/blocks/navigation/sidebar";
import { docsSpec } from "@/content/docs/_meta";

interface DocsSidebarProps {
Expand Down
54 changes: 54 additions & 0 deletions cloud/app/components/docs-toc-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from "react";
import { ContentTOC } from "@/app/components/content-toc";
import { Server } from "lucide-react";
import { ModelProviderDropdown } from "@/app/components/mdx/elements/model-provider-dropdown";
import { type DocContent } from "@/app/lib/content/types";
import { CopyMarkdownButton } from "@/app/components/blocks/copy-markdown-button";

interface TocSidebarProps {
document?: DocContent | null;
}

/**
* DocsTocSidebar - Right sidebar containing the table of contents and controls
*
* Displays provider selection dropdown and table of contents
*/
const DocsTocSidebar: React.FC<TocSidebarProps> = ({ document }) => {
return (
<div className="flex h-full flex-col">
<div className="px-4">
<div className="mb-4 flex flex-col gap-3">
{document && (
<CopyMarkdownButton
content={document.content}
itemId={document.meta.path}
contentType="document_markdown"
/>
)}

{/* Provider dropdown */}
<div className="mt-3">
<h4 className="text-muted-foreground mb-2 text-sm font-medium">
<div className="flex items-center">
<Server className="mr-1 h-3 w-3" />
Provider
</div>
</h4>
<ModelProviderDropdown />
</div>

<h4 className="text-muted-foreground mt-4 text-sm font-medium">
On this page
</h4>
</div>
<ContentTOC
headings={document?.mdx?.tableOfContents || []}
observeHeadings={true}
/>
</div>
</div>
);
};

export default DocsTocSidebar;
4 changes: 2 additions & 2 deletions cloud/app/components/home-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -231,15 +231,15 @@ export const MirascopeBlock = ({ onScrollToTop }: MirascopeBlockProps) => {
/> */}
<div className="bg-background/60 mb-2 w-full max-w-3xl rounded-md">
{/* todo(seb): Add provider tabbed section */}
{/* <ProviderTabbedSection
{/* <ModelProviderTabbedSection
customHeader={
<div className="flex items-center px-1 pb-2">
<MirascopeLogo size="micro" withText={true} />
</div>
}
>
<ProviderCodeWrapper className="textured-bg" code={codeExample} language="python" />
</ProviderTabbedSection> */}
</ModelProviderTabbedSection> */}
</div>

<div className="mt-2 flex w-full max-w-3xl flex-col items-center justify-center gap-4 sm:flex-row">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useState } from "react";
import LoadingContent from "@/app/components/blocks/loading-content";
import { useProvider } from "@/app/components/blocks/model-provider-provider";
import { useProvider } from "@/app/components/mdx/elements/model-provider-provider";
// import { AnalyticsCodeBlock } from "./AnalyticsCodeBlock";
interface ProviderCodeBlockProps {
examplePath: string; // Path relative to public/examples
Expand Down
4 changes: 2 additions & 2 deletions cloud/app/components/mdx/elements/install-snippet.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useProvider } from "@/app/components/blocks/model-provider-provider";
import type { Provider } from "@/app/components/blocks/model-provider-provider";
import { useProvider } from "@/app/components/mdx/elements/model-provider-provider";
import type { Provider } from "@/app/components/mdx/elements/model-provider-provider";
// import { AnalyticsCodeBlock } from "@/app/components/blocks/mdx/AnalyticsCodeBlock";
import { cn } from "@/app/lib/utils";
import { TabbedSection, Tab } from "./tabbed-section";
Expand Down
56 changes: 56 additions & 0 deletions cloud/app/components/mdx/elements/model-provider-dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Button } from "@/app/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/app/components/ui/dropdown-menu";
import { ChevronDown } from "lucide-react";
import {
useProvider,
providers,
providerDefaults,
} from "@/app/components/mdx/elements/model-provider-provider";
import { cn } from "@/app/lib/utils";

interface ProviderDropdownProps {
className?: string;
}

export function ModelProviderDropdown({ className }: ProviderDropdownProps) {
const { provider, setProvider } = useProvider();

return (
<div className={cn("flex flex-col", className)}>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
size="sm"
className={cn(
"w-full justify-between text-base",
"text-primary border-primary", // Always show the selected provider in primary color
)}
>
{providerDefaults[provider].displayName}
<ChevronDown className="ml-2 h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-[200px]">
{providers.map((p) => (
<DropdownMenuItem
key={p}
onClick={() => setProvider(p)}
className={cn(
"text-foreground cursor-pointer text-base",
provider === p && "text-primary font-medium",
)}
>
{providerDefaults[p].displayName}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export function replaceProviderVariables(
import { temporarilyEnableSyncHighlighting } from "@/app/lib/code-highlight";

// Create a context to share the selected provider
interface ProviderContextType {
interface ModelProviderProviderType {
provider: Provider;
setProvider: (provider: Provider) => void;
providerInfo: {
Expand All @@ -139,7 +139,7 @@ interface ProviderContextType {
};
}

const ProviderContext = createContext<ProviderContextType | undefined>(
const ProviderContext = createContext<ModelProviderProviderType | undefined>(
undefined,
);

Expand All @@ -155,7 +155,7 @@ const validateProvider = (
};

// Provider component that wraps the content and provides the state
export function ProviderContextProvider({
export function ModelProviderProvider({
children,
defaultProvider = "openai",
onProviderChange,
Expand Down
Loading