# Canlı Tema ve Karanlık Mod

> Canlı tema — ThemeConfig, tema birleştirme sırası, Studio Tema paneli ve hazır paletler, --theme-* CSS değişkenleri, fontlar, karanlık mod (config.darkMode) ve tema yardımcıları.
>
> Kaynak: https://tecof-app-dev.vercel.app/editor-theme · Bölüm: Tema geliştirme · Son güncelleme: 2018-10-20

Studio’daki **Tema** paneli sayfanın renklerini, tipografisini ve boşluk değerlerini düzenler. Değişiklikler hem editöre hem kanvasa anında `--theme-*` CSS değişkenleri olarak uygulanır; yayında `TecofRender` aynı değişkenleri kendisi basar.

## Tema modeli

```ts
interface ThemeConfig {
  colors: ThemeColors;          // primary, secondary, accent, background, foreground, muted,
                                // mutedForeground, border, card, cardForeground, destructive
  darkColors?: Partial<ThemeColors>; // yalnız config.darkMode açıkken
  typography: ThemeTypography;  // fontFamily, headingFontFamily, baseFontSize, lineHeight,
                                // headingScale { h1…h6 }, fontWeightNormal/Medium/Bold
  spacing: ThemeSpacing;        // containerMaxWidth, sectionPaddingY/X, componentGap,
                                // borderRadius, borderRadiusLg, borderRadiusSm
  customTokens?: Record<string, string>;
  customFonts?: CustomFont[];   // yüklenen @font-face dosyaları
  fonts?: string[];             // kullanılan yerleşik font kimlikleri
}
```

**Birleştirme sırası:** yerleşik varsayılanlar ← `config.theme` (temanın marka değerleri) ← sayfanın kendi ayarı (`root.props._tecofTheme`, Tema panelinde düzenlenen). Tema sayfa verisinde saklandığı için kayda, geri al ve yinele akışına dahildir.

```tsx title="app/editor-config.tsx"
export const editorConfig: StudioConfig = {
  components,
  theme: {
    colors: { primary: "#a3472f", background: "#f5f3ed", foreground: "#242721", border: "#d7d7cc" },
    typography: { fontFamily: "'Inter', sans-serif", headingFontFamily: "'Inter', sans-serif", lineHeight: 1.7 },
    spacing: { containerMaxWidth: 1440, sectionPaddingY: 96, borderRadius: 0 },
    fonts: ["inter"],
  },
  themePresets: [
    { id: "clay", label: "Kil", colors: { primary: "#a3472f", accent: "#a3472f", background: "#f5f3ed" } },
    { id: "forest", label: "Orman", colors: { primary: "#365745", accent: "#365745", background: "#f2f4ef" } },
  ],
};
```

`themePresets` Tema panelindeki **Renkler** bölümünün üstünde kart olarak listelenir; tıklayınca yalnız renkler `_tecofTheme.colors` üzerine uygulanır (tipografi ve boşluk değişmez), kullanıcı sonra tek tek renkleri düzenlemeye devam edebilir.

## CSS değişkenleri

`generateCSSVariables(theme)` aşağıdaki değişkenleri üretir:

| Grup | Değişkenler |
| :--- | :--- |
| Renkler | `--theme-color-primary`, `-secondary`, `-accent`, `-background`, `-foreground`, `-muted`, `-muted-foreground`, `-border`, `-card`, `-card-foreground`, `-destructive` |
| Tipografi | `--theme-font-family`, `--theme-heading-font-family`, `--theme-font-size-base`, `--theme-line-height`, `--theme-font-weight-normal/-medium/-bold`, `--theme-heading-h1` … `-h6` |
| Fontlar | `--font-<id>` (ör. `--font-inter`) |
| Boşluk | `--theme-container-max-width`, `--theme-section-padding-y/-x`, `--theme-component-gap`, `--theme-border-radius`, `-lg`, `-sm` |

Bileşenlerinizde tema rengini doğrudan kullanın; tema panelindeki değişiklik bileşene yansır:

```tsx
<section className="bg-[var(--theme-color-background)] text-[var(--theme-color-foreground)]">…</section>
```

## Yayına uygulama

`TecofRender` çözülmüş temadan `<style data-tecof-theme>` (tema değişkenleri), Google Fonts `<link>`’i ve yüklenen fontlar için `@font-face` kurallarını **kendisi** basar. Ek kurulum gerekmez.

