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

EPMRPP-91645 || Added collapsed state for field text #43

2 changes: 2 additions & 0 deletions src/components/fieldText/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Has 36px height & width adjusted by content.
- **isRequired**: _bool_, optional, default = false
- **hasDoubleMessage**: _bool_, optional, default = false
- **displayError**: _bool_, optional, default = true
- **collapsible**: _bool_, optional, default = false
- **loading**: _bool_, optional, default = false

### Events:

Expand Down
13 changes: 9 additions & 4 deletions src/components/fieldText/fieldText.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react';
import { DeleteIcon } from '@components/icons';
import { FieldText } from './fieldText';
import { ChangeEvent, useState } from 'react';
import { ChangeEvent, useRef, useState } from 'react';

const meta: Meta<typeof FieldText> = {
title: 'Field Text',
Expand All @@ -13,12 +13,17 @@ const meta: Meta<typeof FieldText> = {
render: (args) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const [value, setValue] = useState('');

// eslint-disable-next-line react-hooks/rules-of-hooks
const ref = useRef<HTMLInputElement>(null);
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setValue(event.target.value);
const val = event.target.value;
setValue(val);
if (val === 'blur') {
ref?.current?.blur();
}
};

return <FieldText {...args} value={value} onChange={handleChange} />;
return <FieldText {...args} value={value} onChange={handleChange} ref={ref} />;
},
};

Expand Down
41 changes: 24 additions & 17 deletions src/components/fieldText/fieldText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
ReactElement,
ReactNode,
useState,
useImperativeHandle,
useRef,
InputHTMLAttributes,
MutableRefObject,
} from 'react';
import classNames from 'classnames/bind';
import { ClearIcon } from '@components/icons';
Expand All @@ -22,6 +22,8 @@ interface FieldTextProps extends InputHTMLAttributes<HTMLInputElement> {
placeholder?: string;
disabled?: boolean;
onChange?: ChangeEventHandler<HTMLInputElement>;
onFocus?: ChangeEventHandler<HTMLInputElement>;
onBlur?: ChangeEventHandler<HTMLInputElement>;
touched?: boolean;
title?: string;
label?: string;
Expand All @@ -38,11 +40,8 @@ interface FieldTextProps extends InputHTMLAttributes<HTMLInputElement> {
collapsible?: boolean;
loading?: boolean;
}
interface FocusableInputHandle {
focus: () => void;
}

export const FieldText = forwardRef<FocusableInputHandle, FieldTextProps>(
export const FieldText = forwardRef<HTMLInputElement, FieldTextProps>(
(
{
value = '',
Expand All @@ -66,20 +65,25 @@ export const FieldText = forwardRef<FocusableInputHandle, FieldTextProps>(
displayError = true,
collapsible = false,
loading = false,
onFocus = () => {},
onBlur = () => {},
...rest
},
ref,
): ReactElement => {
const internalRef = useRef<HTMLInputElement>(null);
const inputRef = ref || internalRef;
const [focused, setFocused] = useState(false);
const onFocus = () => setFocused(true);
const onBlur = () => setFocused(false);

useImperativeHandle(ref, () => ({
focus: () => {
internalRef.current?.focus();
},
}));
const onFocusHandler = (event: React.FocusEvent<HTMLInputElement>) => {
setFocused(true);
onFocus(event);
};

const onBlurHandler = (event: React.FocusEvent<HTMLInputElement>) => {
setFocused(false);
onBlur(event);
};

const clearInput = () => {
if (onClear) {
Expand All @@ -101,7 +105,7 @@ export const FieldText = forwardRef<FocusableInputHandle, FieldTextProps>(
<div
className={cx('field', className, {
error,
touched: touched,
touched,
disabled,
'default-width': defaultWidth,
collapsed: collapsible && !focused && !value,
Expand All @@ -114,22 +118,25 @@ export const FieldText = forwardRef<FocusableInputHandle, FieldTextProps>(
startIcon && (
<span
className={cx('icon-container-start')}
onClick={() => internalRef.current?.focus()}
onClick={() => {
const input = inputRef as MutableRefObject<HTMLInputElement>;
input.current?.focus();
}}
>
<span className={cx('icon')}>{startIcon}</span>
</span>
)
)}
<span className={cx('input-container')}>
<input
ref={internalRef}
ref={inputRef}
type={type}
className={cx('input')}
value={value}
disabled={disabled}
onChange={onChange}
onFocus={onFocus}
onBlur={onBlur}
onFocus={onFocusHandler}
onBlur={onBlurHandler}
{...rest}
/>
{placeholder && !value && (
Expand Down
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export { Dropdown } from './dropdown';
export { Toggle } from './toggle';
export { FieldNumber } from './fieldNumber';
export { BubblesLoader } from './bubblesLoader';
export { SpinLoader } from './spinLoader';
export { FieldTextFlex } from './fieldTextFlex';
export { Radio } from './radio';
export { Tooltip } from './tooltip';
Expand Down
12 changes: 2 additions & 10 deletions src/components/spinLoader/spinLoader.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,15 @@
border-radius: 50%;
flex-shrink: 0;
position: relative;
mask: radial-gradient(circle, transparent 55%, var(--rp-ui-color-primary) 0%);

&.color-topaz {
background: conic-gradient(#0000 0%, var(--rp-ui-base-topaz));
background: conic-gradient(#0000 0%, var(--rp-ui-color-primary));
AmsterGet marked this conversation as resolved.
Show resolved Hide resolved
}
AmsterGet marked this conversation as resolved.
Show resolved Hide resolved

animation: spin 1s infinite linear;
}

.spinner::before {
content: "";
flex-shrink: 0;
height: 80%;
width: 80%;
background: #fff;
border-radius: 50%;
}


AmsterGet marked this conversation as resolved.
Show resolved Hide resolved
@keyframes spin {
to {
Expand Down
20 changes: 20 additions & 0 deletions src/components/spinLoader/spinLoader.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { Meta, StoryObj } from '@storybook/react';

import { SpinLoader } from './spinLoader';

const meta: Meta<typeof SpinLoader> = {
title: 'Spinner Loader',
component: SpinLoader,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
};

export default meta;

type Story = StoryObj<typeof SpinLoader>;

export const Default: Story = {
args: {},
};
11 changes: 4 additions & 7 deletions src/components/spinLoader/spinLoader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@ import styles from './spinLoader.module.scss';

const cx = classNames.bind(styles);

interface SpinLoaderLoaderProps {
interface SpinLoaderProps {
color?: string;
className?: string;
}

export const SpinLoader: FC<SpinLoaderLoaderProps> = ({
color = 'topaz',
className,
}): ReactElement => (
<div className={cx('spin-loader', className, { [`color-${color}`]: color })}>
<div className={cx('spinner')} />
export const SpinLoader: FC<SpinLoaderProps> = ({ color = 'topaz', className }): ReactElement => (
<div className={cx('spin-loader', className)}>
<div className={cx('spinner', { [`color-${color}`]: color })} />
</div>
);
Loading