I-015 Interaction medium

Chromatic Palette Studio クロマティックパレットスタジオ

Harmonic color scheme generator showcasing 5 interactive color swatches across 3 curated palette presets. 5色のスウォッチと3種のプリセットでカラーコードを瞬時に確認。

ライブデモ Live Demo

Palette Harmonizer

#0DF2C9
#7928CA
#FF0080
#0070F3
#F5A623

概要・用途・特徴Overview, Usage & Features

何ができるかWhat it does

Harmonic color scheme generator showcasing 5 interactive color swatches across 3 curated palette presets.

5色のスウォッチと3種のプリセットでカラーコードを瞬時に確認。

どこで使うかWhere to use

Portfolio, product showcase, landing page.

ポートフォリオ、製品紹介、ランディングページ。

特徴Key features

Harmonic color scheme generator showcasing 5 interactive color swatches across 3 curated palette presets.

5色のスウォッチと3種のプリセットでカラーコードを瞬時に確認。

調整可能パラメータ Adjustable Parameters

Parameter Default Description
--demo-accent#60a5faAccent color for the panel border and keyboard focus ring.

実装コード Implementation Code

<div class="demo-stage cp-root" role="region" aria-label="Chromatic Palette Studio"><div class="cp-panel"><div class="cp-header"><h3 class="cp-title">Palette Harmonizer</h3><div class="cp-preset-buttons" role="group" aria-label="Palette presets"><button type="button" class="cp-preset-btn cp-active" data-preset="cyber" aria-pressed="true" aria-label="Select Cyber Neon preset">Cyber</button><button type="button" class="cp-preset-btn" data-preset="sunset" aria-pressed="false" aria-label="Select Sunset Glow preset">Sunset</button><button type="button" class="cp-preset-btn" data-preset="pastel" aria-pressed="false" aria-label="Select Pastel Mint preset">Pastel</button></div></div><div class="cp-swatches" aria-live="polite" aria-atomic="true" role="list" aria-label="Color swatches"><div class="cp-swatch-card" role="listitem"><div class="cp-color-box" style="background-color:#0df2c9;"></div><span class="cp-hex">#0DF2C9</span></div><div class="cp-swatch-card" role="listitem"><div class="cp-color-box" style="background-color:#7928ca;"></div><span class="cp-hex">#7928CA</span></div><div class="cp-swatch-card" role="listitem"><div class="cp-color-box" style="background-color:#ff0080;"></div><span class="cp-hex">#FF0080</span></div><div class="cp-swatch-card" role="listitem"><div class="cp-color-box" style="background-color:#0070f3;"></div><span class="cp-hex">#0070F3</span></div><div class="cp-swatch-card" role="listitem"><div class="cp-color-box" style="background-color:#f5a623;"></div><span class="cp-hex">#F5A623</span></div></div></div></div>
<script>
document.querySelectorAll('.cp-root').forEach(root => {
  const presetBtns = root.querySelectorAll('.cp-preset-btn');
  const swatches = root.querySelectorAll('.cp-swatch-card');
  if (!presetBtns.length || !swatches.length) return;
  const presets = {
    cyber: ['#0DF2C9', '#7928CA', '#FF0080', '#0070F3', '#F5A623'],
    sunset: ['#FF4E50', '#FC913A', '#F9D423', '#EDE574', '#E1F5C4'],
    pastel: ['#A8DADC', '#457B9D', '#1D3557', '#F1FAEE', '#E63946']
  };
  presetBtns.forEach(btn => {
    btn.addEventListener('click', () => {
      presetBtns.forEach(b => {
        b.classList.remove('cp-active');
        b.setAttribute('aria-pressed', 'false');
      });
      btn.classList.add('cp-active');
      btn.setAttribute('aria-pressed', 'true');
      const colors = presets[btn.dataset.preset];
      if (!colors) return;
      swatches.forEach((swatch, idx) => {
        const box = swatch.querySelector('.cp-color-box');
        const hex = swatch.querySelector('.cp-hex');
        if (box && hex && colors[idx]) {
          box.style.backgroundColor = colors[idx];
          hex.textContent = colors[idx];
        }
      });
    });
  });
});
</script>
.cp-root {
  box-sizing: border-box;
  width: 100%;
  max-width: 560px;
  max-height: 420px;
  min-width: 0;
  margin: 0 auto;
  padding: 16px;
  background: #111217;
  border-radius: 16px;
  border: 1px solid #22252f;
  box-shadow: 0 16px 36px rgba(0, 0, 0, 0.6);
  font-family: system-ui, -apple-system, sans-serif;
  color: #f1f3f9;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.cp-root *, .cp-root *::before, .cp-root *::after {
  box-sizing: border-box;
  min-width: 0;
}
.cp-root .cp-panel {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.cp-root .cp-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
}
.cp-root .cp-title {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  color: #ffffff;
}
.cp-root .cp-preset-buttons {
  display: flex;
  gap: 6px;
}
.cp-root .cp-preset-btn {
  appearance: none;
  border: 1px solid #2e3344;
  background: #1b1e28;
  color: #94a3b8;
  padding: 6px 14px;
  border-radius: 6px;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
}
.cp-root .cp-preset-btn:hover {
  background: #252a38;
  color: #ffffff;
}
.cp-root .cp-preset-btn.cp-active {
  background: #3b82f6;
  border-color: #60a5fa;
  color: #ffffff;
}
.cp-root .cp-preset-btn:focus-visible {
  outline: 2px solid #60a5fa;
  outline-offset: 2px;
}
.cp-root .cp-swatches {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
}
.cp-root .cp-swatch-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
}
.cp-root .cp-color-box {
  width: 100%;
  height: 80px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.cp-root .cp-hex {
  font-size: 10px;
  font-family: monospace;
  color: #cbd5e1;
  font-weight: 600;
}
@media (prefers-reduced-motion: no-preference) {
  .cp-root .cp-color-box {
    transition: background-color 0.35s ease, transform 0.2s ease;
  }
  .cp-root .cp-color-box:hover {
    transform: translateY(-2px);
  }
  .cp-root .cp-preset-btn {
    transition: background 0.2s ease, border-color 0.2s ease, transform 0.1s ease;
  }
  .cp-root .cp-preset-btn:active {
    transform: scale(0.95);
  }
}
.cp-root{max-height:none;--demo-accent:#60a5fa;border-color:var(--demo-accent)}.cp-root button:focus-visible{outline-color:var(--demo-accent)}
import { useState } from "react";
import "./I-015.css";
const presets = {
  cyber: ["#0DF2C9", "#7928CA", "#FF0080", "#0070F3", "#F5A623"],
  sunset: ["#FF4E50", "#FC913A", "#F9D423", "#EDE574", "#E1F5C4"],
  pastel: ["#A8DADC", "#457B9D", "#1D3557", "#F1FAEE", "#E63946"]
};
function ChromaticPaletteStudio() {
  const [preset, setPreset] = useState("cyber");
  return <div className="demo-stage cp-root" role="region" aria-label="Chromatic Palette Studio"><div className="cp-panel"><div className="cp-header"><h3 className="cp-title">{"Palette Harmonizer"}</h3><div className="cp-preset-buttons" role="group" aria-label="Palette presets"><button type="button" data-preset="cyber" aria-label="Select Cyber Neon preset" className={"cp-preset-btn" + (preset === "cyber" ? " cp-active" : "")} aria-pressed={preset === "cyber"} onClick={() => setPreset("cyber")}>{"Cyber"}</button><button type="button" data-preset="sunset" aria-label="Select Sunset Glow preset" className={"cp-preset-btn" + (preset === "sunset" ? " cp-active" : "")} aria-pressed={preset === "sunset"} onClick={() => setPreset("sunset")}>{"Sunset"}</button><button type="button" data-preset="pastel" aria-label="Select Pastel Mint preset" className={"cp-preset-btn" + (preset === "pastel" ? " cp-active" : "")} aria-pressed={preset === "pastel"} onClick={() => setPreset("pastel")}>{"Pastel"}</button></div></div><div className="cp-swatches" aria-live="polite" aria-atomic="true" role="list" aria-label="Color swatches"><div className="cp-swatch-card" role="listitem"><div className="cp-color-box" style={{ backgroundColor: presets[preset][0] }} /><span className="cp-hex">{presets[preset][0]}</span></div><div className="cp-swatch-card" role="listitem"><div className="cp-color-box" style={{ backgroundColor: presets[preset][1] }} /><span className="cp-hex">{presets[preset][1]}</span></div><div className="cp-swatch-card" role="listitem"><div className="cp-color-box" style={{ backgroundColor: presets[preset][2] }} /><span className="cp-hex">{presets[preset][2]}</span></div><div className="cp-swatch-card" role="listitem"><div className="cp-color-box" style={{ backgroundColor: presets[preset][3] }} /><span className="cp-hex">{presets[preset][3]}</span></div><div className="cp-swatch-card" role="listitem"><div className="cp-color-box" style={{ backgroundColor: presets[preset][4] }} /><span className="cp-hex">{presets[preset][4]}</span></div></div></div></div>;
}
export {
  ChromaticPaletteStudio as default
};
.cp-root {
  box-sizing: border-box;
  width: 100%;
  max-width: 560px;
  max-height: 420px;
  min-width: 0;
  margin: 0 auto;
  padding: 16px;
  background: #111217;
  border-radius: 16px;
  border: 1px solid #22252f;
  box-shadow: 0 16px 36px rgba(0, 0, 0, 0.6);
  font-family: system-ui, -apple-system, sans-serif;
  color: #f1f3f9;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.cp-root *, .cp-root *::before, .cp-root *::after {
  box-sizing: border-box;
  min-width: 0;
}
.cp-root .cp-panel {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.cp-root .cp-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
}
.cp-root .cp-title {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  color: #ffffff;
}
.cp-root .cp-preset-buttons {
  display: flex;
  gap: 6px;
}
.cp-root .cp-preset-btn {
  appearance: none;
  border: 1px solid #2e3344;
  background: #1b1e28;
  color: #94a3b8;
  padding: 6px 14px;
  border-radius: 6px;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
}
.cp-root .cp-preset-btn:hover {
  background: #252a38;
  color: #ffffff;
}
.cp-root .cp-preset-btn.cp-active {
  background: #3b82f6;
  border-color: #60a5fa;
  color: #ffffff;
}
.cp-root .cp-preset-btn:focus-visible {
  outline: 2px solid #60a5fa;
  outline-offset: 2px;
}
.cp-root .cp-swatches {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
}
.cp-root .cp-swatch-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
}
.cp-root .cp-color-box {
  width: 100%;
  height: 80px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.cp-root .cp-hex {
  font-size: 10px;
  font-family: monospace;
  color: #cbd5e1;
  font-weight: 600;
}
@media (prefers-reduced-motion: no-preference) {
  .cp-root .cp-color-box {
    transition: background-color 0.35s ease, transform 0.2s ease;
  }
  .cp-root .cp-color-box:hover {
    transform: translateY(-2px);
  }
  .cp-root .cp-preset-btn {
    transition: background 0.2s ease, border-color 0.2s ease, transform 0.1s ease;
  }
  .cp-root .cp-preset-btn:active {
    transform: scale(0.95);
  }
}
.cp-root{max-height:none;--demo-accent:#60a5fa;border-color:var(--demo-accent)}.cp-root button:focus-visible{outline-color:var(--demo-accent)}

仕組みとカスタマイズHow It Works & Customization

仕組みHow it works

Scoped CSS creates the visual design; small vanilla JavaScript handlers update the local demo state.

スコープ化したCSSで描画し、Vanilla JavaScriptでデモ内の状態だけを更新します。

カスタマイズ方法Customization

Accent color for the panel border and keyboard focus ring.

パネルの枠線とキーボードフォーカスの色を変更します。

注意点Caveats

The sample content is fictional. No external assets or libraries are required. Motion follows the operating system preference. Demo labels are English; surrounding documentation supports Japanese and English.

デモ内容は架空です。外部素材・ライブラリは不要。OSの動きを減らす設定に対応します。デモ内のラベルは英語、解説は日英対応です。

よくある質問 Frequently Asked Questions

Does this demo need external libraries? 外部ライブラリは必要ですか?

The sample content is fictional. No external assets or libraries are required. Motion follows the operating system preference. Demo labels are English; surrounding documentation supports Japanese and English.

デモ内容は架空です。外部素材・ライブラリは不要。OSの動きを減らす設定に対応します。デモ内のラベルは英語、解説は日英対応です。

AIへの指示テンプレート AI Prompt Template

以下をAIに貼り付けると実装を依頼できます。 Paste the following into your AI assistant to request implementation.