From c9dfbd51c83b4fbc792e393a68ad7f6f28155ff6 Mon Sep 17 00:00:00 2001 From: Yuchao Wu Date: Thu, 27 Jun 2024 09:51:41 +1000 Subject: [PATCH 1/5] fix(VField/VInput): centerAffix doesn't work for underlined/filled --- .../vuetify/src/components/VField/VField.sass | 13 ++++++------ .../vuetify/src/components/VField/VField.tsx | 2 +- .../vuetify/src/components/VInput/VInput.sass | 20 +++++++++---------- .../vuetify/src/components/VInput/VInput.tsx | 2 +- .../src/components/VTextField/VTextField.tsx | 3 ++- .../src/components/VTextarea/VTextarea.tsx | 4 ++-- 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/packages/vuetify/src/components/VField/VField.sass b/packages/vuetify/src/components/VField/VField.sass index 051542e5bdb..57a8094a375 100644 --- a/packages/vuetify/src/components/VField/VField.sass +++ b/packages/vuetify/src/components/VField/VField.sass @@ -197,12 +197,13 @@ .v-field.v-field--variant-underlined, .v-field.v-field--variant-plain - .v-field__append-inner, - .v-field__clearable, - .v-field__prepend-inner - align-items: flex-start - padding-top: $field-input-padding-top - padding-bottom: $field-input-padding-bottom + &:not(.v-field--center-affix) + .v-field__append-inner, + .v-field__clearable, + .v-field__prepend-inner + align-items: flex-start + padding-top: $field-input-padding-top + padding-bottom: $field-input-padding-bottom .v-field__prepend-inner, .v-field__append-inner diff --git a/packages/vuetify/src/components/VField/VField.tsx b/packages/vuetify/src/components/VField/VField.tsx index b3d658c127a..b1049df476e 100644 --- a/packages/vuetify/src/components/VField/VField.tsx +++ b/packages/vuetify/src/components/VField/VField.tsx @@ -64,7 +64,7 @@ export const makeVFieldProps = propsFactory({ active: Boolean, centerAffix: { type: Boolean, - default: undefined, + default: false, }, color: String, baseColor: String, diff --git a/packages/vuetify/src/components/VInput/VInput.sass b/packages/vuetify/src/components/VInput/VInput.sass index 11ded05238b..344c9bb2e9e 100644 --- a/packages/vuetify/src/components/VInput/VInput.sass +++ b/packages/vuetify/src/components/VInput/VInput.sass @@ -104,13 +104,13 @@ -moz-appearance: textfield &--plain-underlined - - .v-input__prepend, - .v-input__append - $this: & - align-items: flex-start - - @at-root - @include tools.density('v-input', $input-density) using ($modifier) - @at-root #{selector.append(&, $this)} - padding-top: calc(var(--v-input-padding-top) + #{math.max(0px, 4px + $modifier * .25)}) + &:not(.v-input--center-affix) + .v-input__prepend, + .v-input__append + $this: & + align-items: flex-start + + @at-root + @include tools.density('v-input', $input-density) using ($modifier) + @at-root #{selector.append(&, $this)} + padding-top: calc(var(--v-input-padding-top) + #{math.max(0px, 4px + $modifier * .25)}) diff --git a/packages/vuetify/src/components/VInput/VInput.tsx b/packages/vuetify/src/components/VInput/VInput.tsx index 4234aeb0aad..39cfcc4edce 100644 --- a/packages/vuetify/src/components/VInput/VInput.tsx +++ b/packages/vuetify/src/components/VInput/VInput.tsx @@ -42,7 +42,7 @@ export const makeVInputProps = propsFactory({ appendIcon: IconValue, centerAffix: { type: Boolean, - default: true, + default: false, }, prependIcon: IconValue, hideDetails: [Boolean, String] as PropType, diff --git a/packages/vuetify/src/components/VTextField/VTextField.tsx b/packages/vuetify/src/components/VTextField/VTextField.tsx index c2f09caf664..60dc1a9f291 100644 --- a/packages/vuetify/src/components/VTextField/VTextField.tsx +++ b/packages/vuetify/src/components/VTextField/VTextField.tsx @@ -176,7 +176,7 @@ export const VTextField = genericComponent()({ style={ props.style } { ...rootAttrs } { ...inputProps } - centerAffix={ !isPlainOrUnderlined.value } + centerAffix={ props.centerAffix } focused={ isFocused.value } > {{ @@ -202,6 +202,7 @@ export const VTextField = genericComponent()({ dirty={ isDirty.value || props.dirty } disabled={ isDisabled.value } focused={ isFocused.value } + centerAffix={ props.centerAffix } error={ isValid.value === false } > {{ diff --git a/packages/vuetify/src/components/VTextarea/VTextarea.tsx b/packages/vuetify/src/components/VTextarea/VTextarea.tsx index 3d8a93007a1..0a9d23ce875 100644 --- a/packages/vuetify/src/components/VTextarea/VTextarea.tsx +++ b/packages/vuetify/src/components/VTextarea/VTextarea.tsx @@ -228,7 +228,7 @@ export const VTextarea = genericComponent()({ style={ props.style } { ...rootAttrs } { ...inputProps } - centerAffix={ rows.value === 1 && !isPlainOrUnderlined.value } + centerAffix={ props.centerAffix ?? (rows.value === 1 && !isPlainOrUnderlined.value) } focused={ isFocused.value } > {{ @@ -253,7 +253,7 @@ export const VTextarea = genericComponent()({ { ...fieldProps } id={ id.value } active={ isActive.value || isDirty.value } - centerAffix={ rows.value === 1 && !isPlainOrUnderlined.value } + centerAffix={ props.centerAffix ?? (rows.value === 1 && !isPlainOrUnderlined.value) } dirty={ isDirty.value || props.dirty } disabled={ isDisabled.value } focused={ isFocused.value } From 411bee05b8917d2daf74a99b990e86ac49725673 Mon Sep 17 00:00:00 2001 From: Yuchao Wu Date: Thu, 27 Jun 2024 11:05:05 +1000 Subject: [PATCH 2/5] refactor: improve code quality --- packages/vuetify/src/components/VInput/VInput.tsx | 2 +- packages/vuetify/src/components/VTextarea/VTextarea.tsx | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/vuetify/src/components/VInput/VInput.tsx b/packages/vuetify/src/components/VInput/VInput.tsx index 39cfcc4edce..4234aeb0aad 100644 --- a/packages/vuetify/src/components/VInput/VInput.tsx +++ b/packages/vuetify/src/components/VInput/VInput.tsx @@ -42,7 +42,7 @@ export const makeVInputProps = propsFactory({ appendIcon: IconValue, centerAffix: { type: Boolean, - default: false, + default: true, }, prependIcon: IconValue, hideDetails: [Boolean, String] as PropType, diff --git a/packages/vuetify/src/components/VTextarea/VTextarea.tsx b/packages/vuetify/src/components/VTextarea/VTextarea.tsx index 0a9d23ce875..173f9192621 100644 --- a/packages/vuetify/src/components/VTextarea/VTextarea.tsx +++ b/packages/vuetify/src/components/VTextarea/VTextarea.tsx @@ -152,6 +152,7 @@ export const VTextarea = genericComponent()({ const sizerRef = ref() const rows = ref(+props.rows) const isPlainOrUnderlined = computed(() => ['plain', 'underlined'].includes(props.variant)) + const isCenterAffix = computed(() => props.centerAffix ?? (rows.value === 1 && !isPlainOrUnderlined.value)) watchEffect(() => { if (!props.autoGrow) rows.value = +props.rows }) @@ -228,7 +229,7 @@ export const VTextarea = genericComponent()({ style={ props.style } { ...rootAttrs } { ...inputProps } - centerAffix={ props.centerAffix ?? (rows.value === 1 && !isPlainOrUnderlined.value) } + centerAffix={ isCenterAffix.value } focused={ isFocused.value } > {{ @@ -253,7 +254,7 @@ export const VTextarea = genericComponent()({ { ...fieldProps } id={ id.value } active={ isActive.value || isDirty.value } - centerAffix={ props.centerAffix ?? (rows.value === 1 && !isPlainOrUnderlined.value) } + centerAffix={ isCenterAffix.value } dirty={ isDirty.value || props.dirty } disabled={ isDisabled.value } focused={ isFocused.value } From e02337c1b6299ab01e85b5cf965856e4d4078c66 Mon Sep 17 00:00:00 2001 From: Yuchao Wu Date: Thu, 27 Jun 2024 11:08:26 +1000 Subject: [PATCH 3/5] chore: update doc --- packages/api-generator/src/locale/en/VInput.json | 2 +- packages/api-generator/src/locale/en/VTextField.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/api-generator/src/locale/en/VInput.json b/packages/api-generator/src/locale/en/VInput.json index 47f3a7804c3..d6f181d023a 100644 --- a/packages/api-generator/src/locale/en/VInput.json +++ b/packages/api-generator/src/locale/en/VInput.json @@ -1,7 +1,7 @@ { "props": { "backgroundColor": "Changes the background-color of the input.", - "centerAffix": "Vertically align **appendInner**, **prependInner**, **clearIcon** and **label** in the center.", + "centerAffix": "Vertically align **append** and **prepend** in the center.", "direction": "Changes the direction of the input.", "hideDetails": "Hides hint and validation errors. When set to `auto` messages will be rendered only if there's a message (hint, error message, counter value etc) to display.", "hideSpinButtons": "Hides spin buttons on the input when type is set to `number`.", diff --git a/packages/api-generator/src/locale/en/VTextField.json b/packages/api-generator/src/locale/en/VTextField.json index 0eff6833e5c..f9a72501c6e 100644 --- a/packages/api-generator/src/locale/en/VTextField.json +++ b/packages/api-generator/src/locale/en/VTextField.json @@ -1,6 +1,7 @@ { "props": { "autofocus": "Enables autofocus.", + "centerAffix": "Vertically align **append**, **appendInner**, **prepend**, **prependInner**, **clearIcon** and **label** in the center.", "clearIcon": "Applied when using **clearable** and the input is dirty.", "counterValue": "Function returns the counter display text.", "flat": "Removes elevation (shadow) added to element when using the **solo** or **solo-inverted** props.", From 75da39bdc8567c97c489a62bdc2da9e69282faea Mon Sep 17 00:00:00 2001 From: Yuchao Wu Date: Sun, 30 Jun 2024 12:58:25 +1000 Subject: [PATCH 4/5] refactor: apply singleLIne under the hood --- .../api-generator/src/locale/en/VField.json | 2 +- .../src/locale/en/VTextField.json | 1 - .../vuetify/src/components/VField/VField.sass | 21 ++++++++++-------- .../vuetify/src/components/VField/VField.tsx | 7 +++--- .../vuetify/src/components/VInput/VInput.sass | 22 +++++++++---------- .../vuetify/src/components/VInput/VInput.tsx | 2 +- .../src/components/VTextField/VTextField.tsx | 1 - .../src/components/VTextarea/VTextarea.tsx | 11 +++++----- 8 files changed, 34 insertions(+), 33 deletions(-) diff --git a/packages/api-generator/src/locale/en/VField.json b/packages/api-generator/src/locale/en/VField.json index 2ce083c09fc..82bc8788628 100644 --- a/packages/api-generator/src/locale/en/VField.json +++ b/packages/api-generator/src/locale/en/VField.json @@ -2,7 +2,7 @@ "props": { "appendInnerIcon": "Creates a [v-icon](/api/v-icon/) component in the **append-inner** slot.", "baseColor": "Sets the color of the input when it is not focused.", - "centerAffix": "Vertically align **appendInner**, **prependInner**, **clearIcon** and **label** in the center.", + "centerAffix": "Automatically apply **[singleLine](/api/v-field/#props-single-line)** under the hood, and vertically align **appendInner**, **prependInner**, **clearIcon**, **label** and **input field** in the center.", "clearIcon": "The icon used when the **clearable** prop is set to true.", "dirty": "Manually apply the dirty state styling.", "disabled": "Removes the ability to click or target the input.", diff --git a/packages/api-generator/src/locale/en/VTextField.json b/packages/api-generator/src/locale/en/VTextField.json index f9a72501c6e..0eff6833e5c 100644 --- a/packages/api-generator/src/locale/en/VTextField.json +++ b/packages/api-generator/src/locale/en/VTextField.json @@ -1,7 +1,6 @@ { "props": { "autofocus": "Enables autofocus.", - "centerAffix": "Vertically align **append**, **appendInner**, **prepend**, **prependInner**, **clearIcon** and **label** in the center.", "clearIcon": "Applied when using **clearable** and the input is dirty.", "counterValue": "Function returns the counter display text.", "flat": "Removes elevation (shadow) added to element when using the **solo** or **solo-inverted** props.", diff --git a/packages/vuetify/src/components/VField/VField.sass b/packages/vuetify/src/components/VField/VField.sass index 57a8094a375..6a698fabcf4 100644 --- a/packages/vuetify/src/components/VField/VField.sass +++ b/packages/vuetify/src/components/VField/VField.sass @@ -141,6 +141,10 @@ $root: & + @at-root #{selector.nest('.v-field.v-field--center-affix.v-field--variant-underlined, .v-field.v-field--center-affix.v-field--variant-plain', &)} + padding-top: unset + padding-bottom: unset + @at-root @include tools.density('v-input', $input-density) using ($modifier) @at-root #{selector.nest(&, $root)} @@ -195,15 +199,14 @@ align-items: center padding-top: 0 - .v-field.v-field--variant-underlined, - .v-field.v-field--variant-plain - &:not(.v-field--center-affix) - .v-field__append-inner, - .v-field__clearable, - .v-field__prepend-inner - align-items: flex-start - padding-top: $field-input-padding-top - padding-bottom: $field-input-padding-bottom + .v-field:not(.v-field--center-affix).v-field--variant-underlined, + .v-field:not(.v-field--center-affix).v-field--variant-plain + .v-field__append-inner, + .v-field__clearable, + .v-field__prepend-inner + align-items: flex-start + padding-top: $field-input-padding-top + padding-bottom: $field-input-padding-bottom .v-field__prepend-inner, .v-field__append-inner diff --git a/packages/vuetify/src/components/VField/VField.tsx b/packages/vuetify/src/components/VField/VField.tsx index b1049df476e..948e9f9a7cb 100644 --- a/packages/vuetify/src/components/VField/VField.tsx +++ b/packages/vuetify/src/components/VField/VField.tsx @@ -136,8 +136,9 @@ export const VField = genericComponent( const { roundedClasses } = useRounded(props) const { rtlClasses } = useRtl() + const isSingleLine = computed(() => props.singleLine || props.centerAffix) const isActive = computed(() => props.dirty || props.active) - const hasLabel = computed(() => !props.singleLine && !!(props.label || slots.label)) + const hasLabel = computed(() => !isSingleLine.value && !!(props.label || slots.label)) const uid = getUid() const id = computed(() => props.id || `input-${uid}`) @@ -242,7 +243,7 @@ export const VField = genericComponent( { 'v-field--active': isActive.value, 'v-field--appended': hasAppend, - 'v-field--center-affix': props.centerAffix ?? !isPlainOrUnderlined.value, + 'v-field--center-affix': props.centerAffix, 'v-field--disabled': props.disabled, 'v-field--dirty': props.dirty, 'v-field--error': props.error, @@ -251,7 +252,7 @@ export const VField = genericComponent( 'v-field--persistent-clear': props.persistentClear, 'v-field--prepended': hasPrepend, 'v-field--reverse': props.reverse, - 'v-field--single-line': props.singleLine, + 'v-field--single-line': isSingleLine.value, 'v-field--no-label': !label(), [`v-field--variant-${props.variant}`]: true, }, diff --git a/packages/vuetify/src/components/VInput/VInput.sass b/packages/vuetify/src/components/VInput/VInput.sass index 344c9bb2e9e..2441ec1dde6 100644 --- a/packages/vuetify/src/components/VInput/VInput.sass +++ b/packages/vuetify/src/components/VInput/VInput.sass @@ -103,14 +103,14 @@ input[type=number] -moz-appearance: textfield - &--plain-underlined - &:not(.v-input--center-affix) - .v-input__prepend, - .v-input__append - $this: & - align-items: flex-start - - @at-root - @include tools.density('v-input', $input-density) using ($modifier) - @at-root #{selector.append(&, $this)} - padding-top: calc(var(--v-input-padding-top) + #{math.max(0px, 4px + $modifier * .25)}) + &--plain-underlined:not(&--center-affix) + + .v-input__prepend, + .v-input__append + $this: & + align-items: flex-start + + @at-root + @include tools.density('v-input', $input-density) using ($modifier) + @at-root #{selector.append(&, $this)} + padding-top: calc(var(--v-input-padding-top) + #{math.max(0px, 4px + $modifier * .25)}) diff --git a/packages/vuetify/src/components/VInput/VInput.tsx b/packages/vuetify/src/components/VInput/VInput.tsx index 4234aeb0aad..39cfcc4edce 100644 --- a/packages/vuetify/src/components/VInput/VInput.tsx +++ b/packages/vuetify/src/components/VInput/VInput.tsx @@ -42,7 +42,7 @@ export const makeVInputProps = propsFactory({ appendIcon: IconValue, centerAffix: { type: Boolean, - default: true, + default: false, }, prependIcon: IconValue, hideDetails: [Boolean, String] as PropType, diff --git a/packages/vuetify/src/components/VTextField/VTextField.tsx b/packages/vuetify/src/components/VTextField/VTextField.tsx index 60dc1a9f291..3e835143866 100644 --- a/packages/vuetify/src/components/VTextField/VTextField.tsx +++ b/packages/vuetify/src/components/VTextField/VTextField.tsx @@ -176,7 +176,6 @@ export const VTextField = genericComponent()({ style={ props.style } { ...rootAttrs } { ...inputProps } - centerAffix={ props.centerAffix } focused={ isFocused.value } > {{ diff --git a/packages/vuetify/src/components/VTextarea/VTextarea.tsx b/packages/vuetify/src/components/VTextarea/VTextarea.tsx index 173f9192621..e675b3c0c1f 100644 --- a/packages/vuetify/src/components/VTextarea/VTextarea.tsx +++ b/packages/vuetify/src/components/VTextarea/VTextarea.tsx @@ -18,7 +18,7 @@ import Intersect from '@/directives/intersect' // Utilities import { computed, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, watch, watchEffect } from 'vue' -import { callEvent, clamp, convertToUnit, filterInputAttrs, genericComponent, propsFactory, useRender } from '@/util' +import { callEvent, clamp, convertToUnit, filterInputAttrs, genericComponent, omit, propsFactory, useRender } from '@/util' // Types import type { PropType } from 'vue' @@ -48,8 +48,8 @@ export const makeVTextareaProps = propsFactory({ suffix: String, modelModifiers: Object as PropType>, - ...makeVInputProps(), - ...makeVFieldProps(), + ...omit(makeVInputProps(), ['centerAffix']), + ...omit(makeVFieldProps(), ['centerAffix']), }, 'VTextarea') type VTextareaSlots = Omit & { @@ -152,7 +152,6 @@ export const VTextarea = genericComponent()({ const sizerRef = ref() const rows = ref(+props.rows) const isPlainOrUnderlined = computed(() => ['plain', 'underlined'].includes(props.variant)) - const isCenterAffix = computed(() => props.centerAffix ?? (rows.value === 1 && !isPlainOrUnderlined.value)) watchEffect(() => { if (!props.autoGrow) rows.value = +props.rows }) @@ -229,7 +228,7 @@ export const VTextarea = genericComponent()({ style={ props.style } { ...rootAttrs } { ...inputProps } - centerAffix={ isCenterAffix.value } + centerAffix={ false } focused={ isFocused.value } > {{ @@ -254,7 +253,7 @@ export const VTextarea = genericComponent()({ { ...fieldProps } id={ id.value } active={ isActive.value || isDirty.value } - centerAffix={ isCenterAffix.value } + centerAffix={ false } dirty={ isDirty.value || props.dirty } disabled={ isDisabled.value } focused={ isFocused.value } From 935a3c6a69f580707b64c859ed3e9027e9574861 Mon Sep 17 00:00:00 2001 From: John Leider Date: Tue, 9 Jul 2024 11:15:35 -0500 Subject: [PATCH 5/5] refactor(VInput/VField): update centerAffix prop --- packages/vuetify/src/components/VField/VField.tsx | 5 +---- packages/vuetify/src/components/VInput/VInput.tsx | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/vuetify/src/components/VField/VField.tsx b/packages/vuetify/src/components/VField/VField.tsx index 948e9f9a7cb..037cf02a23a 100644 --- a/packages/vuetify/src/components/VField/VField.tsx +++ b/packages/vuetify/src/components/VField/VField.tsx @@ -62,10 +62,7 @@ export const makeVFieldProps = propsFactory({ default: '$clear', }, active: Boolean, - centerAffix: { - type: Boolean, - default: false, - }, + centerAffix: Boolean, color: String, baseColor: String, dirty: Boolean, diff --git a/packages/vuetify/src/components/VInput/VInput.tsx b/packages/vuetify/src/components/VInput/VInput.tsx index 39cfcc4edce..f12b059b9d7 100644 --- a/packages/vuetify/src/components/VInput/VInput.tsx +++ b/packages/vuetify/src/components/VInput/VInput.tsx @@ -40,10 +40,7 @@ export interface VInputSlot { export const makeVInputProps = propsFactory({ id: String, appendIcon: IconValue, - centerAffix: { - type: Boolean, - default: false, - }, + centerAffix: Boolean, prependIcon: IconValue, hideDetails: [Boolean, String] as PropType, hideSpinButtons: Boolean,