Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
happylolonly committed May 29, 2024
1 parent 552ada0 commit cbd5be2
Show file tree
Hide file tree
Showing 19 changed files with 814 additions and 123 deletions.
3 changes: 2 additions & 1 deletion front/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"build": "vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
Expand Down Expand Up @@ -35,6 +35,7 @@
"react-loader-spinner": "^6.1.6",
"react-number-format": "^5.3.4",
"react-router-dom": "^6.14.2",
"react-textarea-autosize": "^8.5.3",
"recoil": "^0.7.7",
"recoil-persist": "^5.1.0",
"rollup-plugin-node-polyfills": "^0.2.1",
Expand Down
Binary file added front/src/assets/fonts/Play-Regular.ttf
Binary file not shown.
82 changes: 82 additions & 0 deletions front/src/components/Input/Input.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
.textbox {
width: 100%;
height: 42px;
position: relative;
transform-style: preserve-3d;
background-color: transparent;
transition: all 0.2s ease;
display: flex;
flex-direction: column;

input,
textarea {
width: 90%;
margin: auto;
height: 100%;
border: none;
padding: 0 2px;
background-color: transparent;
font-size: 1.25rem;
display: block;
color: var(--primary-color);
text-align: end;
filter: drop-shadow(0 0 15px rgba(0, 0, 0, 0.5));
text-transform: initial;

&::placeholder {
color: #272343;
opacity: 0.5;
text-transform: lowercase;
}

&:disabled {
font-size: 14px; // need update root style
color: #e4e4e4;
opacity: 0.5;
}

&:focus {
outline: none;
}
}
}

.textarea {
height: unset;

textarea {
position: relative;
top: -5px;
color: white;
resize: none;
box-shadow: unset;
text-align: left;
overflow-y: hidden;
min-height: unset;
}
}

.error {
color: red;
}

.amount {
position: absolute;
right: 10px;
top: -15px;

display: flex;
gap: 0 10px;

button {
color: var(--blue-light);

&:not(:last-of-type) {
opacity: 0.5;
}

&:hover {
opacity: 1;
}
}
}
37 changes: 37 additions & 0 deletions front/src/components/Input/Input.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* eslint-disable import/no-unused-modules */
import { Story, Meta } from '@storybook/react';
import Input, { Props } from './Input';
import { useState } from 'react';

export default {
title: 'Atoms/Input',
component: Input,
argTypes: {
color: {
control: {
type: 'inline-radio',
options: ['pink', undefined],
},
},
},
} as Meta;

const Template: Story<Props> = (args) => {
const [value, setValue] = useState('Search');
return (
<div style={{ width: 400 }}>
<Input
{...args}
title="Search"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
</div>
);
};

export const Default = Template.bind({});
Default.args = {
placeholder: 'Enter...',
value: 'Default',
};
163 changes: 163 additions & 0 deletions front/src/components/Input/Input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import cx from 'classnames';
import TextareaAutosize from 'react-textarea-autosize';
import React, { useEffect, useState } from 'react';
import styles from './Input.module.scss';
import LinearGradientContainer, {
Color,
} from '../LinearGradientContainer/LinearGradientContainer';

export type Props = {
color?: Color;
width?: string;
title?: string;
className?: string;
classNameTextbox?: string;
focusedProps?: boolean;
isTextarea?: boolean;
type?: 'text' | 'password';
error?: string;
value: string;
maxValue?: number;
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
onBlurFnc?: () => void;
onFocusFnc?: () => void;
disabled?: boolean;
} & React.InputHTMLAttributes<HTMLInputElement>;

const dataPercentAttribute = 'data-percent';

const Input = React.forwardRef<HTMLInputElement, Props>(
(
{
color,
placeholder,
onChange,
title,
width,
type = 'text',
value,
autoFocus,
disabled,
className,
classNameTextbox,
focusedProps,
maxValue,
isTextarea,
onBlurFnc,
onFocusFnc,
error,
...props
},
ref
) => {
const [focused, setFocused] = useState(focusedProps || false);

useEffect(() => {
if (!ref?.current) {
return;
}

if (focused) {
ref.current.focus();
} else {
ref.current.blur();
}
}, [focused, ref]);

useEffect(() => {
if (typeof focusedProps === 'boolean') {
setFocused(focusedProps);
}
}, [focusedProps]);

const Tag = isTextarea ? TextareaAutosize : 'input';

const handlerOnFocused = () => {
setFocused(true);

if (onFocusFnc) {
onFocusFnc();
}
};

const handlerOnBlur = () => {
setFocused(false);

if (onBlurFnc) {
onBlurFnc();
}
};

function handleMax(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
const target = e.target as HTMLButtonElement;
const percent = target.getAttribute(dataPercentAttribute);
const newValue = ((maxValue! * Number(percent)) / 100).toFixed(0);

// FIXME: need refactor other components
onChange({
target: {
value: String(newValue),
// issue with number input
focus() {},
},
});
}

return (
<div
className={cx(
styles.textbox,
focused && styles.focused,
isTextarea && styles.textarea,
classNameTextbox
)}
style={{ width }}
>
<LinearGradientContainer
active={focusedProps || focused}
color={disabled ? Color.Black : color}
title={title}
>
{focused && !!maxValue && (
<div className={styles.amount}>
{[25, 50, 75, 100].map((percent) => {
return (
<button
key={percent}
type="button"
// onMouseDown be called before onBlur
onMouseDown={handleMax}
{...{ [dataPercentAttribute]: percent }}
>
{percent === 100 ? 'max' : `${percent}%`}
</button>
);
})}
</div>
)}

<Tag
type={type}
ref={ref}
value={value}
className={className}
onChange={onChange}
disabled={disabled}
// eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus={autoFocus}
onFocus={handlerOnFocused}
onBlur={handlerOnBlur}
placeholder={placeholder}
autoComplete="off"
{...props}
/>
</LinearGradientContainer>
{error && <div className={styles.error}>{error}</div>}
</div>
);
}
);

Input.displayName = 'Input';

export default Input;
32 changes: 32 additions & 0 deletions front/src/components/Input/InputNumber/InputNumber.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* eslint-disable import/no-unused-modules */

import { Meta, StoryObj } from '@storybook/react';

import InputNumber from './InputNumber';

const meta: Meta<typeof InputNumber> = {
component: InputNumber,
title: 'Atoms/Input/InputNumber',
parameters: {
design: {
type: 'figma',
url: 'https://www.figma.com/file/7i0Ly3YF587km0F8iDZod4/cyb?type=design&node-id=11052-15433',
},
},
};
export default meta;

type Story = StoryObj<typeof InputNumber>;

const defaultArgs = {
value: 1100000000,
onValueChange: () => {},
};

export const Main: Story = {
args: defaultArgs,
};

export const withMax: Story = {
args: { ...defaultArgs, maxValue: 1000000000000 },
};
Loading

0 comments on commit cbd5be2

Please sign in to comment.