Skip to content

Keyboard ​

17:06

Description ​

A custom keyboard that slides up from the bottom with three built-in layouts: number, ID card (card) and license plate (car). The top toolbar provides cancel and confirm; both collapse the keyboard before emitting confirm / cancel. Supports closing by tapping the mask, bottom safe-area adaptation, shuffled keys and custom toolbar text.

Compatibility ​

PlatformSupport
App✅ Supported
H5✅ Supported
WeChat Mini Program✅ Supported

Examples ​

Number Keyboard (mode="number") ​

The default number keyboard; dot-enabled controls the decimal point; tapping a key emits change and backspace fires on deletion.

View source
vue
<template>
    <view class="keyboard-display">
        <text>{{ inputValue.length > 0 ? inputValue : '请点击按钮唤起键盘' }}</text>
    </view>
    <ux-button type="primary" shape="round" text="打开数字键盘" @click="open" />
    <ux-keyboard v-model="show" mode="number" @change="onChange" @backspace="onBackspace" @confirm="onConfirm" @cancel="onCancel" />
    <ux-toast ref="toastRef" />
</template>

<script setup lang="uts">
const toastRef = ref<any>();
const show = ref(false);
const inputValue = ref('');

const open = () => {
    show.value = true;
};

const keyToString = (key: string | number): string => {
    return typeof key == 'number' ? (key as number).toString() : key as string;
};

const onChange = (key: string | number) => {
    inputValue.value = inputValue.value + keyToString(key);
};

const onBackspace = () => {
    inputValue.value = inputValue.length > 0 ? inputValue.substring(0, inputValue.length - 1) : '';
};

const onConfirm = () => {
    toastRef.value?.show?.({ title: '输入完成:' + inputValue.value, type: 'success', duration: 2000 });
};

const onCancel = () => {
    toastRef.value?.show?.({ title: '已取消输入', type: 'info', duration: 2000 });
};
</script>

<style scoped>
.keyboard-display {
    display: flex;
    flex-direction: row;
    align-items: center;
    padding: 12px 15px;
    border-radius: 6px;
    background-color: #f8f8f8;
    margin-bottom: 12px;
}
</style>

ID Card Keyboard (mode="card") ​

Adds an X key on top of the number layout, suitable for ID card input.

View source
vue
<template>
    <ux-button type="primary" shape="round" text="打开身份证键盘" @click="open" />
    <ux-keyboard v-model="show" mode="card" @change="onChange" @confirm="onConfirm" />
    <ux-toast ref="toastRef" />
</template>

<script setup lang="uts">
const toastRef = ref<any>();
const show = ref(false);
const inputValue = ref('');

const open = () => {
    show.value = true;
};

const onChange = (key: string | number) => {
    inputValue.value = inputValue.value + (typeof key == 'number' ? (key as number).toString() : key as string);
};

const onConfirm = () => {
    toastRef.value?.show?.({ title: '输入完成:' + inputValue.value, type: 'success', duration: 2000 });
};
</script>

Plate Keyboard (mode="car") ​

A mixed layout of province abbreviations, letters and digits, suitable for license plates.

View source
vue
<template>
    <ux-button type="primary" shape="round" text="打开车牌号键盘" @click="open" />
    <ux-keyboard v-model="show" mode="car" @change="onChange" @confirm="onConfirm" />
    <ux-toast ref="toastRef" />
</template>

<script setup lang="uts">
const toastRef = ref<any>();
const show = ref(false);
const inputValue = ref('');

const open = () => {
    show.value = true;
};

const onChange = (key: string | number) => {
    inputValue.value = inputValue.value + (typeof key == 'number' ? (key as number).toString() : key as string);
};

const onConfirm = () => {
    toastRef.value?.show?.({ title: '输入完成:' + inputValue.value, type: 'success', duration: 2000 });
};
</script>

Custom Labels & Keys ​

tips / cancel-text / confirm-text customize the toolbar labels; random shuffles the keys.

View source
vue
<template>
    <ux-button type="warning" shape="round" text="打乱按键并定制文案" @click="open" />
    <ux-keyboard
        v-model="show"
        mode="number"
        :random="true"
        tips="安全输入"
        cancel-text="重输"
        confirm-text="确定"
        @change="onChange"
        @backspace="onBackspace"
        @confirm="onConfirm"
        @cancel="onCancel"
    />
    <ux-toast ref="toastRef" />
</template>

<script setup lang="uts">
const toastRef = ref<any>();
const show = ref(false);
const inputValue = ref('');

const open = () => {
    show.value = true;
};

const onChange = (key: string | number) => {
    inputValue.value = inputValue.value + (typeof key == 'number' ? (key as number).toString() : key as string);
};

const onBackspace = () => {
    inputValue.value = inputValue.length > 0 ? inputValue.substring(0, inputValue.length - 1) : '';
};

