feat: profile banner
This commit is contained in:
parent
b49956c708
commit
f557fe3d4f
4 changed files with 171 additions and 0 deletions
BIN
public/blank-cover.png
Normal file
BIN
public/blank-cover.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
169
src/components/ProfileBanner.vue
Normal file
169
src/components/ProfileBanner.vue
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
defineProps<{
|
||||
icon?: string;
|
||||
color?: string;
|
||||
img?: string;
|
||||
bgColor?: string;
|
||||
title?: string;
|
||||
caption?: string;
|
||||
cover?: string;
|
||||
|
||||
hideFade?: boolean;
|
||||
active?: boolean;
|
||||
readonly?: boolean;
|
||||
|
||||
menu?: { icon: string; color: string; bgColor: string }[];
|
||||
}>();
|
||||
|
||||
defineEmits<{
|
||||
(e: 'view'): void;
|
||||
(e: 'edit'): void;
|
||||
}>();
|
||||
|
||||
const showOverlay = ref(false);
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
class="cover rounded bordered relative-position"
|
||||
:style="`background-image: linear-gradient(
|
||||
90deg, ${
|
||||
$q.dark.isActive
|
||||
? `hsla(var(--gray-10-hsl) / ${hideFade ? '0' : '1'}) 10%,hsla(var(--gray-10-hsl) / 0) 100%`
|
||||
: `rgba(255, 255, 255, ${hideFade ? '0' : '1'}) 10%,rgba(255, 255, 255, 0) 100%`
|
||||
}
|
||||
),
|
||||
url(${cover || 'blank-cover.png'});`"
|
||||
>
|
||||
<!-- profile -->
|
||||
<div class="absolute-top flex items-center full-height q-pl-lg">
|
||||
<div
|
||||
class="surface-1"
|
||||
style="border-radius: 50%; border: 4px solid var(--surface-1)"
|
||||
>
|
||||
<div
|
||||
class="avatar__status"
|
||||
style="z-index: 2"
|
||||
:style="`${active ? 'background-color: hsla(var(--positive-bg) / 1)' : 'background-color: hsla(var(--text-mute) / 1)'}`"
|
||||
></div>
|
||||
<q-avatar
|
||||
size="6rem"
|
||||
font-size="3rem"
|
||||
class="cursor-pointer"
|
||||
style="z-index: 1; overflow: hidden"
|
||||
:style="`background-color: ${img ? 'white' : bgColor || 'var(--brand-1)'}; color: ${color || 'white'}`"
|
||||
@mouseover="showOverlay = true"
|
||||
@mouseleave="showOverlay = false"
|
||||
@click.stop="$emit('view')"
|
||||
>
|
||||
<q-img v-if="img" :src="img" :ratio="1" />
|
||||
<q-icon v-if="!img" :name="icon || 'mdi-account'" />
|
||||
|
||||
<Transition name="slide-fade">
|
||||
<div
|
||||
v-if="showOverlay && !readonly"
|
||||
class="absolute-bottom text-caption flex items-center justify-center upload-overlay"
|
||||
:class="{ dark: $q.dark.isActive }"
|
||||
@click.stop="$emit('edit')"
|
||||
>
|
||||
{{ $t('editImage') }}
|
||||
</div>
|
||||
</Transition>
|
||||
</q-avatar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- text -->
|
||||
<div
|
||||
class="absolute-bottom relative-position justify-between row text-cover"
|
||||
:class="{ dark: $q.dark.isActive }"
|
||||
>
|
||||
<div class="column">
|
||||
<span class="text-bold q-pt-xs text-body1">{{ title }}</span>
|
||||
<span class="app-text-muted">{{ caption }}</span>
|
||||
</div>
|
||||
|
||||
<!-- icon -->
|
||||
<div class="row items-center q-pr-lg">
|
||||
<div class="q-gutter-x-sm">
|
||||
<q-btn
|
||||
v-for="(item, n) in menu"
|
||||
:key="n"
|
||||
flat
|
||||
size="sm"
|
||||
class="q-pa-xs rounded"
|
||||
:icon="item.icon"
|
||||
:style="`background-color: ${item.bgColor}; color: ${item.color}`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.cover {
|
||||
height: 15vh;
|
||||
overflow: hidden;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: top center;
|
||||
}
|
||||
|
||||
.text-cover {
|
||||
height: 7.5vh;
|
||||
padding-left: 150px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(255, 255, 255, 1) 35%,
|
||||
rgba(255, 255, 255, 0.5) 100%
|
||||
);
|
||||
backdrop-filter: blur(11.2px);
|
||||
-webkit-backdrop-filter: blur(11.2px);
|
||||
|
||||
&.dark {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
hsla(var(--gray-10-hsl) / 1) 35%,
|
||||
hsla(var(--gray-10-hsl) / 0.3) 100%
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.avatar__status {
|
||||
content: ' ';
|
||||
display: block;
|
||||
block-size: 1rem;
|
||||
aspect-ratio: 1;
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
left: 6.5rem;
|
||||
border: 1px solid var(--surface-1);
|
||||
top: calc(80% - 1.2rem);
|
||||
}
|
||||
|
||||
.upload-overlay {
|
||||
top: 3.5rem;
|
||||
background-color: hsla(var(--gray-10-hsl) / 0.2);
|
||||
backdrop-filter: blur(8px);
|
||||
color: white;
|
||||
|
||||
&.dark {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.slide-fade-enter-active {
|
||||
transition: all 0.15s ease-out;
|
||||
}
|
||||
|
||||
.slide-fade-leave-active {
|
||||
transition: all 0.15s cubic-bezier(1, 0.5, 0.8, 1);
|
||||
}
|
||||
|
||||
.slide-fade-enter-from,
|
||||
.slide-fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -67,6 +67,7 @@ export default {
|
|||
createdAt: 'Created At',
|
||||
noResults: 'No Data',
|
||||
notRecorded: 'You have not yet saved.',
|
||||
editImage: 'Edit Image',
|
||||
...status,
|
||||
...main,
|
||||
...address,
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ export default {
|
|||
createdAt: 'สร้างเมื่อ',
|
||||
noResults: 'ไม่มีข้อมูล',
|
||||
notRecorded: 'คุณยังไม่ได้บันทึก',
|
||||
editImage: 'แก้ไขรูป',
|
||||
...status,
|
||||
...main,
|
||||
...address,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue