Skip to content

Commit

Permalink
EPMRPP-91645 || Added collapsed state for field text (#43)
Browse files Browse the repository at this point in the history
* EPMRPP-91645 || Added collapsed state for field text

* EPMRPP-91645 || Updated storybook version

* EPMRPP-91645 || added spin Loader

* EPMRPP-91645 || revert .prettierrc changes

* EPMRPP-91645 || code review fix - 1

* EPMRPP-91645 || small fix

* EPMRPP-91645 || added cursor:pointer to startIcon

* EPMRPP-91645 || code review fix - 2
  • Loading branch information
maria-hambardzumian authored Sep 2, 2024
1 parent 87bd9f4 commit 24da190
Show file tree
Hide file tree
Showing 12 changed files with 1,845 additions and 5,738 deletions.
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
"trailingComma": "all",
"printWidth": 100,
"bracketSpacing": true
}
}
7,379 changes: 1,670 additions & 5,709 deletions package-lock.json

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@
"react-datepicker": "^7.3.0"
},
"devDependencies": {
"@storybook/addon-essentials": "^7.2.0",
"@storybook/addon-interactions": "^7.2.0",
"@storybook/addon-links": "^7.2.0",
"@storybook/addon-onboarding": "^1.0.8",
"@storybook/blocks": "^7.2.0",
"@storybook/react": "^7.2.0",
"@storybook/react-vite": "^7.2.0",
"@storybook/testing-library": "^0.2.0",
"@storybook/addon-essentials": "^8.2.9",
"@storybook/addon-interactions": "^8.2.9",
"@storybook/addon-links": "^8.2.9",
"@storybook/addon-onboarding": "^8.2.9",
"@storybook/blocks": "^8.2.9",
"@storybook/react": "^8.2.9",
"@storybook/react-vite": "^8.2.9",
"@storybook/testing-library": "^0.2.2",
"@types/node": "^20.4.5",
"@types/react": "^18.3.3",
"@types/react-datepicker": "^6.2.0",
Expand All @@ -58,14 +58,14 @@
"eslint-plugin-react": "^7.33.1",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"eslint-plugin-storybook": "^0.6.13",
"eslint-plugin-storybook": "^0.8.0",
"husky": "^8.0.3",
"lint-staged": "^13.2.3",
"prettier": "^3.0.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"sass": "^1.64.1",
"storybook": "^7.2.2",
"storybook": "^8.2.9",
"typescript": "^5.0.2",
"vite": "^4.4.5",
"vite-plugin-dts": "^3.4.0",
Expand Down
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
25 changes: 21 additions & 4 deletions src/components/fieldText/fieldText.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
.icon-container-start {
@extend .icon-container;
margin-right: 4px;

.collapsed & {
cursor: pointer;
}
}

.icon-container-end {
Expand Down Expand Up @@ -73,6 +77,22 @@
border: 1px solid var(--rp-ui-color-field-border-3);
border-radius: 3px;
background-color: var(--rp-ui-color-field-bg-3);
transition: width 200ms, padding 200ms, border 100ms;

&.default-width {
width: 240px;
}

&.collapsed {
width: 22px;
border-width: 0;
overflow: hidden;
padding: 0;

.placeholder {
display: none;
}
}

&:hover:not(.disabled) {
border-color: var(--rp-ui-color-field-border-3-hover);
Expand All @@ -96,10 +116,6 @@
color: var(--rp-ui-base-e-300);
}
}

&.default-width {
width: 240px;
}
}

