OpenPress

<Press theme> + press/<slug>/theme/

テーマ (Themes)

OpenPress themes には二つの層があります:typed theme object は Press metadata と CSS variables を提供し、Press-local theme directory は active CSS と font loading を持ちます。

OpenPress の theme には二つの層があります。

Typed theme object は press/<slug>/press.tsx に置き、<Press theme={...}> に渡します。Engine はこれを使って Press profile(documentslidebare)を知り、measurement と runtime に --op-theme-* CSS variables を注入します。

Folder-local theme directory、press/<slug>/theme/、は active CSS source のままです。Font loading、prose rules、slide template classes、project-specific selectors をここに置きます。Generic page shell、measurement CSS、print reset、default MDX prose surface は framework が所有します。

なぜ theme は Press ごとに置くのか?

ひとつの workspace に A4 report と 16:9 slide deck が同居することがあります。これらの形式が意図せずグローバルな視覚状態を共有してはいけません。Theme object と theme directory を owning Press に置くことで、それぞれの output に明確な styling boundary を与えます。

Theme object は次の用途に使います:

  • Profile selection: page-based document には defineDocumentTheme()、slide deck には defineSlideTheme()
  • Portable color、font、typography tokens。
  • Workbench と reader の theme metadata。
  • Pagination measurement が必要とする CSS variables。

Theme files は次の用途に使います:

  • tokens.css: 色、書体、余白、artifact-level design decisions の CSS variables。
  • fonts.css: portable な @font-face loading。
  • --op-theme-* variables を読む prose / slide-template selectors。

Theme ファイルで page shell を再実装しないでください。新しい work では base/page-contract.cssbase/print.cssbase/typography.css を含めません。これらの契約は framework-owned です。

Basic workflow

Page-based document:

import { Press } from "@open-press/core";
import { defineDocumentTheme } from "@open-press/core/theme";

const documentTheme = defineDocumentTheme({
  name: "Report Theme",
  colors: {
    paper: "#ffffff",
    ink: "#16161d",
    accent: "#0d5f89",
  },
  typography: {
    heading: { font: "serif", size: "28pt", lineHeight: 1.18, color: "ink" },
    body: { font: "body", size: "10.5pt", lineHeight: 1.7, color: "ink" },
  },
});

export default function ReportPress() {
  return <Press slug="report" title="Report" page="a4" theme={documentTheme}>{/* pages */}</Press>;
}

Slide deck:

import { Press, Slide } from "@open-press/core";
import { defineSlideTheme } from "@open-press/core/theme";

const slideTheme = defineSlideTheme({
  name: "Deck Theme",
  colors: {
    bg: "#fcf7e9",
    ink: "#16161d",
    accent: "#d42a20",
  },
  typography: {
    display: { font: "serif", size: 138, lineHeight: 1.05, color: "ink" },
    body: { font: "sans", size: 36, lineHeight: 1.48, color: "muted" },
  },
});

export default function DeckPress() {
  return (
    <Press slug="deck" title="Deck" type="slides" page="slide-16-9" theme={slideTheme}>
      <Slide id="cover" />
    </Press>
  );
}

Profile must match the Press type. Slide Press uses defineSlideTheme(). Page-based Press uses defineDocumentTheme().

Page geometry

ページサイズは CSS ではなく <Press page> に置きます。generic format には built-in preset を使います:

<Press page="a4" />
<Press page="slide-16-9" />

プロジェクト固有の format には custom object を使います:

<Press
  page={{ id: "field-guide-card", label: "Field Guide Card", width: "148mm", height: "210mm" }}
/>

Exporter は resolved geometry を document theme metadata に書き込み、--openpress-page-width--openpress-page-height などの runtime CSS variables を注入します。Theme object は typography と color を定義できますが、<Press page> を置き換えません。

Tailwind v4 and prose

新しい UI は Tailwind-first です。Page chrome、cover、TOC、slide layout、prose variants は React components に置き、Tailwind classes で表現します。MDX body content は framework の prose surface を使い、component classes または prose preset で調整します。shared typography CSS に戻さないでください。

複数の Press が Tailwind token name を共有する場合、Tailwind v4 @theme entries は generic または variable-backed にします。Artifact-specific values は owning Press wrapper または component に置き、ある Press が別の Press を汚染しないようにします。