LogoNotyra Docs

カスタムテーマを作成する

NotyraはJSONファイルを使用してテーマのカスタマイズが可能です。ユーザーは独自のカラーテーマを作成し、Notyraの外観を完全に自分好みに変更できます。

テーマファイルの構造

テーマは以下の形式の単一 .json ファイルです。

{
  "id": "my-theme",
  "name": "My Theme",
  "nameJa": "マイテーマ",
  "description": "A short description in English",
  "descriptionJa": "日本語での説明",
  "swatches": ["#accent", "#background", "#subtle"],
  "swatchesDark": ["#accent-dark", "#background-dark", "#subtle-dark"],
  "light": {
    "--background": "oklch(...)",
    "--foreground": "oklch(...)",
    "...": "..."
  },
  "dark": {
    "--background": "oklch(...)",
    "--foreground": "oklch(...)",
    "...": "..."
  }
}

トップレベルフィールド

フィールド必須説明
idstringYes一意な識別子。小文字とハイフンを使用してください(例:"ocean-blue")。
namestringYes英語での表示名。
nameJastringYes日本語での表示名。
descriptionstringNo英語での短い説明。
descriptionJastringNo日本語での短い説明。
swatchesstring[]Yesライトモードのプレビューチップ用の3色(hex):[アクセント, 背景, サブトル]
swatchesDarkstring[]Yesダークモードのプレビューチップ用の3色(hex):[アクセント, 背景, サブトル]
lightobjectYesライトモードで適用されるCSS変数マップ。
darkobjectYesダークモードで適用されるCSS変数マップ。

CSS 変数リファレンス

light および dark の値はすべて element.style.setProperty() によって :root に設定されます。OKLch・hex・rgba()・他の変数への参照(var(--foreground) など)を含む任意の有効なCSS値を使用できます。

ベース変数(shadcn/ui 互換)

shadcn/ui の規約に従い、全体的なカラーパレットを制御します。

