feat: promote command grid builder
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
<script lang="ts">
|
||||
import ItemIcon from '$lib/components/ItemIcon.svelte';
|
||||
|
||||
export type MatrixCell = {
|
||||
id: string;
|
||||
label: string;
|
||||
name: string;
|
||||
meta: string;
|
||||
summary: string;
|
||||
iconUrl?: string;
|
||||
};
|
||||
|
||||
let {
|
||||
active,
|
||||
doctrine,
|
||||
abilities,
|
||||
weapons,
|
||||
gear,
|
||||
protocol,
|
||||
configured,
|
||||
onselect
|
||||
}: {
|
||||
active: string;
|
||||
doctrine: MatrixCell;
|
||||
abilities: MatrixCell[];
|
||||
weapons: MatrixCell[];
|
||||
gear: MatrixCell[];
|
||||
protocol: MatrixCell;
|
||||
configured: boolean;
|
||||
onselect: (id: string) => void;
|
||||
} = $props();
|
||||
|
||||
const selected = (cell: MatrixCell) =>
|
||||
active === cell.id
|
||||
|| (cell.id.startsWith('ability:') && active.startsWith('chip:')
|
||||
&& Math.floor(Number(active.split(':')[1]) / 3) === Number(cell.id.split(':')[1]));
|
||||
</script>
|
||||
|
||||
<section class="loadout-matrix" aria-label="Loadout matrix">
|
||||
<header>
|
||||
<span>LOADOUT MATRIX</span>
|
||||
<b class:ready={configured}>{configured ? 'COMBAT READY' : 'CONFIGURATION INCOMPLETE'}</b>
|
||||
</header>
|
||||
|
||||
<div class="matrix-section doctrine-section">
|
||||
<small class="section-label">DOCTRINE · ROOT CHOICE</small>
|
||||
<button
|
||||
type="button"
|
||||
class="doctrine-cell"
|
||||
class:active={selected(doctrine)}
|
||||
aria-pressed={selected(doctrine)}
|
||||
onclick={() => onselect(doctrine.id)}
|
||||
>
|
||||
<ItemIcon src={doctrine.iconUrl} alt="" className="matrix-icon" />
|
||||
<span><small>{doctrine.label}</small><strong>{doctrine.name}</strong><em>{doctrine.summary}</em></span>
|
||||
<i aria-hidden="true"></i>
|
||||
</button>
|
||||
<div class="supply-line"><span>SUPPLIES 3 ABILITIES</span></div>
|
||||
<div class="ability-cells">
|
||||
{#each abilities as cell}
|
||||
<button type="button" class:active={selected(cell)} aria-pressed={selected(cell)} onclick={() => onselect(cell.id)}>
|
||||
<ItemIcon src={cell.iconUrl} alt="" className="matrix-icon" />
|
||||
<span><small>{cell.label}</small><strong>{cell.name}</strong><em>{cell.summary}</em></span>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="matrix-section">
|
||||
<small class="section-label">WEAPONS · PRIMARY + SECONDARY</small>
|
||||
<div class="equipment-cells">
|
||||
{#each weapons as cell}
|
||||
<button type="button" class:active={selected(cell)} aria-pressed={selected(cell)} onclick={() => onselect(cell.id)}>
|
||||
<ItemIcon src={cell.iconUrl} alt="" className="matrix-icon" />
|
||||
<span><small>{cell.label}</small><strong>{cell.name}</strong><em>{cell.summary}</em></span>
|
||||
<i aria-hidden="true"></i>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="matrix-section">
|
||||
<small class="section-label">GEAR · 6 POSITIONS</small>
|
||||
<div class="equipment-cells gear-cells">
|
||||
{#each gear as cell}
|
||||
<button type="button" class:active={selected(cell)} aria-pressed={selected(cell)} onclick={() => onselect(cell.id)}>
|
||||
<ItemIcon src={cell.iconUrl} alt="" className="matrix-icon" />
|
||||
<span><small>{cell.label}</small><strong>{cell.name}</strong><em>{cell.summary}</em></span>
|
||||
<i aria-hidden="true"></i>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="matrix-section protocol-section">
|
||||
<small class="section-label">AGENT SYSTEM · ONE OS PROTOCOL</small>
|
||||
<button type="button" class:active={selected(protocol)} aria-pressed={selected(protocol)} onclick={() => onselect(protocol.id)}>
|
||||
<ItemIcon src={protocol.iconUrl} alt="" className="matrix-icon" />
|
||||
<span><small>{protocol.label}</small><strong>{protocol.name}</strong><em>{protocol.summary}</em></span>
|
||||
<i aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.loadout-matrix{min-width:0;border:1px solid var(--shd-border);background:var(--shd-surface)}
|
||||
.loadout-matrix>header{min-height:40px;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:0 10px;border-bottom:1px solid var(--shd-border);background:#0c0f10;color:var(--shd-text-muted);font-size:var(--shd-type-telemetry);font-weight:900;letter-spacing:.08em}
|
||||
.loadout-matrix>header b{color:var(--shd-warning);font-size:9px;text-align:right}.loadout-matrix>header b.ready{color:var(--shd-success)}
|
||||
.matrix-section{padding:5px;border-bottom:1px solid var(--shd-border)}.matrix-section:last-child{border-bottom:0}
|
||||
.section-label{display:block;padding:2px 3px 5px;color:var(--shd-text-dim);font-size:9px;font-weight:900;letter-spacing:.09em}
|
||||
.doctrine-cell,.equipment-cells button,.ability-cells button,.protocol-section>button{min-width:0;display:grid;grid-template-columns:34px minmax(0,1fr) 3px;align-items:center;gap:7px;padding:7px;border:1px solid var(--shd-border-soft);background:var(--shd-builder-canvas);color:var(--shd-text);text-align:left}
|
||||
.doctrine-cell{width:100%;min-height:76px;grid-template-columns:42px minmax(0,1fr) 3px}.doctrine-cell :global(.matrix-icon){width:40px;height:40px}
|
||||
:global(.matrix-icon){width:30px;height:30px;object-fit:contain}
|
||||
button>span{min-width:0;display:grid;gap:2px}button small,button em{overflow:hidden;color:var(--shd-text-dim);font-size:9px;font-style:normal;letter-spacing:.04em;text-overflow:ellipsis;white-space:nowrap}button strong{overflow:hidden;font-size:11px;text-overflow:ellipsis;white-space:nowrap}button>i{align-self:stretch;background:var(--quality-high-end)}
|
||||
button:hover,button:focus-visible{border-color:var(--shd-border-strong);background:var(--shd-surface-active);outline:none}button.active{border-color:var(--shd-builder-selection-border);background:var(--shd-builder-selection);box-shadow:inset 2px 0 var(--shd-orange)}
|
||||
.supply-line{height:22px;display:grid;place-items:center;background:linear-gradient(90deg,transparent 49.7%,var(--shd-orange) 49.7% 50.3%,transparent 50.3%)}.supply-line span{padding:0 6px;background:var(--shd-surface);color:var(--shd-orange);font-size:8px;font-weight:900;letter-spacing:.08em}
|
||||
.ability-cells{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:3px}.ability-cells button{min-height:68px;grid-template-columns:25px minmax(0,1fr);padding:6px}.ability-cells :global(.matrix-icon){width:24px;height:24px}
|
||||
.equipment-cells{display:grid;grid-template-columns:1fr 1fr;gap:3px}.equipment-cells button{min-height:69px}.protocol-section>button{width:100%;min-height:68px}
|
||||
button:focus-visible{outline:2px solid var(--shd-focus-ring);outline-offset:2px}
|
||||
@media(max-width:1240px){.ability-cells{grid-template-columns:1fr}.ability-cells button{min-height:48px}}
|
||||
@media(max-width:800px){.ability-cells{grid-template-columns:repeat(3,minmax(0,1fr))}}
|
||||
@media(max-width:520px){.ability-cells{grid-template-columns:1fr}.equipment-cells{grid-template-columns:1fr 1fr}}
|
||||
</style>
|
||||
Reference in New Issue
Block a user