docs(design): 补充控制面板设计稿

补充控制面板设计说明,并细化 RuntimeHost 状态与主界面线框图,便于后续实现对齐交互范围。
This commit is contained in:
2026-06-10 18:06:55 +08:00
parent 5cfa0fc591
commit 6ee80834ee
3 changed files with 467 additions and 156 deletions
+168
View File
@@ -0,0 +1,168 @@
<svg width="1600" height="960" viewBox="0 0 1600 960" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="bg" x1="220" y1="96" x2="1364" y2="902" gradientUnits="userSpaceOnUse">
<stop stop-color="#F4F6F8"/>
<stop offset="1" stop-color="#F4F6F8"/>
</linearGradient>
<filter id="cardShadow" x="0" y="0" width="2000" height="1400" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feOffset dy="20"/>
<feGaussianBlur stdDeviation="20"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.133333 0 0 0 0 0.180392 0 0 0 0 0.258824 0 0 0 0.1 0"/>
<feBlend in2="SourceGraphic" result="shape"/>
</filter>
<linearGradient id="statusGlow" x1="136" y1="156" x2="696" y2="428" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFFFFF"/>
<stop offset="1" stop-color="#FFFFFF"/>
</linearGradient>
<linearGradient id="controlGlow" x1="844" y1="132" x2="1440" y2="836" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFFFFF"/>
<stop offset="1" stop-color="#FFFFFF"/>
</linearGradient>
</defs>
<rect width="1600" height="960" fill="url(#bg)"/>
<g filter="url(#cardShadow)">
<rect x="20" y="20" width="1560" height="920" rx="10" fill="#F4F6F8"/>
</g>
<g filter="url(#cardShadow)">
<rect x="36" y="36" width="724" height="302" rx="10" fill="url(#statusGlow)"/>
<rect x="36.75" y="36.75" width="722.5" height="300.5" rx="10" stroke="#C9D1D9" stroke-width="2"/>
<text x="72" y="120" fill="#17202A" font-family="Arial, sans-serif" font-size="22" font-weight="700">RuntimeHost Status</text>
<text x="72" y="148" fill="#52616F" font-family="Arial, sans-serif" font-size="14" font-weight="500">Service lifecycle, bind state, runtime snapshot</text>
<rect x="584" y="94" width="142" height="40" rx="10" fill="#D9F5E5" stroke="#31A66A"/>
<circle cx="610" cy="114" r="6" fill="#31A66A"/>
<text x="625" y="118" fill="#27313B" font-family="Arial, sans-serif" font-size="14" font-weight="700">BOUND</text>
<rect x="72" y="184" width="216" height="118" rx="10" fill="#FFFFFF"/>
<rect x="72.75" y="184.75" width="214.5" height="116.5" rx="10" stroke="#D5DDE5" stroke-width="1.5"/>
<text x="98" y="217" fill="#52616F" font-family="Arial, sans-serif" font-size="14" font-weight="600">Connection</text>
<text x="98" y="263" fill="#17202A" font-family="Arial, sans-serif" font-size="38" font-weight="700">Active</text>
<text x="98" y="286" fill="#31A66A" font-family="Arial, sans-serif" font-size="14" font-weight="700">USB Ready</text>
<rect x="304" y="184" width="216" height="118" rx="10" fill="#FFFFFF"/>
<rect x="304.75" y="184.75" width="214.5" height="116.5" rx="10" stroke="#D5DDE5" stroke-width="1.5"/>
<text x="330" y="217" fill="#52616F" font-family="Arial, sans-serif" font-size="14" font-weight="600">Runtime State</text>
<text x="330" y="263" fill="#17202A" font-family="Arial, sans-serif" font-size="38" font-weight="700">Warm</text>
<text x="330" y="286" fill="#D99000" font-family="Arial, sans-serif" font-size="14" font-weight="700">Last ping 00:01.2</text>
<rect x="536" y="184" width="190" height="118" rx="10" fill="#FFFFFF"/>
<rect x="536.75" y="184.75" width="188.5" height="116.5" rx="10" stroke="#D5DDE5" stroke-width="1.5"/>
<text x="562" y="217" fill="#52616F" font-family="Arial, sans-serif" font-size="14" font-weight="600">Health</text>
<text x="562" y="263" fill="#17202A" font-family="Arial, sans-serif" font-size="38" font-weight="700">98%</text>
<text x="562" y="286" fill="#2F80ED" font-family="Arial, sans-serif" font-size="14" font-weight="700">No crash signal</text>
<text x="72" y="322" fill="#7B8794" font-family="Courier, monospace" font-size="13">Updated 14:32:08 [SDK]</text>
</g>
<g filter="url(#cardShadow)">
<rect x="36" y="346" width="724" height="558" rx="10" fill="#FFFFFF"/>
<rect x="36.75" y="346.75" width="722.5" height="556.5" rx="10" stroke="#C9D1D9" stroke-width="2"/>
<text x="72" y="402" fill="#17202A" font-family="Arial, sans-serif" font-size="22" font-weight="700">Session Log</text>
<text x="72" y="428" fill="#52616F" font-family="Arial, sans-serif" font-size="14" font-weight="500">Tx blue, Rx green, system purple</text>
<rect x="574" y="378" width="154" height="42" rx="10" fill="#E8F1FF"/>
<rect x="574.75" y="378.75" width="152.5" height="40.5" rx="10" stroke="#2F80ED" stroke-width="1.5"/>
<circle cx="598" cy="399" r="7" fill="#31A66A"/>
<text x="656" y="404" text-anchor="middle" fill="#2F80ED" font-family="Arial, sans-serif" font-size="15" font-weight="700">Start / Stop</text>
<rect x="72" y="452" width="640" height="416" rx="10" fill="#FFFFFF"/>
<rect x="72.75" y="452.75" width="638.5" height="414.5" rx="10" stroke="#D5DDE5" stroke-width="1.5"/>
<text x="104" y="492" fill="#2F80ED" font-family="Courier, monospace" font-size="15">14:32:06.212 [TX] bind request sent</text>
<text x="104" y="518" fill="#31A66A" font-family="Courier, monospace" font-size="15">14:32:06.438 [RX] ping =&gt; &quot;pong&quot;</text>
<text x="104" y="544" fill="#7B8794" font-family="Courier, monospace" font-size="15">14:32:07.042 [SYS] state poll updated</text>
<text x="104" y="570" fill="#31A66A" font-family="Courier, monospace" font-size="15">14:32:08.115 [RX] getHealthStateJson =&gt; {&quot;ok&quot;:true}</text>
<text x="104" y="596" fill="#2F80ED" font-family="Courier, monospace" font-size="15">14:32:08.640 [TX] request warm start</text>
<text x="104" y="622" fill="#7B8794" font-family="Courier, monospace" font-size="15">14:32:09.021 [SYS] log stream running</text>
<text x="104" y="648" fill="#31A66A" font-family="Courier, monospace" font-size="15">14:32:09.302 [RX] runtime lifecycle =&gt; WARM</text>
<text x="104" y="674" fill="#2F80ED" font-family="Courier, monospace" font-size="15">14:32:09.618 [TX] getDebugSnapshotJson</text>
<text x="104" y="700" fill="#31A66A" font-family="Courier, monospace" font-size="15">14:32:09.774 [RX] debug snapshot =&gt; 1.4 KB</text>
<text x="104" y="726" fill="#7B8794" font-family="Courier, monospace" font-size="15">14:32:10.001 [SYS] snapshot cached</text>
<rect x="684" y="486" width="12" height="330" rx="6" fill="#E5E9EE"/>
<rect x="685.5" y="566" width="9" height="106" rx="4.5" fill="#A4AFBA"/>
<circle cx="690" cy="474" r="12" fill="#EEF1F4"/>
<path d="M685.5 477L690 471L694.5 477" stroke="#7B8794" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="690" cy="832" r="12" fill="#EEF1F4"/>
<path d="M685.5 829L690 835L694.5 829" stroke="#7B8794" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<g filter="url(#cardShadow)">
<rect x="772" y="36" width="792" height="868" rx="10" fill="url(#controlGlow)"/>
<rect x="772.75" y="36.75" width="790.5" height="866.5" rx="10" stroke="#C9D1D9" stroke-width="2"/>
<text x="832" y="120" fill="#17202A" font-family="Arial, sans-serif" font-size="22" font-weight="700">Controls</text>
<text x="832" y="148" fill="#52616F" font-family="Arial, sans-serif" font-size="14" font-weight="500">Rounded grid buttons fill control card</text>
<g>
<rect x="832" y="214" width="208" height="136" rx="10" fill="#F3F8FF"/>
<rect x="832.75" y="214.75" width="206.5" height="134.5" rx="10" stroke="#2F80ED" stroke-width="1.5"/>
<text x="936" y="276" text-anchor="middle" fill="#17202A" font-family="Arial, sans-serif" font-size="22" font-weight="700">Bind</text>
<text x="936" y="306" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">Start bridge</text>
<text x="936" y="326" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">session</text>
</g>
<g>
<rect x="1064" y="214" width="208" height="136" rx="10" fill="#F3F8FF"/>
<rect x="1064.75" y="214.75" width="206.5" height="134.5" rx="10" stroke="#2F80ED" stroke-width="1.5"/>
<text x="1168" y="276" text-anchor="middle" fill="#17202A" font-family="Arial, sans-serif" font-size="22" font-weight="700">Unbind</text>
<text x="1168" y="306" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">Close service</text>
<text x="1168" y="326" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">link</text>
</g>
<g>
<rect x="1296" y="214" width="208" height="136" rx="10" fill="#F3F8FF"/>
<rect x="1296.75" y="214.75" width="206.5" height="134.5" rx="10" stroke="#2F80ED" stroke-width="1.5"/>
<text x="1400" y="276" text-anchor="middle" fill="#17202A" font-family="Arial, sans-serif" font-size="22" font-weight="700">Ping</text>
<text x="1400" y="306" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">Check round</text>
<text x="1400" y="326" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">trip</text>
</g>
<g>
<rect x="832" y="370" width="208" height="136" rx="10" fill="#FFFFFF"/>
<rect x="832.75" y="370.75" width="206.5" height="134.5" rx="10" stroke="#D5DDE5" stroke-width="1.5"/>
<text x="936" y="432" text-anchor="middle" fill="#17202A" font-family="Arial, sans-serif" font-size="22" font-weight="700">Runtime State</text>
<text x="936" y="462" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">getRuntime</text>
<text x="936" y="482" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">StateJson</text>
</g>
<g>
<rect x="1064" y="370" width="208" height="136" rx="10" fill="#FFFFFF"/>
<rect x="1064.75" y="370.75" width="206.5" height="134.5" rx="10" stroke="#D5DDE5" stroke-width="1.5"/>
<text x="1168" y="432" text-anchor="middle" fill="#17202A" font-family="Arial, sans-serif" font-size="22" font-weight="700">Health</text>
<text x="1168" y="462" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">getHealth</text>
<text x="1168" y="482" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">StateJson</text>
</g>
<g>
<rect x="1296" y="370" width="208" height="136" rx="10" fill="#FFFFFF"/>
<rect x="1296.75" y="370.75" width="206.5" height="134.5" rx="10" stroke="#D5DDE5" stroke-width="1.5"/>
<text x="1400" y="432" text-anchor="middle" fill="#17202A" font-family="Arial, sans-serif" font-size="22" font-weight="700">Debug</text>
<text x="1400" y="462" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">getDebug</text>
<text x="1400" y="482" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">SnapshotJson</text>
</g>
<g>
<rect x="832" y="526" width="208" height="136" rx="10" fill="#FFFFFF"/>
<rect x="832.75" y="526.75" width="206.5" height="134.5" rx="10" stroke="#D5DDE5" stroke-width="1.5"/>
<text x="936" y="588" text-anchor="middle" fill="#17202A" font-family="Arial, sans-serif" font-size="22" font-weight="700">Lifecycle</text>
<text x="936" y="618" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">getRuntimeLifecycle</text>
<text x="936" y="638" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">StateJson</text>
</g>
<g>
<rect x="1064" y="526" width="440" height="136" rx="10" fill="#FFFBED"/>
<rect x="1064.75" y="526.75" width="438.5" height="134.5" rx="10" stroke="#D99000" stroke-width="1.5"/>
<text x="1284" y="588" text-anchor="middle" fill="#17202A" font-family="Arial, sans-serif" font-size="22" font-weight="700">Warm Start</text>
<text x="1284" y="618" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">requestRuntime</text>
<text x="1284" y="638" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">WarmStart</text>
</g>
<g opacity="0.8">
<rect x="832" y="682" width="672" height="140" rx="10" fill="#FFFFFF"/>
<rect x="832.75" y="682.75" width="670.5" height="138.5" rx="10" stroke="#C9D1D9" stroke-width="1.5"/>
<text x="1168" y="744" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="22" font-weight="700">Room for future actions</text>
<text x="1168" y="774" text-anchor="middle" fill="#52616F" font-family="Arial, sans-serif" font-size="14">without shrinking button grid</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