変数説明
--backgroundページ・パネルの背景色
--foregroundデフォルトのテキスト色
--cardカードの背景色
--card-foregroundカード上のテキスト色
--popoverポップオーバー・ドロップダウンの背景色
--popover-foregroundポップオーバー内のテキスト色
--primaryプライマリインタラクション色(ボタン等)
--primary-foregroundプライマリ色上のテキスト色
--secondaryセカンダリサーフェス(コードブロック等)
--secondary-foregroundセカンダリサーフェス上のテキスト色
--muted控えめな背景(タグ・バッジ・ミュートエリア)
--muted-foreground控えめ・サブテキスト色
--accentホバー・フォーカス時のハイライト背景
--accent-foregroundアクセント背景上のテキスト色
--destructive破壊的操作の色
--destructive-foreground破壊的操作上のテキスト色
--borderデフォルトのボーダー色
--input入力フィールドのボーダー色
--ringフォーカスリングの色
--radius基本の角丸(例:"0.5rem"

サイドバー変数

変数説明
--sidebarサイドバーパネルの背景色
--sidebar-foregroundサイドバーのテキスト色
--sidebar-primaryサイドバーのプライマリ色
--sidebar-primary-foregroundサイドバープライマリ上のテキスト色
--sidebar-accentサイドバーのホバー・フォーカス背景
--sidebar-accent-foregroundサイドバーアクセント上のテキスト色
--sidebar-borderサイドバーのボーダー色
--sidebar-ringサイドバーのフォーカスリング色

チャート変数

--chart-1--chart-5 — データビジュアライゼーション要素に使用される5色(基本的なテーマ作成では必須ではありません)。


テーマ固有変数

Notyra 独自の変数です。エディタの見出し・アクティブな選択状態・リンク・バッジ・グラデーション装飾など、UIのアクセントカラーを制御します。

変数説明例(ライト)例(ダーク)
--theme-accentメインのアクセントカラー。選択中アイテム・アクティブアイコン・見出し色(設定時)・インタラクティブなハイライトに使用されます。"#7c3aed""#c084fc"
--theme-accent-hoverソリッドなアクセント背景のホバー時に使用される、アクセントの暗いバリアント。"#6d28d9""#e879f9"
--theme-accent-subtleアクセントの非常に薄い色調。選択アイテムの背景・バッジの背景・フォルダヘッダーのグラデーションに使用されます。ライトモードでは白に近い色、ダークモードでは半透明にするのが適切です。"#faf5ff""rgba(76, 29, 149, 0.2)"
--theme-accent-subtle-hoverホバー時に使用される --theme-accent-subtle のやや強いバリアント。"#ede9fe""rgba(76, 29, 149, 0.3)"
--theme-gradient-from装飾グラデーションの開始色(アプリロゴのラインなど)。"#a78bfa""#a78bfa"
--theme-gradient-to装飾グラデーションの終了色。"#c084fc""#c084fc"
--theme-linkMarkdownプレビューのハイパーリンク色。"#8250df""#a371f7"
--theme-link-hoverホバー時のリンク色。"#a371f7""#c084fc"
--theme-heading-colorエディタとプレビュー両方の Markdown 見出し(h1〜h5)に適用される色。中立的な(黒/白)見出しにするには "var(--foreground)" を、アクセントカラーの見出しにするには hex 値を設定します。"var(--foreground)""var(--foreground)"

カラーフォーマットのヒント

Notyra はベースパレット変数に OKLch を、テーマ固有のアクセント変数に hex / rgba を使用します。

OKLch

OKLch は知覚的に均一なカラースペースです:oklch(L C H) の形式で指定します。

  • L — 明度(0 = 黒、1 = 白)
  • C — 彩度(0 = グレー、高いほど鮮やか)
  • H — 色相角(0〜360度)
oklch(0.99 0.006 285)   → ごくわずかに紫がかった、ほぼ白
oklch(0.13 0.04 285)    → ごくわずかに紫がかった、ほぼ黒(ダーク背景)
oklch(0.45 0.18 250)    → 中明度の青(プライマリボタン)

ヒント: 背景変数(--background--card--sidebar)は彩度(C)を非常に低く保つことで、主張しすぎない絶妙な色調を実現できます。0.0040.01 程度が適切です。

Hex / rgba

テーマ固有変数(--theme-*)には hex を使用してください。これらは鮮明で読みやすい必要があります。

"--theme-accent": "#059669"
"--theme-accent-subtle": "rgba(5, 150, 105, 0.15)"   ← ダークモード用

カスタムテーマの作り方

  1. サンプルテーマのいずれかをベースとしてコピーします。
  2. idnamenameJa・必要に応じて descriptiondescriptionJa を変更します。
  3. swatchesswatchesDark を3色の hex プレビューカラー [アクセント, 背景, サブトル] に更新します。
  4. --background の色相(OKLch の第3値 H)を目的の色系統に合わせて調整します。彩度(C)は 0.0040.01 程度に保ちます。
  5. lightdark 両セクションの --theme-* 変数をアクセントカラーに合わせて更新します。
  6. Notyra で 設定 → カラーテーマ → インポート からJSONファイルを選択します。

最小構成テンプレート

以下のテンプレートには最もよくカスタマイズする変数のみを含めています。記載のない変数はグレースケールのデフォルト値にフォールバックします。

{
  "id": "my-custom-theme",
  "name": "My Custom Theme",
  "nameJa": "カスタムテーマ",
  "description": "My custom color theme",
  "descriptionJa": "カスタムカラーテーマ",
  "swatches": ["#ACCENT_HEX", "#F9FAFB", "#F0F0FF"],
  "swatchesDark": ["#ACCENT_DARK_HEX", "#111118", "#1E1E2E"],
  "light": {
    "--background": "oklch(0.99 0.006 HUE)",
    "--foreground": "oklch(0.13 0 0)",
    "--card": "oklch(0.99 0.006 HUE)",
    "--card-foreground": "oklch(0.13 0 0)",
    "--popover": "oklch(1 0 0)",
    "--popover-foreground": "oklch(0.13 0 0)",
    "--primary": "oklch(0.45 0.18 HUE)",
    "--primary-foreground": "oklch(0.98 0 0)",
    "--secondary": "oklch(0.965 0.008 HUE)",
    "--secondary-foreground": "oklch(0.2 0 0)",
    "--muted": "oklch(0.965 0.008 HUE)",
    "--muted-foreground": "oklch(0.5 0 0)",
    "--accent": "oklch(0.955 0.01 HUE)",
    "--accent-foreground": "oklch(0.18 0 0)",
    "--destructive": "oklch(0.577 0.245 27.325)",
    "--destructive-foreground": "oklch(0.577 0.245 27.325)",
    "--border": "oklch(0.91 0.01 HUE)",
    "--input": "oklch(0.91 0.01 HUE)",
    "--ring": "oklch(0.55 0.18 HUE)",
    "--radius": "0.5rem",
    "--sidebar": "oklch(0.975 0.008 HUE)",
    "--sidebar-foreground": "oklch(0.13 0 0)",
    "--sidebar-primary": "oklch(0.45 0.18 HUE)",
    "--sidebar-primary-foreground": "oklch(0.98 0 0)",
    "--sidebar-accent": "oklch(0.955 0.01 HUE)",
    "--sidebar-accent-foreground": "oklch(0.18 0 0)",
    "--sidebar-border": "oklch(0.91 0.01 HUE)",
    "--sidebar-ring": "oklch(0.55 0.18 HUE)",
    "--theme-accent": "#ACCENT_HEX",
    "--theme-accent-hover": "#ACCENT_DARKER_HEX",
    "--theme-accent-subtle": "#SUBTLE_HEX",
    "--theme-accent-subtle-hover": "#SUBTLE_HOVER_HEX",
    "--theme-gradient-from": "#GRADIENT_FROM_HEX",
    "--theme-gradient-to": "#GRADIENT_TO_HEX",
    "--theme-link": "#LINK_HEX",
    "--theme-link-hover": "#LINK_HOVER_HEX",
    "--theme-heading-color": "var(--foreground)"
  },
  "dark": {
    "--background": "oklch(0.13 0.04 HUE)",
    "--foreground": "oklch(0.94 0 0)",
    "--card": "oklch(0.155 0.04 HUE)",
    "--card-foreground": "oklch(0.94 0 0)",
    "--popover": "oklch(0.13 0.04 HUE)",
    "--popover-foreground": "oklch(0.94 0 0)",
    "--primary": "oklch(0.65 0.18 HUE)",
    "--primary-foreground": "oklch(0.1 0 0)",
    "--secondary": "oklch(0.22 0.045 HUE)",
    "--secondary-foreground": "oklch(0.94 0 0)",
    "--muted": "oklch(0.22 0.045 HUE)",
    "--muted-foreground": "oklch(0.62 0 0)",
    "--accent": "oklch(0.26 0.05 HUE)",
    "--accent-foreground": "oklch(0.94 0 0)",
    "--destructive": "oklch(0.396 0.141 25.723)",
    "--destructive-foreground": "oklch(0.637 0.237 25.331)",
    "--border": "oklch(0.24 0.045 HUE)",
    "--input": "oklch(0.24 0.045 HUE)",
    "--ring": "oklch(0.55 0.18 HUE)",
    "--radius": "0.5rem",
    "--sidebar": "oklch(0.17 0.042 HUE)",
    "--sidebar-foreground": "oklch(0.94 0 0)",
    "--sidebar-primary": "oklch(0.65 0.18 HUE)",
    "--sidebar-primary-foreground": "oklch(0.1 0 0)",
    "--sidebar-accent": "oklch(0.22 0.045 HUE)",
    "--sidebar-accent-foreground": "oklch(0.94 0 0)",
    "--sidebar-border": "oklch(0.24 0.045 HUE)",
    "--sidebar-ring": "oklch(0.55 0.18 HUE)",
    "--theme-accent": "#ACCENT_DARK_HEX",
    "--theme-accent-hover": "#ACCENT_DARK_HOVER_HEX",
    "--theme-accent-subtle": "rgba(R, G, B, 0.15)",
    "--theme-accent-subtle-hover": "rgba(R, G, B, 0.25)",
    "--theme-gradient-from": "#GRADIENT_FROM_DARK_HEX",
    "--theme-gradient-to": "#GRADIENT_TO_DARK_HEX",
    "--theme-link": "#LINK_DARK_HEX",
    "--theme-link-hover": "#LINK_DARK_HOVER_HEX",
    "--theme-heading-color": "var(--foreground)"
  }
}

HUE の部分を目的の色の OKLch 色相角に置き換えてください(例:青 → 250、緑 → 160、アンバー → 55、パープル → 285、ローズ → 10)。


TypeScript インターフェース

Notyra テーマを扱うツールを開発する場合、テーマの型定義は以下の通りです。

interface ColorTheme {
  id: string
  name: string
  nameJa: string
  description?: string
  descriptionJa?: string
  /** [アクセント, 背景, サブトル] — ライトモードプレビューチップ用 hex カラー */
  swatches: string[]
  /** [アクセント, 背景, サブトル] — ダークモードプレビューチップ用 hex カラー */
  swatchesDark: string[]
  /** ライトモードで適用される CSS 変数マップ */
  light: Record<string, string>
  /** ダークモードで適用される CSS 変数マップ */
  dark: Record<string, string>
}

インポート時には以下の最低条件が検証されます。

  • id が空でない文字列であること
  • name が空でない文字列であること
  • swatches が空でない配列であること
  • swatchesDark が空でない配列であること
  • lightdark が null 以外のオブジェクトであること