Sayfayı kendiniz render ediyor ya da `<head>`’i kendiniz kuruyorsanız aynı çıktıyı yardımcılarla üretin:

```ts
import { generateCSSVariables, getDefaultTheme, mergeTheme, themeGoogleFontsHref, themeFontFaceCss } from "@tecof/theme-editor";

const theme = mergeTheme(getDefaultTheme(), editorConfig.theme ?? {});
const css = generateCSSVariables(theme);            // ":root { --theme-color-primary: … }"
const fontsHref = themeGoogleFontsHref(theme);       // Google Fonts adresi ya da boş
const fontFaces = themeFontFaceCss(theme);           // yüklenen fontlar için @font-face
```

Ek yardımcılar: `hexToHsl`, `hslToHex`, `lighten`, `darken`, `deriveDarkColors`, `googleFontsHref`, `customFontFaceCss`, `BUILTIN_FONTS`.

## Fontlar

Tema panelindeki font seçici önizlemeli, küratörlü bir listeden seçtirir ve özel font yüklemeye izin verir. Yerleşik font kimlikleri: `system`, `georgia`, `inter`, `roboto`, `open-sans`, `lato`, `montserrat`, `poppins`, `nunito`, `work-sans`, `dm-sans`, `raleway`, `playfair-display`, `merriweather`, `lora`, `oswald`, `bebas-neue`, `jetbrains-mono`. Seçilen font hem tema değişkenine hem `theme.fonts` listesine yazılır; Stil sekmesindeki düğüm bazlı yazı tipi `[var(--font-<id>)]` token’ı kullanır.

## Karanlık mod

Karanlık mod **isteğe bağlıdır** ve temanın config’inde açılır. `darkMode` yoksa karanlık arayüz, karanlık CSS ve çalışma zamanı hiç yüklenmez.

```tsx
export const editorConfig: StudioConfig = {
  components,
  darkMode: true, // ya da { defaultMode: "system" | "light" | "dark", storageKey: "shop-scheme" }
};
```

**Strateji:** `<html>` üzerindeki `.dark` sınıfı `--theme-color-*` değişkenlerinin **değerlerini** değiştirir; `generateCSSVariables` ikinci bir blok basar:

```css
:root      { --theme-color-background: #ffffff; /* … */ }
:root.dark { --theme-color-background: #09090b; /* … */ }
```

Sayfa içeriğinin sınıfları değişmez (`bg-[var(--theme-color-primary)]` aynı kalır); yalnız değişkenin çözüldüğü değer değişir. Bu yüzden `dark:` varyantı kullanılmaz ve hiçbir safelist gerekmez.

- **Koyu renkler** Tema panelinde düzenlenir (`theme.darkColors`) ya da “Koyu palet üret” ile açık paletten türetilir (`deriveDarkColors`). Girilmeyen anahtar açık moddaki değerine düşer.
- **Editörde önizleme:** üst çubuktaki güneş/ay düğmesi kanvası koyu palete çevirir (yalnız `darkMode` açıkken görünür; dokümana yazılmaz).
- **Ziyaretçi düğmesi:** sayfaya `class="tecof-darkmode-toggle"` taşıyan herhangi bir buton koyun. Çalışma zamanı tıklamayı delege dinler, `.dark`’ı çevirir ve seçimi `localStorage`’a yazar (varsayılan anahtar `tecof-color-scheme`).
- **İlk şema:** `defaultMode` — `system` (varsayılan, işletim sistemini izler), `light` ya da `dark`. Ziyaretçinin kayıtlı seçimi her zaman kazanır.
- **Yanlış tema flaşı olmasın:** `TecofRender` `<head>` üretmez; sıfır flaş için `<head>`’e `darkModeHeadScript(config)` çıktısını satır içi betik olarak koyun.

```tsx title="app/layout.tsx"
import { darkModeHeadScript } from "@tecof/theme-editor";
import { editorConfig } from "@/app/editor-config";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="tr" suppressHydrationWarning>
      <head>
        <script dangerouslySetInnerHTML={{ __html: darkModeHeadScript(editorConfig) }} />
      </head>
      <body>{children}</body>
    </html>
  );
}
```

Kendi sayfasını render eden host’lar için: `initDarkMode(document)`, `darkModeHeadScript(config)`, `deriveDarkColors(light)`, `DARK_MODE_STORAGE_KEY`.
