Skip to content

Commit

Permalink
Merge pull request #5821 from nextcloud-libraries/fix/input-field
Browse files Browse the repository at this point in the history
fix(NcInputField): Make sure label and placeholder is not jumping
  • Loading branch information
susnux authored Jul 18, 2024
2 parents 72722b3 + 938730d commit 0febe32
Showing 1 changed file with 56 additions and 59 deletions.
115 changes: 56 additions & 59 deletions src/components/NcInputField/NcInputField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ For a list of all available props and attributes, please check the [HTMLInputEle
<div class="input-field"
:class="{
'input-field--disabled': disabled,
'input-field--label-outside': labelOutside || !isValidLabel,
'input-field--leading-icon': hasLeadingIcon,
'input-field--trailing-icon': showTrailingButton || hasTrailingIcon,
'input-field--pill': pill,
}">
<div class="input-field__main-wrapper">
Expand All @@ -34,9 +37,6 @@ For a list of all available props and attributes, please check the [HTMLInputEle
aria-live="polite"
:class="[inputClass,
{
'input-field__input--trailing-icon': showTrailingButton || hasTrailingIcon,
'input-field__input--leading-icon': hasLeadingIcon,
'input-field__input--label-outside': labelOutside,
'input-field__input--success': success,
'input-field__input--error': error,
}]"
Expand All @@ -46,10 +46,6 @@ For a list of all available props and attributes, please check the [HTMLInputEle
<!-- Label -->
<label v-if="!labelOutside && isValidLabel"
class="input-field__label"
:class="[{
'input-field__label--trailing-icon': showTrailingButton || hasTrailingIcon,
'input-field__label--leading-icon': hasLeadingIcon,
}]"
:for="computedId">
{{ label }}
</label>
Expand Down Expand Up @@ -330,34 +326,45 @@ export default {
.input-field {
--input-border-radius: var(--border-radius-element, var(--border-radius-large));
// styles
// The padding before the input can start (leading button or border)
--input-padding-start: var(--border-radius-large);
// The padding where the input has to end (trailing button or border)
--input-padding-end: var(--border-radius-large);
// positional styles
position: relative;
width: 100%;
margin-block-start: 6px; // for the label in active state
&__main-wrapper {
height: var(--default-clickable-area);
position: relative;
}
&--disabled {
opacity: 0.4;
filter: saturate(0.4);
}
// If there is no internal label we reset the margin reserved for it
&--label-outside {
margin-block-start: 0;
}
&--leading-icon {
--input-padding-start: calc(var(--default-clickable-area) - var(--default-grid-baseline));
}
&--trailing-icon {
--input-padding-end: calc(var(--default-clickable-area) - var(--default-grid-baseline));
}
&--pill {
--input-border-radius: var(--border-radius-pill);
}
&__input {
margin: 0;
padding-inline: 12px 6px; // align with label 8px margin label + 6px padding label - 2px border input
height: var(--default-clickable-area) !important;
width: 100%;
font-size: var(--default-font-size);
text-overflow: ellipsis;
&__main-wrapper {
height: var(--default-clickable-area);
position: relative;
}
&__input {
// If border width differes between focused and unfocused we need to compensate to prevent jumping
--input-border-width-offset: calc(var(--border-width-input-focused, 2px) - var(--border-width-input, 2px));
background-color: var(--color-main-background);
color: var(--color-main-text);
border: var(--border-width-input, 2px) solid var(--color-border-maxcontrast);
Expand All @@ -368,29 +375,30 @@ export default {
-moz-appearance: textfield !important;
appearance: textfield !important;
// Center text if external label is used
&--label-outside {
padding-block: 0;
}
font-size: var(--default-font-size);
text-overflow: ellipsis;
height: calc(var(--default-clickable-area) - 2 * var(--input-border-width-offset)) !important;
width: 100%;
padding-inline: calc(var(--input-padding-start) + var(--input-border-width-offset)) calc(var(--input-padding-end) + var(--input-border-width-offset));
padding-block: var(--input-border-width-offset);
&:active:not([disabled]),
&:hover:not([disabled]),
&:focus:not([disabled]) {
border-width: var(--border-width-input-focused, 2px);
border-color: var(--color-main-text) !important;
box-shadow: 0 0 0 2px var(--color-main-background) !important;
// Reset padding offset when focused
--input-border-width-offset: 0px;
}
&:focus + .input-field__label,
&:hover:not(:placeholder-shown) + .input-field__label {
color: var(--color-main-text);
}
// Hide placeholder while not focussed -> show label instead (only if internal label is used)
&:not(:focus,&--label-outside)::placeholder {
opacity: 0;
}
&:focus {
cursor: text;
}
Expand All @@ -403,14 +411,6 @@ export default {
box-shadow: unset !important; // Override server rules
}
&--leading-icon {
padding-inline-start: var(--default-clickable-area);
}
&--trailing-icon {
padding-inline-end: var(--default-clickable-area);
}
&--success {
border-color: var(--color-success) !important; //Override hover border color
&:focus-visible {
Expand All @@ -426,12 +426,19 @@ export default {
}
}
// Hide placeholder while not focussed -> show label instead (only if internal label is used)
&:not(&--label-outside) &__input:not(:focus)::placeholder {
opacity: 0;
}
&__label {
--input-label-font-size: var(--default-font-size);
position: absolute;
margin-inline: 14px 0;
margin-inline: var(--input-padding-start) var(--input-padding-end);
max-width: fit-content;
font-size: var(--input-label-font-size);
inset-block-start: calc((var(--default-clickable-area) - var(--default-line-height)) / 2); // center the label vertically
inset-inline: 0;
inset-inline: var(--border-width-input-focused, 2px);
// Fix color so that users do not think the input already has content
color: var(--color-text-maxcontrast);
// only one line labels are allowed
Expand All @@ -442,31 +449,21 @@ export default {
pointer-events: none;
// Position transition
transition: height var(--animation-quick), inset-block-start var(--animation-quick), font-size var(--animation-quick), color var(--animation-quick), background-color var(--animation-quick) var(--animation-slow);
&--leading-icon {
margin-inline-start: var(--default-clickable-area);
}
&--trailing-icon {
margin-inline-end: var(--default-clickable-area);
}
}
&__input:focus + &__label,
&__input:not(:placeholder-shown) + &__label {
inset-block-start: -10px;
--input-label-font-size: 13px; // minimum allowed font size for accessibility
line-height: 1.5; // minimum allowed line height for accessibility
font-size: 13px; // minimum allowed font size for accessibility
// 1.5 * font-size = line-height; line-height / 2 for centering and make it negative as we need to move outside the element
inset-block-start: calc(-1.5 * var(--input-label-font-size) / 2);
font-weight: 500;
border-radius: var(--default-grid-baseline) var(--default-grid-baseline) 0 0;
background-color: var(--color-main-background);
padding-inline: 5px;
margin-inline-start: 9px;
padding-inline: var(--default-grid-baseline);
margin-inline: calc(var(--input-padding-start) - var(--default-grid-baseline)) calc(var(--input-padding-end) - var(--default-grid-baseline));
transition: height var(--animation-quick), inset-block-start var(--animation-quick), font-size var(--animation-quick), color var(--animation-quick);
&--leading-icon {
margin-inline-start: 41px;
}
}
&__icon {
Expand All @@ -478,14 +475,14 @@ export default {
justify-content: center;
opacity: 0.7;
inset-block-end: 0;
&--leading {
inset-block-end: 0;
inset-inline-start: 2px;
inset-inline-start: 0px;
}
&--trailing {
inset-block-end: 0;
inset-inline-end: 2px;
inset-inline-end: 0px;
}
}
Expand Down

0 comments on commit 0febe32

Please sign in to comment.