makepad-2.0-theme について
Splash スクリプトの `theme.*` 変数から利用できる、Makepad 2.0 アプリ向けのデザイントークンシステムです。ダーク、ライト、スケルトンのテーマと、色・タイポグラフィ・間隔・ウィジェット状態のトークンを備えています。
主な機能
- 01ダーク、ライト、スケルトンのテーマ
- 02色とウィジェット状態のトークン
- 03フォントスタイルとサイズ変数
- 04間隔と寸法のプリセット
- 05調整可能なテーマ共通パラメーター
活用シーン
- 01アプリ全体の色、フォント、間隔の統一
- 02アプリのダークテーマとライトテーマの切り替え
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ zhanghandong/ makepad-skills --skill makepad-2.0-themeインストール後、Claude Code で/makepad-2.0-themeを入力して読み込まれたか確認します。
同梱ファイルreferences/theme-variables.md
詳細
Makepad 2.0 テーマシステム
概要
Makepad 2.0 のテーマシステムでは、Splash スクリプト内の theme.* 変数から利用できる、包括的なデザイントークン一式を提供します。アプリケーション全体で、色、タイポグラフィ、余白、ウィジェットの状態に一貫性のあるスタイルを適用できます。
組み込みテーマは 3 種類あります。
mod.themes.dark-- ダークデスクトップテーマ(デフォルト)mod.themes.light-- ライトデスクトップテーマmod.themes.skeleton-- 値がハードコードされた最小限のスケルトンテーマ
最も重要なルール:本番環境の UI で色、フォントサイズ、余白を指定する際は、ハードコードされた値ではなく、必ず theme.* 変数を使用してください。これにより、アプリでテーマを自動的に切り替えられるようになり、視覚的な一貫性も保たれます。
App::run でのテーマ設定
ウィジェットを読み込む前にテーマを読み込む必要があります。標準的なパターンは次のとおりです。
impl App {
fn run(vm: &mut ScriptVm) -> Self {
// Step 1: Load theme definitions (dark, light, skeleton)
crate::makepad_widgets::theme_mod(vm);
// Step 2: Select active theme (MUST come before widgets_mod)
script_eval!(vm, {
mod.theme = mod.themes.light // or mod.themes.dark
});
// Step 3: Load widget definitions (they reference mod.theme)
crate::makepad_widgets::widgets_mod(vm);
// Step 4: Load your app's script_mod
App::from_script_mod(vm, self::script_mod)
}
}
手順 1~2 を省略すると、デフォルトのテーマはダークになります(theme_mod 内で設定されています)。
カウンターの例では、手順 1~3 とデフォルトのダークテーマをまとめた簡略版の 1 行 crate::makepad_widgets::script_mod(vm) を使用しています。
内部での仕組み
theme_mod() は次の処理を行います。
makepad_draw::script_mod(vm)を呼び出して、描画プリミティブを読み込みますmod.themesモジュールを作成しますtheme_desktop_dark、theme_desktop_light、theme_desktop_skeletonを読み込みます- デフォルトとして
mod.theme = mod.themes.darkを設定します
続いて widgets_mod() が theme: mod.theme を含む mod.prelude.widgets_internal を作成し、use mod.prelude.widgets.* を使用するすべてのウィジェットスクリプトで theme.* を利用できるようにします。
テーマのグローバルパラメーター
各テーマでは、全体的な印象を調整するグローバルパラメーターを定義します。
| Parameter | Purpose | Default (dark/light) |
|---|---|---|
color_contrast | カラーパレットの広がりを調整します | 1.0 |
color_tint | 背景に適用する色合い | #0000ff |
color_tint_amount | 色合いの適用量(0~1) | 0.0 |
space_factor | 基本となる余白の倍率 | 6.0 |
corner_radius | 基本となる角の半径 | 2.5 |
beveling | 面取りの強さ | 0.75 |
font_size_base | 基本フォントサイズ(px) | 10.0 |
font_size_contrast | サイズ段階間のフォントサイズの差 | 2.5 |
テーマの色変数 -- プライマリ
アプリケーションコードで最もよく使用する色です。
| Variable | Purpose | Light Appearance | Dark Appearance |
|---|---|---|---|
theme.color_bg_app | アプリの背景 | ライトグレー(約 #DDD) | ダークグレー(約 #333) |
theme.color_fg_app | 前景レイヤー | やや暗め | やや明るめ |
theme.color_bg_container | カード/コンテナーの背景 | 半透明の明色 | 半透明の暗色 |
theme.color_bg_even | 偶数行の背景 | より明るい | より暗い |
theme.color_bg_odd | 奇数行の背景 | より暗い | より明るい |
theme.color_bg_highlight | ハイライトの背景 | 白に近い #FFFFFF22 | 不透明度の低い白に近い色 |
theme.color_bg_highlight_inline | インラインのハイライト | color_d_1 | color_d_3 |
theme.color_bg_unfocussed | フォーカスのないハイライト | bg_highlight の 85% | bg_highlight の 85% |
theme.color_app_caption_bar | キャプションバーの背景 | 透明 | 透明 |
theme.color_white | 純白 | #FFFFFF | #FFFFFF |
theme.color_makepad | Makepad ブランドカラー | #FF5C39 | #FF5C39 |
テーマカラー変数 -- テキストとラベル
| 変数 | 用途 |
|---|---|
theme.color_label_inner | 内側の要素(ボタン、ラベル)の主要テキスト |
theme.color_label_inner_hover | ホバー時のテキスト |
theme.color_label_inner_down | 押下時のテキスト |
theme.color_label_inner_focus | フォーカス時のテキスト |
theme.color_label_inner_active | アクティブ/選択時のテキスト |
theme.color_label_inner_inactive | セカンダリ/控えめなテキスト |
theme.color_label_inner_disabled | 無効時のテキスト |
theme.color_label_outer | 外側の要素(タブ、ヘッダー)の主要テキスト |
theme.color_label_outer_off | オフ時の外側テキスト |
theme.color_label_outer_disabled | 無効時の外側テキスト |
theme.color_text | 一般的なテキストの色 |
theme.color_text_hover | ホバー時のテキスト |
theme.color_text_focus | フォーカス時のテキスト |
theme.color_text_disabled | 無効時のテキスト |
theme.color_text_placeholder | プレースホルダーテキスト |
theme.color_text_meta | メタデータのテキスト |
theme.color_text_cursor | テキストカーソルの色 |
テーマカラー変数 -- ウィジェットの状態
アウトセットカラー(ボタン、隆起した要素):
| 変数 | 用途 |
|---|---|
theme.color_outset | デフォルトのボタン背景 |
theme.color_outset_hover | ホバー時のボタン |
theme.color_outset_down | 押下時のボタン |
theme.color_outset_active | アクティブなトグル状態 |
theme.color_outset_focus | フォーカスされたボタン |
theme.color_outset_disabled | 無効なボタン |
theme.color_outset_inactive | 非アクティブなボタン |
インセットカラー(テキスト入力、チェックボックス、ラジオボタン):
| 変数 | 用途 |
|---|---|
theme.color_inset | デフォルトの入力背景 |
theme.color_inset_hover | ホバー時の入力 |
theme.color_inset_focus | フォーカス時の入力 |
theme.color_inset_disabled | 無効な入力 |
theme.color_inset_empty | 空の入力 |
選択とハイライト:
| 変数 | 用途 |
|---|---|
theme.color_selection_focus | テキスト選択のハイライト |
theme.color_selection_hover | ホバー時の選択 |
theme.color_highlight | 一般的なアクセント/ハイライト |
theme.color_cursor | カーソルの色 |
theme.color_cursor_focus | フォーカス時のカーソル |
テーマカラー変数 -- セマンティック/ステータス
| 変数 | 用途 | 値 |
|---|---|---|
theme.color_error | エラー状態 | 赤(#C00) |
theme.color_warning | 警告状態 | オレンジ(#FA0) |
theme.color_high | 重大度:高 | 赤(#C00) |
theme.color_mid | 重大度:中 | オレンジ(#FA0) |
theme.color_low | 重大度:低 | 黄緑(#8A0) |
theme.color_panic | パニック/重大 | マゼンタ(#f0f) |
テーマカラー変数 -- ベベルシステム
テーマには、3D風のウィジェット効果を実現する多層ベベルシステムがあります。
| グループ | 変数 | 用途 |
|---|---|---|
color_bevel* | _hover、_focus、_active、_down、_disabled | フラットベベル |
color_bevel_inset_1* | 同じ接尾辞 | 内側の影(レイヤー1) |
color_bevel_inset_2* | 同じ接尾辞 | 内側のハイライト(レイヤー2) |
color_bevel_outset_1* | 同じ接尾辞 | 外側のハイライト(レイヤー1) |
color_bevel_outset_2* | 同じ接尾辞 | 外側の影(レイヤー2) |
テーマカラー変数 -- その他のウィジェットカラー
| 変数グループ | 用途 |
|---|---|
theme.color_icon* | アイコンの色(デフォルト、非アクティブ、アクティブ、無効) |
theme.color_mark* | チェックマーク/ラジオマークの色 |
theme.color_val* | プログレスバーとスライダーの塗りつぶし色 |
theme.color_handle* | スライダーハンドルの色 |
theme.color_shadow* | 影の効果 |
theme.color_drag_quad | ドラッグプレビューのオーバーレイ |
theme.color_dock_tab_active | アクティブなドックタブの背景 |
テーマフォント変数
フォントサイズ
フォントサイズは、font_size_base と font_size_contrast から算出されます。
| 変数 | 計算式 | デフォルト値 |
|---|---|---|
theme.font_size_1 | base + 8 * contrast | 30.0(最大の見出し) |
theme.font_size_2 | base + 4 * contrast | 20.0(中サイズの見出し) |
theme.font_size_3 | base + 2 * contrast | 15.0(小サイズの見出し) |
theme.font_size_4 | base + 1 * contrast | 12.5(小見出し) |
theme.font_size_p | base | 10.0(本文) |
theme.font_size_code | 固定 | 9.0(等幅コード) |
フォントスタイル(TextStyle オブジェクト)
| 変数 | 説明 | フォントファイル |
|---|---|---|
theme.font_regular | 標準ウェイトの本文テキスト | IBMPlexSans-Text.ttf |
theme.font_bold | 太字/セミボールドのテキスト | IBMPlexSans-SemiBold.ttf |
theme.font_italic | イタリック体のテキスト | IBMPlexSans-Italic.ttf |
theme.font_bold_italic | 太字のイタリック体テキスト | IBMPlexSans-BoldItalic.ttf |
theme.font_code | 等幅コード用フォント | LiberationMono-Regular.ttf |
theme.font_label | ラベルテキスト(レガシー) | IBMPlexSans-Text.ttf |
theme.font_icons | アイコンフォント(FontAwesome) | fa-solid-900.ttf |
各フォントスタイルは、複数言語をサポートしています。
- ラテン文字:IBM Plex Sans ファミリー
- 中国語:LXGW WenKai ファミリー
- 絵文字:Noto Color Emoji
行間定数
| 変数 | 値 | 用途 |
|---|---|---|
theme.font_wdgt_line_spacing | 1.2 | ウィジェットのテキスト |
theme.font_hl_line_spacing | 1.05 | 見出しのテキスト |
theme.font_longform_line_spacing | 1.2 | 長文テキスト |
テーマの間隔変数
基本の間隔
間隔は space_factor(デフォルトは 6.0)から算出されます。
| 変数 | 計算式 | デフォルト値 |
|---|---|---|
theme.space_1 | 0.5 * space_factor | 3.0(極小) |
theme.space_2 | 1.0 * space_factor | 6.0(小/標準) |
theme.space_3 | 1.5 * space_factor | 9.0(中) |
マージン/パディングのプリセット(Inset オブジェクト)
全辺のプリセット:
| 変数 | 説明 | 値 |
|---|---|---|
theme.mspace_1 | 全辺の XS パディング | 各辺 3px |
theme.mspace_2 | 全辺の SM パディング | 各辺 6px |
theme.mspace_3 | 全辺の MD パディング | 各辺 9px |
水平方向のみのプリセット:
| 変数 | 説明 | 値 |
|---|---|---|
theme.mspace_h_1 | 水平方向の XS パディング | 左/右:3px、上/下:0 |
theme.mspace_h_2 | 水平方向の SM パディング | 左/右:6px、上/下:0 |
theme.mspace_h_3 | 水平方向の MD パディング | 左/右:9px、上/下:0 |
垂直方向のみのプリセット:
| 変数 | 説明 | 値 |
|---|---|---|
theme.mspace_v_1 | 垂直方向の XS パディング | 上/下:3px、左/右:0 |
theme.mspace_v_2 | 垂直方向の SM パディング | 上/下:6px、左/右:0 |
theme.mspace_v_3 | 垂直方向の MD パディング | 上/下:9px、左/右:0 |
寸法変数
| 変数 | 用途 | デフォルト |
|---|---|---|
theme.data_item_height | 標準データ行の高さ | 約23px |
theme.data_icon_width | 標準アイコンの幅 | 約16px |
theme.data_icon_height | 標準アイコンの高さ | 約22px |
theme.container_corner_radius | コンテナの角丸半径 | 5.0 |
theme.textselection_corner_radius | テキスト選択範囲の角丸半径 | 1.25 |
theme.tab_height | タブバーの高さ | 36.0 |
Splash でのテーマ変数の使用
色
// Background color
draw_bg.color: theme.color_bg_container
// Text color
draw_text.color: theme.color_label_inner
// Muted/secondary text
draw_text.color: theme.color_label_inner_inactive
// Color math -- multiply for opacity
draw_text.color: theme.color_label_inner_inactive * 0.8
// Semantic colors
draw_bg.color: theme.color_warning
draw_bg.color: theme.color_error
フォントサイズ
// Body text size
draw_text.text_style.font_size: theme.font_size_p
// Heading sizes
draw_text.text_style.font_size: theme.font_size_1 // Largest
draw_text.text_style.font_size: theme.font_size_2 // Medium
draw_text.text_style.font_size: theme.font_size_3 // Small
draw_text.text_style.font_size: theme.font_size_4 // Sub-heading
// Code font size
draw_text.text_style.font_size: theme.font_size_code
フォントスタイル
// Bold text with custom size (override with {} syntax)
draw_text.text_style: theme.font_bold{font_size: theme.font_size_2}
// Bold text keeping default size
draw_text.text_style: theme.font_bold{}
// Code font
draw_text.text_style: theme.font_code{}
// Override font size using +: merge syntax
draw_text +: {text_style +: {font_size: theme.font_size_3}}
間隔
// Uniform padding
padding: theme.mspace_2
// Padding with overrides
padding: theme.mspace_2{left: theme.space_3, right: theme.space_3}
// Horizontal-only padding with custom values
padding: theme.mspace_h_1{left: theme.space_2, right: theme.space_2}
// Spacing between children
spacing: theme.space_2
// Computed spacing
width: Fill height: 9. * theme.space_1
padding: theme.mspace_3{left: theme.space_3 * 2, right: theme.space_3 * 2}
色の構文リファレンス
Splash は、複数の色形式に対応しています(テーマ固有ではありませんが、重要です)。
| 構文 | 例 | 説明 |
|---|---|---|
#RGB | #f00 | 短縮形式の16進数(赤) |
#RRGGBB | #ff0000 | 完全形式の16進数 |
#RRGGBBAA | #ff000080 | アルファ値付きの16進数 |
#xRRGGBB | #x2ecc71 | e で始まる16進数(接頭辞 #x) |
#N | #D | グレースケールの短縮表記 |
vec4(r,g,b,a) | vec4(1.0, 0.0, 0.0, 1.0) | RGBA 浮動小数点数(0.0-1.0) |
theme.* | theme.color_highlight | テーマ変数 |
重要:16進数の色が文字 e で始まる場合は、科学表記との曖昧さを避けるために #x 接頭辞を使用してください。たとえば、#2ecc71 ではなく #x2ecc71 を使用します。
色の計算に対応しています:
// Multiply for opacity
theme.color_label_inner_inactive * 0.8
// Mix two colors
mix(theme.color_w, theme.color_b, 0.5)
実行時のテーマ切り替え
Rust のイベントハンドラー内で、動的にテーマを切り替えられます:
impl MatchEvent for App {
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) {
if self.ui.button(cx, ids!(toggle_theme)).clicked(actions) {
script_eval!(cx, {
mod.theme = mod.themes.dark // or mod.themes.light
});
// All widgets using theme.* will pick up new values
// You may need to trigger a re-render
}
}
}
または、ウィジェットの読み込み前に(App::run 内で)切り替えて、テーマを固定できます:
fn run(vm: &mut ScriptVm) -> Self {
crate::makepad_widgets::theme_mod(vm);
script_eval!(vm, {
mod.theme = mod.themes.light
});
crate::makepad_widgets::widgets_mod(vm);
App::from_script_mod(vm, self::script_mod)
}
テーマ対応 UI の完全な例
この例では、テーマ変数のみを使ったテーマ対応のカードリストを示します:
script_mod! {
use mod.prelude.widgets.*
let CardItem = RoundedView{
width: Fill height: Fit
padding: theme.mspace_2{left: theme.space_3, right: theme.space_3}
flow: Right spacing: theme.space_2
align: Align{y: 0.5}
draw_bg.color: theme.color_bg_container
draw_bg.border_radius: theme.container_corner_radius
icon := Label{
width: 24 height: 24
text: ""
}
content := View{
width: Fill height: Fit
flow: Down spacing: theme.space_1
title := Label{
text: "Title"
draw_text.color: theme.color_label_inner
draw_text.text_style: theme.font_bold{font_size: theme.font_size_4}
}
subtitle := Label{
text: "Subtitle"
draw_text.color: theme.color_label_inner_inactive
draw_text.text_style.font_size: theme.font_size_p
}
}
badge := RoundedView{
width: Fit height: Fit
padding: theme.mspace_h_1
draw_bg.color: theme.color_bg_highlight_inline
draw_bg.border_radius: 4.0
badge_label := Label{
text: "new"
draw_text.color: theme.color_highlight
draw_text.text_style.font_size: theme.font_size_code
draw_text.text_style: theme.font_bold{}
}
}
}
startup() do #(App::script_component(vm)){
ui: Root{
main_window := Window{
pass.clear_color: theme.color_bg_app
window.inner_size: vec2(400, 600)
body +: {
width: Fill height: Fill
flow: Down spacing: 0
// Header
SolidView{
width: Fill height: Fit
padding: theme.mspace_3
draw_bg.color: theme.color_app_caption_bar
Label{
text: "My Cards"
draw_text.color: theme.color_label_inner
draw_text.text_style: theme.font_bold{font_size: theme.font_size_2}
}
}
// Card list
ScrollYView{
width: Fill height: Fill
padding: theme.mspace_2
flow: Down spacing: theme.space_1
CardItem{title.text: "First Card" subtitle.text: "Description here"}
CardItem{title.text: "Second Card" subtitle.text: "Another card"}
}
// Footer
SolidView{
width: Fill height: Fit
padding: theme.mspace_2
draw_bg.color: theme.color_bg_container
Label{
text: "2 items"
draw_text.color: theme.color_label_inner_inactive
draw_text.text_style.font_size: theme.font_size_code
}
}
}
}
}
}
}
ベストプラクティス
-
本番アプリでは必ず色に
theme.*を使用してください —theme.color_errorがある場合は、#ff0000をハードコードしないでください。これにより、テーマの切り替えとアクセシビリティに対応できます。 -
一貫したタイポグラフィのためにテーマフォントを使用してください — フォントファミリーを手動で指定するよりも、
theme.font_bold{font_size: theme.font_size_2}を優先してください。 -
一貫したレイアウトのためにテーマの間隔を使用してください —
theme.mspace_2とtheme.space_2により、調和の取れたリズムを作れます。padding: Inset{top: 8, ...}のようなマジックナンバーは避けてください。 -
{}構文でオーバーライドしてください — テーマの値を置き換えずに拡張できます:theme.font_bold{font_size: 20}は太字フォントのファミリーを維持しつつ、サイズをオーバーライドします。theme.mspace_2{left: theme.space_3}は上・右・下を維持しつつ、左をオーバーライドします。 -
部分的なオーバーライドには
+:マージを使用してください — ネストされたプロパティを1つだけ変更したい場合に使います:draw_text +: {text_style +: {font_size: theme.font_size_3}} -
適切なテキスト色の変数を選択してください:
theme.color_label_innerは主要な UI テキスト(ボタン、ラベル)に使用しますtheme.color_label_inner_inactiveはセカンダリまたは控えめなテキストに使用しますtheme.color_textは一般的なコンテンツテキストに使用しますtheme.color_text_placeholderはプレースホルダーテキストに使用します
-
状態に対応した色のバリエーションを使用してください — ホバー・フォーカス・押下時に変化するウィジェットには、対応する
_hover、_focus、_downの接尾辞を持つ変数を使用してください。 -
掛け算で控えめな不透明度にしてください —
theme.color_label_inner_inactive * 0.8を使うと、新しい変数を追加せずに、より控えめな色を作れます。 -
widgets_modより前にテーマを選択してください — ウィジェットの定義に正しいテーマ値を反映するには、theme_mod()とwidgets_mod()の呼び出しの間でテーマを設定する必要があります。 -
シンプルなアプリでは、
crate::makepad_widgets::script_mod(vm)を使用してください。これにより、デフォルトのダークテーマですべてを一度に読み込みます。
ソースファイル
- ダークテーマ:
widgets/src/theme_desktop_dark.rs - ライトテーマ:
widgets/src/theme_desktop_light.rs - テーマのひな形:
widgets/src/theme_desktop_skeleton.rs - テーマローダー:
widgets/src/lib.rs(theme_mod関数とwidgets_mod関数) - 使用例:
examples/todo/src/app.rs(テーマ変数を全面的に使用したライトテーマ) - 使用例:
examples/counter/src/app.rs(デフォルトのダークテーマ)