tweaks について
tweaksは、HTML成果物にライブ操作パネルを追加し、見た目のバリエーションを調整するデザインスキルです。CSSカスタムプロパティを更新し、設定をlocalStorageに保存します。
主な機能
- 01CSSカスタムプロパティに表示設定を連携
- 02アクセント色や文字サイズなどを調整
- 03変更を成果物に即時反映
- 04設定をlocalStorageに保存
- 05ショートカットでパネル表示とリセット
活用シーン
- 01生成済みのWeb成果物を微調整
- 02デザインシステムのバリエーションを実演
- 03操作可能な単体デモページを作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nexu-io/ open-design --skill tweaksインストール後、Claude Code で/tweaksを入力して読み込まれたか確認します。
同梱ファイルassets/wrap.htmlexample.html
詳細
Tweaks スキル · パラメーター調整パネル
HTML アーティファクトを、CSS カスタムプロパティを書き換えてリアルタイムに反映し、その値を localStorage に保存するライブコントロール付きのサイドパネルでラップします。
huashu-design の調整パターンに着想を得ています。
生成するもの
次の 2 層からなる、単体で動作する HTML ファイルを 1 つ作成します。
- ステージ — 元のアーティファクト(ランディングページ/デッキ/ダッシュボード)を、すべての視覚的な設定が CSS カスタムプロパティを参照するように変更します。
--accent、--scale、--density、--mode、--motionを使用します。 - パネル — 小さいビューポートではドロワーになる、固定サイドバーを用意します。簡潔なバニラ JS のブリッジを介して、フォームコントロールをこれらのカスタムプロパティにバインドします。アーティファクト識別子をキーとして、変更のたびに
localStorageに保存します。
ユーザーは次の操作を行えます。
- アーティファクトを開くと、保存済みの設定(保存されていない場合は適切なデフォルト値)でステージが表示されます。
- パネルでアクセント/スケール/密度/モード/モーションを調整し、再レンダリングなしでステージが即座に更新される様子を確認できます。
- T を押してパネルの表示/非表示を切り替え、R を押してデフォルト値にリセットできます。
- ページを再読み込みしても、すべての選択内容が保存されています。
使用する場面
- ユーザーが生成物を 80%ほど気に入り、残りの 20%を自分で調整したい場合。
- デザインシステム/ブランドを紹介し、エージェントを再実行するのではなく、閲覧者にバリエーションをその場で試してもらいたい場合。
- 単体で動作するデモ(例:ポートフォリオ作品)を公開し、閲覧者に操作してもらいたい場合。
使用しない場面
- 一度きりのアーティファクトで、反復して調整する予定がない場合(例:ランブック。パラメーターを調整しても役に立ちません)。
- アーティファクトの価値が固定比率にある場合(例:データ可視化のバランスが緻密に調整されたインフォグラフィック。調整項目を設けるとかえって品質が落ちます)。
標準の調整項目 5 つ
アーティファクトに合った項目を選んでください。重要な項目が 2 つだけなら、5 つすべてを実装しないでください。余計な項目は品質の低下につながります。
1. --accent — アクセントカラー
厳選した 5~8 色のスウォッチを並べたセレクトを用意します(自由に色を選べるカラーピッカーは実装しないでください。ユーザーが不適切な色を選び、その責任をあなたに問うことになります)。
const ACCENT_PRESETS = [
{ id: 'rust', val: '#c96442', label: 'Rust' },
{ id: 'cobalt', val: '#2c4d8e', label: 'Cobalt' },
{ id: 'sage', val: '#4a7a3f', label: 'Sage' },
{ id: 'plum', val: '#7a3f6a', label: 'Plum' },
{ id: 'graphite',val: '#3a3a3a', label: 'Graphite' },
];
アーティファクトでハードコードされていたアクセントカラーをすべて var(--accent) に置き換えます。ボーダー/リンク/プルクオートのルール/CTA がすべて連動して切り替わります。
2. --scale — 文字サイズ(0.85 / 1.0 / 1.15)
設定は コンパクト(0.85)、標準(1.0)、ゆったり(1.15)の 3 つです。すべての font-size 宣言に var(--scale) を乗じるには、calc(... * var(--scale)) を使います。
±15%を超える範囲にはしないでください。それを超えるとレイアウトが崩れます(カラムの流れ、ブレークポイント、行数など)。
3. --density — レイアウト密度(詰める/標準/ゆったり)
間隔のスケールを切り替える設定は 3 つです。詰める(0.75)/標準(1.0)/ゆったり(1.4)。すべての padding/gap/margin 宣言に var(--density) を乗じます。
最も大きく影響する調整項目ですが、同時に最も壊れやすい項目です。そのため、ラップする前にレイアウト上重要なすべてのコンテナーで、ベースとなる間隔をカスタムプロパティとして宣言する必要があります。
4. --mode — ライト/ダーク
2 状態の切り替えです。<html> 要素に data-mode="light" または "dark" を設定すると、アーティファクトの :root セレクターが 2 組のカラー設定を切り替えます。
アーティファクトにメディアクエリを使ったダークモードがすでにある場合は、データ属性を使う方式に置き換えてください。ユーザーの選択が OS の設定より優先されるようにします。
5. --motion — オフ/控えめ/活発
設定は 3 つです。CSS 変数 --motion-mult にマッピングし、すべての transition-duration/animation-duration 宣言をスケーリングします。
- オフ —
0s(WebGL キャンバス/装飾アニメーションも無効にします)。 - 控えめ —
1.0(アーティファクトで設定したタイミング)。 - 活発 —
1.6(遷移が遅くなり、動きがより目立ちます)。
prefers-reduced-motion を尊重してください。ユーザーがこの設定を有効にしている場合は、保存済みの設定に関係なく、デフォルトを オフ にします。
ホストとの連携仕様(必須)
OpenDesign ビューアーのツールバーには、iframe の外部からパネルの表示状態を切り替える Tweaks トグルがあります。このトグルをパネルに連携させるには、アーティファクトで次の 2 つのプロトコルのいずれかに対応する必要があります(どちらか 1 つを選び、混在させないでください)。どちらかのシグナルを検知すると、ツールバーが自動的に有効になります。
プロトコル A — postMessage(エージェントが生成した成果物に推奨)
パネルが JS(React、バニラ、その他動的なものすべて)でマウントされる場合にこれを使用します。
成果物 → ホスト:
- マウント時に
{ type: '__edit_mode_available', visible?: boolean }をwindow.parentに post します。ツールバーにパネルの存在を知らせます。任意のvisibleはパネルの初期状態を報告するので、ツールバーのトグルが同期した状態で開始します。 よくある「パネルがすでに画面に表示されている」ケースではvisibleを省略します(ホストは フィールドが欠けている場合をtrueとして扱うため、従来の引数なしメッセージはそのまま 動作し続けます)。デフォルトで閉じたパネルを宣言するにはvisible: falseを渡します。 - ユーザーがパネルをローカルで閉じたとき(× ボタン、Esc など)、
{ type: '__edit_mode_dismissed' }を post します。ツールバーは「オフ」に切り替わります。
ホスト → 成果物:
{ type: '__activate_edit_mode' }— パネルを開きます(setOpen(true))。{ type: '__deactivate_edit_mode' }— パネルを閉じます(setOpen(false))。
最小限のリスナー:
window.addEventListener('message', (e) => {
const t = e?.data?.type;
if (t === '__activate_edit_mode') setOpen(true);
else if (t === '__deactivate_edit_mode') setOpen(false);
});
// Or, for a default-closed panel:
// window.parent.postMessage({ type: '__edit_mode_available', visible: open }, '*');
window.parent.postMessage({ type: '__edit_mode_available' }, '*');
// in your close handler:
const dismiss = () => {
setOpen(false);
window.parent.postMessage({ type: '__edit_mode_dismissed' }, '*');
};
パネルはデフォルトで開いていても閉じていてもかまいません — ホストはそのトグルを 成果物が報告する状態に同期します。
プロトコル B — クラスベース(assets/wrap.html で使用)
テンプレートをそのままラップする場合にのみこれを使用します。成果物は
.tw-panel 要素を提供し、表示/非表示を切り替えるために .tw-hidden クラスをトグルします。
ビューアの iframe ブリッジ(apps/web/src/runtime/srcdoc.ts 内)は、初回の描画時に
パネルを非表示にし、MutationObserver でクラスを監視し、状態を双方向に中継します。
テンプレートがすでに含んでいるもの以外に、成果物側で JS は必要ありません。
セレクターは固定です: .tw-panel(パネルのルート)と .tw-hidden(非表示状態)。
どちらかの名前を変更すると、ブリッジはそれを見つけられません。
アンチパターン
第三のプロトコルを考案したり、どちらかの識別子のセットの名前を変更したりしないでください。 ツールバーのトグルは A または B にのみバインドされます。独自のクラスを持ち postMessage を 使わないカスタムパネルでは、ツールバーはグレーアウトしたままになります。
実装の基本要素
assets/wrap.html を読んでください — パネル + ブリッジを不活性なテンプレートとして
提供しています。あなたの仕事は次のとおりです:
- ユーザーの既存の成果物 HTML を取得します。
- そのアクセント / モード / スペーシング / スケールをカスタムプロパティに
引き上げます(ハードコードされた
#hex/Npx/Nremを検索して変換します)。 - その内容を
wrap.htmlのマークされた領域に貼り付けます。 assets/wrap.htmlのKNOBS配列を編集して、この 成果物に関連すると 判断したノブだけを残します。2 つが重要なら 5 つを出荷しないでください。STORAGE_KEYを一意のスラッグ(tweaks-<artifact-slug>)にパッチします。
wrap.html のブリッジは:
- 初回の描画時に
localStorage[STORAGE_KEY]の JSON を読み込みます。 - 値を
document.documentElement.style.setProperty('--accent', ...)として適用します。 - すべてのフォームコントロールの
changeイベントを監視し、書き戻します。 - T(パネルのトグル)と R(リセット)を公開します。
ワークフロー
ステップ 1 — 成果物を取得する
critique スキルと同じ選択肢です:
- プロジェクトファイル(プロジェクトフォルダ内の
index.html)。 - チャットに貼り付けられた HTML。
- このターンであなたが生成したもの。
ステップ 2 — どのノブを適用するか決める
まず成果物の CSS を読んでください。各ノブについて yes / no を決めます:
--accent— 成果物に 3 回以上使われるアクセントカラーが 1 つあるなら yes。--scale— 成果物がタイポグラフィ主導(記事、デッキ、 価格ページ)なら yes。--density— 成果物に一貫した gap / padding の リズム(デッキ、ダッシュボード、ランディング)があるなら yes。ランブックには no(すでに密です)。--mode— 成果物に作成済みのダークモードトークンがある、または あなたがそれらを導出してもよいなら yes。--motion— 成果物にスケーリングする価値のあるトランジション / アニメーションが あるなら yes。静的なレポート / critique レポートには no。
デフォルト: 3 つのノブが最適です。 5 つは煩雑すぎ、1 つは パネルにする価値がありません。
Step 3 — ハードコードされた値をカスタムプロパティに置き換える
assets/wrap.html の <style> ブロックを開き、カスタムプロパティの
命名規則(--accent、--scale など)をコピーします。ユーザーのアーティファクトで、
該当する値が使われている箇所をすべて見つけ、次のように書き換えます。
color: #c96442→color: var(--accent)font-size: 18px→font-size: calc(18px * var(--scale))padding: 24px 32px→padding: calc(24px * var(--density)) calc(32px * var(--density))transition: opacity 200ms→transition: opacity calc(200ms * var(--motion-mult))
アーティファクトですでに clamp() や vw が使われている場合は、
clamp(...) を分解せず、外側の値にカスタムプロパティを乗算してください。
Step 4 — ラップ用ファイルに貼り付ける
アーティファクトの <style> と <body> をコピーし、
wrap.html の指定された領域に貼り付けます。パネルとブリッジはそのまま残してください。
Step 5 — 一連の動作をテストする
完成したものを開き、各ノブを少なくとも一度クリックしてからページを再読み込みし、 選択内容が保持されることを確認します。ノブによってレイアウトが崩れる場合は、 出荷せずに削除してください。
出力形式
<artifact identifier="tweaks-<artifact-slug>" type="text/html" title="<Artifact Title> · Tweaks">
<!doctype html>
<html>...</html>
</artifact>
アーティファクトの前に、「X を 3 ノブの調整パネル(アクセント/スケール/モード)でラップしました。」という1文を置きます。</artifact> の後に続けてはいけません。
厳守事項
- 自由に色を選べるカラーピッカーは出荷しないでください — 用意されたスウォッチのみを使用します。自由に選べるとユーザーは不適切な色を選んでしまいます。それを防ぐことが何より重要です。
- アーティファクト識別子ごとに永続化する — グローバルキーではなく
tweaks-<slug>を使用します。2つのアーティファクトを2つのタブで開いても、状態を共有してはいけません。 prefers-reduced-motionを尊重する — ユーザーがこの設定を有効にしている場合、モーションはデフォルトでオフにし、明示的なクリックがあった場合にのみ上書きします。- 単一ファイルにする — アーティファクトに既存のインポートがある場合を除き、外部 CSS/JS/フォントを追加してはいけません。パネルとブリッジはインライン化します。
- ビューポートが 720px 未満の場合、パネルはデフォルトで非表示にする — 右上の「T」ボタンでスライドインするドロワーとして表示します。
- ノブは5個を超えないでください。 3個が最適です。