add element-based backgrounds to detail sidebar

This commit is contained in:
Justin Edmund 2025-09-24 03:49:20 -07:00
parent 506d33bf57
commit 6034157d07
2 changed files with 414 additions and 387 deletions

View file

@ -5,7 +5,12 @@
import { getProficiencyLabel } from '$lib/utils/proficiency' import { getProficiencyLabel } from '$lib/utils/proficiency'
import { getRaceLabel } from '$lib/utils/race' import { getRaceLabel } from '$lib/utils/race'
import { getGenderLabel } from '$lib/utils/gender' import { getGenderLabel } from '$lib/utils/gender'
import { getCharacterDetailImage, getWeaponBaseImage, getSummonDetailImage, getCharacterPose } from '$lib/utils/images' import {
getCharacterDetailImage,
getWeaponBaseImage,
getSummonDetailImage,
getCharacterPose
} from '$lib/utils/images'
import UncapIndicator from '$lib/components/uncap/UncapIndicator.svelte' import UncapIndicator from '$lib/components/uncap/UncapIndicator.svelte'
interface Props { interface Props {
@ -42,15 +47,19 @@
// Grid item info (uncap levels from the grid item itself) // Grid item info (uncap levels from the grid item itself)
const gridUncapLevel = $derived( const gridUncapLevel = $derived(
type === 'character' ? (item as GridCharacter).uncapLevel : type === 'character'
type === 'weapon' ? (item as GridWeapon).uncapLevel : ? (item as GridCharacter).uncapLevel
(item as GridSummon).uncapLevel : type === 'weapon'
? (item as GridWeapon).uncapLevel
: (item as GridSummon).uncapLevel
) )
const gridTranscendence = $derived( const gridTranscendence = $derived(
type === 'character' ? (item as GridCharacter).transcendenceStep : type === 'character'
type === 'weapon' ? (item as GridWeapon).transcendenceStep : ? (item as GridCharacter).transcendenceStep
(item as GridSummon).transcendenceStep : type === 'weapon'
? (item as GridWeapon).transcendenceStep
: (item as GridSummon).transcendenceStep
) )
// Get image URL based on type using detail/base variants // Get image URL based on type using detail/base variants
@ -66,21 +75,25 @@
return getSummonDetailImage(id) return getSummonDetailImage(id)
} }
} }
// Get element-based background color
function getElementBackground(): string {
const element = itemData?.element
switch (element) {
case 1: return 'var(--wind-item-detail-bg)'
case 2: return 'var(--fire-item-detail-bg)'
case 3: return 'var(--water-item-detail-bg)'
case 4: return 'var(--earth-item-detail-bg)'
case 5: return 'var(--dark-item-detail-bg)'
case 6: return 'var(--light-item-detail-bg)'
default: return 'var(--null-item-detail-bg)'
}
}
</script> </script>
<div class="details-sidebar"> <div class="details-sidebar">
<div class="item-header"> <div class="item-header" style="background: {getElementBackground()}">
<img <img src={getImageUrl()} alt={displayName(itemData)} class="item-image {type}" />
src={getImageUrl()}
alt={displayName(itemData)}
class="item-image"
/>
<div class="item-title">
<h2>{displayName(itemData)}</h2>
{#if itemData?.granblueId}
<span class="granblue-id">ID: {itemData.granblueId}</span>
{/if}
</div>
</div> </div>
<div class="details-section"> <div class="details-section">
@ -99,7 +112,10 @@
<div class="detail-row"> <div class="detail-row">
<span class="label">Race</span> <span class="label">Race</span>
<span class="value"> <span class="value">
{itemData.race.map(r => getRaceLabel(r)).filter(Boolean).join(', ') || '—'} {itemData.race
.map((r) => getRaceLabel(r))
.filter(Boolean)
.join(', ') || '—'}
</span> </span>
</div> </div>
{/if} {/if}
@ -111,7 +127,10 @@
<div class="detail-row"> <div class="detail-row">
<span class="label">Proficiencies</span> <span class="label">Proficiencies</span>
<span class="value"> <span class="value">
{itemData.proficiency.map(p => getProficiencyLabel(p)).filter(Boolean).join(', ') || '—'} {itemData.proficiency
.map((p) => getProficiencyLabel(p))
.filter(Boolean)
.join(', ') || '—'}
</span> </span>
</div> </div>
{/if} {/if}
@ -127,7 +146,7 @@
<h3>Uncap Status</h3> <h3>Uncap Status</h3>
<div class="uncap-display"> <div class="uncap-display">
<UncapIndicator <UncapIndicator
type={type} {type}
uncapLevel={gridUncapLevel} uncapLevel={gridUncapLevel}
transcendenceStage={gridTranscendence} transcendenceStage={gridTranscendence}
special={itemData?.special} special={itemData?.special}
@ -155,7 +174,9 @@
itemData.uncap.flb && 'FLB', itemData.uncap.flb && 'FLB',
itemData.uncap.ulb && 'ULB', itemData.uncap.ulb && 'ULB',
itemData.uncap.transcendence && 'Transcendence' itemData.uncap.transcendence && 'Transcendence'
].filter(Boolean).join(', ') || 'Standard'} ]
.filter(Boolean)
.join(', ') || 'Standard'}
</span> </span>
</div> </div>
{/if} {/if}
@ -279,41 +300,29 @@
@use '$src/themes/layout' as layout; @use '$src/themes/layout' as layout;
.details-sidebar { .details-sidebar {
padding: spacing.$unit-2x; padding: 0 spacing.$unit-2x spacing.$unit-2x;
color: var(--text-primary, colors.$grey-10); color: var(--text-primary, colors.$grey-10);
display: flex;
flex-direction: column;
gap: spacing.$unit-2x;
} }
.item-header { .item-header {
display: flex; display: flex;
gap: spacing.$unit-2x; gap: spacing.$unit-2x;
align-items: flex-start; align-items: flex-start;
margin-bottom: spacing.$unit-3x;
padding-bottom: spacing.$unit-2x;
border-bottom: 1px solid var(--border-color, colors.$grey-70);
}
.item-image {
width: 80px;
height: 80px;
border-radius: layout.$item-corner; border-radius: layout.$item-corner;
object-fit: cover;
background: colors.$grey-80;
border: 1px solid colors.$grey-70; border: 1px solid colors.$grey-70;
justify-content: center;
transition: background 0.3s ease;
.item-image.weapon {
width: 62%;
} }
.item-title { .item-image.summon,
flex: 1; .item-image.character {
width: 100%;
h2 {
margin: 0 0 calc(spacing.$unit * 0.5) 0;
font-size: typography.$font-xlarge;
font-weight: typography.$medium;
color: var(--text-primary, colors.$grey-10);
}
.granblue-id {
font-size: typography.$font-small;
color: var(--text-secondary, colors.$grey-50);
} }
} }

