add sidebar modification display components
This commit is contained in:
parent
f090d2fe41
commit
249877efe6
6 changed files with 648 additions and 0 deletions
108
src/lib/components/sidebar/modifications/AwakeningDisplay.svelte
Normal file
108
src/lib/components/sidebar/modifications/AwakeningDisplay.svelte
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { getAwakeningImage } from '$lib/utils/modifiers'
|
||||||
|
import type { Awakening } from '$lib/types/api/entities'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
awakening?: {
|
||||||
|
type?: Awakening
|
||||||
|
level?: number
|
||||||
|
} | Awakening
|
||||||
|
size?: 'small' | 'medium' | 'large'
|
||||||
|
showLevel?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
awakening,
|
||||||
|
size = 'medium',
|
||||||
|
showLevel = true
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
|
function getAwakeningData() {
|
||||||
|
if (!awakening) return null
|
||||||
|
|
||||||
|
if ('type' in awakening && awakening.type) {
|
||||||
|
return {
|
||||||
|
type: awakening.type,
|
||||||
|
level: awakening.level || 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: awakening as Awakening,
|
||||||
|
level: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let awakeningData = $derived(getAwakeningData())
|
||||||
|
let imageUrl = $derived(getAwakeningImage(awakeningData))
|
||||||
|
let displayName = $derived(awakeningData?.type?.name?.en || awakeningData?.type?.name?.ja || 'Awakening')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if awakeningData && imageUrl}
|
||||||
|
<div class="awakening-display {size}">
|
||||||
|
<img
|
||||||
|
src={imageUrl}
|
||||||
|
alt={displayName}
|
||||||
|
class="awakening-icon"
|
||||||
|
/>
|
||||||
|
<div class="awakening-info">
|
||||||
|
<span class="awakening-name">{displayName}</span>
|
||||||
|
{#if showLevel && awakeningData.level !== undefined}
|
||||||
|
<span class="awakening-level">Lv{awakeningData.level}</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@use '$src/themes/colors' as colors;
|
||||||
|
@use '$src/themes/spacing' as spacing;
|
||||||
|
@use '$src/themes/typography' as typography;
|
||||||
|
@use '$src/themes/layout' as layout;
|
||||||
|
|
||||||
|
.awakening-display {
|
||||||
|
display: flex;
|
||||||
|
gap: spacing.$unit-2x;
|
||||||
|
align-items: center;
|
||||||
|
padding: spacing.$unit;
|
||||||
|
background: colors.$grey-85;
|
||||||
|
border-radius: layout.$item-corner-small;
|
||||||
|
|
||||||
|
&.small .awakening-icon {
|
||||||
|
width: spacing.$unit-4x;
|
||||||
|
height: spacing.$unit-4x;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.medium .awakening-icon {
|
||||||
|
width: spacing.$unit-6x;
|
||||||
|
height: spacing.$unit-6x;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.large .awakening-icon {
|
||||||
|
width: spacing.$unit-8x;
|
||||||
|
height: spacing.$unit-8x;
|
||||||
|
}
|
||||||
|
|
||||||
|
.awakening-icon {
|
||||||
|
border-radius: layout.$item-corner-small;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.awakening-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: spacing.$unit-half;
|
||||||
|
|
||||||
|
.awakening-name {
|
||||||
|
font-size: typography.$font-regular;
|
||||||
|
color: var(--text-primary, colors.$grey-10);
|
||||||
|
font-weight: typography.$medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.awakening-level {
|
||||||
|
font-size: typography.$font-small;
|
||||||
|
color: var(--text-secondary, colors.$grey-50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { SegmentedControl, Segment } from '$lib/components/ui/segmented-control'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
hasModifications: boolean
|
||||||
|
selectedView: 'canonical' | 'user'
|
||||||
|
onViewChange?: (view: 'canonical' | 'user') => void
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
hasModifications,
|
||||||
|
selectedView = $bindable('canonical'),
|
||||||
|
onViewChange
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
|
function handleViewChange(value: string) {
|
||||||
|
selectedView = value as 'canonical' | 'user'
|
||||||
|
onViewChange?.(selectedView)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="details-sidebar-segmented-control">
|
||||||
|
<SegmentedControl
|
||||||
|
bind:value={selectedView}
|
||||||
|
onValueChange={handleViewChange}
|
||||||
|
variant="background"
|
||||||
|
grow
|
||||||
|
>
|
||||||
|
<Segment value="canonical">
|
||||||
|
<span class="segment-label">Canonical</span>
|
||||||
|
</Segment>
|
||||||
|
{#if hasModifications}
|
||||||
|
<Segment value="user">
|
||||||
|
<span class="segment-label">
|
||||||
|
User Version
|
||||||
|
</span>
|
||||||
|
</Segment>
|
||||||
|
{:else}
|
||||||
|
<div class="disabled-segment">
|
||||||
|
<span class="segment-label disabled">
|
||||||
|
User Version
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</SegmentedControl>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@use '$src/themes/colors' as colors;
|
||||||
|
@use '$src/themes/spacing' as spacing;
|
||||||
|
@use '$src/themes/typography' as typography;
|
||||||
|
|
||||||
|
.details-sidebar-segmented-control {
|
||||||
|
margin-bottom: spacing.$unit-2x;
|
||||||
|
padding: 0 spacing.$unit-2x;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-label {
|
||||||
|
font-size: typography.$font-regular;
|
||||||
|
font-weight: typography.$medium;
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
color: var(--text-tertiary, colors.$grey-60);
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.disabled-segment {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: spacing.$unit;
|
||||||
|
background: colors.$grey-90;
|
||||||
|
border-radius: spacing.$unit-half;
|
||||||
|
cursor: not-allowed;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import type { Snippet } from 'svelte'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string
|
||||||
|
visible?: boolean
|
||||||
|
children: Snippet
|
||||||
|
}
|
||||||
|
|
||||||
|
let { title, visible = true, children }: Props = $props()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if visible}
|
||||||
|
<div class="modification-section">
|
||||||
|
<h3>{title}</h3>
|
||||||
|
<div class="modification-content">
|
||||||
|
{@render children()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@use '$src/themes/colors' as colors;
|
||||||
|
@use '$src/themes/spacing' as spacing;
|
||||||
|
@use '$src/themes/typography' as typography;
|
||||||
|
@use '$src/themes/layout' as layout;
|
||||||
|
|
||||||
|
.modification-section {
|
||||||
|
margin-bottom: spacing.$unit-3x;
|
||||||
|
padding: spacing.$unit-2x;
|
||||||
|
background: colors.$grey-90;
|
||||||
|
border-radius: layout.$item-corner;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: typography.$font-regular;
|
||||||
|
font-weight: typography.$medium;
|
||||||
|
color: var(--text-secondary, colors.$grey-40);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
margin: 0 0 spacing.$unit-2x 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modification-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: spacing.$unit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
<script lang="ts">
|
||||||
|
interface Props {
|
||||||
|
label: string
|
||||||
|
value: string | number
|
||||||
|
suffix?: string
|
||||||
|
icon?: string
|
||||||
|
variant?: 'default' | 'enhanced' | 'max'
|
||||||
|
class?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
suffix = '',
|
||||||
|
icon,
|
||||||
|
variant = 'default',
|
||||||
|
class: className = ''
|
||||||
|
}: Props = $props()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="stat-modifier {variant} {className}">
|
||||||
|
{#if icon}
|
||||||
|
<img src={icon} alt="" class="stat-icon" />
|
||||||
|
{/if}
|
||||||
|
<span class="label">{label}</span>
|
||||||
|
<span class="value">{value}{suffix}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@use '$src/themes/colors' as colors;
|
||||||
|
@use '$src/themes/spacing' as spacing;
|
||||||
|
@use '$src/themes/typography' as typography;
|
||||||
|
@use '$src/themes/layout' as layout;
|
||||||
|
@use '$src/themes/effects' as effects;
|
||||||
|
|
||||||
|
.stat-modifier {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: spacing.$unit;
|
||||||
|
background: colors.$grey-90;
|
||||||
|
border-radius: layout.$item-corner-small;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
.stat-icon {
|
||||||
|
width: spacing.$unit-2x;
|
||||||
|
height: spacing.$unit-2x;
|
||||||
|
margin-right: spacing.$unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: typography.$font-small;
|
||||||
|
color: var(--text-secondary, colors.$grey-50);
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-size: typography.$font-regular;
|
||||||
|
font-weight: typography.$medium;
|
||||||
|
color: var(--text-primary, colors.$grey-10);
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.enhanced {
|
||||||
|
background: colors.$grey-85;
|
||||||
|
box-shadow: effects.$hover-shadow;
|
||||||
|
|
||||||
|
.value {
|
||||||
|
color: var(--color-success, #4caf50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.max {
|
||||||
|
background: linear-gradient(135deg, colors.$grey-85, colors.$grey-80);
|
||||||
|
box-shadow: effects.$hover-shadow;
|
||||||
|
|
||||||
|
.value {
|
||||||
|
color: #ffd700;
|
||||||
|
font-weight: typography.$bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,172 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import UncapIndicator from '$lib/components/uncap/UncapIndicator.svelte'
|
||||||
|
import { formatUncapLevel, formatTranscendenceStep } from '$lib/utils/modificationFormatters'
|
||||||
|
import StatModifierItem from './StatModifierItem.svelte'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
type: 'character' | 'weapon' | 'summon'
|
||||||
|
uncapLevel?: number | null
|
||||||
|
transcendenceStep?: number | null
|
||||||
|
maxUncap?: number
|
||||||
|
special?: boolean
|
||||||
|
flb?: boolean
|
||||||
|
ulb?: boolean
|
||||||
|
transcendence?: boolean
|
||||||
|
showIndicator?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
type,
|
||||||
|
uncapLevel = 0,
|
||||||
|
transcendenceStep = 0,
|
||||||
|
maxUncap = 3,
|
||||||
|
special = false,
|
||||||
|
flb = false,
|
||||||
|
ulb = false,
|
||||||
|
transcendence = false,
|
||||||
|
showIndicator = true
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
|
function getMaxPossibleUncap(): number {
|
||||||
|
if (transcendence) return 6
|
||||||
|
if (ulb) return 5
|
||||||
|
if (flb) return 4
|
||||||
|
return maxUncap || 3
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUncapStatus(): string {
|
||||||
|
const current = uncapLevel || 0
|
||||||
|
const max = getMaxPossibleUncap()
|
||||||
|
|
||||||
|
if (current >= max) return 'Max'
|
||||||
|
return `${current} / ${max}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMaxUncap(): boolean {
|
||||||
|
return (uncapLevel || 0) >= getMaxPossibleUncap()
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMaxTranscendence(): boolean {
|
||||||
|
return transcendenceStep === 5
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="uncap-status-display">
|
||||||
|
{#if showIndicator}
|
||||||
|
<div class="uncap-indicator-wrapper">
|
||||||
|
<UncapIndicator
|
||||||
|
{type}
|
||||||
|
{uncapLevel}
|
||||||
|
transcendenceStage={transcendenceStep}
|
||||||
|
{special}
|
||||||
|
{flb}
|
||||||
|
{ulb}
|
||||||
|
{transcendence}
|
||||||
|
editable={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="uncap-details">
|
||||||
|
<StatModifierItem
|
||||||
|
label="Uncap Level"
|
||||||
|
value={formatUncapLevel(uncapLevel)}
|
||||||
|
variant={isMaxUncap() ? 'max' : 'default'}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{#if transcendence && transcendenceStep && transcendenceStep > 0}
|
||||||
|
<StatModifierItem
|
||||||
|
label="Transcendence"
|
||||||
|
value={formatTranscendenceStep(transcendenceStep)}
|
||||||
|
variant={isMaxTranscendence() ? 'max' : 'enhanced'}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="available-uncaps">
|
||||||
|
<span class="label">Available Upgrades</span>
|
||||||
|
<div class="uncap-badges">
|
||||||
|
{#if flb}
|
||||||
|
<span class="badge" class:active={uncapLevel >= 4}>FLB</span>
|
||||||
|
{/if}
|
||||||
|
{#if ulb}
|
||||||
|
<span class="badge" class:active={uncapLevel >= 5}>ULB</span>
|
||||||
|
{/if}
|
||||||
|
{#if transcendence}
|
||||||
|
<span class="badge" class:active={transcendenceStep > 0}>Trans</span>
|
||||||
|
{/if}
|
||||||
|
{#if !flb && !ulb && !transcendence}
|
||||||
|
<span class="badge standard">Standard</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@use '$src/themes/colors' as colors;
|
||||||
|
@use '$src/themes/spacing' as spacing;
|
||||||
|
@use '$src/themes/typography' as typography;
|
||||||
|
@use '$src/themes/layout' as layout;
|
||||||
|
|
||||||
|
.uncap-status-display {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: spacing.$unit-2x;
|
||||||
|
|
||||||
|
.uncap-indicator-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: spacing.$unit-2x;
|
||||||
|
background: colors.$grey-90;
|
||||||
|
border-radius: layout.$item-corner;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uncap-details {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: spacing.$unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.available-uncaps {
|
||||||
|
padding: spacing.$unit;
|
||||||
|
background: colors.$grey-90;
|
||||||
|
border-radius: layout.$item-corner-small;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
display: block;
|
||||||
|
font-size: typography.$font-small;
|
||||||
|
color: var(--text-secondary, colors.$grey-50);
|
||||||
|
margin-bottom: spacing.$unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uncap-badges {
|
||||||
|
display: flex;
|
||||||
|
gap: spacing.$unit;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
padding: spacing.$unit-half spacing.$unit;
|
||||||
|
background: colors.$grey-85;
|
||||||
|
border-radius: layout.$item-corner-small;
|
||||||
|
font-size: typography.$font-tiny;
|
||||||
|
color: var(--text-tertiary, colors.$grey-60);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
font-weight: typography.$medium;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: var(--color-success-bg, rgba(76, 175, 80, 0.2));
|
||||||
|
color: var(--color-success, #4caf50);
|
||||||
|
border: 1px solid var(--color-success, #4caf50);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.standard {
|
||||||
|
background: colors.$grey-85;
|
||||||
|
color: var(--text-secondary, colors.$grey-50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
157
src/lib/components/sidebar/modifications/WeaponKeysList.svelte
Normal file
157
src/lib/components/sidebar/modifications/WeaponKeysList.svelte
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { getWeaponKeyImages } from '$lib/utils/modifiers'
|
||||||
|
import type { WeaponKey } from '$lib/types/api/entities'
|
||||||
|
import type { LocalizedName } from '$lib/types/api/entities'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
weaponKeys?: WeaponKey[]
|
||||||
|
weaponData?: {
|
||||||
|
element?: number
|
||||||
|
proficiency?: number | number[]
|
||||||
|
series?: number
|
||||||
|
name?: LocalizedName
|
||||||
|
}
|
||||||
|
layout?: 'list' | 'grid'
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
weaponKeys,
|
||||||
|
weaponData,
|
||||||
|
layout = 'list'
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
|
let keyImages = $derived(
|
||||||
|
getWeaponKeyImages(
|
||||||
|
weaponKeys,
|
||||||
|
weaponData?.element,
|
||||||
|
Array.isArray(weaponData?.proficiency) ? weaponData?.proficiency[0] : weaponData?.proficiency,
|
||||||
|
weaponData?.series,
|
||||||
|
weaponData?.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
function getKeyDescription(key: WeaponKey): string {
|
||||||
|
if (key.name?.en) return key.name.en
|
||||||
|
if (key.name?.ja) return key.name.ja
|
||||||
|
return key.slug || 'Weapon Key'
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSlotLabel(slot: number, series?: number): string {
|
||||||
|
if (series === 2) {
|
||||||
|
return slot === 0 ? 'Alpha Pendulum' : 'Pendulum'
|
||||||
|
}
|
||||||
|
if (series === 3 || series === 34) {
|
||||||
|
return `Teluma ${slot + 1}`
|
||||||
|
}
|
||||||
|
if (series === 17) {
|
||||||
|
return slot === 0 ? 'Gauph Key' : `Ultima Key`
|
||||||
|
}
|
||||||
|
if (series === 22) {
|
||||||
|
return `Emblem Slot ${slot + 1}`
|
||||||
|
}
|
||||||
|
return `Slot ${slot + 1}`
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if weaponKeys && weaponKeys.length > 0}
|
||||||
|
<div class="weapon-keys-list {layout}">
|
||||||
|
{#each weaponKeys as key, index}
|
||||||
|
{@const imageData = keyImages[index]}
|
||||||
|
<div class="weapon-key-item">
|
||||||
|
{#if imageData}
|
||||||
|
<img
|
||||||
|
src={imageData.url}
|
||||||
|
alt={imageData.alt}
|
||||||
|
class="weapon-key-icon"
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
<div class="weapon-key-info">
|
||||||
|
<span class="slot-label">
|
||||||
|
{getSlotLabel(key.slot, weaponData?.series)}
|
||||||
|
</span>
|
||||||
|
<span class="key-name">
|
||||||
|
{getKeyDescription(key)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@use '$src/themes/colors' as colors;
|
||||||
|
@use '$src/themes/spacing' as spacing;
|
||||||
|
@use '$src/themes/typography' as typography;
|
||||||
|
@use '$src/themes/layout' as layout;
|
||||||
|
|
||||||
|
.weapon-keys-list {
|
||||||
|
display: flex;
|
||||||
|
gap: spacing.$unit;
|
||||||
|
|
||||||
|
&.list {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.grid {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: spacing.$unit-2x;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weapon-key-item {
|
||||||
|
display: flex;
|
||||||
|
gap: spacing.$unit-2x;
|
||||||
|
align-items: center;
|
||||||
|
padding: spacing.$unit;
|
||||||
|
background: colors.$grey-85;
|
||||||
|
border-radius: layout.$item-corner-small;
|
||||||
|
transition: background 0.2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: colors.$grey-80;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weapon-key-icon {
|
||||||
|
width: spacing.$unit-5x;
|
||||||
|
height: spacing.$unit-5x;
|
||||||
|
border-radius: layout.$item-corner-small;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weapon-key-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: spacing.$unit-fourth;
|
||||||
|
|
||||||
|
.slot-label {
|
||||||
|
font-size: typography.$font-tiny;
|
||||||
|
color: var(--text-tertiary, colors.$grey-60);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-name {
|
||||||
|
font-size: typography.$font-small;
|
||||||
|
color: var(--text-primary, colors.$grey-10);
|
||||||
|
font-weight: typography.$medium;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
.weapon-key-item {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
padding: spacing.$unit-2x;
|
||||||
|
|
||||||
|
.weapon-key-icon {
|
||||||
|
width: spacing.$unit-6x;
|
||||||
|
height: spacing.$unit-6x;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weapon-key-info {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in a new issue