Skip to content

Commit

Permalink
refactor(field-decorator): support hint animation when the icon exist…
Browse files Browse the repository at this point in the history
…ed and optimize code
  • Loading branch information
haoziqaq committed Feb 5, 2024
1 parent c23f0ae commit ba440cb
Show file tree
Hide file tree
Showing 13 changed files with 270 additions and 195 deletions.
55 changes: 38 additions & 17 deletions packages/varlet-ui/src/field-decorator/FieldDecorator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
color,
cursor,
overflow: isFloating ? 'visible' : 'hidden',
'--field-decorator-middle-offset-left': middleOffsetLeft,
'--field-decorator-middle-offset-height': middleOffsetHeight,
}"
>
<div :class="classes(n('icon'), [!hint, n('--icon-non-hint')])">
<slot name="prepend-icon" />
</div>

<div :class="classes(n('middle'), [!hint, n('--middle-non-hint')])">
<div ref="middleEl" :class="classes(n('middle'), [!hint, n('--middle-non-hint')])">
<slot />
</div>

Expand All @@ -33,8 +35,10 @@
n('placeholder'),
n('$--ellipsis'),
[isFocus, n('--focus')],
[hintCenter, n('--hint-center')],
[formDisabled || disabled, n('--disabled')],
[errorMessage, n('--error')],
[transitionDisabled, n('--transition-disabled')],
computePlaceholderState()
)
"
Expand Down Expand Up @@ -106,7 +110,7 @@

