Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Input fields): update iconButton in all fields #1042

Merged
merged 8 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expected change: the button's area has increased

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is expected. The previous implementation was not using correct touchable area for these buttons

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions src/__stories__/text-field-story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {TextField, Box, Text1, Stack, ResponsiveLayout} from '..';
import {inspect} from 'util';
import IconMusicRegular from '../generated/mistica-icons/icon-music-regular';
import {countriesList} from './helpers';
import {iconSize} from '../text-field-base.css';
import {iconSize} from '../icon-button.css';

export default {
title: 'Components/Input fields/TextField',
Expand Down Expand Up @@ -75,7 +75,7 @@ export const Controlled: StoryComponent<TextFieldControlledArgs> = ({
autoComplete="off"
dataAttributes={{testid: 'text-field'}}
maxLength={maxLength ? 200 : undefined}
endIcon={icon ? <IconMusicRegular size={iconSize} /> : undefined}
endIcon={icon ? <IconMusicRegular size={iconSize.default} /> : undefined}
getSuggestions={suggestions ? getCountrySuggestions : undefined}
{...rest}
/>
Expand Down Expand Up @@ -131,7 +131,7 @@ export const Uncontrolled: StoryComponent<TextFieldUncontrolledArgs> = ({
autoComplete="off"
dataAttributes={{testid: 'text-field'}}
maxLength={maxLength ? 200 : undefined}
endIcon={icon ? <IconMusicRegular size={iconSize} /> : undefined}
endIcon={icon ? <IconMusicRegular size={iconSize.default} /> : undefined}
{...rest}
/>
<Stack space={8}>
Expand Down
12 changes: 6 additions & 6 deletions src/credit-card-number-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {createChangeEvent} from './utils/dom';
import {combineRefs} from './utils/common';
import * as styles from './credit-card-number-field.css';
import {vars} from './skins/skin-contract.css';
import {iconSize} from './text-field-base.css';
import {iconSize} from './icon-button.css';

import type {CardOptions} from './utils/credit-card';
import type {CommonFormFieldProps} from './text-field-base';
Expand Down Expand Up @@ -77,20 +77,20 @@ const CreditCardInput: React.FC<Props> = ({inputRef, value, defaultValue, onChan

const getAnimationTarget = (value?: string) => {
if (isVisa(value)) {
return <IconVisa size={iconSize} />;
return <IconVisa size={iconSize.default} />;
}
if (isMasterCard(value)) {
return <IconMastercard size={iconSize} />;
return <IconMastercard size={iconSize.default} />;
}
if (isAmericanExpress(value)) {
return <IconAmex size={iconSize} />;
return <IconAmex size={iconSize.default} />;
}
return null;
};

const initialState = {
showBackface: false,
animationTarget: <IconCreditCardVisaRegular size={iconSize} />,
animationTarget: <IconCreditCardVisaRegular size={iconSize.default} />,
isAnimating: false,
};

Expand Down Expand Up @@ -138,7 +138,7 @@ const CreditcardAdornment = ({value}: {value?: string}) => {
onTransitionEnd={() => isAnimating && dispatch({type: 'TRANSITION_END'})}
>
<div className={styles.flipFront}>
<IconCreditCardVisaRegular size={iconSize} color={vars.colors.neutralMedium} />
<IconCreditCardVisaRegular size={iconSize.default} color={vars.colors.neutralMedium} />
</div>
<div className={styles.flipBack}>{animationTarget}</div>
</div>
Expand Down
7 changes: 4 additions & 3 deletions src/date-field.css.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {style} from '@vanilla-extract/css';
import {fieldRightPadding, iconButtonSize, iconSize} from './text-field-base.css';
import {iconSize} from './icon-button.css';
import {fieldRightPadding, iconButtonSize} from './text-field-base.css';

export const iconContainer = style({
position: 'absolute',
Expand All @@ -8,6 +9,6 @@ export const iconContainer = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
right: `calc(${fieldRightPadding}px + (${iconButtonSize} - ${iconSize}) / 2)`,
marginRight: -8,
right: `calc(${fieldRightPadding}px + (${iconButtonSize} - ${iconSize.default}) / 2)`,
marginRight: -12,
});
4 changes: 2 additions & 2 deletions src/date-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {getLocalDateString} from './utils/time';
import {useTheme} from './hooks';
import {isFirefox} from './utils/platform';
import * as styles from './date-field.css';
import {iconSize} from './text-field-base.css';
import {iconSize} from './icon-button.css';

import type {CommonFormFieldProps} from './text-field-base';

Expand Down Expand Up @@ -98,7 +98,7 @@ const DateField: React.FC<DateFieldProps> = ({
type="date"
endIconOverlay={
<div className={styles.iconContainer}>
<IconCalendarRegular size={iconSize} />
<IconCalendarRegular size={iconSize.default} />
</div>
}
dataAttributes={{'component-name': 'DateField', ...dataAttributes}}
Expand Down
4 changes: 2 additions & 2 deletions src/date-time-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import {getLocalDateTimeString} from './utils/time';
import IconCalendarRegular from './generated/mistica-icons/icon-calendar-regular';
import {isFirefox} from './utils/platform';
import {useTheme} from './hooks';
import {iconSize} from './text-field-base.css';
import * as dateStyles from './date-field.css';
import {iconSize} from './icon-button.css';

import type {CommonFormFieldProps} from './text-field-base';

Expand Down Expand Up @@ -104,7 +104,7 @@ const FormDateField: React.FC<DateFieldProps> = ({
type="datetime-local"
endIconOverlay={
<div className={dateStyles.iconContainer}>
<IconCalendarRegular size={iconSize} />
<IconCalendarRegular size={iconSize.default} />
</div>
}
dataAttributes={{'component-name': 'DateTimeField', ...dataAttributes}}
Expand Down
5 changes: 2 additions & 3 deletions src/date-time-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import 'moment/locale/es';
import 'moment/locale/de';
import 'moment/locale/pt-br';
import 'moment/locale/en-gb';
import {endIcon} from './text-field-base.css';

import type {CommonFormFieldProps} from './text-field-base';
import type Moment from 'moment';
Expand Down Expand Up @@ -112,7 +111,7 @@ const DateTimePicker: React.FC<DateTimePickerProps> = ({withTime, mode, isValidD
<FieldEndIcon
Icon={IconCloseRegular}
aria-label={texts.clearButton}
className={endIcon}
hasBackgroundColor={false}
onPress={() => setValue('')}
/>
);
Expand All @@ -122,7 +121,7 @@ const DateTimePicker: React.FC<DateTimePickerProps> = ({withTime, mode, isValidD
Icon={IconCalendarRegular}
aria-label=""
disabled={rest.disabled}
className={endIcon}
hasBackgroundColor={false}
onPress={() => setShowPicker(!showPicker)}
/>
);
Expand Down
2 changes: 1 addition & 1 deletion src/icon-button.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ const minButtonArea = {
touchable: '48px',
};

const iconContainerSize = {
export const iconContainerSize = {
default: '3rem',
small: '2rem',
};
Expand Down
8 changes: 6 additions & 2 deletions src/icon-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,10 @@ export type IconButtonProps = BaseProps &
ExclusifyUnion<HrefProps | ToProps | OnPressProps | MaybeProps> &
ExclusifyUnion<{'aria-label': string} | {'aria-labelledby': string}>;

export const RawIconButton = React.forwardRef<TouchableElement, IconButtonProps & {isOverMedia?: boolean}>(
export const RawIconButton = React.forwardRef<
TouchableElement,
IconButtonProps & {isOverMedia?: boolean; hasOverlay?: boolean}
>(
(
{
disabled,
Expand All @@ -187,6 +190,7 @@ export const RawIconButton = React.forwardRef<TouchableElement, IconButtonProps
type = 'neutral',
backgroundType = 'transparent',
isOverMedia,
hasOverlay = true,
'aria-label': ariaLabel,
'aria-labelledby': ariaLabelledby,
small,
Expand Down Expand Up @@ -243,7 +247,7 @@ export const RawIconButton = React.forwardRef<TouchableElement, IconButtonProps

const content = (
<div className={classNames(styles.iconContainer[buttonSize], {[styles.isLoading]: showSpinner})}>
<div className={styles.overlay} />
{hasOverlay && <div className={styles.overlay} />}

<div aria-hidden={showSpinner ? true : undefined} className={styles.icon}>
<Icon size={styles.iconSize[buttonSize]} color="currentColor" />
Expand Down
4 changes: 2 additions & 2 deletions src/month-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import IconCalendarRegular from './generated/mistica-icons/icon-calendar-regular
import {getLocalYearMonthString} from './utils/time';
import {useTheme} from './hooks';
import * as dateStyles from './date-field.css';
import {iconSize} from './text-field-base.css';
import {iconSize} from './icon-button.css';

import type {CommonFormFieldProps} from './text-field-base';

Expand Down Expand Up @@ -91,7 +91,7 @@ const DateField: React.FC<DateFieldProps> = ({
type="month"
endIconOverlay={
<div className={dateStyles.iconContainer}>
<IconCalendarRegular size={iconSize} />
<IconCalendarRegular size={iconSize.default} />
</div>
}
dataAttributes={{'component-name': 'MonthField', ...dataAttributes}}
Expand Down
2 changes: 0 additions & 2 deletions src/password-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {FieldEndIcon, TextFieldBaseAutosuggest} from './text-field-base';
import {useTheme} from './hooks';
import IconEyeOffRegular from './generated/mistica-icons/icon-eye-off-regular';
import IconEyeRegular from './generated/mistica-icons/icon-eye-regular';
import {endIconWithShadow} from './text-field-base.css';

import type {CommonFormFieldProps} from './text-field-base';

Expand All @@ -23,7 +22,6 @@ const PasswordAdornment: React.FC<{
<FieldEndIcon
Icon={isVisible ? IconEyeOffRegular : IconEyeRegular}
aria-label={texts.togglePasswordVisibilityLabel}
className={endIconWithShadow}
onPress={() => {
setVisibility(!isVisible);
focus();
Expand Down
5 changes: 2 additions & 3 deletions src/search-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import IconCloseRegular from './generated/mistica-icons/icon-close-regular';
import {useTheme} from './hooks';
import {createChangeEvent} from './utils/dom';
import {combineRefs} from './utils/common';
import {endIconWithShadow, iconSize} from './text-field-base.css';
import {iconSize} from './icon-button.css';

import type {CommonFormFieldProps} from './text-field-base';

Expand Down Expand Up @@ -79,12 +79,11 @@ const SearchField = React.forwardRef<any, SearchFieldProps>(
return (
<TextFieldBaseAutosuggest
ref={combineRefs(inputRef, ref)}
startIcon={<IconSearchRegular size={iconSize} />}
startIcon={<IconSearchRegular size={iconSize.default} />}
endIcon={
controlledValue ? (
<FieldEndIcon
Icon={IconCloseRegular}
className={endIconWithShadow}
aria-label={theme.texts.formSearchClear}
onPress={clearInput}
/>
Expand Down
39 changes: 3 additions & 36 deletions src/text-field-base.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {sprinkles} from './sprinkles.css';
import {vars} from './skins/skin-contract.css';
import * as mq from './media-queries.css';
import {pxToRem} from './utils/css';
import {iconContainerSize} from './icon-button.css';

const borderSize = 1;

Expand All @@ -12,8 +13,7 @@ export const fieldLeftPadding = 12 - borderSize;
export const fieldRightPadding = 16 - borderSize;

export const fieldElementsGap = 12;
export const iconSize = pxToRem(24);
export const iconButtonSize = pxToRem(40);
export const iconButtonSize = iconContainerSize.default;

export const mobileFontSize = pxToRem(16);
export const desktopFontSize = pxToRem(18);
Expand Down Expand Up @@ -365,40 +365,7 @@ globalStyle(`${suggestionsContainer} > ul`, {
margin: 0,
});

export const endIcon = style([
sprinkles({
background: 'transparent',
padding: 0,
}),
{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
]);

export const endIconWithShadow = style([
endIcon,
sprinkles({
borderRadius: '50%',
}),
{
height: iconButtonSize,
width: iconButtonSize,
backgroundSize: '200%',
transition: 'background-color 0.1s ease-in-out',

'@media': {
[mq.supportsHover]: {
':hover': {
background: vars.colors.backgroundAlternative,
},
},
},
},
]);

export const fieldEndIconContainer = style({
// remove extra button space on the right so that icon is not too far from field's container
marginRight: -8,
marginRight: -12,
});
27 changes: 11 additions & 16 deletions src/text-field-base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import classNames from 'classnames';
import {combineRefs} from './utils/common';
import * as styles from './text-field-base.css';
import {vars} from './skins/skin-contract.css';
import {BaseIconButton} from './icon-button';
import {RawIconButton} from './icon-button';
import {ThemeVariant} from './theme-variant-context';
import {iconSize} from './icon-button.css';

import type {DataAttributes, IconProps} from './utils/types';
import type {InputState} from './text-field-components';
Expand All @@ -29,35 +30,29 @@ const isValidInputValue = (value?: string, inputType?: React.HTMLInputTypeAttrib

interface FieldEndIconProps {
Icon: React.FC<IconProps>;
className?: string;
/** In date fields, we want the icon's background to stay transparent when hovering/pressing it */
hasBackgroundColor?: boolean;
marcoskolodny marked this conversation as resolved.
Show resolved Hide resolved
onPress: (event: React.MouseEvent<HTMLElement>) => void;
disabled?: boolean;
'aria-label'?: string;
}

export const FieldEndIcon: React.FC<FieldEndIconProps> = ({
Icon,
className,
hasBackgroundColor = true,
onPress,
disabled,
'aria-label': ariaLabel,
}) => {
return (
/**
* If we try to add fieldEndIconContainer styles to the BaseIconButton instead,
* there may be collisions because that component sets margin internally. We
* create a wrapper around it so that the margin's value won't be overrided.
*/
<div className={styles.fieldEndIconContainer}>
<BaseIconButton
<RawIconButton
Icon={Icon}
disabled={disabled}
aria-label={ariaLabel}
aria-label={ariaLabel || ''}
onPress={onPress}
size={styles.iconButtonSize}
className={className}
>
<Icon size={styles.iconSize} />
</BaseIconButton>
hasOverlay={hasBackgroundColor}
/>
</div>
);
};
Expand Down Expand Up @@ -263,7 +258,7 @@ export const TextFieldBase = React.forwardRef<any, TextFieldBaseProps>(
...inputProps,
};

const startIconWidth = `calc(${styles.iconSize} + ${styles.fieldElementsGap}px)`;
const startIconWidth = `calc(${iconSize.default} + ${styles.fieldElementsGap}px)`;
const endIconWidth = `calc(${styles.iconButtonSize} + ${styles.fieldElementsGap}px)`;

const isShrinked = shrinkLabel || inputState === 'focused' || inputState === 'filled';
Expand Down
Loading