or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cli.mdconfiguration.mdindex.mdplugins.mdtheme-api.mdutilities.md
tile.json

theme-api.mddocs/

Theme API

React hooks and components for building custom themes and accessing site data, navigation, and component metadata.

Capabilities

Data Hooks

Access site-wide data and metadata through React hooks.

/**
 * Access site data context including configuration and metadata
 * @returns Site data object with theme config and global settings
 */
function useSiteData(): {
  themeConfig: IThemeConfig;
  components: Record<string, AtomComponentAsset>;
  locales: ILocalesConfig;
  _2_level_nav_available: boolean;
  [key: string]: any;
};

/**
 * Get component asset metadata for current route
 * @returns Asset metadata for components, functions, and other atoms
 */
function useAtomAssets(): {
  components: Record<string, AtomComponentAsset>;
};

/**
 * Get navigation data for the current locale
 * @returns Navigation items array with titles, links, and hierarchy
 */
function useNavData(): INavItems;

/**
 * Get sidebar data for the current route
 * @returns Sidebar groups and items for current location
 */
function useSidebarData(): ISidebarGroup[];

/**
 * Get full sidebar data including all routes
 * @returns Complete sidebar structure for entire site
 */
function useFullSidebarData(): Record<string, ISidebarGroup[]>;

/**
 * Get current route metadata including frontmatter and content
 * @returns Route metadata with frontmatter, TOC, and text content
 */
function useRouteMeta(): IRouteMeta;

/**
 * Get matched route information
 * @returns Current matched route object
 */
function useMatchedRoute(): {
  id: string;
  path: string;
  parentId?: string;
  [key: string]: any;
};

Usage:

import { 
  useSiteData, 
  useNavData, 
  useSidebarData,
  useRouteMeta 
} from "dumi/theme";

function CustomHeader() {
  const { themeConfig } = useSiteData();
  const nav = useNavData();
  
  return (
    <header>
      <h1>{themeConfig.name}</h1>
      <nav>
        {nav.map(item => (
          <a key={item.link} href={item.link}>
            {item.title}
          </a>
        ))}
      </nav>
    </header>
  );
}

function CustomSidebar() {
  const sidebar = useSidebarData();
  const routeMeta = useRouteMeta();
  
  return (
    <aside>
      <h2>{routeMeta.frontmatter.title}</h2>
      {sidebar.map(group => (
        <div key={group.title}>
          <h3>{group.title}</h3>
          {group.children.map(item => (
            <a key={item.link} href={item.link}>
              {item.title}
            </a>
          ))}
        </div>
      ))}
    </aside>
  );
}

UI State Hooks

Manage user interface state and preferences.

/**
 * Get current locale information
 * @returns Current locale data
 */
function useLocale(): ILocale;

/**
 * Get color scheme preference and switching utilities
 * @returns Current color scheme and toggle function
 */
function usePrefersColor(): {
  color: 'light' | 'dark' | 'auto';
  setColor: (color: 'light' | 'dark' | 'auto') => void;
};

/**
 * Get tab metadata for tabbed content pages
 * @returns Current tab information and switching utilities
 */
function useTabMeta(): {
  tab: string;
  setTab: (tab: string) => void;
  tabs: {
    key: string;
    title?: string;
    titleIntlId?: string;
    components: {
      default: ReactComponentType;
      Extra: ReactComponentType;
      Action: ReactComponentType;
    };
  }[];
};

Usage:

import { useLocale, usePrefersColor, useTabMeta } from "dumi/theme";

function LocaleDisplay() {
  const locale = useLocale();
  
  return (
    <div>
      <span>Current locale: {locale.name} ({locale.id})</span>
    </div>
  );
}

function ColorModeToggle() {
  const { color, setColor } = usePrefersColor();
  
  return (
    <button onClick={() => setColor(color === 'dark' ? 'light' : 'dark')}>
      {color === 'dark' ? 'โ˜€๏ธ' : '๐ŸŒ™'}
    </button>
  );
}

Demo and Component Hooks

Work with live demos and component rendering.

/**
 * Get live demo compilation and rendering utilities
 * @param id - Demo ID
 * @param opts - Live demo options
 * @returns Functions for compiling and rendering live code demos
 */
function useLiveDemo(id: string, opts?: {
  containerRef?: RefObject<HTMLElement>;
  iframe?: boolean;
}): {
  /** Demo React node */
  node: ReactNode;
  /** Loading state */
  loading: boolean;
  /** Error state */
  error: Error | null;
  /** Set demo source code */
  setSource: (source: Record<string, string>) => Promise<void>;
};

/**
 * Get site search functionality and data
 * @returns Search utilities and indexed content
 */
function useSiteSearch(): {
  /** Search through site content */
  search: (query: string) => Promise<Array<{
    title: string;
    content: string;
    path: string;
  }>>;
  /** Current search results */
  results: Array<any>;
  /** Search loading state */
  loading: boolean;
};

Usage:

import { useLiveDemo, useSiteSearch } from "dumi/theme";

function LiveCodeEditor({ initialCode }: { initialCode: string }) {
  const { renderDemo } = useLiveDemo();
  const [code, setCode] = useState(initialCode);
  const [demo, setDemo] = useState<React.ComponentType | null>(null);
  
  useEffect(() => {
    renderDemo(code, { filename: 'demo.tsx' })
      .then(setDemo)
      .catch(console.error);
  }, [code, renderDemo]);
  
  return (
    <div>
      <textarea 
        value={code} 
        onChange={(e) => setCode(e.target.value)} 
      />
      {demo && <demo />}
    </div>
  );
}

Built-in Components

Pre-built React components for common documentation needs.

