98 lines
1.8 KiB
Vue
98 lines
1.8 KiB
Vue
<template>
|
|
<view>
|
|
<view
|
|
class="action-sheet-mask"
|
|
:class="{ 'action-sheet-mask-show': show }"
|
|
@click="handleClose"
|
|
@touchmove.prevent
|
|
></view>
|
|
<view class="action-sheet pb-safe" :class="{ 'action-sheet-show': show }" @touchmove.prevent>
|
|
<view class="action-sheet-header" v-if="title">
|
|
<text class="action-sheet-title">{{ title }}</text>
|
|
</view>
|
|
<view class="action-sheet-content">
|
|
<slot></slot>
|
|
</view>
|
|
<view class="action-sheet-footer" v-if="$slots.footer">
|
|
<slot name="footer"></slot>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
defineProps<{
|
|
show: boolean
|
|
title?: string
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'update:show', value: boolean): void
|
|
}>()
|
|
|
|
const handleClose = () => {
|
|
emit('update:show', false)
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.action-sheet-mask {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
z-index: 999;
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
transition: all 0.3s ease;
|
|
|
|
&-show {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
}
|
|
}
|
|
|
|
.action-sheet {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: #fff;
|
|
transform: translateY(100%);
|
|
transition: all 0.3s ease;
|
|
z-index: 1000;
|
|
border-radius: 24rpx 24rpx 0 0;
|
|
|
|
&-show {
|
|
transform: translateY(0);
|
|
}
|
|
|
|
&-header {
|
|
padding: 24rpx 32rpx;
|
|
text-align: center;
|
|
position: relative;
|
|
border-bottom: 2rpx solid #f5f5f5;
|
|
}
|
|
|
|
&-title {
|
|
font-size: 32rpx;
|
|
font-weight: 500;
|
|
color: #333;
|
|
}
|
|
|
|
&-content {
|
|
max-height: 75vh;
|
|
overflow-y: auto;
|
|
min-height: 500rpx;
|
|
}
|
|
|
|
&-footer {
|
|
padding: 24rpx 32rpx;
|
|
border-top: 2rpx solid #f5f5f5;
|
|
box-shadow: 0rpx -8rpx 8rpx 0rpx rgba(225, 225, 225, 0.2);
|
|
}
|
|
}
|
|
</style>
|