<script lang="ts">
import VarIcon from '../icon'
import { defineComponent, ref, onUpdated, computed } from 'vue'
import { defineComponent, ref, computed, nextTick , onUpdated } from 'vue'
import { props } from './props'
import { isEmpty, getStyle, call } from '@varlet/shared'
import { createNamespace } from '../utils/components'
Expand All @@ -118,16 +122,29 @@ export default defineComponent({
name,
components: { VarIcon },
props,
setup(props, { slots }) {
setup(props) {
const placeholderTextEl = ref<HTMLElement | null>(null)
const middleEl = ref<HTMLElement | null>(null)
const legendWidth = ref('')
const isFloating = computed(() => props.hint && (!isEmpty(props.value) || props.isFocus || slots['prepend-icon']))
const middleOffsetLeft = ref('0px')
const middleOffsetHeight = ref('0px')
const transitionDisabled = ref(true)
const isFloating = computed(() => props.hint && (!isEmpty(props.value) || props.isFocus))
const color = computed<string | undefined>(() =>
!props.errorMessage ? (props.isFocus ? props.focusColor : props.blurColor) : undefined
)
onWindowResize(resize)
onSmartMounted(resize)
onSmartMounted(() => {
resize()
nextTick().then(() => {
transitionDisabled.value = false
})
})
onUpdated(resize)
function computePlaceholderState() {
Expand All @@ -142,18 +159,6 @@ export default defineComponent({
}
}
function resize() {
const { size, hint, variant, placeholder } = props
if (!placeholder || !hint || variant !== 'outlined') {
legendWidth.value = ''
return
}
const placeholderTextStyle = getStyle(placeholderTextEl.value!)
const placeholderSpace = `var(--field-decorator-outlined-${size}-placeholder-space)`
legendWidth.value = `calc(${placeholderTextStyle!.width} * 0.75 + ${placeholderSpace} * 2)`
}
function handleClear(e: Event) {
call(props.onClear, e)
}
Expand All @@ -162,11 +167,27 @@ export default defineComponent({
call(props.onClick, e)
}
function resize() {
middleOffsetLeft.value = `${middleEl.value!.offsetLeft}px`
middleOffsetHeight.value = `${middleEl.value!.offsetHeight}px`
if (props.variant === 'outlined' && placeholderTextEl.value) {
const placeholderTextStyle = getStyle(placeholderTextEl.value)
const placeholderSpace = `var(--field-decorator-outlined-${props.size}-placeholder-space)`
legendWidth.value = `calc(${placeholderTextStyle.width} * 0.75 + ${placeholderSpace} * 2)`
}
}
return {
placeholderTextEl,
middleEl,
middleOffsetLeft,
middleOffsetHeight,
color,
legendWidth,
isFloating,
transitionDisabled,
resize,
computePlaceholderState,
n,
classes,
Expand Down
159 changes: 104 additions & 55 deletions packages/varlet-ui/src/field-decorator/fieldDecorator.less
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,30 @@
--field-decorator-line-focus-size: 2px;
--field-decorator-line-border-radius: 4px;
--field-decorator-disabled-color: var(--color-text-disabled);
--field-decorator-standard-normal-padding-top: 22px;
--field-decorator-standard-normal-padding-bottom: 4px;
--field-decorator-standard-normal-icon-padding: 22px 0 4px;
--field-decorator-standard-normal-non-hint-padding-top: 4px;
--field-decorator-standard-normal-placeholder-translate-y: var(--field-decorator-standard-normal-padding-top);
--field-decorator-standard-small-padding-top: 18px;
--field-decorator-standard-small-padding-bottom: 4px;
--field-decorator-standard-small-icon-padding: 18px 0 4px;
--field-decorator-standard-small-non-hint-padding-top: 2px;
--field-decorator-standard-small-placeholder-translate-y: var(--field-decorator-standard-small-padding-top);
--field-decorator-outlined-normal-padding-top: 16px;
--field-decorator-outlined-normal-padding-bottom: 16px;
--field-decorator-standard-normal-margin-top: 22px;
--field-decorator-standard-normal-margin-bottom: 4px;
--field-decorator-standard-normal-icon-margin-top: 22px;
--field-decorator-standard-normal-icon-margin-bottom: 4px;
--field-decorator-standard-normal-non-hint-margin-top: 4px;
--field-decorator-standard-small-margin-top: 18px;
--field-decorator-standard-small-margin-bottom: 4px;
--field-decorator-standard-small-icon-margin-top: 18px;
--field-decorator-standard-small-icon-margin-bottom: 4px;
--field-decorator-standard-small-non-hint-margin-top: 2px;
--field-decorator-outlined-normal-margin-top: 16px;
--field-decorator-outlined-normal-margin-bottom: 16px;
--field-decorator-outlined-normal-padding-left: 16px;
--field-decorator-outlined-normal-padding-right: 16px;
--field-decorator-outlined-normal-placeholder-space: 4px;
--field-decorator-outlined-normal-icon-padding: 16px 0 16px;
--field-decorator-outlined-normal-placeholder-translate-y: var(--field-decorator-outlined-normal-padding-top);
--field-decorator-outlined-small-padding-top: 8px;
--field-decorator-outlined-small-padding-bottom: 8px;
--field-decorator-outlined-normal-icon-margin-top: 16px;
--field-decorator-outlined-normal-icon-margin-bottom: 16px;
--field-decorator-outlined-small-margin-top: 8px;
--field-decorator-outlined-small-margin-bottom: 8px;
--field-decorator-outlined-small-padding-left: 12px;
--field-decorator-outlined-small-padding-right: 12px;
--field-decorator-outlined-small-placeholder-space: 2px;
--field-decorator-outlined-small-icon-padding: 8px 0 8px;
--field-decorator-outlined-small-placeholder-translate-y: var(--field-decorator-outlined-small-padding-top);
--field-decorator-outlined-small-icon-margin-top: 8px;
--field-decorator-outlined-small-icon-margin-bottom: 8px;
}

.var-field-decorator {
Expand Down Expand Up @@ -84,6 +84,25 @@
cursor: pointer;
}

&__placeholder-text {
max-width: calc(
133% - var(--field-decorator-outlined-normal-padding-left) - var(--field-decorator-outlined-normal-padding-right)
);
position: absolute;
z-index: -1;
display: inline-block;
pointer-events: none;
opacity: 0;
height: 0;
font-size: var(--field-decorator-placeholder-size);
}

&__placeholder-text--small {
max-width: calc(
133% - var(--field-decorator-outlined-small-padding-left) - var(--field-decorator-outlined-small-padding-right)
);
}

&--placeholder-hidden {
visibility: hidden;
}
Expand All @@ -103,17 +122,21 @@

&--standard {
.var-field-decorator__middle {
padding: var(--field-decorator-standard-normal-padding-top) 0
var(--field-decorator-standard-normal-padding-bottom);
margin-top: var(--field-decorator-standard-normal-margin-top);
margin-bottom: var(--field-decorator-standard-normal-margin-bottom);
}

.var-field-decorator__icon {
padding: var(--field-decorator-standard-normal-icon-padding);
margin-top: var(--field-decorator-standard-normal-icon-margin-top);
margin-bottom: var(--field-decorator-standard-normal-icon-margin-bottom);
}

.var-field-decorator__placeholder {
max-width: 100%;
transform: translate(0, var(--field-decorator-standard-normal-placeholder-translate-y));
transform: translate(
var(--field-decorator-middle-offset-left),
var(--field-decorator-standard-normal-margin-top)
);
}

.var-field-decorator--placeholder-hint {
Expand Down Expand Up @@ -142,11 +165,18 @@
}

.var-field-decorator--middle-non-hint {
padding-top: var(--field-decorator-standard-normal-non-hint-padding-top);
margin-top: var(--field-decorator-standard-normal-non-hint-margin-top);
}

.var-field-decorator--icon-non-hint {
padding-top: var(--field-decorator-standard-normal-non-hint-padding-top);
margin-top: var(--field-decorator-standard-normal-non-hint-margin-top);
}

.var-field-decorator--hint-center {
transform: translate(
var(--field-decorator-middle-offset-left),
calc(var(--field-decorator-standard-normal-margin-top) + var(--field-decorator-middle-offset-height) / 2 - 50%)
);
}

.var-field-decorator--line-focus {
Expand All @@ -165,12 +195,13 @@
}

.var-field-decorator__middle {
padding: var(--field-decorator-outlined-normal-padding-top) 0
var(--field-decorator-outlined-normal-padding-bottom) 0;
margin-top: var(--field-decorator-outlined-normal-margin-top);
margin-bottom: var(--field-decorator-outlined-normal-margin-bottom);
}

.var-field-decorator__icon {
padding: var(--field-decorator-outlined-normal-icon-padding);
margin-top: var(--field-decorator-outlined-normal-icon-margin-top);
margin-bottom: var(--field-decorator-outlined-normal-icon-margin-bottom);
}

.var-field-decorator__placeholder {
Expand All @@ -180,11 +211,22 @@
);
transform: translate(
var(--field-decorator-outlined-normal-padding-left),
var(--field-decorator-outlined-normal-placeholder-translate-y)
var(--field-decorator-outlined-normal-margin-top)
)
scale(1);
}

.var-field-decorator--hint-center {
max-width: calc(
133% - var(--field-decorator-outlined-normal-padding-left) -
var(--field-decorator-outlined-normal-padding-right)
);
transform: translate(
var(--field-decorator-middle-offset-left),
calc(var(--field-decorator-outlined-normal-margin-top) + var(--field-decorator-middle-offset-height) / 2 - 50%)
);
}

.var-field-decorator--placeholder-hint {
max-width: calc(
133% - var(--field-decorator-outlined-normal-padding-left) -
Expand Down Expand Up @@ -259,24 +301,34 @@
&--small {
.var-field-decorator--standard& {
.var-field-decorator__middle {
padding: var(--field-decorator-standard-small-padding-top) 0
var(--field-decorator-standard-small-padding-bottom);
margin-top: var(--field-decorator-standard-small-margin-top);
margin-bottom: var(--field-decorator-standard-small-margin-bottom);
}

.var-field-decorator__placeholder {
transform: translate(0, var(--field-decorator-standard-small-placeholder-translate-y));
transform: translate(
var(--field-decorator-middle-offset-left),
var(--field-decorator-standard-small-margin-top)
);
}

.var-field-decorator--middle-non-hint {
max-width: calc(
133% - var(--field-decorator-outlined-small-padding-left) -
var(--field-decorator-outlined-small-padding-right)
);
padding-top: var(--field-decorator-standard-small-non-hint-padding-top);
margin-top: var(--field-decorator-standard-small-non-hint-margin-top);
}

.var-field-decorator--icon-non-hint {
padding-top: var(--field-decorator-standard-small-non-hint-padding-top);
margin-top: var(--field-decorator-standard-small-non-hint-margin-top);
}

.var-field-decorator--hint-center {
transform: translate(
var(--field-decorator-middle-offset-left),
calc(var(--field-decorator-standard-small-margin-top) + var(--field-decorator-middle-offset-height) / 2 - 50%)
);
}
}

Expand All @@ -287,12 +339,13 @@
}

.var-field-decorator__middle {
padding: var(--field-decorator-outlined-small-padding-top) 0
var(--field-decorator-outlined-small-padding-bottom) 0;
margin-top: var(--field-decorator-outlined-small-margin-top);
margin-bottom: var(--field-decorator-outlined-small-margin-bottom);
}

.var-field-decorator__icon {
padding: var(--field-decorator-outlined-small-icon-padding);
margin-top: var(--field-decorator-outlined-small-icon-margin-top);
margin-bottom: var(--field-decorator-outlined-small-icon-margin-bottom);
}

.var-field-decorator__placeholder {
Expand All @@ -302,11 +355,22 @@
);
transform: translate(
var(--field-decorator-outlined-small-padding-left),
var(--field-decorator-outlined-small-placeholder-translate-y)
var(--field-decorator-outlined-small-margin-top)
)
scale(1);
}

.var-field-decorator--hint-center {
max-width: calc(
133% - var(--field-decorator-outlined-small-padding-left) -
var(--field-decorator-outlined-small-padding-right)
);
transform: translate(
var(--field-decorator-middle-offset-left),
calc(var(--field-decorator-outlined-small-margin-top) + var(--field-decorator-middle-offset-height) / 2 - 50%)
);
}

.var-field-decorator--placeholder-hint {
transform: translate(calc(var(--field-decorator-outlined-small-padding-left)), -50%) scale(0.75);
}
Expand Down Expand Up @@ -338,23 +402,8 @@
}
}
}
}

.var-field-decorator__placeholder-text {
max-width: calc(
133% - var(--field-decorator-outlined-normal-padding-left) - var(--field-decorator-outlined-normal-padding-right)
);
position: absolute;
z-index: -1;
display: inline-block;
pointer-events: none;
opacity: 0;
height: 0;
font-size: var(--field-decorator-placeholder-size);
}

.var-field-decorator__placeholder-text--small {
max-width: calc(
133% - var(--field-decorator-outlined-small-padding-left) - var(--field-decorator-outlined-small-padding-right)
);
&--transition-disabled {
transition: none;
}
}
4 changes: 4 additions & 0 deletions packages/varlet-ui/src/field-decorator/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ export const props = {
type: Boolean,
default: true,
},
hintCenter: {
type: Boolean,
default: true,
},
textColor: String,
focusColor: String,
blurColor: String,
Expand Down
Loading

0 comments on commit ba440cb

Please sign in to comment.