MUI Docs Infra

Abstract Create Demo

The abstractCreateDemo function helps you create structured demo factories that work seamlessly with the CodeHighlighter component ecosystem. It provides a standardized way to create demos that combine component previews with code display, making it easier to build consistent documentation interfaces.

Tip

For the underlying architectural rationale (URLs as identity, variant enumeration, precompute, server/client split) see the Built Factories Pattern.

Overview

Demo factories created with abstractCreateDemo automatically integrate with:

Factory Function Requirements

At the fundamental level, the loadPrecomputedCodeHighlighter function expects factory functions with these signatures:

// Single component demo
export const createDemo = (url: string, component: React.ComponentType, options?: any) => {
  return () => <>Demo Content</>;
}

// Multi-variant demo
export const createDemoWithVariants = (url: string, variants: Record<string, React.ComponentType>, options?: any) => {
  return () => <>Demo Content</>;
}

Implementation

To quickly implement these factory functions, use the abstractCreateDemo utilities:

import 'server-only'; // this should be omitted if using the <CodeProvider> or the pages router

import {
  createDemoFactory,
  createDemoWithVariantsFactory,
} from '@mui/internal-docs-infra/abstractCreateDemo';

import { DemoContent } from './DemoContent';
import { DemoDataTheme } from '../demo-data/theme';

const demoGlobalData = [DemoDataTheme];

/**
 * Creates a demo component for displaying code examples with syntax highlighting.
 * @param url Depends on `import.meta.url` to determine the source file location.
 * @param component The component to be rendered in the demo.
 * @param meta Additional meta for the demo.
 */
export const createDemo = createDemoFactory({
  DemoContent,
  demoGlobalData,
});

/**
 * Creates a demo component for displaying code examples with syntax highlighting.
 * A variant is a different implementation style of the same component.
 * @param url Depends on `import.meta.url` to determine the source file location.
 * @param variants The variants of the component to be rendered in the demo.
 * @param meta Additional meta for the demo.
 */
export const createDemoWithVariants = createDemoWithVariantsFactory({
  DemoContent,
  demoGlobalData,
});

Global Dependencies

Global dependencies allow you to inject shared code (like providers, themes, or utilities) into all demos. These are passed through the demoGlobalData option:

// docs/src/demo-data/theme/index.ts
import { createDemoGlobalWithVariants } from '@mui/internal-docs-infra/createDemoData';
import type { DemoGlobalData } from '@mui/internal-docs-infra/createDemoData/types';
import { DemoThemeProvider as CssModules } from './css-modules';

export const DemoDataTheme: DemoGlobalData = createDemoGlobalWithVariants(import.meta.url, {
  CssModules,
});
// docs/src/demo-data/theme/css-modules/index.ts
import './theme.css';

export function DemoThemeProvider({ children }: { children: React.ReactNode }) {
  return children;
}
// docs/src/utils/createDemo.ts

import 'server-only'; // this should be omitted if using the <CodeProvider> or the pages router

import { createDemoFactory } from '@mui/internal-docs-infra/abstractCreateDemo';
import { Demo as DemoContent } from '../components/Demo/Demo';
import { DemoDataTheme } from '../demo-data/theme';

const demoGlobalData = [DemoDataTheme];

export const createDemo = createDemoFactory({
  DemoContent,
  demoGlobalData, // Available in all demos
});

The globals are automatically merged with demo code and displayed alongside existing demo files.

Loader Configuration

To make global demo data work properly, use withDocsInfra which automatically includes the demo-data patterns:

// next.config.js
import { withDocsInfra } from '@mui/internal-docs-infra/withDocsInfra';

export default withDocsInfra({
  // withDocsInfra automatically includes:
  // - './app/**/demos/*/index.ts'
  // - './app/**/demos/*/client.ts'
  // - './src/demo-data/*/index.ts' (for globals)
  // - './src/demo-data/*/client.ts' (for client-side globals)
});

If you need additional patterns, you can add them via additionalDemoPatterns:

export default withDocsInfra({
  additionalDemoPatterns: {
    index: ['./src/**/snippets/*/index.ts'],
    client: ['./src/**/snippets/*/client.ts'],
  },
});

Types

See Types

Related