const onConfirm = () => {
    toastRef.value?.show?.({ title: '输入完成:' + inputValue.value, type: 'success', duration: 2000 });
};

const onCancel = () => {
    toastRef.value?.show?.({ title: '已取消输入', type: 'info', duration: 2000 });
};
</script>

Toolbar & Mask Switches ​

tooltip hides the whole toolbar; show-tips / cancel-btn / confirm-btn control each element; mask / mask-close-able / dot-enabled control the mask and keys.

View source
vue
<template>
    <view class="keyboard-row">
        <ux-button custom-class="keyboard-item" type="success" size="small" shape="round" text="无工具条" @click="openBoard('noTooltip')" />
        <ux-button custom-class="keyboard-item" type="success" size="small" shape="round" text="隐藏提示与按钮" @click="openBoard('noTips')" />
        <ux-button custom-class="keyboard-item" type="success" size="small" shape="round" text="无遮罩无小数点" @click="openBoard('noMask')" />
    </view>
    <ux-keyboard
        v-model="show"
        mode="number"
        :tooltip="tooltip"
        :show-tips="showTips"
        :cancel-btn="cancelBtn"
        :confirm-btn="confirmBtn"
        :dot-enabled="dotEnabled"
        :mask="mask"
    />
</template>

<script setup lang="uts">
const show = ref(false);
const tooltip = ref(true);
const showTips = ref(true);
const cancelBtn = ref(true);
const confirmBtn = ref(true);
const dotEnabled = ref(true);
const mask = ref(true);

const openBoard = (kind: string) => {
    if (kind == 'noTooltip') {
        tooltip.value = false;
    } else if (kind == 'noTips') {
        showTips.value = false;
        cancelBtn.value = false;
        confirmBtn.value = false;
    } else {
        dotEnabled.value = false;
        mask.value = false;
    }
    show.value = true;
};
</script>

<style scoped>
.keyboard-row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}
.keyboard-item {
    margin-right: 8px;
    margin-bottom: 8px;
}
</style>

Safe Area & z-index ​

safe-area-inset-bottom adapts to the bottom safe area; z-index customizes the popup level.

View source
vue
<template>
    <ux-button type="info" shape="round" text="遮罩不可关 + 自定义层级" @click="open" />
    <ux-keyboard
        v-model="show"
        mode="number"
        :mask-close-able="false"
        :safe-area-inset-bottom="true"
        :z-index="9999"
    />
</template>

<script setup lang="uts">
const show = ref(false);

const open = () => {
    show.value = true;
};
</script>

API ​

Props ​

PropertyDescriptionTypeDefaultVersion
modeKeyboard type: number / card / carString'number'-
dotEnabledWhether to show the "." key; applies to number and card modesBooleantrue-
tooltipWhether to show the top toolbarBooleantrue-
showTipsWhether to show the hint in the middle of the toolbarBooleantrue-
tipsHint text; falls back to the localized default for the current modeString''-
cancelBtnWhether to show the cancel button on the left of the toolbarBooleantrue-
confirmBtnWhether to show the confirm button on the right of the toolbarBooleantrue-
randomWhether to shuffle key orderBooleanfalse-
safeAreaInsetBottomWhether to enable bottom safe-area adaptationBooleantrue-
maskCloseAbleWhether tapping the mask closes the keyboardBooleantrue-
modelValueControls keyboard visibility via v-modelBooleanfalse-
maskWhether to show the maskBooleantrue-
zIndexPopup z-index; falls back to the global popup layerString|Number--
cancelTextCancel button text; falls back to the localized defaultString''-
confirmTextConfirm button text; falls back to the localized defaultString''-
customClassCustom class for the root nodeString''-
customStyleCustom style for the root nodeObject|String--

Events ​

EventDescriptionParamsVersion
changeEmitted when a key is tapped, carrying the key valuevalue: string | number-
confirmEmitted when the toolbar confirm button is tapped--
cancelEmitted when the toolbar cancel button is tapped--
backspaceEmitted when backspace is tapped; long-pressing fires it repeatedly--

Slots ​

SlotDescriptionVersion
defaultCustom content above the toolbar at the top of the popup-

Notes ​

  1. Tapping confirm or cancel first writes modelValue=false to collapse the keyboard, then emits the matching event. Closing via the mask only emits update:modelValue and never fires cancel, so track the close source yourself if the difference matters.
  2. dotEnabled only affects number / card; the car layout is defined by the plate keyboard and ignores it.
  3. When tips / cancelText / confirmText are omitted, localized text is resolved from mode and the current locale and follows language changes; explicit values stay fixed.
  4. The default slot renders before the toolbar, so visually it sits above it — a good place for a title or extra hint.
  5. An empty zIndex falls back to the global popup layer. Mask closing is controlled by maskCloseAble; with mask=false there is neither a mask nor tap-to-close.
  6. Continuous backspace on long press is implemented by the inner number/plate keyboard; this component only forwards backspace.