.input-container {
Expand Down Expand Up @@ -138,6 +154,7 @@
top: 2px;
left: 0;
pointer-events: none;
white-space: nowrap;

.asterisk:after {
@include asterisk();
Expand Down
18 changes: 18 additions & 0 deletions src/components/fieldText/fieldText.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react';
import { DeleteIcon } from '@components/icons';
import { FieldText } from './fieldText';
import { ChangeEvent, useRef, useState } from 'react';

const meta: Meta<typeof FieldText> = {
title: 'Field Text',
Expand All @@ -9,6 +10,21 @@ const meta: Meta<typeof FieldText> = {
layout: 'centered',
},
tags: ['autodocs'],
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>) => {
const val = event.target.value;
setValue(val);
if (val === 'blur') {
ref?.current?.blur();
}
};

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

export default meta;
Expand Down Expand Up @@ -73,5 +89,7 @@ export const FullyDescribed: Story = {
touched: true,
hasDoubleMessage: true,
startIcon: <DeleteIcon />,
collapsible: true,
loading: true,
},
};
64 changes: 50 additions & 14 deletions src/components/fieldText/fieldText.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
import {
FC,
ChangeEventHandler,
forwardRef,
ForwardedRef,
ReactElement,
ReactNode,
ComponentPropsWithRef,
useState,
useRef,
InputHTMLAttributes,
MutableRefObject,
} from 'react';
import classNames from 'classnames/bind';
import { ClearIcon } from '@components/icons';
import styles from './fieldText.module.scss';
import { SpinLoader } from '@components/spinLoader';

const cx = classNames.bind(styles);

interface FieldTextProps extends ComponentPropsWithRef<'input'> {
interface FieldTextProps extends InputHTMLAttributes<HTMLInputElement> {
value?: string;
className?: string;
error?: string;
placeholder?: string;
disabled?: boolean;
onChange?: ChangeEventHandler<HTMLInputElement>;
onFocus?: ChangeEventHandler<HTMLInputElement>;
onBlur?: ChangeEventHandler<HTMLInputElement>;
touched?: boolean;
title?: string;
label?: string;
Expand All @@ -33,12 +37,11 @@ interface FieldTextProps extends ComponentPropsWithRef<'input'> {
hasDoubleMessage?: boolean;
type?: string;
displayError?: boolean;
collapsible?: boolean;
loading?: boolean;
}

// TODO: Remove ts-ignore
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
export const FieldText: FC<FieldTextProps> = forwardRef(
export const FieldText = forwardRef<HTMLInputElement, FieldTextProps>(
(
{
value = '',
Expand All @@ -60,13 +63,33 @@ export const FieldText: FC<FieldTextProps> = forwardRef(
hasDoubleMessage = false,
type = 'text',
displayError = true,
collapsible = false,
loading = false,
onFocus = () => {},
onBlur = () => {},
...rest
},
ref: ForwardedRef<HTMLInputElement>,
ref,
): ReactElement => {
const internalRef = useRef<HTMLInputElement>(null);
const inputRef = ref || internalRef;
const [focused, setFocused] = useState(false);

const onFocusHandler = (event: React.FocusEvent<HTMLInputElement>) => {
setFocused(true);
onFocus(event);
};

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

const clearInput = () => {
if (onClear) {
onClear(value);
const input = inputRef as MutableRefObject<HTMLInputElement>;
input.current?.focus();
}
};

Expand All @@ -87,22 +110,35 @@ export const FieldText: FC<FieldTextProps> = forwardRef(
touched,
disabled,
'default-width': defaultWidth,
collapsed: collapsible && !focused && !value,
})}
title={title}
>
{startIcon && (
<span className={cx('icon-container-start')}>
<span className={cx('icon')}>{startIcon}</span>
</span>
{loading ? (
<SpinLoader />
) : (
startIcon && (
<span
className={cx('icon-container-start')}
onClick={() => {
const input = inputRef as MutableRefObject<HTMLInputElement>;
input.current?.focus();
}}
>
<span className={cx('icon')}>{startIcon}</span>
</span>
)
)}
<span className={cx('input-container')}>
<input
ref={ref}
ref={inputRef}
type={type}
className={cx('input')}
value={value}
disabled={disabled}
onChange={onChange}
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
5 changes: 5 additions & 0 deletions src/components/spinLoader/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SpinLoader } from './spinLoader';

export { SpinLoader };

export default SpinLoader;
31 changes: 31 additions & 0 deletions src/components/spinLoader/spinLoader.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.spin-loader {
width: 16px;
height: 16px;
margin: 3px 7px 3px 3px;
flex-shrink: 0;
}

.spinner {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
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(transparent 0%, var(--rp-ui-color-primary));
}

animation: spin 1s infinite linear;
}


@keyframes spin {
to {
transform: rotate(1turn);
}
}
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: {},
};
16 changes: 16 additions & 0 deletions src/components/spinLoader/spinLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { FC, ReactElement } from 'react';
import classNames from 'classnames/bind';
import styles from './spinLoader.module.scss';

const cx = classNames.bind(styles);

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

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

0 comments on commit 24da190

Please sign in to comment.