[FEAT] Improved UI
This commit is contained in:
@@ -29,102 +29,132 @@
|
||||
</div>
|
||||
</Teleport>
|
||||
|
||||
<div class="space-y-6 w-full max-w-full overflow-hidden">
|
||||
<div class="bg-cyan-50 dark:bg-cyan-900/20 rounded-lg p-3 border border-cyan-100 dark:border-cyan-800/50 flex items-start gap-3">
|
||||
<i class="fas fa-info-circle text-cyan-600 dark:text-cyan-400 mt-0.5 flex-shrink-0"></i>
|
||||
<p class="text-sm text-cyan-800 dark:text-cyan-200"><span class="font-semibold">Tip:</span> Right-click any sprite to open the context menu for quick actions: add, replace, or remove sprites.</p>
|
||||
<div class="space-y-3 w-full max-w-full overflow-hidden">
|
||||
<!-- Compact tip banner -->
|
||||
<div class="bg-cyan-50/80 dark:bg-cyan-900/20 rounded-md px-3 py-2 border border-cyan-100 dark:border-cyan-800/50 flex items-center gap-2">
|
||||
<i class="fas fa-lightbulb text-xs text-cyan-500 dark:text-cyan-400"></i>
|
||||
<p class="text-xs text-cyan-700 dark:text-cyan-300"><span class="font-medium">Tip:</span> Right-click sprites for quick actions • Hold Ctrl/Cmd to multi-select • Delete key removes selection</p>
|
||||
</div>
|
||||
|
||||
<section class="w-full bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-1 shadow-sm">
|
||||
<div class="flex flex-wrap items-center gap-1">
|
||||
<!-- Toggles Group -->
|
||||
<div class="flex items-center gap-1 p-1">
|
||||
<label class="flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors" title="Toggle Multi-Select Mode">
|
||||
<input id="multi-select-mode" type="checkbox" v-model="isMultiSelectMode" class="w-4 h-4 rounded text-blue-600 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600" />
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-200">Multi-Select</span>
|
||||
</label>
|
||||
<label class="flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors" title="Show Selection Borders">
|
||||
<input id="show-active-border" type="checkbox" v-model="showActiveBorder" class="w-4 h-4 rounded text-blue-600 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600" />
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-200">Borders</span>
|
||||
</label>
|
||||
<div class="w-px h-4 bg-gray-200 dark:bg-gray-700 mx-1"></div>
|
||||
<label class="flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors" title="Pixel Perfect">
|
||||
<input id="pixel-perfect" type="checkbox" v-model="settingsStore.pixelPerfect" class="w-4 h-4 rounded text-blue-600 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600" />
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-200">Pixel Perfect</span>
|
||||
</label>
|
||||
<label class="flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors" title="Cell Swapping">
|
||||
<input id="allow-cell-swap" type="checkbox" v-model="allowCellSwap" class="w-4 h-4 rounded text-blue-600 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600" />
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-200">Swap</span>
|
||||
</label>
|
||||
<label class="flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors" title="Compare Sprites">
|
||||
<input id="show-all-sprites" type="checkbox" v-model="showAllSprites" class="w-4 h-4 rounded text-blue-600 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600" />
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-200">Compare</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="w-px h-6 bg-gray-200 dark:bg-gray-700 mx-1"></div>
|
||||
|
||||
<!-- Spacing & Grid Group -->
|
||||
<div class="flex items-center gap-1 p-1">
|
||||
<label class="flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors" title="Negative Spacing">
|
||||
<input id="negative-spacing" type="checkbox" v-model="settingsStore.negativeSpacingEnabled" class="w-4 h-4 rounded text-blue-600 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600" />
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-200">Spacing</span>
|
||||
</label>
|
||||
<label class="flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors" title="Checkerboard Background">
|
||||
<input id="checkerboard" type="checkbox" v-model="settingsStore.checkerboardEnabled" class="w-4 h-4 rounded text-blue-600 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600" />
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-200">Grid</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="w-px h-6 bg-gray-200 dark:bg-gray-700 mx-1"></div>
|
||||
|
||||
<!-- Background Color -->
|
||||
<div class="flex items-center gap-2 px-3 py-2">
|
||||
<label for="bg-color" class="text-sm font-medium text-gray-600 dark:text-gray-400">Bg:</label>
|
||||
<div class="flex items-center gap-2">
|
||||
<select
|
||||
id="bg-color"
|
||||
v-model="bgSelectValue"
|
||||
class="px-2 py-1 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 dark:text-gray-200 text-sm focus:ring-2 focus:ring-blue-500 outline-none transition-all cursor-pointer hover:border-gray-400 dark:hover:border-gray-500"
|
||||
<!-- Compact Toolbar -->
|
||||
<section class="w-full bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 shadow-sm">
|
||||
<div class="flex flex-wrap items-center gap-0.5 px-1.5 py-1">
|
||||
<!-- Selection Tools -->
|
||||
<div class="flex items-center">
|
||||
<Tooltip text="Select multiple sprites at once. Also works with Ctrl/Cmd+Click.">
|
||||
<button
|
||||
@click="isMultiSelectMode = !isMultiSelectMode"
|
||||
:class="['px-2 py-1 rounded text-xs font-medium transition-all cursor-pointer', isMultiSelectMode ? 'bg-blue-100 dark:bg-blue-900/40 text-blue-700 dark:text-blue-300' : 'text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700']"
|
||||
>
|
||||
<option value="transparent">Transparent</option>
|
||||
<option value="#ffffff">White</option>
|
||||
<option value="#000000">Black</option>
|
||||
<option value="#f9fafb">Light Gray</option>
|
||||
<option value="custom">Custom</option>
|
||||
</select>
|
||||
<div v-if="bgSelectValue === 'custom'" class="relative w-6 h-6 rounded-full overflow-hidden border border-gray-300 dark:border-gray-600 shadow-sm">
|
||||
<input type="color" v-model="customColor" @input="settingsStore.setBackgroundColor(customColor)" class="absolute -top-2 -left-2 w-10 h-10 cursor-pointer p-0 border-0" />
|
||||
</div>
|
||||
<i class="fas fa-object-group mr-1"></i>Multi
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip text="Show blue borders around selected sprites for visibility.">
|
||||
<button
|
||||
@click="showActiveBorder = !showActiveBorder"
|
||||
:class="['px-2 py-1 rounded text-xs font-medium transition-all cursor-pointer', showActiveBorder ? 'bg-blue-100 dark:bg-blue-900/40 text-blue-700 dark:text-blue-300' : 'text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700']"
|
||||
>
|
||||
<i class="fas fa-vector-square mr-1"></i>Borders
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div class="w-px h-4 bg-gray-200 dark:bg-gray-600 mx-1"></div>
|
||||
|
||||
<!-- Display Options -->
|
||||
<div class="flex items-center">
|
||||
<Tooltip text="Disable anti-aliasing for crisp pixel art rendering.">
|
||||
<button
|
||||
@click="settingsStore.pixelPerfect = !settingsStore.pixelPerfect"
|
||||
:class="['px-2 py-1 rounded text-xs font-medium transition-all cursor-pointer', settingsStore.pixelPerfect ? 'bg-green-100 dark:bg-green-900/40 text-green-700 dark:text-green-300' : 'text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700']"
|
||||
>
|
||||
<i class="fas fa-th mr-1"></i>Pixel
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip text="Drag sprites between cells to swap their positions.">
|
||||
<button
|
||||
@click="allowCellSwap = !allowCellSwap"
|
||||
:class="['px-2 py-1 rounded text-xs font-medium transition-all cursor-pointer', allowCellSwap ? 'bg-purple-100 dark:bg-purple-900/40 text-purple-700 dark:text-purple-300' : 'text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700']"
|
||||
>
|
||||
<i class="fas fa-exchange-alt mr-1"></i>Swap
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip text="Show ghost overlays of all sprites for alignment comparison.">
|
||||
<button
|
||||
@click="showAllSprites = !showAllSprites"
|
||||
:class="['px-2 py-1 rounded text-xs font-medium transition-all cursor-pointer', showAllSprites ? 'bg-amber-100 dark:bg-amber-900/40 text-amber-700 dark:text-amber-300' : 'text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700']"
|
||||
>
|
||||
<i class="fas fa-clone mr-1"></i>Compare
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div class="w-px h-4 bg-gray-200 dark:bg-gray-600 mx-1"></div>
|
||||
|
||||
<!-- Canvas Options -->
|
||||
<div class="flex items-center">
|
||||
<Tooltip text="Add padding around sprites to prevent bleeding artifacts.">
|
||||
<button
|
||||
@click="settingsStore.negativeSpacingEnabled = !settingsStore.negativeSpacingEnabled"
|
||||
:class="['px-2 py-1 rounded text-xs font-medium transition-all cursor-pointer', settingsStore.negativeSpacingEnabled ? 'bg-teal-100 dark:bg-teal-900/40 text-teal-700 dark:text-teal-300' : 'text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700']"
|
||||
>
|
||||
<i class="fas fa-compress-alt mr-1"></i>Spacing
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip text="Show checkerboard pattern to visualize transparent areas.">
|
||||
<button
|
||||
@click="settingsStore.checkerboardEnabled = !settingsStore.checkerboardEnabled"
|
||||
:class="['px-2 py-1 rounded text-xs font-medium transition-all cursor-pointer', settingsStore.checkerboardEnabled ? 'bg-gray-200 dark:bg-gray-600 text-gray-700 dark:text-gray-200' : 'text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700']"
|
||||
>
|
||||
<i class="fas fa-chess-board mr-1"></i>Grid
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip text="Display X,Y offset coordinates on each sprite.">
|
||||
<button
|
||||
@click="showOffsetLabels = !showOffsetLabels"
|
||||
:class="['px-2 py-1 rounded text-xs font-medium transition-all cursor-pointer', showOffsetLabels ? 'bg-cyan-100 dark:bg-cyan-900/40 text-cyan-700 dark:text-cyan-300' : 'text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700']"
|
||||
>
|
||||
<i class="fas fa-tag mr-1"></i>Labels
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div class="w-px h-4 bg-gray-200 dark:bg-gray-600 mx-1"></div>
|
||||
|
||||
<!-- Background Color (Compact) -->
|
||||
<div class="flex items-center gap-1.5 px-1">
|
||||
<span class="text-[10px] font-medium text-gray-400 uppercase">Bg</span>
|
||||
<select v-model="bgSelectValue" class="px-1.5 py-0.5 text-xs border border-gray-200 dark:border-gray-600 rounded bg-gray-50 dark:bg-gray-700 dark:text-gray-200 outline-none cursor-pointer hover:border-gray-300">
|
||||
<option value="transparent">None</option>
|
||||
<option value="#ffffff">White</option>
|
||||
<option value="#000000">Black</option>
|
||||
<option value="#f9fafb">Gray</option>
|
||||
<option value="custom">Pick</option>
|
||||
</select>
|
||||
<div v-if="bgSelectValue === 'custom'" class="relative w-5 h-5 rounded overflow-hidden border border-gray-300 dark:border-gray-600">
|
||||
<input type="color" v-model="customColor" @input="settingsStore.setBackgroundColor(customColor)" class="absolute -top-1 -left-1 w-8 h-8 cursor-pointer p-0 border-0" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-1"></div>
|
||||
|
||||
<!-- Zoom Controls -->
|
||||
<div class="flex items-center bg-gray-100 dark:bg-gray-700 rounded-lg p-1 mr-1">
|
||||
<button @click="zoomOut" class="p-1.5 hover:bg-white dark:hover:bg-gray-600 text-gray-600 dark:text-gray-300 rounded-md transition-all" title="Zoom Out">
|
||||
<i class="fas fa-minus text-xs"></i>
|
||||
<!-- Zoom Controls (Compact) -->
|
||||
<div class="flex items-center bg-gray-100 dark:bg-gray-700 rounded px-1 py-0.5">
|
||||
<button @click="zoomOut" class="p-1 hover:bg-white dark:hover:bg-gray-600 text-gray-500 dark:text-gray-400 rounded transition-all cursor-pointer" title="Zoom Out">
|
||||
<i class="fas fa-search-minus text-[10px]"></i>
|
||||
</button>
|
||||
<span class="px-2 text-xs font-mono text-gray-600 dark:text-gray-300 min-w-[3ch] text-center">{{ Math.round(zoom * 100) }}%</span>
|
||||
<button @click="zoomIn" class="p-1.5 hover:bg-white dark:hover:bg-gray-600 text-gray-600 dark:text-gray-300 rounded-md transition-all" title="Zoom In">
|
||||
<i class="fas fa-plus text-xs"></i>
|
||||
<span class="px-1.5 text-[10px] font-mono text-gray-500 dark:text-gray-400 min-w-[4ch] text-center">{{ Math.round(zoom * 100) }}%</span>
|
||||
<button @click="zoomIn" class="p-1 hover:bg-white dark:hover:bg-gray-600 text-gray-500 dark:text-gray-400 rounded transition-all cursor-pointer" title="Zoom In">
|
||||
<i class="fas fa-search-plus text-[10px]"></i>
|
||||
</button>
|
||||
<div class="w-px h-4 bg-gray-300 dark:bg-gray-600 mx-1"></div>
|
||||
<button @click="resetZoom" class="p-1.5 hover:bg-white dark:hover:bg-gray-600 text-gray-600 dark:text-gray-300 rounded-md transition-all" title="Reset Zoom">
|
||||
<i class="fas fa-expand text-xs"></i>
|
||||
<button @click="resetZoom" class="p-1 hover:bg-white dark:hover:bg-gray-600 text-gray-500 dark:text-gray-400 rounded transition-all cursor-pointer ml-0.5" title="Reset Zoom">
|
||||
<i class="fas fa-compress-arrows-alt text-[10px]"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Offset Labels Toggle -->
|
||||
<label class="flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors border-l border-gray-100 dark:border-gray-700" title="Show Offset Labels">
|
||||
<input id="show-offset-labels" type="checkbox" v-model="showOffsetLabels" class="w-4 h-4 rounded text-blue-600 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600" />
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-200">Labels</span>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="relative bg-white dark:bg-gray-800 border-2 border-gray-200 dark:border-gray-700 rounded-2xl shadow-lg overflow-auto max-h-[calc(100vh-400px)] min-h-[500px] w-full">
|
||||
<div class="relative bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl shadow-sm overflow-auto max-h-[calc(100vh-340px)] min-h-[400px] w-full">
|
||||
<div class="canvas-container touch-manipulation relative inline-block min-w-full">
|
||||
<div
|
||||
ref="gridContainerRef"
|
||||
@@ -267,6 +297,7 @@
|
||||
import { useZoom } from '@/composables/useZoom';
|
||||
import { useDragSprite } from '@/composables/useDragSprite';
|
||||
import { useFileDrop } from '@/composables/useFileDrop';
|
||||
import Tooltip from '@/components/utilities/Tooltip.vue';
|
||||
|
||||
import type { Layer } from '@/types/sprites';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user