mirror of
https://github.com/Coldsmiles/infstarweb.git
synced 2026-04-23 02:30:41 +08:00
feat: add shared components for donation, facility, feature bento, filter panel, join wizard, leaderboard, player, playstyle, and town cards
- Implemented DonationCard.vue for displaying donation details. - Created FacilityCard.vue to showcase facility information with status badges. - Developed FeatureBentoCard.vue and FeatureBentoGrid.vue for feature display in a grid layout. - Added FilterPanel.vue for filtering content with search and tag options. - Introduced JoinWizard.vue for a step-by-step joining process with device and playstyle selection. - Created LeaderboardCard.vue to display leaderboard information. - Implemented PlayerCard.vue for showcasing player profiles and stats. - Developed PlaystyleCard.vue for selecting playstyle options. - Added TownCard.vue to present town details with badges and images. - Included demo data in demoData.js for testing and development purposes.
This commit is contained in:
144
src/components/layout/MobileNavDrawer.vue
Normal file
144
src/components/layout/MobileNavDrawer.vue
Normal file
@@ -0,0 +1,144 @@
|
||||
<script setup>
|
||||
defineProps({
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
items: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
ctaLabel: {
|
||||
type: String,
|
||||
default: '加入游戏',
|
||||
},
|
||||
ctaHref: {
|
||||
type: String,
|
||||
default: '/join',
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<transition name="drawer-fade">
|
||||
<div v-if="open" class="mobile-drawer-mask" @click="emit('close')">
|
||||
<aside class="mobile-drawer" @click.stop>
|
||||
<div class="mobile-drawer__header">
|
||||
<p>站点导航</p>
|
||||
<button type="button" class="mobile-drawer__close" aria-label="关闭菜单" @click="emit('close')">
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
<nav class="mobile-drawer__links" aria-label="移动端导航">
|
||||
<a
|
||||
v-for="item in items"
|
||||
:key="item.href"
|
||||
class="mobile-drawer__link"
|
||||
:href="item.href"
|
||||
@click="emit('close')"
|
||||
>
|
||||
<span>{{ item.label }}</span>
|
||||
<small v-if="item.description">{{ item.description }}</small>
|
||||
</a>
|
||||
</nav>
|
||||
<a class="mobile-drawer__cta" :href="ctaHref" @click="emit('close')">{{ ctaLabel }}</a>
|
||||
</aside>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.drawer-fade-enter-active,
|
||||
.drawer-fade-leave-active {
|
||||
transition: opacity 0.25s ease;
|
||||
}
|
||||
|
||||
.drawer-fade-enter-from,
|
||||
.drawer-fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.mobile-drawer-mask {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1200;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
background: rgba(15, 23, 42, 0.28);
|
||||
backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
.mobile-drawer {
|
||||
width: min(360px, 100%);
|
||||
height: 100%;
|
||||
padding: 24px 20px 28px;
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
box-shadow: -20px 0 60px rgba(15, 23, 42, 0.16);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mobile-drawer__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.mobile-drawer__header p {
|
||||
margin: 0;
|
||||
font-size: 0.9rem;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--bl-text-tertiary);
|
||||
}
|
||||
|
||||
.mobile-drawer__close {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background: var(--bl-surface-muted);
|
||||
font-size: 1.4rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mobile-drawer__links {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.mobile-drawer__link {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
padding: 14px 16px;
|
||||
border-radius: var(--bl-radius-md);
|
||||
background: #fff;
|
||||
text-decoration: none;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.mobile-drawer__link span {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.mobile-drawer__link small {
|
||||
color: var(--bl-text-secondary);
|
||||
}
|
||||
|
||||
.mobile-drawer__cta {
|
||||
margin-top: auto;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 48px;
|
||||
border-radius: 999px;
|
||||
background: var(--bl-accent);
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user