fix: add is-active state to weapon and summon units
This commit is contained in:
parent
2f0b67cb44
commit
ff7199fbbb
2 changed files with 55 additions and 0 deletions
|
|
@ -9,6 +9,7 @@
|
||||||
import { getSummonImage } from '$lib/features/database/detail/image'
|
import { getSummonImage } from '$lib/features/database/detail/image'
|
||||||
import { openDetailsSidebar } from '$lib/features/details/openDetailsSidebar.svelte'
|
import { openDetailsSidebar } from '$lib/features/details/openDetailsSidebar.svelte'
|
||||||
import { sidebar } from '$lib/stores/sidebar.svelte'
|
import { sidebar } from '$lib/stores/sidebar.svelte'
|
||||||
|
import { GridType } from '$lib/types/enums'
|
||||||
import * as m from '$lib/paraglide/messages'
|
import * as m from '$lib/paraglide/messages'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -23,6 +24,8 @@
|
||||||
updateParty: (p: Party) => void
|
updateParty: (p: Party) => void
|
||||||
canEdit: () => boolean
|
canEdit: () => boolean
|
||||||
getEditKey: () => string | null
|
getEditKey: () => string | null
|
||||||
|
getSelectedSlot?: () => number
|
||||||
|
getActiveTab?: () => GridType
|
||||||
services: { gridService: any; partyService: any }
|
services: { gridService: any; partyService: any }
|
||||||
openPicker?: (opts: { type: 'weapon' | 'summon' | 'character'; position: number; item?: any }) => void
|
openPicker?: (opts: { type: 'weapon' | 'summon' | 'character'; position: number; item?: any }) => void
|
||||||
}
|
}
|
||||||
|
|
@ -48,6 +51,13 @@
|
||||||
// Check if this item is currently active in the sidebar
|
// Check if this item is currently active in the sidebar
|
||||||
let isActive = $derived(item?.id && sidebar.activeItemId === String(item.id))
|
let isActive = $derived(item?.id && sidebar.activeItemId === String(item.id))
|
||||||
|
|
||||||
|
// Check if this empty slot is currently selected for adding an item
|
||||||
|
let isEmptySelected = $derived(
|
||||||
|
!item &&
|
||||||
|
ctx?.getSelectedSlot?.() === position &&
|
||||||
|
ctx?.getActiveTab?.() === GridType.Summon
|
||||||
|
)
|
||||||
|
|
||||||
// Determine element class for focus ring
|
// Determine element class for focus ring
|
||||||
let elementClass = $derived.by(() => {
|
let elementClass = $derived.by(() => {
|
||||||
const element = item?.summon?.element
|
const element = item?.summon?.element
|
||||||
|
|
@ -106,6 +116,7 @@
|
||||||
class:friend={item?.friend || position === 6}
|
class:friend={item?.friend || position === 6}
|
||||||
class:cell={!((item?.main || position === -1) || (item?.friend || position === 6))}
|
class:cell={!((item?.main || position === -1) || (item?.friend || position === 6))}
|
||||||
class:editable={ctx?.canEdit()}
|
class:editable={ctx?.canEdit()}
|
||||||
|
class:is-active={isActive}
|
||||||
onclick={() => viewDetails()}
|
onclick={() => viewDetails()}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
|
|
@ -159,6 +170,7 @@
|
||||||
class:friend={position === 6}
|
class:friend={position === 6}
|
||||||
class:cell={!(position === -1 || position === 6)}
|
class:cell={!(position === -1 || position === 6)}
|
||||||
class:editable={ctx?.canEdit()}
|
class:editable={ctx?.canEdit()}
|
||||||
|
class:is-selected={isEmptySelected}
|
||||||
onclick={() => ctx?.canEdit() && ctx?.openPicker && ctx.openPicker({ type: 'summon', position, item })}
|
onclick={() => ctx?.canEdit() && ctx?.openPicker && ctx.openPicker({ type: 'summon', position, item })}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
|
|
@ -270,6 +282,21 @@
|
||||||
opacity: 0.95;
|
opacity: 0.95;
|
||||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Slot selection - subtle dark pulsing glow (works for both empty and filled)
|
||||||
|
&.is-selected,
|
||||||
|
&.is-active {
|
||||||
|
animation: pulse-slot-shadow 2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-slot-shadow {
|
||||||
|
0%, 100% {
|
||||||
|
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12), 0 0 4px 2px rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.24), 0 0 8px 4px rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.frame.summon.main,
|
.frame.summon.main,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import { openDetailsSidebar } from '$lib/features/details/openDetailsSidebar.svelte'
|
import { openDetailsSidebar } from '$lib/features/details/openDetailsSidebar.svelte'
|
||||||
import { getAwakeningImage, getWeaponKeyImages, getAxSkillImages } from '$lib/utils/modifiers'
|
import { getAwakeningImage, getWeaponKeyImages, getAxSkillImages } from '$lib/utils/modifiers'
|
||||||
import { sidebar } from '$lib/stores/sidebar.svelte'
|
import { sidebar } from '$lib/stores/sidebar.svelte'
|
||||||
|
import { GridType } from '$lib/types/enums'
|
||||||
import * as m from '$lib/paraglide/messages'
|
import * as m from '$lib/paraglide/messages'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -24,6 +25,8 @@
|
||||||
updateParty: (p: Party) => void
|
updateParty: (p: Party) => void
|
||||||
canEdit: () => boolean
|
canEdit: () => boolean
|
||||||
getEditKey: () => string | null
|
getEditKey: () => string | null
|
||||||
|
getSelectedSlot?: () => number
|
||||||
|
getActiveTab?: () => GridType
|
||||||
services: { gridService: any; partyService: any }
|
services: { gridService: any; partyService: any }
|
||||||
openPicker?: (opts: { type: 'weapon' | 'summon' | 'character'; position: number; item?: any }) => void
|
openPicker?: (opts: { type: 'weapon' | 'summon' | 'character'; position: number; item?: any }) => void
|
||||||
}
|
}
|
||||||
|
|
@ -69,6 +72,13 @@
|
||||||
// Check if this item is currently active in the sidebar
|
// Check if this item is currently active in the sidebar
|
||||||
let isActive = $derived(item?.id && sidebar.activeItemId === String(item.id))
|
let isActive = $derived(item?.id && sidebar.activeItemId === String(item.id))
|
||||||
|
|
||||||
|
// Check if this empty slot is currently selected for adding an item
|
||||||
|
let isEmptySelected = $derived(
|
||||||
|
!item &&
|
||||||
|
ctx?.getSelectedSlot?.() === position &&
|
||||||
|
ctx?.getActiveTab?.() === GridType.Weapon
|
||||||
|
)
|
||||||
|
|
||||||
// Determine element class for focus ring
|
// Determine element class for focus ring
|
||||||
let elementClass = $derived.by(() => {
|
let elementClass = $derived.by(() => {
|
||||||
// For weapons with null element that have an instance element, use it
|
// For weapons with null element that have an instance element, use it
|
||||||
|
|
@ -148,6 +158,7 @@
|
||||||
class:cell={!(item?.mainhand || position === -1)}
|
class:cell={!(item?.mainhand || position === -1)}
|
||||||
class:extra={position >= 9}
|
class:extra={position >= 9}
|
||||||
class:editable={ctx?.canEdit()}
|
class:editable={ctx?.canEdit()}
|
||||||
|
class:is-active={isActive}
|
||||||
onclick={() => viewDetails()}
|
onclick={() => viewDetails()}
|
||||||
>
|
>
|
||||||
<div class="modifiers">
|
<div class="modifiers">
|
||||||
|
|
@ -212,6 +223,7 @@
|
||||||
class:cell={position !== -1}
|
class:cell={position !== -1}
|
||||||
class:extra={position >= 9}
|
class:extra={position >= 9}
|
||||||
class:editable={ctx?.canEdit()}
|
class:editable={ctx?.canEdit()}
|
||||||
|
class:is-selected={isEmptySelected}
|
||||||
onclick={() =>
|
onclick={() =>
|
||||||
ctx?.canEdit() && ctx?.openPicker && ctx.openPicker({ type: 'weapon', position, item })}
|
ctx?.canEdit() && ctx?.openPicker && ctx.openPicker({ type: 'weapon', position, item })}
|
||||||
>
|
>
|
||||||
|
|
@ -360,6 +372,22 @@
|
||||||
opacity: 0.95;
|
opacity: 0.95;
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Slot selection - subtle dark pulsing glow (works for both empty and filled)
|
||||||
|
&.is-selected,
|
||||||
|
&.is-active {
|
||||||
|
animation: pulse-slot-shadow 2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-slot-shadow {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12), 0 0 4px 2px rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.24), 0 0 8px 4px rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.frame.weapon.main {
|
.frame.weapon.main {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue