Skip to content

Modal Component

A popup modal, commonly used for message prompts, message confirmation, and completing specific interactive operations within the current page.

📌 Platform Differences

APP(vue)H5WeChat Mini ProgramAlipay Mini Program

⚠️ Notes

Notes

  • When closeOnClickOverlay is enabled, clicking the overlay will only trigger the close event and will not automatically close the modal; you need to handle the closing logic yourself
  • The asyncClose and asyncCancelClose properties have been replaced by the loading and autoClose properties in the current implementation
  • When a custom slot is passed, the content property becomes invalid

🏯 Basic Usage Examples

Basic Modal

html
<template>
    <view>
        <hy-button text="Open Modal" @click="show = true"></hy-button>
        <hy-modal v-model="show" content="This is a basic modal"></hy-modal>
    </view>
</template>

<script setup>
    import { ref } from 'vue';

    const show = ref(false);
</script>
html
<template>
    <view>
        <hy-button text="Open Modal with Title" @click="show = true"></hy-button>
        <hy-modal
            v-model="show"
            title="System Notice"
            content="This is an important notice, please read it carefully."
            @confirm="show = false"
        ></hy-modal>
    </view>
</template>

<script setup>
    import { ref } from 'vue';

    const show = ref(false);
</script>

With Cancel Button

html
<template>
    <view>
        <hy-button text="Open Modal with Cancel Button" @click="show = true"></hy-button>
        <hy-modal
            v-model="show"
            title="Notice"
            content="Are you sure you want to perform this operation?"
            show-cancel-button
            @confirm="onConfirm"
            @cancel="show = false"
        ></hy-modal>
    </view>
</template>

<script setup>
    import { ref } from 'vue';

    const show = ref(false);

    const onConfirm = () => {
        uni.showToast({
            title: 'Confirmed',
            icon: 'success',
        });
        show.value = false;
    };
</script>

Swap Button Positions

html
<template>
    <view>
        <hy-button text="Open Modal with Swapped Buttons" @click="show = true"></hy-button>
        <hy-modal
            v-model="show"
            title="Notice"
            content="The cancel button is on the right, and the confirm button is on the left"
            show-cancel-button
            button-reverse
            @confirm="show = false"
            @cancel="show = false"
        ></hy-modal>
    </view>
</template>

<script setup>
    import { ref } from 'vue';

    const show = ref(false);
</script>

Close on Overlay Click

html
<template>
    <view>
        <hy-button text="Close on Overlay Click" @click="show = true"></hy-button>
        <hy-modal
            v-model="show"
            title="Notice"
            content="Click the overlay area to close the modal"
            close-on-click-overlay
            @close="show = false"
        ></hy-modal>
    </view>
</template>

<script setup>
    import { ref } from 'vue';

    const show = ref(false);
</script>

Control Modal Width

html
<template>
    <view>
        <hy-button text="Custom Width" @click="show = true"></hy-button>
        <hy-modal
            v-model="show"
            title="Custom Width"
            content="The modal width is 400rpx"
            width="400rpx"
            @confirm="show = false"
        ></hy-modal>
    </view>
</template>

<script setup>
    import { ref } from 'vue';

    const show = ref(false);
</script>

Async Close (with Loading State)

html
<template>
    <view>
        <hy-button text="Async Close" @click="show = true"></hy-button>
        <hy-modal
            v-model="show"
            title="Submitting"
            content="Processing your request, please wait..."
            :auto-close="false"
            :loading="loading"
            @confirm="onAsyncConfirm"
        ></hy-modal>
    </view>
</template>

<script setup>
    import { ref } from 'vue';

    const show = ref(false);
    const loading = ref(false);

    const onAsyncConfirm = () => {
        loading.value = true;
        // Simulate an async operation
        setTimeout(() => {
            uni.showToast({
                title: 'Operation successful',
                icon: 'success',
            });
            loading.value = false;
            show.value = false;
        }, 2000);
    };
</script>
html
<template>
    <view>
        <hy-button text="Open Form Modal" @click="show = true"></hy-button>
        <hy-modal
            v-model="show"
            title="Fill in Information"
            :auto-close="false"
            :loading="loading"
            @confirm="onSubmit"
            @cancel="show = false"
        >
            <view class="form-content">
                <view class="form-item">
                    <text class="form-label">Name</text>
                    <input v-model="formData.name" class="form-input" placeholder="Please enter a name" />
                </view>
                <view class="form-item">
                    <text class="form-label">Description</text>
                    <textarea
                        v-model="formData.desc"
                        class="form-textarea"
                        placeholder="Please enter a description"
                    />
                </view>
            </view>
        </hy-modal>
    </view>
