Skip to content

Commit

Permalink
sticky profile header
Browse files Browse the repository at this point in the history
  • Loading branch information
arily committed May 21, 2024
1 parent 29d0729 commit 3c6d028
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 223 deletions.
28 changes: 14 additions & 14 deletions src/assets/styles/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,29 +40,29 @@ dialog {
}

.two-tone {
@apply relative;
@apply z-[1] sticky top-[3.625rem] mb-1 mx-2 lg:mx-0;
&::before {
@apply absolute top-0 left-0 right-0 bottom-0 -z-10;
@apply rounded-2xl;
@apply rounded-lg shadow-md;
content: "";
background: linear-gradient(
110deg,
transparent,
theme("colors.gbase.200 / 30%") 16.6%,
theme("colors.gbase.300 / 50%") 16.7%,
theme("colors.gbase.300 / 60%") 83.3%,
theme("colors.gbase.200 / 30%") 83.4%,
transparent 100%
theme("colors.gbase.50"),
theme("colors.gbase.100") 16.6%,
theme("colors.gbase.200") 16.7%,
theme("colors.gbase.200") 83.3%,
theme("colors.gbase.100") 83.4%,
theme("colors.gbase.50")
);
@media (prefers-color-scheme: dark) {
background: linear-gradient(
110deg,
transparent,
theme("colors.gbase.700 / 30%") 16.6%,
theme("colors.gbase.700 / 50%") 16.7%,
theme("colors.gbase.700 / 60%") 83.3%,
theme("colors.gbase.700 / 30%") 83.4%,
transparent 100%
theme("colors.gbase.800"),
theme("colors.gbase.700") 16.6%,
theme("colors.gbase.600") 16.7%,
theme("colors.gbase.600") 83.3%,
theme("colors.gbase.700") 83.4%,
theme("colors.gbase.800")
);
}
}
Expand Down
206 changes: 102 additions & 104 deletions src/components/app/score-list-item.vue
Original file line number Diff line number Diff line change
Expand Up @@ -86,123 +86,121 @@ de-DE:
</i18n>

<template>
<div class="score">
<div class="flex justify-between">
<div class="flex min-w-0 gap-4">
<div class="hidden md:block">
<picture
v-if="beatmap
&& beatmapIsVisible(beatmap)
&& beatmap.beatmapset.source === BeatmapSource.Bancho"
<div class="flex justify-between mx-1 lg:mx-0">
<div class="flex min-w-0 gap-4">
<div class="hidden md:block">
<picture
v-if="beatmap
&& beatmapIsVisible(beatmap)
&& beatmap.beatmapset.source === BeatmapSource.Bancho"
>
<source v-if="beatmap.beatmapset.assets['list@2x']" :srcset="`${beatmap.beatmapset.assets.list} 1x, ${beatmap.beatmapset.assets['list@2x']} 2x`">
<img
:src="beatmap.beatmapset.assets.list"
:alt="autoLocale(beatmap.beatmapset.meta).title"
:onerror="placeholder"
class="object-cover w-20 h-16 shadow-md rounded-xl"
>
<source v-if="beatmap.beatmapset.assets['list@2x']" :srcset="`${beatmap.beatmapset.assets.list} 1x, ${beatmap.beatmapset.assets['list@2x']} 2x`">
<img
:src="beatmap.beatmapset.assets.list"
:alt="autoLocale(beatmap.beatmapset.meta).title"
:onerror="placeholder"
class="object-cover w-20 h-16 shadow-md rounded-xl"
>
</picture>
<icon v-else class="w-20 h-16" name="clarity:unknown-status-line" size="100%" />
</div>
<div class="flex flex-col min-w-0">
<router-link
v-if="beatmap && beatmapIsVisible(beatmap)"
class="truncate"
:to="{
name: 'beatmapset-id',
params: {
id: beatmap.beatmapset.id as string,
},
query: {
beatmap: beatmap.id as string,
mode: props.mode,
ruleset: props.ruleset,
rank: [Rank.TotalScore, Rank.RankedScore].includes(
props.rankingSystem,
)
? 'score'
: props.rankingSystem,
},
}"
>
<icon
v-if="rankingStatusIconMapping[beatmap.status]"
size="100%"
class="w-5 h-5 md:w-6 md:h-6"
:name="rankingStatusIconMapping[beatmap.status]!"
:aria-label="beatmap.status"
/>
<span v-if="meta" class="text-sm font-bold truncate md:text-md xl:text-lg">
{{ meta.artist }} - {{ meta.title }}
</picture>
<icon v-else class="w-20 h-16" name="clarity:unknown-status-line" size="100%" />
</div>
<div class="flex flex-col min-w-0">
<router-link
v-if="beatmap && beatmapIsVisible(beatmap)"
class="truncate"
:to="{
name: 'beatmapset-id',
params: {
id: beatmap.beatmapset.id as string,
},
query: {
beatmap: beatmap.id as string,
mode: props.mode,
ruleset: props.ruleset,
rank: [Rank.TotalScore, Rank.RankedScore].includes(
props.rankingSystem,
)
? 'score'
: props.rankingSystem,
},
}"
>
<icon
v-if="rankingStatusIconMapping[beatmap.status]"
size="100%"
class="w-5 h-5 md:w-6 md:h-6"
:name="rankingStatusIconMapping[beatmap.status]!"
:aria-label="beatmap.status"
/>
<span v-if="meta" class="text-sm font-bold truncate md:text-md xl:text-lg">
{{ meta.artist }} - {{ meta.title }}
</span>
<div class="absolute flex flex-wrap gap-2 text-xs md:text-sm lg:text-md">
<span v-if="beatmap" class="font-semibold">
{{ beatmap.version }}
</span>
<span v-if="score.mods.length" class="flex justify-end gap-1 tooltip tooltip-primary lg:tooltip-right" :data-tip="score.mods.map(m => StableMod[m]).join(', ')">
<app-mod v-for="mod in score.mods" :key="mod" :mod="mod" class="w-4 h-4 md:w-5 md:h-5 lg:w-6 lg:h-6" />
</span>
<div class="absolute flex flex-wrap gap-2 text-xs md:text-sm lg:text-md">
<span v-if="beatmap" class="font-semibold">
{{ beatmap.version }}
</span>
<span v-if="score.mods.length" class="flex justify-end gap-1 tooltip tooltip-primary lg:tooltip-right" :data-tip="score.mods.map(m => StableMod[m]).join(', ')">
<app-mod v-for="mod in score.mods" :key="mod" :mod="mod" class="w-4 h-4 md:w-5 md:h-5 lg:w-6 lg:h-6" />
</span>
</div>
<div class="text-xs md:text-sm lg:text-md opacity-0 pointer-events-none">
IM HERE TO TAKE HEIGHT
</div>
</router-link>
<div v-else>
{{ t('unknown-beatmap') }}
</div>
<div class="mt-auto map-date">
<time class="text-xs italic lg:text-sm font-extralight">
{{ score.playedAt.toLocaleString(locale, { dateStyle: 'long', timeStyle: 'full' }) }}
</time>
<div class="text-xs md:text-sm lg:text-md opacity-0 pointer-events-none">
IM HERE TO TAKE HEIGHT
</div>
</router-link>
<div v-else>
{{ t('unknown-beatmap') }}
</div>
<div class="mt-auto map-date">
<time class="text-xs italic lg:text-sm font-extralight">
{{ score.playedAt.toLocaleString(locale, { dateStyle: 'long', timeStyle: 'full' }) }}
</time>
</div>
</div>
<div class="relative flex">
<div class="flex flex-col">
<div class="flex items-center justify-end flex-grow text-lg sm:text-xl lg:text-2xl">
<template v-if="(ppRankingSystems).includes(props.rankingSystem as LeaderboardPPRankingSystem)">
<div class="font-mono font-bold">
{{ score.pp.toFixed(2) }}
</div>
<span class="font-light">{{ $t('global.pp') }}</span>
</template>
<template v-else-if="(leaderboardScoreRankingSystems).includes(props.rankingSystem as LeaderboardScoreRankingSystem)">
<div class="font-mono font-bold">
{{ numberFmt(score.score) }}
</div>
</template>
</div>
<div class="justify-end mt-auto text-sm md:text-md lg:text-md whitespace-nowrap">
<div class="text-right">
<template v-if="beatmap">
<span class="font-semibold align-middle">
{{ score.maxCombo }}
</span>
<span class="font-light align-middle">
/
</span>
<span class="align-middle">
{{ beatmap.properties.maxCombo }}
</span>
</template>
<span v-else class="align-middle">
</div>
<div class="relative flex">
<div class="flex flex-col">
<div class="flex items-center justify-end flex-grow text-lg sm:text-xl lg:text-2xl">
<template v-if="(ppRankingSystems).includes(props.rankingSystem as LeaderboardPPRankingSystem)">
<div class="font-mono font-bold">
{{ score.pp.toFixed(2) }}
</div>
<span class="font-light">{{ $t('global.pp') }}</span>
</template>
<template v-else-if="(leaderboardScoreRankingSystems).includes(props.rankingSystem as LeaderboardScoreRankingSystem)">
<div class="font-mono font-bold">
{{ numberFmt(score.score) }}
</div>
</template>
</div>
<div class="justify-end mt-auto text-sm md:text-md lg:text-md whitespace-nowrap">
<div class="text-right">
<template v-if="beatmap">
<span class="font-semibold align-middle">
{{ score.maxCombo }}
</span>
<span class="font-light align-middle">
x
/
</span>
</div>

