hensei-web/src/lib/components/collection/CollectionArtifactCard.svelte

139 lines
3.2 KiB
Svelte

<svelte:options runes={true} />
<script lang="ts">
import type { CollectionArtifact } from '$lib/types/api/artifact'
import { getArtifactImage } from '$lib/utils/images'
import ElementLabel from '$lib/components/labels/ElementLabel.svelte'
import ProficiencyLabel from '$lib/components/labels/ProficiencyLabel.svelte'
interface Props {
artifact: CollectionArtifact
onClick?: () => void
}
let { artifact, onClick }: Props = $props()
const imageUrl = $derived(getArtifactImage(artifact.artifact?.granblueId))
const displayName = $derived.by(() => {
const name = artifact.artifact?.name
if (!name) return '—'
if (typeof name === 'string') return name
return name.en || name.ja || '—'
})
// Is this a quirk artifact?
const isQuirk = $derived(artifact.artifact?.rarity === 'quirk')
// Proficiency: quirk artifacts use instance proficiency, standard use canonical
const proficiency = $derived(artifact.proficiency ?? artifact.artifact?.proficiency)
</script>
<button type="button" class="artifact-card" onclick={onClick}>
<div class="card-image">
<img class="artifact-image" src={imageUrl} alt={displayName} loading="lazy" />
<span class="level-badge">Lv.{artifact.level}</span>
{#if isQuirk}
<span class="quirk-badge">Q</span>
{/if}
</div>
{#if artifact.nickname}
<span class="artifact-name nickname">{artifact.nickname}</span>
{:else}
<span class="artifact-name">{displayName}</span>
{/if}
<div class="card-info">
<ElementLabel element={artifact.element} size="small" />
<ProficiencyLabel {proficiency} size="small" />
</div>
</button>
<style lang="scss">
@use '$src/themes/spacing' as *;
@use '$src/themes/typography' as *;
@use '$src/themes/layout' as *;
.artifact-card {
display: flex;
flex-direction: column;
align-items: center;
gap: $unit-half;
padding: 0;
border: none;
background: transparent;
cursor: pointer;
transition: transform 0.2s ease;
&:hover {
transform: scale(1.05);
}
&:focus-visible {
outline: 2px solid var(--accent-color, #3366ff);
outline-offset: 2px;
border-radius: $item-corner;
}
}
.card-image {
position: relative;
width: 100%;
aspect-ratio: 1 / 1;
border-radius: $item-corner;
overflow: hidden;
background: var(--card-bg, #f5f5f5);
}
.artifact-image {
width: 100%;
height: 100%;
object-fit: contain;
border-radius: $item-corner;
}
.level-badge {
position: absolute;
top: $unit-fourth;
right: $unit-fourth;
font-size: $font-small;
font-weight: $bold;
padding: 2px 6px;
border-radius: 4px;
line-height: 1;
background: var(--grey-80, #e9e9e9);
color: var(--grey-40, #444);
}
.quirk-badge {
position: absolute;
top: $unit-fourth;
left: $unit-fourth;
font-size: $font-small;
font-weight: $bold;
padding: 2px 6px;
border-radius: 4px;
line-height: 1;
background: var(--purple-50, #b6b2fc);
color: var(--purple-10, #4f3c79);
}
.card-info {
display: flex;
align-items: center;
gap: $unit-half;
}
.artifact-name {
font-size: $font-small;
color: var(--text-tertiary);
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 100%;
&.nickname {
font-weight: $bold;
}
}
</style>