EmcyDocs

Reference

Theme Configuration

Configure preset palettes, mode, accent tuning, density, shell sizing, and token overrides from one nested theme object.

5 sections3 locales
Theme API

Drive docs chrome with one nested theme object and optional headless state

EmcyDocs ships a headless theme engine. Pass a static theme prop to DocsLayout, or wrap the layout in DocsThemeProvider when users should edit, persist, or share theme state.

See layout usage

Color system

Start with `neutral`, `dusk`, `ocean`, or `sqlos`, then tune mode, accent hue, accent strength, and surface style.

Layout system

Control density, shell width, content width, sidebar width, and TOC width without creating new layout components.

Token overrides

Override semantic shell tokens last when a preset gets you close but not all the way to your product's visual language.

Static theme prop#

TSX
import type { DocsThemeConfig } from "@emcy/docs";
 
const docsTheme: DocsThemeConfig = {
  color: {
    preset: "ocean",
    mode: "dark",
    accentHue: 188,
    accentStrength: "bold",
    surfaceStyle: "elevated",
  },
  layout: {
    density: "compact",
    layoutWidth: "1480px",
    contentWidth: "50rem",
    sidebarWidth: "272px",
    tocWidth: "232px",
  },
  shape: {
    radius: "xl",
  },
};
 
<DocsLayout
  navigation={docsSource.getNavigation()}
  theme={docsTheme}
/>
Static vs live theming

DocsLayout reads theme state from DocsThemeProvider when present and falls back to its own theme prop otherwise. Use the prop for fixed themes and the provider for a studio, persisted preferences, or share URLs.

Live theme state#

TSX
import {
  DocsLayout,
  DocsThemeProvider,
  useDocsTheme,
  type DocsThemeConfig,
} from "@emcy/docs";
 
const initialTheme: DocsThemeConfig = {
  color: {
    preset: "neutral",
    mode: "light",
  },
};
 
function ThemeModeToggle() {
  const { resolvedTheme, updateTheme } = useDocsTheme();
  const nextMode =
    resolvedTheme.config.color.mode === "light" ? "dark" : "light";
 
  return (
    <button onClick={() => updateTheme({ color: { mode: nextMode } })}>
      Toggle mode
    </button>
  );
}
 
export default function Layout({ children }) {
  return (
    <DocsThemeProvider initialTheme={initialTheme}>
      <DocsLayout
        navigation={docsSource.getNavigation()}
        themeSwitcher={<ThemeModeToggle />}
      >
        {children}
      </DocsLayout>
    </DocsThemeProvider>
  );
}

Presets#

Use this as the balanced baseline for product docs, design systems, and app-embedded help centers. It works well in both light and dark.

What the knobs do#

color.preset and color.mode

preset selects the base palette family. mode forces light or dark, and every preset now supports both.

color.accentHue and color.accentStrength

accentHue re-centers the brand hue without abandoning the preset. accentStrength decides how hard that hue pushes primary buttons, focus rings, accent surfaces, and soft-highlight states.

color.surfaceStyle

flat, tinted, and elevated change how much panel tint, border contrast, and shadow depth the shell uses.

layout.density and layout widths

density changes spacing rhythm across navigation, cards, TOC items, and page gutters. layoutWidth, contentWidth, sidebarWidth, and tocWidth let one layout cover wide product docs, denser references, and narrower reading-focused pages.

shape.radius

Choose md, lg, or xl to tighten or soften the surface language across cards, banners, tabs, dialogs, and shell chrome.

tokens

tokens are semantic overrides applied last. Use them when the preset plus knobs gets close, but you need exact background, border, card, accent, code, or shadow values to match a product brand.

Site studio vs library API#

The popup in this site is example-app code

DocsThemeStudio only ships inside /site. The library ships the headless primitives: resolveDocsTheme(theme), DocsThemeProvider, and useDocsTheme(). Build your own switcher UI around them, or keep the theme fixed and skip runtime controls entirely.

The example docs route uses those primitives to power preset switching, live token overrides, shareable URLs, and persisted preferences without requiring a bundled library switcher component.