Orbital Process Steps 軌道プロセスステップ
Cosmic themed multi-stage progress tracker with planetary orbital nodes, progression controls, and full reset action. 宇宙軌道風デザインの3段階進行ステップとリセット操作。
ライブデモ Live Demo
Thruster Ignition
Calibrating telemetry and initializing primary propulsion burn.
概要・用途・特徴Overview, Usage & Features
何ができるかWhat it does
Cosmic themed multi-stage progress tracker with planetary orbital nodes, progression controls, and full reset action.
宇宙軌道風デザインの3段階進行ステップとリセット操作。
どこで使うかWhere to use
Portfolio, product showcase, landing page.
ポートフォリオ、製品紹介、ランディングページ。
特徴Key features
Cosmic themed multi-stage progress tracker with planetary orbital nodes, progression controls, and full reset action.
宇宙軌道風デザインの3段階進行ステップとリセット操作。
調整可能パラメータ Adjustable Parameters
| Parameter | Default | Description |
|---|---|---|
--demo-accent | #818cf8 | Accent color for the panel border and keyboard focus ring. |
実装コード Implementation Code
<div class="demo-stage op-root" role="region" aria-label="Orbital Process Stepper"><div class="op-console"><div class="op-orbit-view" aria-hidden="true"><div class="op-orbit-ring"><div class="op-core-sun"></div><div class="op-satellite op-sat-1 op-active">1</div><div class="op-satellite op-sat-2">2</div><div class="op-satellite op-sat-3">3</div></div></div><div class="op-details" aria-live="polite"><span class="op-stage-counter">MISSION STAGE 1 / 3</span><h3 class="op-stage-name">Thruster Ignition</h3><p class="op-stage-desc">Calibrating telemetry and initializing primary propulsion burn.</p></div><div class="op-controls"><button type="button" class="op-btn op-next-btn" aria-label="Advance to next orbital stage">Next Stage</button><button type="button" class="op-btn op-reset-btn" aria-label="Reset orbital stage sequence">Reset</button></div></div></div>
<script>
document.querySelectorAll('.op-root').forEach(root => {
const nextBtn = root.querySelector('.op-next-btn');
const resetBtn = root.querySelector('.op-reset-btn');
const counterEl = root.querySelector('.op-stage-counter');
const nameEl = root.querySelector('.op-stage-name');
const descEl = root.querySelector('.op-stage-desc');
const sats = root.querySelectorAll('.op-satellite');
if (!nextBtn || !resetBtn || !counterEl || !nameEl || !descEl || !sats.length) return;
const stages = [
{ name: 'Thruster Ignition', desc: 'Calibrating telemetry and initializing primary propulsion burn.' },
{ name: 'Orbital Insertion', desc: 'Stabilizing vector path within the geostationary transfer corridor.' },
{ name: 'Solar Array Deployment', desc: 'Full photovoltaic array locked and energy harvesting active.' }
];
let current = 0;
const update = () => {
counterEl.textContent = `MISSION STAGE ${current + 1} / ${stages.length}`;
nameEl.textContent = stages[current].name;
descEl.textContent = stages[current].desc;
sats.forEach((s, idx) => {
s.classList.toggle('op-active', idx === current);
s.classList.toggle('op-done', idx < current);
});
nextBtn.textContent = current === stages.length - 1 ? 'Completed' : 'Next Stage';
nextBtn.disabled = current === stages.length - 1;
};
nextBtn.addEventListener('click', () => {
if (current < stages.length - 1) {
current++;
update();
}
});
resetBtn.addEventListener('click', () => {
current = 0;
update();
});
});
</script>
.op-root {
box-sizing: border-box;
width: 100%;
max-width: 560px;
max-height: 420px;
min-width: 0;
margin: 0 auto;
padding: 16px;
background: radial-gradient(circle at 50% 20%, #15162c, #070814);
border-radius: 16px;
border: 1px solid #272a52;
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.65);
font-family: system-ui, -apple-system, sans-serif;
color: #e2e8f0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.op-root *, .op-root *::before, .op-root *::after {
box-sizing: border-box;
min-width: 0;
}
.op-root .op-console {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
gap: 14px;
}
.op-root .op-orbit-view {
position: relative;
width: 140px;
height: 90px;
display: flex;
align-items: center;
justify-content: center;
}
.op-root .op-orbit-ring {
position: relative;
width: 130px;
height: 60px;
border: 1px dashed #4338ca;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.op-root .op-core-sun {
width: 18px;
height: 18px;
border-radius: 50%;
background: radial-gradient(circle, #fde047, #ea580c);
box-shadow: 0 0 16px #f59e0b;
}
.op-root .op-satellite {
position: absolute;
width: 20px;
height: 20px;
border-radius: 50%;
background: #1e1e38;
border: 1px solid #6366f1;
color: #cbd5e1;
font-size: 10px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
}
.op-root .op-sat-1 {
top: -10px;
left: 20px;
}
.op-root .op-sat-2 {
top: 18px;
right: -10px;
}
.op-root .op-sat-3 {
bottom: -10px;
left: 36px;
}
.op-root .op-satellite.op-active {
background: #6366f1;
color: #ffffff;
box-shadow: 0 0 12px #6366f1;
transform: scale(1.15);
}
.op-root .op-satellite.op-done {
background: #10b981;
border-color: #34d399;
color: #ffffff;
}
.op-root .op-details {
text-align: center;
display: flex;
flex-direction: column;
gap: 4px;
}
.op-root .op-stage-counter {
font-size: 10px;
font-weight: 700;
letter-spacing: 1px;
color: #818cf8;
}
.op-root .op-stage-name {
margin: 0;
font-size: 16px;
font-weight: 700;
color: #f8fafc;
}
.op-root .op-stage-desc {
margin: 0 auto;
max-width: 400px;
font-size: 11px;
color: #94a3b8;
line-height: 1.4;
}
.op-root .op-controls {
display: flex;
gap: 10px;
flex-wrap: wrap;
justify-content: center;
}
.op-root .op-btn {
appearance: none;
padding: 7px 18px;
border-radius: 8px;
font-size: 12px;
font-weight: 600;
cursor: pointer;
}
.op-root .op-next-btn {
border: 1px solid #6366f1;
background: #4f46e5;
color: #ffffff;
}
.op-root .op-next-btn:hover:not(:disabled) {
background: #4338ca;
}
.op-root .op-next-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.op-root .op-reset-btn {
border: 1px solid #334155;
background: #1e293b;
color: #94a3b8;
}
.op-root .op-reset-btn:hover {
background: #283548;
color: #ffffff;
}
.op-root .op-btn:focus-visible {
outline: 2px solid #818cf8;
outline-offset: 2px;
}
@media (prefers-reduced-motion: no-preference) {
.op-root .op-satellite {
transition: background 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
}
.op-root .op-btn {
transition: background 0.2s ease, transform 0.1s ease;
}
.op-root .op-btn:active:not(:disabled) {
transform: scale(0.96);
}
}
.op-root{max-height:none;--demo-accent:#818cf8;border-color:var(--demo-accent)}.op-root button:focus-visible{outline-color:var(--demo-accent)}
import { useState } from "react";
import "./N-012.css";
const stages = [
{ name: "Thruster Ignition", desc: "Calibrating telemetry and initializing primary propulsion burn." },
{ name: "Orbital Insertion", desc: "Stabilizing vector path within the geostationary transfer corridor." },
{ name: "Solar Array Deployment", desc: "Full photovoltaic array locked and energy harvesting active." }
];
function OrbitalProcessSteps() {
const [selected, setSelected] = useState(0);
return <div className="demo-stage op-root" role="region" aria-label="Orbital Process Stepper"><div className="op-console"><div className="op-orbit-view" aria-hidden="true"><div className="op-orbit-ring"><div className="op-core-sun" /><div className={"op-satellite op-sat-1" + (selected === 0 ? " op-active" : selected > 0 ? " op-done" : "")}>{"1"}</div><div className={"op-satellite op-sat-2" + (selected === 1 ? " op-active" : selected > 1 ? " op-done" : "")}>{"2"}</div><div className={"op-satellite op-sat-3" + (selected === 2 ? " op-active" : selected > 2 ? " op-done" : "")}>{"3"}</div></div></div><div className="op-details" aria-live="polite"><span className="op-stage-counter">{"MISSION STAGE " + (selected + 1) + " / 3"}</span><h3 className="op-stage-name">{stages[selected].name}</h3><p className="op-stage-desc">{stages[selected].desc}</p></div><div className="op-controls"><button type="button" className="op-btn op-next-btn" aria-label="Advance to next orbital stage" onClick={() => setSelected((value) => Math.min(2, value + 1))} disabled={selected === 2}>{selected === 2 ? "Completed" : "Next Stage"}</button><button type="button" className="op-btn op-reset-btn" aria-label="Reset orbital stage sequence" onClick={() => setSelected(0)}>{"Reset"}</button></div></div></div>;
}
export {
OrbitalProcessSteps as default
};
.op-root {
box-sizing: border-box;
width: 100%;
max-width: 560px;
max-height: 420px;
min-width: 0;
margin: 0 auto;
padding: 16px;
background: radial-gradient(circle at 50% 20%, #15162c, #070814);
border-radius: 16px;
border: 1px solid #272a52;
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.65);
font-family: system-ui, -apple-system, sans-serif;
color: #e2e8f0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.op-root *, .op-root *::before, .op-root *::after {
box-sizing: border-box;
min-width: 0;
}
.op-root .op-console {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
gap: 14px;
}
.op-root .op-orbit-view {
position: relative;
width: 140px;
height: 90px;
display: flex;
align-items: center;
justify-content: center;
}
.op-root .op-orbit-ring {
position: relative;
width: 130px;
height: 60px;
border: 1px dashed #4338ca;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.op-root .op-core-sun {
width: 18px;
height: 18px;
border-radius: 50%;
background: radial-gradient(circle, #fde047, #ea580c);
box-shadow: 0 0 16px #f59e0b;
}
.op-root .op-satellite {
position: absolute;
width: 20px;
height: 20px;
border-radius: 50%;
background: #1e1e38;
border: 1px solid #6366f1;
color: #cbd5e1;
font-size: 10px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
}
.op-root .op-sat-1 {
top: -10px;
left: 20px;
}
.op-root .op-sat-2 {
top: 18px;
right: -10px;
}
.op-root .op-sat-3 {
bottom: -10px;
left: 36px;
}
.op-root .op-satellite.op-active {
background: #6366f1;
color: #ffffff;
box-shadow: 0 0 12px #6366f1;
transform: scale(1.15);
}
.op-root .op-satellite.op-done {
background: #10b981;
border-color: #34d399;
color: #ffffff;
}
.op-root .op-details {
text-align: center;
display: flex;
flex-direction: column;
gap: 4px;
}
.op-root .op-stage-counter {
font-size: 10px;
font-weight: 700;
letter-spacing: 1px;
color: #818cf8;
}
.op-root .op-stage-name {
margin: 0;
font-size: 16px;
font-weight: 700;
color: #f8fafc;
}
.op-root .op-stage-desc {
margin: 0 auto;
max-width: 400px;
font-size: 11px;
color: #94a3b8;
line-height: 1.4;
}
.op-root .op-controls {
display: flex;
gap: 10px;
flex-wrap: wrap;
justify-content: center;
}
.op-root .op-btn {
appearance: none;
padding: 7px 18px;
border-radius: 8px;
font-size: 12px;
font-weight: 600;
cursor: pointer;
}
.op-root .op-next-btn {
border: 1px solid #6366f1;
background: #4f46e5;
color: #ffffff;
}
.op-root .op-next-btn:hover:not(:disabled) {
background: #4338ca;
}
.op-root .op-next-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.op-root .op-reset-btn {
border: 1px solid #334155;
background: #1e293b;
color: #94a3b8;
}
.op-root .op-reset-btn:hover {
background: #283548;
color: #ffffff;
}
.op-root .op-btn:focus-visible {
outline: 2px solid #818cf8;
outline-offset: 2px;
}
@media (prefers-reduced-motion: no-preference) {
.op-root .op-satellite {
transition: background 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
}
.op-root .op-btn {
transition: background 0.2s ease, transform 0.1s ease;
}
.op-root .op-btn:active:not(:disabled) {
transform: scale(0.96);
}
}
.op-root{max-height:none;--demo-accent:#818cf8;border-color:var(--demo-accent)}.op-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.