Skip to content

Commit

Permalink
refactor(experience): add label for input field (#6200)
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoyijun authored Jul 9, 2024
1 parent addb528 commit dbda05a
Show file tree
Hide file tree
Showing 16 changed files with 383 additions and 96 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
@use '@/scss/underscore' as _;

.container {
position: absolute;
inset: 0;
pointer-events: none;

.border,
.outline {
text-align: left;
position: absolute;
inset: -8px 0 0;
border: _.border(var(--color-line-border));
border-radius: var(--radius);
pointer-events: none;
display: block;

legend {
display: inline-block;
visibility: hidden;
padding: 0;
// fix to the label font height to keep space for the input container
height: 20px;
// Set to 0 to avoid the empty space in the top border
width: 0;

span {
padding: 0 _.unit(1);
opacity: 0%;
visibility: hidden;
display: inline-block;
font: var(--font-body-3);
}
}
}

.outline {
display: none;
inset: -9px -2px -2px;
border-radius: 10px;
border: 3px outset var(--color-overlay-brand-focused);
}

.label {
position: absolute;
left: _.unit(4);
font: var(--font-body-1);
color: var(--color-type-secondary);
pointer-events: none;
top: 50%;
transform: translateY(-46%);
transition: 0.2s ease-out;
transition-property: position, font, top;
background-color: transparent;
z-index: 1;
}

&.active {
.border,
.outline {
legend {
visibility: visible;
width: auto;
}
}

.label {
top: 0;
left: _.unit(3);
font: var(--font-body-3);
color: var(--color-type-secondary);
padding: 0 _.unit(1);
}
}

&.focused {
.border {
border-color: var(--color-brand-default);
}

.label {
color: var(--color-brand-default);
}
}
}


.container.danger {
.border {
border-color: var(--color-danger-default);
}

.outline {
border-color: var(--color-overlay-danger-focused);
}

&.active {
.label {
color: var(--color-danger-default);
}
}
}

.container.noLabel {
.border,
.outline {
legend {
width: 0;
}
}
}

:global(body.desktop) {
.container {
&:not(.active) {
.label {
font: var(--font-body-2);
}
}

&.focused {
.outline {
display: block;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import classNames from 'classnames';

import * as styles from './index.module.scss';

type Props = {
readonly label: string;
readonly isActive: boolean;
readonly isDanger: boolean;
readonly isFocused: boolean;
};

/**
* NotchedBorder Component
*
* This component creates a customizable border with a notch for labels in form inputs.
* It enhances the visual appearance and accessibility of input fields by providing
* a floating label effect and customizable border/outline styles.
*
* Key implementation details:
* 1. Uses two fieldset elements:
* - The first creates the main border effect.
* - The second creates a separate outline effect, avoiding gaps between the built-in outline and border.
* 2. Utilizes the fieldset's legend for the label, allowing it to overlap the border:
* - This creates a "floating" label effect.
* - The legend's background becomes transparent, preventing it from blocking the background.
*
*/
const NotchedBorder = ({ label, isActive, isDanger, isFocused }: Props) => {
return (
<div
className={classNames(
styles.container,
isDanger && styles.danger,
isActive && styles.active,
isFocused && styles.focused,
!label && styles.noLabel
)}
>
<fieldset className={styles.border}>
<legend>
<span>{label}</span>
</legend>
</fieldset>
<fieldset className={styles.outline}>
<legend>
<span>{label}</span>
</legend>
</fieldset>
{Boolean(label) && <label className={styles.label}>{label}</label>}
</div>
);
};

export default NotchedBorder;
Original file line number Diff line number Diff line change
@@ -1,93 +1,106 @@
@use '@/scss/underscore' as _;

.inputField {
.container {
position: relative;
@include _.flex-row;
border: _.border(var(--color-line-border));
border-radius: var(--radius);
overflow: hidden;
transition-property: outline, border;
transition-timing-function: ease-in-out;
transition-duration: 0.2s;
align-items: stretch;

// fix in safari input field line-height issue
height: 44px;

input {
transition: width 0.3s ease-in;
padding: 0 _.unit(4);
flex: 1;
background: var(--color-bg-body);
caret-color: var(--color-brand-default);
font: var(--font-body-1);
color: var(--color-type-primary);
.inputField {
position: relative;
@include _.flex-row;
overflow: hidden;
transition-property: border;
transition-timing-function: ease-in-out;
transition-duration: 0.2s;
background: inherit;
align-items: stretch;

// fix in safari input field line-height issue
height: 44px;

&::placeholder {
color: var(--color-type-secondary);
input {
transition: width 0.3s ease-in;
padding: 0 _.unit(4);
flex: 1;
background: inherit;
caret-color: var(--color-brand-default);
font: var(--font-body-1);
color: var(--color-type-primary);
outline: none;
border-radius: var(--radius);
margin: -1px 1px 0;

&::placeholder {
color: var(--color-type-secondary);
transition: opacity 0.2s ease-out;
opacity: 0%;
}
}
}

.suffix {
position: absolute;
right: _.unit(2);
top: 50%;
transform: translateY(-50%);
width: _.unit(8);
height: _.unit(8);
display: none;
z-index: 1;
}

.suffix {
position: absolute;
right: _.unit(2);
top: 50%;
transform: translateY(-50%);
width: _.unit(8);
height: _.unit(8);
display: none;
z-index: 1;
}

&:focus-within {
border: _.border(var(--color-brand-default));
&.isSuffixFocusVisible:focus-within {
input {
padding-right: _.unit(10);
}

input {
outline: none;
.suffix {
display: flex;
}
}
}

&.danger {
border: _.border(var(--color-danger-default));

input {
caret-color: var(--color-danger-default);
&.active {
.inputField {
input::placeholder {
opacity: 100%;
}
}
}

&.isSuffixFocusVisible:focus-within {
input {
padding-right: _.unit(10);
&.noLabel {
.inputField {
input::placeholder {
opacity: 100%;
}
}
}

.suffix {
display: flex;
&.danger {
.inputField {
/* stylelint-disable-next-line no-descending-specificity */
input {
caret-color: var(--color-danger-default);
}
}
}

// override for firefox & safari focus outline since we are using custom notchedOutline
&:focus-visible {
outline: none;
}
}

.errorMessage {
margin-top: _.unit(1);
margin-left: _.unit(0.5);
}

:global(body.desktop) {
.inputField {
outline: 3px solid transparent;

/* stylelint-disable-next-line no-descending-specificity */
input {
font: var(--font-body-2);
background: var(--color-bg-float);
}

&:focus-within {
outline-color: var(--color-overlay-brand-focused);
}

&.danger:focus-within {
outline-color: var(--color-overlay-danger-focused);
:global(body.desktop) {
.container {
.inputField {
/* stylelint-disable-next-line no-descending-specificity */
input {
font: var(--font-body-2);
}
}
}
}
Loading

0 comments on commit dbda05a

Please sign in to comment.