View file

@ -233,6 +233,15 @@
--light-nav-selected-bg: #{colors.$light-bg-20}; --light-nav-selected-bg: #{colors.$light-bg-20};
--dark-nav-selected-bg: #{colors.$dark-bg-20}; --dark-nav-selected-bg: #{colors.$dark-bg-20};
// Item detail backgrounds (same colors as nav selected)
--null-item-detail-bg: #{colors.$grey-85};
--wind-item-detail-bg: #{colors.$wind-bg-20};
--fire-item-detail-bg: #{colors.$fire-bg-20};
--water-item-detail-bg: #{colors.$water-bg-20};
--earth-item-detail-bg: #{colors.$earth-bg-20};
--light-item-detail-bg: #{colors.$light-bg-20};
--dark-item-detail-bg: #{colors.$dark-bg-20};
// Light - Element navigation selected text // Light - Element navigation selected text
--null-nav-selected-text: #{colors.$grey-40}; --null-nav-selected-text: #{colors.$grey-40};
--wind-nav-selected-text: #{colors.$wind-text-20}; --wind-nav-selected-text: #{colors.$wind-text-20};
@ -511,6 +520,15 @@
--light-nav-selected-bg: #{colors.$light-bg-20}; --light-nav-selected-bg: #{colors.$light-bg-20};
--dark-nav-selected-bg: #{colors.$dark-bg-20}; --dark-nav-selected-bg: #{colors.$dark-bg-20};
// Item detail backgrounds (same colors as nav selected)
--null-item-detail-bg: #{colors.$grey-85};
--wind-item-detail-bg: #{colors.$wind-bg-20};
--fire-item-detail-bg: #{colors.$fire-bg-20};
--water-item-detail-bg: #{colors.$water-bg-20};
--earth-item-detail-bg: #{colors.$earth-bg-20};
--light-item-detail-bg: #{colors.$light-bg-20};
--dark-item-detail-bg: #{colors.$dark-bg-20};
// Dark - Element navigation selected text (same as light theme) // Dark - Element navigation selected text (same as light theme)
--null-nav-selected-text: #{colors.$grey-40}; --null-nav-selected-text: #{colors.$grey-40};
--wind-nav-selected-text: #{colors.$wind-text-20}; --wind-nav-selected-text: #{colors.$wind-text-20};