WithCharacterLimit

View source
An input component with character limit and live counter display.

Introduction

MWithCharacterLimit is an input component with a character limit and real-time counter display. It shows the current character count and maximum limit to the right of the input field, helping users control input length.

Built on Nuxt UI's Input component

Usage

Default limit is 50 characters, with current/max count displayed in real time on the right:

23/50
<script setup lang="ts">
const value = ref("Type up to the limit...")
</script>

<template>
  <MWithCharacterLimit v-model="value" />
</template>

maxLength Character Limit

Set the maximum character count via maxLength:

0/10
<template>
  <MWithCharacterLimit :max-length="10" />
</template>

leadingIcon Leading Icon

Add a semantic icon to the input via leadingIcon:

0/50
<template>
  <MWithCharacterLimit leading-icon="i-lucide-message-square" />
</template>

size Size

Switch input and counter size via size:

0/50
<template>
  <MWithCharacterLimit size="md" />
</template>

ui Styles

Customize the counter style via ui.counter:

0/100
<template>
  <MWithCharacterLimit :max-length="100" :ui="{ counter: 'text-success' }" />
</template>

API

Props

Prop Default Type
as'div'any

The element or component this component should render as.

maxLength50number

最大允许输入的字符数

idstring
namestring
type"number" | "color" | "button" | "checkbox" | "date" | "datetime-local" | "email" | "file" | "hidden" | "image" | "month" | "password" | "radio" | "range" | "reset" | "search" | "submit" | "tel" | "text" | "time" | "url" | "week" | string & {}
placeholderstring

The placeholder text when the input is empty.

color'primary'"primary" | "secondary" | "info" | "success" | "warning" | "error" | "important" | "neutral"
variant'outline'"outline" | "soft" | "subtle" | "ghost" | "none"
size'md'"xs" | "sm" | "md" | "lg" | "xl"
autocompletestring & {} | "on" | "off"
autofocusDelaynumber
defaultValueT
modelModifiersModelModifiers
iconany

Display an icon based on the leading and trailing props.

avatarAvatarProps

Display an avatar on the left side.

leadingIconany

Display an icon on the left side.

trailingIconany

Display an icon on the right side.

loadingIconappConfig.ui.icons.loadingany

The icon when the loading prop is true.

liststring
maxstring | number
maxlengthstring | number
minstring | number
minlengthstring | number
patternstring
readonlyfalse | true | "true" | "false"
stepstring | number
modelValueT
requiredboolean
autofocusboolean
disabledboolean
highlightboolean

Highlight the ring color like a focus state.

fixedboolean

Keep the mobile text size on all breakpoints.

leadingboolean

When true, the icon will be displayed on the left side.

trailingboolean

When true, the icon will be displayed on the right side.

loadingboolean

When true, the loading icon will be displayed.

uiRecord<string, ClassNameValue> & { root?: SlotClass; base?: SlotClass; leading?: SlotClass; leadingIcon?: SlotClass; leadingAvatar?: SlotClass; leadingAvatarSize?: SlotClass; trailing?: SlotClass; trailingIcon?: SlotClass; counter?: SlotClass; }

Emits

Event Type
update:modelValue[value: T]
blur[event: FocusEvent]
change[event: Event]

Slots

Slot Type
leading{ ui: { root: (props?: Record<string, any>) => string; base: (props?: Record<string, any>) => string; leading: (props?: Record<string, any>) => string; leadingIcon: (props?: Record<string, any>) => string; leadingAvatar: (props?: Record<string, any>) => string; leadingAvatarSize: (props?: Record<string, any>) => string; trailing: (props?: Record<string, any>) => string; trailingIcon: (props?: Record<string, any>) => string; }; }
default{ ui: { root: (props?: Record<string, any>) => string; base: (props?: Record<string, any>) => string; leading: (props?: Record<string, any>) => string; leadingIcon: (props?: Record<string, any>) => string; leadingAvatar: (props?: Record<string, any>) => string; leadingAvatarSize: (props?: Record<string, any>) => string; trailing: (props?: Record<string, any>) => string; trailingIcon: (props?: Record<string, any>) => string; }; }

Theme

app.config.ts
export default defineAppConfig({
  ui: {
    withCharacterLimit: {
      slots: {
        trailing: 'pointer-events-none',
        counter: 'text-xs text-muted tabular-nums'
      }
    }
  }
})

Changelog

No recent changes
Copyright © 2025 - 2026 YiXuan - MIT License