+151 -156
View File
@@ -1,175 +1,170 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="1120" viewBox="0 0 1600 1120">
<svg xmlns="http://www.w3.org/2000/svg" width="3840" height="2160" viewBox="0 0 3840 2160">
<defs>
<style>
.bg { fill: #f4f6f8; }
.panel { fill: #ffffff; stroke: #c9d1d9; stroke-width: 2; }
.panel-disabled { fill: #eef1f4; stroke: #c9d1d9; stroke-width: 2; }
.panel-active { fill: #ffffff; stroke: #2f80ed; stroke-width: 3; }
.preview { fill: #101820; stroke: #2f80ed; stroke-width: 2; }
.title { font-family: Arial; font-size: 25px; font-weight: 700; fill: #17202a; }
.subtitle { font-family: Arial; font-size: 16px; fill: #52616f; }
.section { font-family: Arial; font-size: 17px; font-weight: 700; fill: #17202a; }
.label { font-family: Arial; font-size: 14px; fill: #27313b; }
.muted { font-family: Arial; font-size: 13px; fill: #7b8794; }
.disabled-text { font-family: Arial; font-size: 14px; fill: #8a96a3; }
.mono { font-family: Courier; font-size: 12px; fill: #39434d; }
.mono-light { font-family: Courier; font-size: 12px; fill: #c9d9ea; }
.chip-ok { fill: #d9f5e5; stroke: #31a66a; }
.chip-warn { fill: #fff4d7; stroke: #d99000; }
.chip-off { fill: #e5e9ee; stroke: #a4afba; }
.button { fill: #f8fafc; stroke: #aab4bf; stroke-width: 1.5; }
.button-primary { fill: #e8f1ff; stroke: #2f80ed; stroke-width: 1.5; }
.button-disabled { fill: #e3e7eb; stroke: #c2cbd3; stroke-width: 1.5; }
.panel { fill: #ffffff; stroke: #c9d1d9; stroke-width: 3; }
.panel-disabled { fill: #eef1f4; stroke: #c9d1d9; stroke-width: 3; }
.panel-active { fill: #ffffff; stroke: #2f80ed; stroke-width: 4; }
.preview { fill: #101820; stroke: #2f80ed; stroke-width: 3; }
.title { font-family: Arial; font-size: 48px; font-weight: 700; fill: #17202a; }
.subtitle { font-family: Arial; font-size: 28px; fill: #52616f; }
.section { font-family: Arial; font-size: 32px; font-weight: 700; fill: #17202a; }
.label { font-family: Arial; font-size: 24px; fill: #27313b; }
.muted { font-family: Arial; font-size: 23px; fill: #7b8794; }
.disabled-text { font-family: Arial; font-size: 24px; fill: #8a96a3; }
.mono { font-family: Courier; font-size: 24px; fill: #39434d; }
.mono-light { font-family: Courier; font-size: 30px; fill: #c9d9ea; }
.chip-ok { fill: #d9f5e5; stroke: #31a66a; stroke-width: 2; }
.chip-warn { fill: #fff4d7; stroke: #d99000; stroke-width: 2; }
.chip-off { fill: #e5e9ee; stroke: #a4afba; stroke-width: 2; }
.button { fill: #ffffff; stroke: #aab4bf; stroke-width: 2; }
.button-primary { fill: #e8f1ff; stroke: #2f80ed; stroke-width: 2; }
.button-disabled { fill: #e3e7eb; stroke: #c2cbd3; stroke-width: 2; }
</style>
</defs>
<rect class="bg" x="0" y="0" width="1600" height="1120"/>
<rect class="bg" x="0" y="0" width="3840" height="2160"/>
<text class="title" x="40" y="50">kiwii-sdk-control-panel</text>
<text class="subtitle" x="40" y="78">AAR SDK validation control panel. Device components stay visible; unavailable components stay gray until capability detected.</text>
<text class="title" x="80" y="90">kiwii-sdk-control-panel</text>
<text class="subtitle" x="80" y="136">AAR SDK validation control panel. Components stay visible; unavailable surfaces stay gray until detected.</text>
<rect class="panel-active" x="40" y="105" width="1520" height="120" rx="8"/>
<text class="section" x="64" y="140">Global RuntimeHost Status</text>
<rect class="chip-warn" x="64" y="158" width="145" height="32" rx="16"/>
<text class="label" x="86" y="179">Bound: false</text>
<rect class="chip-off" x="228" y="158" width="175" height="32" rx="16"/>
<text class="label" x="250" y="179">Ping: NOT_BOUND</text>
<text class="muted" x="425" y="178">Last API: none</text>
<text class="muted" x="610" y="178">Last error: waiting for RuntimeHost bind</text>
<rect class="button-primary" x="64" y="200" width="85" height="32" rx="6"/>
<text class="label" x="92" y="221">Bind</text>
<rect class="button" x="160" y="200" width="95" height="32" rx="6"/>
<text class="label" x="187" y="221">Unbind</text>
<rect class="button" x="266" y="200" width="85" height="32" rx="6"/>
<text class="label" x="295" y="221">Ping</text>
<text class="mono" x="375" y="220">RuntimeHost bound enables component detection; component availability is still per-device.</text>
<rect class="panel-active" x="80" y="190" width="3680" height="230" rx="10"/>
<text class="section" x="130" y="246">Global RuntimeHost Status</text>
<text class="muted" x="130" y="288">RuntimeHost binding controls SDK access. Component availability remains detected per device.</text>
<rect class="panel-active" x="40" y="255" width="365" height="205" rx="8"/>
<text class="section" x="62" y="290">RuntimeHostStatusComponent</text>
<rect class="chip-ok" x="62" y="307" width="112" height="28" rx="14"/>
<text class="label" x="84" y="326">Active</text>
<text class="muted" x="62" y="357">Always interactive; owns bind state refresh.</text>
<rect class="button-primary" x="62" y="382" width="112" height="30" rx="6"/>
<text class="label" x="86" y="402">Bind Host</text>
<rect class="button" x="186" y="382" width="112" height="30" rx="6"/>
<text class="label" x="214" y="402">Runtime</text>
<rect class="button" x="62" y="420" width="112" height="30" rx="6"/>
<text class="label" x="90" y="440">Health</text>
<rect class="button" x="186" y="420" width="112" height="30" rx="6"/>
<text class="label" x="212" y="440">Lifecycle</text>
<rect class="chip-warn" x="130" y="320" width="230" height="54" rx="10"/>
<text class="label" x="170" y="355">Bound: false</text>
<rect class="chip-off" x="390" y="320" width="280" height="54" rx="10"/>
<text class="label" x="428" y="355">Ping: NOT_BOUND</text>
<text class="muted" x="720" y="355">Last API: none</text>
<text class="muted" x="980" y="355">Last error: waiting for RuntimeHost bind</text>
<rect class="panel-disabled" x="425" y="255" width="365" height="205" rx="8"/>
<text class="section" x="447" y="290">CameraComponent</text>
<rect class="chip-off" x="447" y="307" width="150" height="28" rx="14"/>
<text class="disabled-text" x="469" y="326">Gray: not detected</text>
<text class="disabled-text" x="447" y="357">Needs RuntimeHost bound + camera state available.</text>
<rect class="button" x="447" y="382" width="112" height="30" rx="6"/>
<text class="label" x="486" y="402">Detect</text>
<rect class="button-disabled" x="571" y="382" width="112" height="30" rx="6"/>
<text class="disabled-text" x="598" y="402">State</text>
<rect class="button-disabled" x="447" y="420" width="236" height="30" rx="6"/>
<text class="disabled-text" x="502" y="440">Open Full Camera View</text>
<rect class="button-primary" x="2980" y="260" width="180" height="64" rx="10"/>
<text class="label" x="3035" y="301">Bind</text>
<rect class="button" x="3190" y="260" width="200" height="64" rx="10"/>
<text class="label" x="3240" y="301">Unbind</text>
<rect class="button" x="3420" y="260" width="160" height="64" rx="10"/>
<text class="label" x="3470" y="301">Ping</text>
<rect class="panel-disabled" x="810" y="255" width="365" height="205" rx="8"/>
<text class="section" x="832" y="290">LeftHandleComponent</text>
<rect class="chip-off" x="832" y="307" width="150" height="28" rx="14"/>
<text class="disabled-text" x="854" y="326">Gray: not detected</text>
<text class="disabled-text" x="832" y="357">Needs left handle data.</text>
<rect class="button" x="832" y="382" width="112" height="30" rx="6"/>
<text class="label" x="871" y="402">Detect</text>
<rect class="button-disabled" x="956" y="382" width="112" height="30" rx="6"/>
<text class="disabled-text" x="984" y="402">IMU</text>
<rect class="button-disabled" x="832" y="420" width="112" height="30" rx="6"/>
<text class="disabled-text" x="864" y="440">HE Static</text>
<rect class="button-disabled" x="956" y="420" width="112" height="30" rx="6"/>
<text class="disabled-text" x="987" y="440">HE Stream</text>
<rect class="panel-active" x="80" y="470" width="875" height="300" rx="10"/>
<text class="section" x="130" y="528">RuntimeHostStatus</text>
<rect class="chip-ok" x="130" y="552" width="170" height="46" rx="10"/>
<text class="label" x="172" y="582">Active</text>
<text class="muted" x="130" y="642">Always interactive. Owns bind, runtime, health, and lifecycle checks.</text>
<rect class="button-primary" x="130" y="682" width="180" height="54" rx="10"/>
<text class="label" x="168" y="717">Bind Host</text>
<rect class="button" x="330" y="682" width="180" height="54" rx="10"/>
<text class="label" x="378" y="717">Runtime</text>
<rect class="button" x="530" y="682" width="150" height="54" rx="10"/>
<text class="label" x="573" y="717">Health</text>
<rect class="button" x="700" y="682" width="180" height="54" rx="10"/>
<text class="label" x="742" y="717">Lifecycle</text>
<rect class="panel-disabled" x="1195" y="255" width="365" height="205" rx="8"/>
<text class="section" x="1217" y="290">RightHandleComponent</text>
<rect class="chip-off" x="1217" y="307" width="150" height="28" rx="14"/>
<text class="disabled-text" x="1239" y="326">Gray: not detected</text>
<text class="disabled-text" x="1217" y="357">Needs right handle data.</text>
<rect class="button" x="1217" y="382" width="112" height="30" rx="6"/>
<text class="label" x="1256" y="402">Detect</text>
<rect class="button-disabled" x="1341" y="382" width="112" height="30" rx="6"/>
<text class="disabled-text" x="1369" y="402">IMU</text>
<rect class="button-disabled" x="1217" y="420" width="112" height="30" rx="6"/>
<text class="disabled-text" x="1249" y="440">HE Static</text>
<rect class="button-disabled" x="1341" y="420" width="112" height="30" rx="6"/>
<text class="disabled-text" x="1372" y="440">HE Stream</text>
<rect class="panel-disabled" x="995" y="470" width="875" height="300" rx="10"/>
<text class="section" x="1045" y="528">Camera</text>
<rect class="chip-off" x="1045" y="552" width="270" height="46" rx="10"/>
<text class="disabled-text" x="1085" y="582">Gray: not detected</text>
<text class="disabled-text" x="1045" y="642">Requires RuntimeHost binding and camera state availability.</text>
<rect class="button" x="1045" y="682" width="180" height="54" rx="10"/>
<text class="label" x="1100" y="717">Detect</text>
<rect class="button-disabled" x="1245" y="682" width="160" height="54" rx="10"/>
<text class="disabled-text" x="1293" y="717">State</text>
<rect class="button-disabled" x="1425" y="682" width="280" height="54" rx="10"/>
<text class="disabled-text" x="1460" y="717">Full Camera View</text>
<rect class="panel-disabled" x="40" y="485" width="365" height="205" rx="8"/>
<text class="section" x="62" y="520">BalanceBoardComponent</text>
<rect class="chip-off" x="62" y="537" width="150" height="28" rx="14"/>
<text class="disabled-text" x="84" y="556">Gray: not detected</text>
<text class="disabled-text" x="62" y="587">Needs balance board data.</text>
<rect class="button" x="62" y="612" width="112" height="30" rx="6"/>
<text class="label" x="101" y="632">Detect</text>
<rect class="button-disabled" x="186" y="612" width="112" height="30" rx="6"/>
<text class="disabled-text" x="216" y="632">State</text>
<rect class="button-disabled" x="62" y="650" width="112" height="30" rx="6"/>
<text class="disabled-text" x="93" y="670">Balance</text>
<rect class="button-disabled" x="186" y="650" width="112" height="30" rx="6"/>
<text class="disabled-text" x="217" y="670">Telemetry</text>
<rect class="panel-disabled" x="1910" y="470" width="875" height="300" rx="10"/>
<text class="section" x="1960" y="528">Left Handle</text>
<rect class="chip-off" x="1960" y="552" width="270" height="46" rx="10"/>
<text class="disabled-text" x="2000" y="582">Gray: not detected</text>
<text class="disabled-text" x="1960" y="642">Requires left handle data before IMU and haptics are enabled.</text>
<rect class="button" x="1960" y="682" width="180" height="54" rx="10"/>
<text class="label" x="2015" y="717">Detect</text>
<rect class="button-disabled" x="2160" y="682" width="150" height="54" rx="10"/>
<text class="disabled-text" x="2208" y="717">IMU</text>
<rect class="button-disabled" x="2330" y="682" width="180" height="54" rx="10"/>
<text class="disabled-text" x="2372" y="717">Haptics</text>
<rect class="panel-disabled" x="425" y="485" width="365" height="205" rx="8"/>
<text class="section" x="447" y="520">MotorComponent</text>
<rect class="chip-off" x="447" y="537" width="150" height="28" rx="14"/>
<text class="disabled-text" x="469" y="556">Gray: not detected</text>
<text class="disabled-text" x="447" y="587">Needs motor state/control state.</text>
<rect class="button" x="447" y="612" width="112" height="30" rx="6"/>
<text class="label" x="486" y="632">Detect</text>
<rect class="button-disabled" x="571" y="612" width="112" height="30" rx="6"/>
<text class="disabled-text" x="605" y="632">Set Kg</text>
<rect class="button-disabled" x="447" y="650" width="112" height="30" rx="6"/>
<text class="disabled-text" x="475" y="670">Set Mode</text>
<rect class="button-disabled" x="571" y="650" width="112" height="30" rx="6"/>
<text class="disabled-text" x="604" y="670">State</text>
<rect class="panel-disabled" x="2825" y="470" width="935" height="300" rx="10"/>
<text class="section" x="2875" y="528">Right Handle</text>
<rect class="chip-off" x="2875" y="552" width="270" height="46" rx="10"/>
<text class="disabled-text" x="2915" y="582">Gray: not detected</text>
<text class="disabled-text" x="2875" y="642">Requires right handle data before IMU and haptics are enabled.</text>
<rect class="button" x="2875" y="682" width="180" height="54" rx="10"/>
<text class="label" x="2930" y="717">Detect</text>
<rect class="button-disabled" x="3075" y="682" width="150" height="54" rx="10"/>
<text class="disabled-text" x="3123" y="717">IMU</text>
<rect class="button-disabled" x="3245" y="682" width="180" height="54" rx="10"/>
<text class="disabled-text" x="3287" y="717">Haptics</text>
<rect class="panel-disabled" x="810" y="485" width="365" height="205" rx="8"/>
<text class="section" x="832" y="520">TelemetrySafetyComponent</text>
<rect class="chip-off" x="832" y="537" width="125" height="28" rx="14"/>
<text class="disabled-text" x="854" y="556">Gray: bound</text>
<text class="disabled-text" x="832" y="587">Available after RuntimeHost bound.</text>
<rect class="button-disabled" x="832" y="612" width="112" height="30" rx="6"/>
<text class="disabled-text" x="858" y="632">Telemetry</text>
<rect class="button-disabled" x="956" y="612" width="112" height="30" rx="6"/>
<text class="disabled-text" x="987" y="632">Safety</text>
<rect class="button-disabled" x="832" y="650" width="112" height="30" rx="6"/>
<text class="disabled-text" x="852" y="670">Device Cmd</text>
<rect class="button-disabled" x="956" y="650" width="112" height="30" rx="6"/>
<text class="disabled-text" x="990" y="670">Trace</text>
<rect class="panel-disabled" x="80" y="820" width="875" height="300" rx="10"/>
<text class="section" x="130" y="878">Balance Board</text>
<rect class="chip-off" x="130" y="902" width="270" height="46" rx="10"/>
<text class="disabled-text" x="170" y="932">Gray: not detected</text>
<text class="disabled-text" x="130" y="992">Requires balance board data before telemetry views are enabled.</text>
<rect class="button" x="130" y="1032" width="180" height="54" rx="10"/>
<text class="label" x="185" y="1067">Detect</text>
<rect class="button-disabled" x="330" y="1032" width="170" height="54" rx="10"/>
<text class="disabled-text" x="383" y="1067">State</text>
<rect class="button-disabled" x="520" y="1032" width="200" height="54" rx="10"/>
<text class="disabled-text" x="570" y="1067">Balance</text>
<rect class="panel" x="1195" y="485" width="365" height="205" rx="8"/>
<text class="section" x="1217" y="520">SessionLogComponent</text>
<rect class="chip-ok" x="1217" y="537" width="112" height="28" rx="14"/>
<text class="label" x="1239" y="556">Active</text>
<text class="muted" x="1217" y="587">Records all SDK calls.</text>
<rect x="1217" y="612" width="305" height="58" rx="6" fill="#f8fafc" stroke="#d5dde5"/>
<text class="mono" x="1232" y="636">16:27:00 bind() -> false</text>
<text class="mono" x="1232" y="660">16:27:05 camera.detect -> skipped</text>
<rect class="panel-disabled" x="995" y="820" width="875" height="300" rx="10"/>
<text class="section" x="1045" y="878">Motor</text>
<rect class="chip-off" x="1045" y="902" width="270" height="46" rx="10"/>
<text class="disabled-text" x="1085" y="932">Gray: not detected</text>
<text class="disabled-text" x="1045" y="992">Requires motor state and motor control state.</text>
<rect class="button" x="1045" y="1032" width="180" height="54" rx="10"/>
<text class="label" x="1100" y="1067">Detect</text>
<rect class="button-disabled" x="1245" y="1032" width="180" height="54" rx="10"/>
<text class="disabled-text" x="1290" y="1067">Set Kg</text>
<rect class="button-disabled" x="1445" y="1032" width="180" height="54" rx="10"/>
<text class="disabled-text" x="1495" y="1067">Mode</text>
<rect class="panel" x="40" y="720" width="930" height="350" rx="8"/>
<text class="section" x="64" y="756">CameraComponent Detail View</text>
<text class="muted" x="64" y="786">When CameraComponent is selected, user can open full camera preview without hiding device cards.</text>
<rect class="preview" x="64" y="805" width="610" height="230" rx="8"/>
<text class="mono-light" x="268" y="925">Full Camera Preview</text>
<text class="mono-light" x="248" y="950">16:9 frame, full visible image</text>
<rect class="button-disabled" x="700" y="805" width="180" height="34" rx="6"/>
<text class="disabled-text" x="738" y="827">Camera State</text>
<rect class="button-disabled" x="700" y="852" width="180" height="34" rx="6"/>
<text class="disabled-text" x="736" y="874">Refresh Frame</text>
<rect class="button-disabled" x="700" y="899" width="180" height="34" rx="6"/>
<text class="disabled-text" x="730" y="921">Open Fullscreen</text>
<text class="mono" x="700" y="970">status: unavailable</text>
<text class="mono" x="700" y="996">reason: Host not bound</text>
<rect class="panel-disabled" x="1910" y="820" width="875" height="300" rx="10"/>
<text class="section" x="1960" y="878">Telemetry Safety</text>
<rect class="chip-off" x="1960" y="902" width="220" height="46" rx="10"/>
<text class="disabled-text" x="1998" y="932">Gray: bound</text>
<text class="disabled-text" x="1960" y="992">Available after RuntimeHost is bound.</text>
<rect class="button-disabled" x="1960" y="1032" width="210" height="54" rx="10"/>
<text class="disabled-text" x="2010" y="1067">Telemetry</text>
<rect class="button-disabled" x="2190" y="1032" width="170" height="54" rx="10"/>
<text class="disabled-text" x="2240" y="1067">Safety</text>
<rect class="button-disabled" x="2380" y="1032" width="220" height="54" rx="10"/>
<text class="disabled-text" x="2425" y="1067">Device Cmd</text>
<rect class="panel" x="1000" y="720" width="560" height="350" rx="8"/>
<text class="section" x="1024" y="756">Selected Component Result</text>
<text class="muted" x="1024" y="786">Latest call, params, status, return summary, error summary.</text>
<rect x="1024" y="805" width="500" height="150" rx="6" fill="#f8fafc" stroke="#d5dde5"/>
<text class="mono" x="1044" y="835">selected=CameraComponent</text>
<text class="mono" x="1044" y="862">call=detect</text>
<text class="mono" x="1044" y="889">status=idle</text>
<text class="mono" x="1044" y="916">result=waiting for RuntimeHost bind</text>
<rect class="panel" x="2825" y="820" width="935" height="300" rx="10"/>
<text class="section" x="2875" y="878">Session Log</text>
<rect class="chip-ok" x="2875" y="902" width="170" height="46" rx="10"/>
<text class="label" x="2918" y="932">Active</text>
<text class="muted" x="2875" y="992">Records SDK calls and skipped actions.</text>
<rect x="2875" y="1032" width="760" height="54" rx="10" fill="#ffffff" stroke="#d5dde5"/>
<text class="mono" x="2900" y="1067">16:27:05 camera.detect -> skipped</text>
<rect class="panel" x="80" y="1170" width="2390" height="850" rx="10"/>
<text class="section" x="130" y="1230">CameraComponent Detail View</text>
<text class="muted" x="130" y="1270">Selected camera detail keeps the component grid visible while showing a full preview and camera actions.</text>
<rect class="preview" x="130" y="1310" width="1520" height="580" rx="10"/>
<text class="mono-light" x="690" y="1588">Full Camera Preview</text>
<text class="mono-light" x="655" y="1636">16:9 frame, full visible image</text>
<rect class="button-disabled" x="1710" y="1310" width="320" height="64" rx="10"/>
<text class="disabled-text" x="1790" y="1352">Camera State</text>
<rect class="button-disabled" x="1710" y="1400" width="320" height="64" rx="10"/>
<text class="disabled-text" x="1780" y="1442">Refresh Frame</text>
<rect class="button-disabled" x="1710" y="1490" width="320" height="64" rx="10"/>
<text class="disabled-text" x="1775" y="1532">Open Fullscreen</text>
<text class="mono" x="1710" y="1645">status: unavailable</text>
<text class="mono" x="1710" y="1685">reason: Host not bound</text>
<rect class="panel" x="2530" y="1170" width="1230" height="850" rx="10"/>
<text class="section" x="2580" y="1230">Selected Component Result</text>
<text class="muted" x="2580" y="1270">Latest call, params, status, result, and error summary.</text>
<rect x="2580" y="1310" width="1040" height="210" rx="10" fill="#ffffff" stroke="#d5dde5"/>
<text class="mono" x="2610" y="1360">selected=CameraComponent</text>
<text class="mono" x="2610" y="1405">call=detect</text>
<text class="mono" x="2610" y="1450">status=idle</text>
<text class="mono" x="2610" y="1495">result=waiting for RuntimeHost bind</text>
<rect x="2580" y="1570" width="1040" height="340" rx="10" fill="#ffffff" stroke="#d5dde5"/>
<text class="mono" x="2610" y="1620">16:27:00 bind() -> false</text>
<text class="mono" x="2610" y="1665">16:27:05 camera.detect -> skipped</text>
<text class="mono" x="2610" y="1710">16:27:08 motor.detect -> skipped</text>
</svg>

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB