diff --git a/packages/vuetify/src/components/VTextarea/VTextarea.sass b/packages/vuetify/src/components/VTextarea/VTextarea.sass index b9bce78586b..f97c74aa3e2 100644 --- a/packages/vuetify/src/components/VTextarea/VTextarea.sass +++ b/packages/vuetify/src/components/VTextarea/VTextarea.sass @@ -15,11 +15,13 @@ .v-field__input $a: calc((var(--v-field-padding-top, 0) + var(--v-input-padding-top, 0)) - 6px) $b: calc(var(--v-field-padding-top, 0) + var(--v-input-padding-top, 0) + 4px) + $c: calc(100% - var(--v-textarea-scroll-bar-width, 16px)) flex: 1 1 auto outline: none - -webkit-mask-image: linear-gradient(to bottom, transparent, transparent $a, black $b) - mask-image: linear-gradient(to bottom, transparent, transparent $a, black $b) + + -webkit-mask-image: linear-gradient(to bottom, transparent, transparent $a, black $b), linear-gradient(to right, transparent, transparent $c, black $c) + mask-image: linear-gradient(to bottom, transparent, transparent $a, black $b), linear-gradient(to right, transparent, transparent $c, black $c) &.v-textarea__sizer visibility: hidden diff --git a/packages/vuetify/src/components/VTextarea/VTextarea.tsx b/packages/vuetify/src/components/VTextarea/VTextarea.tsx index c5b6d5db648..8746445e6f2 100644 --- a/packages/vuetify/src/components/VTextarea/VTextarea.tsx +++ b/packages/vuetify/src/components/VTextarea/VTextarea.tsx @@ -9,6 +9,7 @@ import { makeVFieldProps } from '@/components/VField/VField' import { makeVInputProps, VInput } from '@/components/VInput/VInput' // Composables +import { useDisplay } from '@/composables' import { makeAutocompleteProps, useAutocomplete } from '@/composables/autocomplete' import { useAutofocus } from '@/composables/autofocus' import { useFocus } from '@/composables/focus' @@ -101,6 +102,8 @@ export const VTextarea = genericComponent()({ const vFieldRef = ref() const controlHeight = shallowRef('') const textareaRef = ref() + const scrollbarWidth = ref(0) + const { platform } = useDisplay() const autocomplete = useAutocomplete(props) const isActive = computed(() => ( props.persistentPlaceholder || @@ -157,6 +160,16 @@ export const VTextarea = genericComponent()({ if (!props.autoGrow) rows.value = Number(props.rows) }) function calculateInputHeight () { + nextTick(() => { + if (!textareaRef.value) return + if (platform.value.firefox) { + scrollbarWidth.value = 12 + return + } + const { offsetWidth, clientWidth } = textareaRef.value + scrollbarWidth.value = Math.max(0, offsetWidth - clientWidth) + }) + if (!props.autoGrow) return nextTick(() => { @@ -232,7 +245,12 @@ export const VTextarea = genericComponent()({ }, props.class, ]} - style={ props.style } + style={[ + { + '--v-textarea-scroll-bar-width': convertToUnit(scrollbarWidth.value), + }, + props.style, + ]} { ...rootAttrs } { ...inputProps } centerAffix={ rows.value === 1 && !isPlainOrUnderlined.value }