Skip to content

fix(VTextField): hide-details="auto" with counter (#19998)#22620

Open
Yanis-Riani wants to merge 2 commits into
vuetifyjs:masterfrom
Yanis-Riani:fix/19998-hide-details-auto-counter
Open

fix(VTextField): hide-details="auto" with counter (#19998)#22620
Yanis-Riani wants to merge 2 commits into
vuetifyjs:masterfrom
Yanis-Riani:fix/19998-hide-details-auto-counter

Conversation

@Yanis-Riani
Copy link
Copy Markdown
Contributor

Description

Fixes #19998

When using hide-details="auto" with the counter prop on VTextField, VTextarea, or VFileInput, the .v-input__details section remains visible as blank space even when there are no messages and the field is not focused.

Root cause

VTextField always provides VInput's details slot when a counter exists, regardless of whether the counter is actually visible. VCounter handles its own visibility internally via v-show (through the active prop), but the slot function itself is always passed to VInput. Since VInput's auto logic checks !!slots.details to determine if there is content to show, the details section never hides.

What this PR does

In VTextField, VTextarea, and VFileInput, the details slot is now only provided when the counter is actually active or when hideDetails is not "auto":

const hasDetails = !!(
  (hasCounter && (props.hideDetails !== 'auto' ||
    props.persistentCounter || isFocused.value)) ||
  slots.details
)
  • Normal mode (hideDetails unset): no change in behavior, counter transitions work as before.
  • Auto mode, focused: details slot is provided, counter is visible.
  • Auto mode, not focused, no messages: details slot is not provided, no blank space.
  • Auto mode, with error messages: details are shown by VInput via hasMessages.

Known limitation

This is a partial fix. When hideDetails="auto" and error messages are already visible, the counter is not in the DOM. Focusing the field mounts the counter fresh instead of transitioning it via v-show. The counter appears instantly rather than sliding in.

Toward a complete solution

The root issue is that communication between VInput and its children is unidirectional. Children can influence the auto mode by providing a details slot (!!slots.details), and they manage their own content visibility internally (e.g. VCounter uses v-show via active). But children have no way to know whether VInput is already displaying details (e.g. due to error messages). This means a child like VTextField cannot decide to keep its counter in the DOM for transitions while also preventing the blank space in auto mode.

A complete fix would require bidirectional communication — allowing children to both influence the auto behavior and react to VInput's details state (e.g. via provide/inject). I intentionally kept this PR scoped to avoid potential breaking changes in VInput without futher guidance.

Markup

<template>
  <v-app>
    <v-container>
      <p>Counter only</p>
      <v-text-field
        v-model="msg"
        :rules="[requiredValidator]"
        class="bg-indigo-lighten-2"
        hint="usefull hint"
        variant="outlined"
        counter
      />
      <p>Counter & hide details</p>
      <v-text-field
        v-model="msg"
        :rules="[requiredValidator]"
        class="bg-indigo-lighten-2"
        hide-details="auto"
        hint="usefull hint"
        variant="outlined"
        counter
      />
      <p>Error & counter & hide details (should have transition)</p>
      <v-text-field
        v-model="msg"
        class="bg-indigo-lighten-2"
        error-messages="I hate you"
        hide-details="auto"
        hint="usefull hint"
        variant="outlined"
        counter
      />
      <p>Normal behavior</p>
      <v-text-field
        v-model="msg"
        :rules="[requiredValidator]"
        class="bg-indigo-lighten-2"
        hide-details="auto"
        hint="usefull hint"
        variant="outlined"
      />
    </v-container>
  </v-app>
</template>

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

const msg = ref("Hello World!");

const requiredValidator = (value) => {
  return !!String(value).trim().length || "This field is required";
};
</script>

When using hide-details="auto" with the counter prop, the details
section was always visible because VInput's auto logic considers
slots.details as content to show. VTextField always provides this
slot when a counter exists, causing a permanent blank space.

Only provide the details slot when the counter is actually active
(focused or persistentCounter) or when hideDetails is not "auto".
Apply the same fix to VTextarea and VFileInput.

resolves vuetifyjs#19998
@Yanis-Riani Yanis-Riani marked this pull request as draft February 15, 2026 12:05
@Yanis-Riani Yanis-Riani marked this pull request as ready for review February 18, 2026 12:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug Report][3.6.9] V-input with counter and hide-details='auto' Fails to Fully Hide Details

1 participant