Extract shared editor CSS and fix vehicle nav spacing

Move duplicated preview, spinner, navigation, and side-button styles
from VehicleEditor, ActorEditor, and PlantEditor into a shared
editor-common.css. Standardize class names (nav-index, nav-name,
side-btn) and fix VehicleEditor part-info min-width (100px → 150px)
to match the other editors.
This commit is contained in:
Christian Semmler 2026-02-14 08:56:39 -08:00
parent 02949aab96
commit e1b9f2e696
No known key found for this signature in database
GPG Key ID: 086DAA1360BEEE5C
4 changed files with 140 additions and 348 deletions

View File

@ -8,6 +8,7 @@
import NavButton from '../NavButton.svelte';
import ResetButton from '../ResetButton.svelte';
import EditorTooltip from '../EditorTooltip.svelte';
import './editor-common.css';
export let slot;
export let onUpdate = () => {};
@ -328,15 +329,15 @@
<div class="part-nav">
<NavButton direction="left" onclick={prevActor} />
<div class="part-info">
<span class="actor-index">{actorIndex + 1} / {ActorInfoInit.length}</span>
<span class="actor-name">{actorName}</span>
<span class="nav-index">{actorIndex + 1} / {ActorInfoInit.length}</span>
<span class="nav-name">{actorName}</span>
</div>
<NavButton direction="right" onclick={nextActor} />
</div>
{#if vehicleInfo}
<button
type="button"
class="vehicle-toggle-btn"
class="side-btn"
class:active={showVehicle}
onclick={() => { showVehicle = !showVehicle; }}
title={showVehicle ? 'Show without vehicle' : `Show with ${vehicleName}`}
@ -355,127 +356,3 @@
</div>
</EditorTooltip>
<style>
.preview-container {
position: relative;
}
canvas {
display: block;
border-radius: 8px;
cursor: grab;
max-width: 100%;
}
canvas:active {
cursor: grabbing;
}
canvas:focus {
outline: none;
}
canvas.hidden {
visibility: hidden;
}
.preview-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: var(--color-bg-input);
border-radius: 8px;
}
.preview-overlay.error {
color: var(--color-error, #e74c3c);
font-size: 0.75em;
padding: 12px;
text-align: center;
}
.spinner {
width: 32px;
height: 32px;
border-radius: 50%;
background:
radial-gradient(transparent 55%, transparent 56%),
conic-gradient(var(--color-primary, #FFD700) 0deg 90deg, var(--color-border-dark, #333) 90deg 360deg);
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.part-nav-wrapper {
position: relative;
margin-top: 10px;
}
.part-nav {
display: flex;
align-items: center;
gap: 12px;
}
.part-info {
text-align: center;
min-width: 150px;
}
.actor-index {
display: block;
font-size: 0.7em;
color: var(--color-text-muted);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.actor-name {
display: block;
font-size: 0.9em;
color: var(--color-text-light);
}
.vehicle-toggle-btn {
position: absolute;
right: -36px;
top: 50%;
transform: translateY(-50%);
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
padding: 0;
background: var(--color-bg-input);
border: 1px solid var(--color-border-medium);
border-radius: 6px;
color: var(--color-text-light);
cursor: pointer;
transition: all 0.2s ease;
}
.vehicle-toggle-btn.active {
border-color: var(--color-primary);
color: var(--color-primary);
}
@media (hover: hover) {
.vehicle-toggle-btn:hover {
border-color: var(--color-primary);
color: var(--color-primary);
}
}
.reset-container {
height: 1.6em;
}
</style>

View File

@ -12,6 +12,7 @@
import NavButton from '../NavButton.svelte';
import ResetButton from '../ResetButton.svelte';
import EditorTooltip from '../EditorTooltip.svelte';
import './editor-common.css';
export let slot;
export let onUpdate = () => {};
@ -272,8 +273,8 @@
<div class="part-nav">
<NavButton direction="left" onclick={prevPlant} />
<div class="part-info">
<span class="plant-index">{plantIndex + 1} / {PLANT_COUNT}</span>
<span class="plant-name">{colorName} {variantName}</span>
<span class="nav-index">{plantIndex + 1} / {PLANT_COUNT}</span>
<span class="nav-name">{colorName} {variantName}</span>
</div>
<NavButton direction="right" onclick={nextPlant} />
</div>
@ -286,95 +287,3 @@
</div>
</EditorTooltip>
<style>
.preview-container {
position: relative;
}
canvas {
display: block;
border-radius: 8px;
cursor: grab;
max-width: 100%;
}
canvas:active {
cursor: grabbing;
}
canvas:focus {
outline: none;
}
canvas.hidden {
visibility: hidden;
}
.preview-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: var(--color-bg-input);
border-radius: 8px;
}
.preview-overlay.error {
color: var(--color-error, #e74c3c);
font-size: 0.75em;
padding: 12px;
text-align: center;
}
.spinner {
width: 32px;
height: 32px;
border-radius: 50%;
background:
radial-gradient(transparent 55%, transparent 56%),
conic-gradient(var(--color-primary, #FFD700) 0deg 90deg, var(--color-border-dark, #333) 90deg 360deg);
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.part-nav-wrapper {
margin-top: 10px;
}
.part-nav {
display: flex;
align-items: center;
gap: 12px;
}
.part-info {
text-align: center;
min-width: 150px;
}
.plant-index {
display: block;
font-size: 0.7em;
color: var(--color-text-muted);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.plant-name {
display: block;
font-size: 0.9em;
color: var(--color-text-light);
}
.reset-container {
height: 1.6em;
}
</style>

View File

@ -18,6 +18,7 @@
import ResetButton from '../ResetButton.svelte';
import EditorTooltip from '../EditorTooltip.svelte';
import TexturePickerModal from './TexturePickerModal.svelte';
import './editor-common.css';
export let slot;
export let onUpdate = () => {};
@ -353,15 +354,15 @@
<div class="part-nav">
<NavButton direction="left" onclick={prevPart} />
<div class="part-info">
<span class="vehicle-name">{VehicleNames[vehicle]}</span>
<span class="part-name">{currentPart?.label || 'Unknown'}</span>
<span class="nav-index">{VehicleNames[vehicle]}</span>
<span class="nav-name">{currentPart?.label || 'Unknown'}</span>
</div>
<NavButton direction="right" onclick={nextPart} />
</div>
{#if textureInfo}
<button
type="button"
class="texture-btn"
class="side-btn"
class:disabled={!canEditTexture}
onclick={openTexturePicker}
disabled={!canEditTexture}
@ -391,127 +392,3 @@
/>
{/if}
<style>
.preview-container {
position: relative;
}
canvas {
display: block;
border-radius: 8px;
cursor: grab;
max-width: 100%;
}
canvas:active {
cursor: grabbing;
}
canvas:focus {
outline: none;
}
canvas.hidden {
visibility: hidden;
}
.preview-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: var(--color-bg-input);
border-radius: 8px;
}
.preview-overlay.error {
color: var(--color-error, #e74c3c);
font-size: 0.75em;
padding: 12px;
text-align: center;
}
.spinner {
width: 32px;
height: 32px;
border-radius: 50%;
background:
radial-gradient(transparent 55%, transparent 56%),
conic-gradient(var(--color-primary, #FFD700) 0deg 90deg, var(--color-border-dark, #333) 90deg 360deg);
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.part-nav-wrapper {
position: relative;
margin-top: 10px;
}
.part-nav {
display: flex;
align-items: center;
gap: 12px;
}
.part-info {
text-align: center;
min-width: 100px;
}
.vehicle-name {
display: block;
font-size: 0.7em;
color: var(--color-text-muted);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.part-name {
display: block;
font-size: 0.9em;
color: var(--color-text-light);
}
.reset-container {
height: 1.6em;
}
.texture-btn {
position: absolute;
right: -36px;
top: 50%;
transform: translateY(-50%);
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
padding: 0;
background: var(--color-bg-input);
border: 1px solid var(--color-border-medium);
border-radius: 6px;
color: var(--color-text-light);
cursor: pointer;
transition: all 0.2s ease;
}
@media (hover: hover) {
.texture-btn:hover:not(.disabled) {
border-color: var(--color-primary);
color: var(--color-primary);
}
}
.texture-btn.disabled {
opacity: 0.35;
cursor: not-allowed;
}
</style>

View File

@ -0,0 +1,129 @@
/* Shared styles for VehicleEditor, ActorEditor, PlantEditor */
.preview-container {
position: relative;
}
.preview-container canvas {
display: block;
border-radius: 8px;
cursor: grab;
max-width: 100%;
}
.preview-container canvas:active {
cursor: grabbing;
}
.preview-container canvas:focus {
outline: none;
}
.preview-container canvas.hidden {
visibility: hidden;
}
.preview-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: var(--color-bg-input);
border-radius: 8px;
}
.preview-overlay.error {
color: var(--color-error, #e74c3c);
font-size: 0.75em;
padding: 12px;
text-align: center;
}
.spinner {
width: 32px;
height: 32px;
border-radius: 50%;
background:
radial-gradient(transparent 55%, transparent 56%),
conic-gradient(var(--color-primary, #FFD700) 0deg 90deg, var(--color-border-dark, #333) 90deg 360deg);
animation: editor-spin 1s linear infinite;
}
@keyframes editor-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.part-nav-wrapper {
position: relative;
margin-top: 10px;
}
.part-nav {
display: flex;
align-items: center;
gap: 12px;
}
.part-info {
text-align: center;
min-width: 150px;
}
.nav-index {
display: block;
font-size: 0.7em;
color: var(--color-text-muted);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.nav-name {
display: block;
font-size: 0.9em;
color: var(--color-text-light);
}
.reset-container {
height: 1.6em;
}
.side-btn {
position: absolute;
right: -36px;
top: 50%;
transform: translateY(-50%);
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
padding: 0;
background: var(--color-bg-input);
border: 1px solid var(--color-border-medium);
border-radius: 6px;
color: var(--color-text-light);
cursor: pointer;
transition: all 0.2s ease;
}
@media (hover: hover) {
.side-btn:hover:not(.disabled) {
border-color: var(--color-primary);
color: var(--color-primary);
}
}
.side-btn.disabled {
opacity: 0.35;
cursor: not-allowed;
}
.side-btn.active {
border-color: var(--color-primary);
color: var(--color-primary);
}