</template>

<script setup>
    import { ref, reactive } from 'vue';

    const show = ref(false);
    const loading = ref(false);
    const formData = reactive({
        name: '',
        desc: '',
    });

    const onSubmit = () => {
        if (!formData.name) {
            uni.showToast({
                title: 'Please fill in the name',
                icon: 'none',
            });
            return;
        }

        loading.value = true;
        setTimeout(() => {
            uni.showToast({
                title: 'Submitted successfully',
                icon: 'success',
            });
            loading.value = false;
            show.value = false;
        }, 1500);
    };
</script>

<style scoped>
    .form-content {
        padding: 20rpx;
    }

    .form-item {
        margin-bottom: 30rpx;
    }

    .form-label {
        font-size: 28rpx;
        color: #333;
        display: block;
        margin-bottom: 15rpx;
    }

    .form-input {
        width: 100%;
        height: 80rpx;
        border: 1rpx solid #ddd;
        border-radius: 8rpx;
        padding: 0 20rpx;
        font-size: 28rpx;
    }

    .form-textarea {
        width: 100%;
        height: 160rpx;
        border: 1rpx solid #ddd;
        border-radius: 8rpx;
        padding: 20rpx;
        font-size: 28rpx;
    }
</style>

Custom Button Styles

html
<template>
    <view>
        <hy-button text="Custom Button Colors" @click="show = true"></hy-button>
        <hy-modal
            v-model="show"
            title="Custom Buttons"
            content="The confirm button is green, and the cancel button is gray"
            show-cancel-button
            confirm-color="#07c160"
            cancel-color="#999"
            @confirm="show = false"
            @cancel="show = false"
        ></hy-modal>
    </view>
</template>

<script setup>
    import { ref } from 'vue';

    const show = ref(false);
</script>

Disable Zoom Effect

html
<template>
    <view>
        <hy-button text="Disable Zoom Effect" @click="show = true"></hy-button>
        <hy-modal
            v-model="show"
            title="No Zoom Effect"
            content="No zoom animation when opening and closing"
            :zoom="false"
            @confirm="show = false"
        ></hy-modal>
    </view>
</template>

<script setup>
    import { ref } from 'vue';

    const show = ref(false);
</script>

Custom Border Radius

html
<template>
    <view>
        <hy-button text="Custom Border Radius" @click="show = true"></hy-button>
        <hy-modal
            v-model="show"
            title="Custom Border Radius"
            content="The border radius is 30rpx"
            round="30rpx"
            @confirm="show = false"
        ></hy-modal>
    </view>
</template>

<script setup>
    import { ref } from 'vue';

    const show = ref(false);
</script>

API

Props

ParameterDescriptionTypeDefault
modelValueWhether to show the modalbooleanfalse
titleTitle contentstring-
contentModal content; invalid if slot content is passedstring-
confirmTextText of the confirm buttonstringConfirm
cancelTextText of the cancel buttonstringCancel
showConfirmButtonWhether to show the confirm buttonbooleantrue
showCancelButtonWhether to show the cancel buttonbooleanfalse
confirmColorColor of the confirm buttonstring-
cancelColorColor of the cancel buttonstring-
buttonReverseSwap the positions of the confirm and cancel buttonsbooleanfalse
zoomWhether to enable zoom modebooleantrue
roundModal border radius; supports number, px, and rpx unitsstring|number16
autoCloseWhether to close automatically after clicking the confirm buttonbooleantrue
loadingWhether to show the loading statebooleanfalse
closeOnClickOverlayWhether to allow closing the modal by clicking the overlay (Note: the close event must be handled manually; the close callback is only triggered when clicking the overlay layer after closeOnClickOverlay is enabled)booleanfalse
negativeTopUpward offset value; applies a negative margin-top to shift the modal upward, avoiding overlap with the keyboard; default unit is pxnumber0
widthModal width; percentages are not supported; default unit is px for numeric values, rpx is supportedstring|number550rpx
confirmButtonShapeConfirm button style; when set, the cancel button will not be displayed; optional values: circle, squarestring-
contentTextAlignText alignment; optional values: left, center, rightstringleft
customStyleCustom external styles to be appliedCSSProperties-
customClassCustom external class namestring-

Events

Event NameDescriptionCallback Parameters
confirmTriggered when the confirm button is clicked-
cancelTriggered when the cancel button is clicked-
closeTriggered when closing by clicking the overlay; only valid when closeOnClickOverlay is true-

Slots

Slot NameDescriptionAccepted Values
defaultPass custom content, overriding the content property-
confirmButtonPass a custom button, used in scenarios where authorization via button is required in WeChat Mini Program popups-
03:29