<span class="text-right">
<span><b class="font-mono">{{ score.accuracy.toFixed(2) }}</b></span>
<span class="text-light">% {{ $t('global.acc') }}</span>
<span class="align-middle">
{{ beatmap.properties.maxCombo }}
</span>
</template>
<span v-else class="align-middle">
{{ score.maxCombo }}
</span>
<span class="font-light align-middle">
x
</span>
</div>

<span class="text-right">
<span><b class="font-mono">{{ score.accuracy.toFixed(2) }}</b></span>
<span class="text-light">% {{ $t('global.acc') }}</span>
</span>
</div>
<div class="font-mono text-4xl text-center md:text-5xl w-14 md:w-20">
{{ score.grade }}
</div>
</div>
<div class="font-mono text-4xl text-center md:text-5xl w-14 md:w-20">
{{ score.grade }}
</div>
</div>
</div>
Expand Down
98 changes: 48 additions & 50 deletions src/components/userpage/best-scores.vue
Original file line number Diff line number Diff line change
Expand Up @@ -178,61 +178,59 @@ de-DE:
{{ bpError }}
</div>
<template v-else-if="page.user">
<div class="space-y-6">
<section v-if="bp?.scores?.length">
<div class="card" :class="[pendingBP && 'pointer-events-none']">
<div class="p-1 two-tone flex items-center w-100">
<icon name="carbon:letter-pp" class="w-1/6" size="2em" />
<div class="w-2/3 flex">
<div class="text-3xl font-semibold mx-auto">
{{ t('bp') }}
</div>
<section v-if="bp?.scores?.length">
<div class="card" :class="[pendingBP && 'pointer-events-none']">
<div class="flex items-center p-1 two-tone w-100">
<icon name="carbon:letter-pp" class="w-1/6" size="2em" />
<div class="flex w-2/3">
<div class="mx-auto text-3xl font-semibold">
{{ t('bp') }}
</div>
</div>
<div
class="transition-[filter] transition-opacity duration-200" :class="{
'saturate-50 opacity-30': pendingBP,
}"
>
<div class="relative">
<transition :name="transition">
<ul
:key="bp.lastSwitcherStatus.mode
+ bp.lastSwitcherStatus.ruleset
+ stabilizeScoreRank(bp.lastSwitcherStatus.rankingSystem)
+ page.user.id
+ bp.page
"
>
<li v-for="i in bp.scores" :key="`bests-${i.id}`" class="score">
<app-score-list-item
:score="i" :mode="bp.lastSwitcherStatus.mode"
:ruleset="bp.lastSwitcherStatus.ruleset" :ranking-system="bp.lastSwitcherStatus.rankingSystem"
/>
</li>
</ul>
</transition>
</div>
</div>
<div
class="btn-group flex w-full bg-gbase-300/30 dark:bg-gbase-700/50 rounded-2xl shadow"
style="--rounded-btn: 1rem"
>
<button class="btn btn-ghost" :disabled="bpPage === 0" @click="prevBp">
«
</button>
<button class="btn btn-ghost grow" @click="refreshBP()">
{{ t('page', { page: bpPage + 1 }) }}
</button>
<button class="btn btn-ghost" :disabled="bp.scores.length < 10" @click="nextBp">
»
</button>
</div>
<div
class="transition-[filter] transition-opacity duration-200" :class="{
'saturate-50 opacity-30': pendingBP,
}"
>
<div class="relative">
<transition :name="transition">
<ul
:key="bp.lastSwitcherStatus.mode
+ bp.lastSwitcherStatus.ruleset
+ stabilizeScoreRank(bp.lastSwitcherStatus.rankingSystem)
+ page.user.id
+ bp.page
"
>
<li v-for="i in bp.scores" :key="`bests-${i.id}`" class="score">
<app-score-list-item
:score="i" :mode="bp.lastSwitcherStatus.mode"
:ruleset="bp.lastSwitcherStatus.ruleset" :ranking-system="bp.lastSwitcherStatus.rankingSystem"
/>
</li>
</ul>
</transition>
</div>
</div>
</section>
<div v-else-if="!bp?.scores.length && pendingBP">
{{ t('loading') }}
</div>
<div
class="flex w-full mt-1 rounded-lg shadow join bg-gbase-300/30 dark:bg-gbase-700/50"
style="--rounded-btn: 1rem"
>
<button class="join-item btn btn-ghost" :disabled="bpPage === 0" @click="prevBp">
«
</button>
<button class="join-item btn btn-ghost grow" @click="refreshBP()">
{{ t('page', { page: bpPage + 1 }) }}
</button>
<button class="join-item btn btn-ghost" :disabled="bp.scores.length < 10" @click="nextBp">
»
</button>
</div>
</section>
<div v-else-if="!bp?.scores.length && pendingBP">
{{ t('loading') }}
</div>
</template>
</template>
2 changes: 1 addition & 1 deletion src/components/userpage/score-rank-composition.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function createStyleObject(count: number) {
</script>

<template>
<div v-if="composition" class="dropdown dropdown-hover block">
<div v-if="composition" class="dropdown dropdown-hover block z-[2]">
<div
class="multi-progress-bar-container bg-emerald-200"
tabindex="0"
Expand Down
Loading

0 comments on commit 3c6d028

Please sign in to comment.