/**
 * Demo preview component with code display and live rendering
 */
interface DumiDemo {
  (props: IPreviewerProps): JSX.Element;
}

interface IPreviewerProps {
  /** Demo title */
  title?: string;
  /** Demo description */
  description?: string;
  /** Source filename */
  filename?: string;
  /** Render in iframe */
  iframe?: boolean | number;
  /** Debug mode flag */
  debug?: boolean;
  /** Show code by default */
  defaultShowCode?: boolean;
  /** Demo URL for standalone viewing */
  demoUrl: string;
  /** Disable padding */
  compact?: boolean;
  /** Apply transform for positioning */
  transform?: boolean;
  /** Background color */
  background?: string;
  /** Asset metadata */
  asset: ExampleBlockAsset;
  /** React children (the demo component) */
  children: ReactNode;
}

/**
 * Component for rendering component atoms/examples
 */
interface AtomRenderer {
  (props: { atom: string }): JSX.Element;
}

/**
 * Demo grid layout component
 */
interface DumiDemoGrid {
  (props: { 
    items: IDemoData[];
    cols?: number;
  }): JSX.Element;
}

/**
 * Page wrapper component
 */
interface DumiPage {
  (props: { 
    children: ReactNode;
    route: any;
  }): JSX.Element;
}

Usage:

import { DumiDemo, AtomRenderer, DumiDemoGrid } from "dumi/theme";

function CustomPreviewer(props: IPreviewerProps) {
  return (
    <div className="custom-demo">
      <h3>{props.title}</h3>
      <p>{props.description}</p>
      <DumiDemo {...props} />
    </div>
  );
}

function ComponentShowcase({ atom }: { atom: string }) {
  return (
    <div className="showcase">
      <AtomRenderer atom={atom} />
    </div>
  );
}

Utility Functions

Helper functions for external integrations and demo management.

/**
 * Open current demo in CodeSandbox
 * @param opts - Configuration for CodeSandbox integration
 */
function openCodeSandbox(opts: {
  /** Demo code */
  code: string;
  /** Demo dependencies */
  deps?: Record<string, string>;
  /** Demo title */
  title?: string;
  /** Demo description */
  description?: string;
}): void;

/**
 * Open current demo in StackBlitz
 * @param opts - Configuration for StackBlitz integration
 */
function openStackBlitz(opts: {
  /** Demo code */
  code: string;
  /** Demo dependencies */
  deps?: Record<string, string>;
  /** Demo title */
  title?: string;
  /** Demo description */
  description?: string;
}): void;

Usage:

import { openCodeSandbox, openStackBlitz } from "dumi/theme";

function DemoActions({ code, deps }: { 
  code: string; 
  deps: Record<string, string>;
}) {
  const handleOpenCodeSandbox = () => {
    openCodeSandbox({
      code,
      deps,
      title: "Component Demo",
      description: "Generated from dumi",
    });
  };
  
  const handleOpenStackBlitz = () => {
    openStackBlitz({
      code,
      deps,
      title: "Component Demo",
    });
  };
  
  return (
    <div>
      <button onClick={handleOpenCodeSandbox}>
        Open in CodeSandbox
      </button>
      <button onClick={handleOpenStackBlitz}>
        Open in StackBlitz
      </button>
    </div>
  );
}

Internationalization Components

React-intl components for internationalized documentation.

// Re-exported from react-intl
function FormattedMessage(props: { 
  id: string; 
  defaultMessage?: string; 
  values?: Record<string, any>;
}): JSX.Element;

function FormattedDate(props: { 
  value: Date | number; 
  year?: 'numeric' | '2-digit';
  month?: 'numeric' | '2-digit' | 'long' | 'short' | 'narrow';
  day?: 'numeric' | '2-digit';
}): JSX.Element;

function FormattedNumber(props: { 
  value: number; 
  style?: 'decimal' | 'currency' | 'percent';
  currency?: string;
}): JSX.Element;

function IntlProvider(props: { 
  locale: string; 
  messages: Record<string, string>;
  children: ReactNode;
}): JSX.Element;

function useIntl(): {
  formatMessage: (descriptor: { id: string; defaultMessage?: string }, values?: Record<string, any>) => string;
  formatDate: (value: Date | number, options?: any) => string;
  formatNumber: (value: number, options?: any) => string;
};

Usage:

import { FormattedMessage, useIntl } from "dumi/theme";

function InternationalizedContent() {
  const intl = useIntl();
  
  return (
    <div>
      <h1>
        <FormattedMessage 
          id="title" 
          defaultMessage="Welcome" 
        />
      </h1>
      <p>
        {intl.formatMessage(
          { id: "description", defaultMessage: "This is a demo" },
          { name: "Component" }
        )}
      </p>
    </div>
  );
}

Advanced Theme Development

Custom Theme Structure

Create custom themes by organizing components and hooks:

// src/theme/components/Header.tsx
import { useSiteData, useNavData } from "dumi/theme";

export function Header() {
  const { themeConfig } = useSiteData();
  const nav = useNavData();
  
  return (
    <header>
      <img src={themeConfig.logo} alt={themeConfig.name} />
      <nav>
        {nav.map(item => (
          <a key={item.link} href={item.link}>
            {item.title}
          </a>
        ))}
      </nav>
    </header>
  );
}

Theme Plugin Integration

Integrate with dumi's plugin system for advanced customization:

// Theme plugin that modifies theme data
export default (api: IApi) => {
  api.modifyTheme((memo) => {
    // Add custom components
    memo.builtins.CustomComponent = require.resolve('./CustomComponent');
    
    // Modify internationalization
    memo.locales.en.messages.customKey = 'Custom Message';
    
    return memo;
  });
};