Skip to content

Commit

Permalink
fix(inputs): textarea auto-grow, consistent padding (#14683)
Browse files Browse the repository at this point in the history
fixes #15375
fixes #15409
fixes #15411
fixes #15508
  • Loading branch information
KaelWD committed Aug 9, 2022
1 parent c579e62 commit 8962d6b
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const VAutocomplete = genericComponent<new <
modelValue?: Readonly<V>
'onUpdate:modelValue'?: (val: V) => void
}
$slots: VInputSlots & VFieldSlots & MakeSlots<{
$slots: Omit<VInputSlots & VFieldSlots, 'default'> & MakeSlots<{
item: [{ item: T, index: number, props: Record<string, unknown> }]
chip: [{ item: T, index: number, props: Record<string, unknown> }]
selection: [{ item: T, index: number }]
Expand Down
2 changes: 1 addition & 1 deletion packages/vuetify/src/components/VCombobox/VCombobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const VCombobox = genericComponent<new <
modelValue?: Readonly<V>
'onUpdate:modelValue'?: (val: V) => void
}
$slots: VInputSlots & VFieldSlots & MakeSlots<{
$slots: Omit<VInputSlots & VFieldSlots, 'default'> & MakeSlots<{
item: [{ item: T, index: number, props: Record<string, unknown> }]
chip: [{ item: T, index: number, props: Record<string, unknown> }]
selection: [{ item: T, index: number }]
Expand Down
47 changes: 28 additions & 19 deletions packages/vuetify/src/components/VField/VField.sass
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
flex: 1 0
grid-area: control
position: relative
overflow: hidden

&--disabled
opacity: var(--v-disabled-opacity)
Expand All @@ -31,12 +32,8 @@
/* endregion */
/* region MODIFIERS */
.v-field
$root: &

&--prepended
padding-inline-start: $field-control-affixed-padding
--v-field-padding-start: #{$field-control-affixed-inner-padding}
--v-field-padding-end: #{$field-control-affixed-inner-padding}

&--appended
padding-inline-end: $field-control-affixed-padding
Expand All @@ -56,16 +53,20 @@
&--variant-underlined
border-radius: 0
padding: 0
--v-field-padding-start: 0
--v-field-padding-end: 0
--v-field-padding-top: 0

&.v-field--single-line
--v-field-padding-top: 0
--v-field-padding-start: 0px
--v-field-padding-end: 0px
--v-field-padding-top: 6px
--v-field-padding-bottom: 2px

&--variant-outlined,
&--single-line
--v-field-padding-top: 0
--v-field-padding-top: 0px
$root: &

@at-root
@include tools.density('v-input', $input-density) using ($modifier)
@at-root #{selector.nest(&, $root)}
--v-field-padding-bottom: #{16px + $modifier * .5}

&--variant-solo,
&--variant-filled
Expand All @@ -77,14 +78,21 @@
--v-input-control-height: #{$field-control-height + $modifier}
--v-field-padding-bottom: #{$field-control-padding-bottom + $modifier * .5}

&--variant-plain,
&--variant-underlined
$root: &

@at-root
@include tools.density('v-input', $input-density) using ($modifier)
@at-root #{selector.nest(&, $root)}
--v-input-control-height: #{$field-control-underlined-height + $modifier}
--v-field-padding-bottom: #{$field-control-padding-bottom + $modifier * .25}

// These are separate so they can override the default variant styles
&--prepended
--v-field-padding-start: #{$field-control-affixed-inner-padding}

&--appended
--v-field-padding-end: #{$field-control-affixed-inner-padding}

/* endregion */
/* region ELEMENTS */
Expand All @@ -94,11 +102,12 @@
flex-wrap: wrap
letter-spacing: $field-letter-spacing
opacity: $field-input-opacity
min-height: var(--v-input-control-height, $input-control-height)
padding-inline-start: var(--v-field-padding-start)
padding-inline-end: var(--v-field-padding-end)
padding-top: var(--v-field-padding-top, $field-control-padding-top)
flex: 1 0 0
min-width: 0
padding-top: calc(var(--v-field-padding-top, $field-control-padding-top) + var(--v-input-padding-top, 0))
padding-bottom: var(--v-field-padding-bottom, $field-control-padding-bottom)
width: 100%

input
letter-spacing: inherit
Expand All @@ -119,10 +128,10 @@

.v-field__field
flex: 1 0
min-height: var(--v-input-control-height, $input-control-height)
grid-area: field
padding-bottom: var(--v-field-padding-bottom, $field-control-padding-bottom)
position: relative
align-items: flex-start
display: flex

/* endregion */
/* region AFFIXES */
Expand All @@ -137,7 +146,6 @@
grid-area: append-inner
padding-inline-start: var(--v-field-padding-after)

.v-field__field,
.v-field__prepend-inner,
.v-field__append-inner,
.v-field__clearable
Expand Down Expand Up @@ -190,6 +198,7 @@
max-width: calc(100% - var(--v-field-padding-start) - var(--v-field-padding-end))
pointer-events: none
position: absolute
top: var(--v-input-padding-top, $field-control-padding-top)
transform-origin: left center
transition: $field-transition-timing
transition-property: opacity, transform
Expand Down Expand Up @@ -225,7 +234,7 @@

.v-field--variant-plain &,
.v-field--variant-underlined &
transform: translateY(-6px)
transform: translateY(-16px)
margin: 0

.v-field--variant-outlined &
Expand Down
5 changes: 3 additions & 2 deletions packages/vuetify/src/components/VField/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ $field-control-solo-elevation: 2 !default;
$field-control-filled-background: rgba(var(--v-theme-on-surface), var(--v-idle-opacity)) !default;
$field-control-padding-start: 16px !default;
$field-control-padding-end: 16px !default;
$field-control-padding-top: 8px !default;
$field-control-padding-top: 10px !default;
$field-control-padding-bottom: 6px !default;
$field-control-affixed-padding: 12px !default;
$field-control-affixed-inner-padding: 6px !default;
$field-control-underlined-height: 40px !default;
$field-control-underlined-height: 48px !default;
$field-control-underlined-padding-bottom: 2px !default;
$field-control-height: 56px !default;

// INPUT
Expand Down
1 change: 1 addition & 0 deletions packages/vuetify/src/components/VInput/VInput.sass
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
flex: 1 1 auto
font-size: $input-font-size
font-weight: $input-font-weight
line-height: 1.5

&--disabled
pointer-events: none
Expand Down
2 changes: 1 addition & 1 deletion packages/vuetify/src/components/VSelect/VSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const VSelect = genericComponent<new <
modelValue?: Readonly<V>
'onUpdate:modelValue'?: (val: V) => void
}
$slots: VInputSlots & VFieldSlots & MakeSlots<{
$slots: Omit<VInputSlots & VFieldSlots, 'default'> & MakeSlots<{
item: [{ item: T, index: number, props: Record<string, unknown> }]
chip: [{ item: T, index: number, props: Record<string, unknown> }]
selection: [{ item: T, index: number }]
Expand Down
3 changes: 2 additions & 1 deletion packages/vuetify/src/components/VTextField/VTextField.sass
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@
cursor: default
display: flex
opacity: 0
padding-top: var(--v-field-padding-top)
transition: inherit
white-space: nowrap
padding-top: calc(var(--v-field-padding-top, 4px) + var(--v-input-padding-top, 0))
padding-bottom: var(--v-field-padding-bottom, 6px)

.v-field--active &
opacity: 1
Expand Down
68 changes: 36 additions & 32 deletions packages/vuetify/src/components/VTextField/VTextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,21 @@ import { forwardRefs } from '@/composables/forwardRefs'
import { useProxiedModel } from '@/composables/proxiedModel'

// Utilities
import { computed, nextTick, ref } from 'vue'
import { cloneVNode, computed, nextTick, ref } from 'vue'
import { filterInputAttrs, genericComponent, useRender } from '@/util'

// Types
import type { PropType } from 'vue'
import type { MakeSlots } from '@/util'
import type { VFieldSlots } from '@/components/VField/VField'
import type { VInputSlots } from '@/components/VInput/VInput'

const activeTypes = ['color', 'file', 'time', 'date', 'datetime-local', 'week', 'month']

export const VTextField = genericComponent<new <T>() => {
$slots: VInputSlots & VFieldSlots
$slots: Omit<VInputSlots & VFieldSlots, 'default'> & MakeSlots<{
default: []
}>
}>()({
name: 'VTextField',

Expand Down Expand Up @@ -125,9 +128,6 @@ export const VTextField = genericComponent<new <T>() => {
emit('click:clear', e)
})
}
function onInput (e: Event) {
model.value = (e.target as HTMLInputElement).value
}

useRender(() => {
const hasCounter = !!(slots.counter || props.counter || props.counterValue)
Expand Down Expand Up @@ -187,6 +187,27 @@ export const VTextField = genericComponent<new <T>() => {
default: ({
props: { class: fieldClass, ...slotProps },
}) => {
const inputNode = (
<input
ref={ inputRef }
v-model={ model.value }
v-intersect={[{
handler: onIntersect,
}, null, ['once']]}
autofocus={ props.autofocus }
readonly={ isReadonly.value }
disabled={ isDisabled.value }
name={ props.name }
placeholder={ props.placeholder }
size={ 1 }
type={ props.type }
onFocus={ onFocus }
onBlur={ () => (isFocused.value = false) }
{ ...slotProps }
{ ...inputAttrs }
/>
)

return (
<>
{ props.prefix && (
Expand All @@ -195,33 +216,16 @@ export const VTextField = genericComponent<new <T>() => {
</span>
) }

<div
class={ fieldClass }
onClick={ e => emit('click:input', e) }
data-no-activator=""
>
{ slots.default?.() }

<input
ref={ inputRef }
value={ model.value }
onInput={ onInput }
v-intersect={[{
handler: onIntersect,
}, null, ['once']]}
autofocus={ props.autofocus }
readonly={ isReadonly.value }
disabled={ isDisabled.value }
name={ props.name }
placeholder={ props.placeholder }
size={ 1 }
type={ props.type }
onFocus={ onFocus }
onBlur={ () => (isFocused.value = false) }
{ ...slotProps }
{ ...inputAttrs }
/>
</div>
{ slots.default ? (
<div
class={ fieldClass }
onClick={ e => emit('click:input', e) }
data-no-activator=""
>
{ slots.default() }
{ inputNode }
</div>
) : cloneVNode(inputNode, { class: fieldClass }) }

{ props.suffix && (
<span class="v-text-field__suffix">
Expand Down
11 changes: 9 additions & 2 deletions packages/vuetify/src/components/VTextarea/VTextarea.sass
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@
@use './variables' as *

.v-textarea
.v-field__field
--v-input-control-height: var(--v-textarea-control-height)

.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)

flex: 1 1 auto
line-height: $textarea-line-height
outline: none
mask-image: linear-gradient(to bottom, transparent, transparent calc(var(--v-field-padding-top, 0) / 1.25), black var(--v-field-padding-top, 0))
-webkit-mask-image: linear-gradient(to bottom, transparent, transparent $a, black $b)
mask-image: linear-gradient(to bottom, transparent, transparent $a, black $b)

&--auto-grow
.v-field__input
Expand All @@ -25,6 +31,7 @@
top: 0
left: 0
height: 0 !important
min-height: 0 !important
pointer-events: none

.v-field--has-label
Expand Down
Loading

0 comments on commit 8962d6b

Please sign in to comment.