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

Review #3

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@
"react-dom": "^18.2.0"
},
"lint-staged": {
"*.{css,scss}": "yarn stylelint:fix",
"*.{js,jsx,ts,tsx}": "yarn lint",
"*.{js,jsx,ts,tsx,json,css,scss,md}": "yarn format"
"*.{css,scss}": "npm run stylelint:fix",
"*.{js,jsx,ts,tsx}": "npm run lint",
"*.{js,jsx,ts,tsx,json,css,scss,md}": "npm run format"
},
"config": {
"commitizen": {
Expand Down
9 changes: 9 additions & 0 deletions src/components/arrow-button/ArrowButton.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@
transition: transform 0.5s ease;
}

.container:hover {
background-color: var(--gold, #ffc802);
cursor: pointer;
}

.container:active {
background-color: #787878;
}

.container_open {
transform: translate(616px);
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/arrow-button/ArrowButton.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const ArrowButtonStory: Story = {
render: () => {
return (
<>
<ArrowButton />
<ArrowButton onClick={() => console.log('click')} isOpenForm={false} />
</>
);
},
Expand Down
25 changes: 21 additions & 4 deletions src/components/arrow-button/ArrowButton.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
import arrow from 'src/images/arrow.svg';

import styles from './ArrowButton.module.scss';
import clsx from 'clsx';

/** Функция для обработки открытия/закрытия формы */
export type OnClick = () => void;
export type OnClick = (isOpenForm: boolean) => void;

export const ArrowButton = () => {
export type TArrowButton = {
isOpenForm: boolean;
onClick: OnClick;
};

export const ArrowButton = ({ isOpenForm, onClick }: TArrowButton) => {
return (
/* Не забываем указаывать role и aria-label атрибуты для интерактивных элементов */
<div
role='button'
aria-label='Открыть/Закрыть форму параметров статьи'
tabIndex={0}
className={styles.container}>
<img src={arrow} alt='иконка стрелочки' className={styles.arrow} />
className={clsx(styles.container, {
[styles.container_open]: isOpenForm,
})}
onClick={() => {
onClick(!isOpenForm);
}}>
<img
src={arrow}
alt='иконка стрелочки'
className={clsx(styles.arrow, {
[styles.arrow_open]: isOpenForm,
})}
/>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
display: flex;
flex-shrink: 0;
flex-direction: column;
gap: 50px;
box-sizing: border-box;
width: 616px;
height: auto;
Expand Down
125 changes: 118 additions & 7 deletions src/components/article-params-form/ArticleParamsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,130 @@ import { ArrowButton } from 'components/arrow-button';
import { Button } from 'components/button';

import styles from './ArticleParamsForm.module.scss';
import { useState, useRef } from 'react';
import clsx from 'clsx';

import { Text } from '../text';
import { Select } from '../select';
import {
ArticleStateType,
fontSizeOptions,
contentWidthArr,
fontFamilyOptions,
fontColors,
backgroundColors,
OptionType,
defaultArticleState,
} from 'src/constants/articleProps';
import { RadioGroup } from '../radio-group';
import { Separator } from '../separator';
import { useOutsideClickClose } from '../select/hooks/useOutsideClickClose';

export type TArticleParamsForm = {
articleState: ArticleStateType;
onSubmitState: (articleState: ArticleStateType) => void;
};

export const ArticleParamsForm = ({
articleState,
onSubmitState,
}: TArticleParamsForm) => {
const [isOpenForm, setOpenForm] = useState<boolean>(false);
const [isOptionForm, setOptionForm] =
useState<ArticleStateType>(articleState);
const formRef = useRef<HTMLDivElement | null>(null);

const onSubmitForm = (e: React.FormEvent) => {
e.preventDefault();
onSubmitState(isOptionForm);
};

useOutsideClickClose({
rootRef: formRef,
isOpen: isOpenForm,
onChange: () => setOpenForm(false),
});

const onChangeSelected = (
key: keyof ArticleStateType,
option: OptionType
) => {
setOptionForm((prev) => ({ ...prev, [key]: option }));
};

export const ArticleParamsForm = () => {
return (
<>
<ArrowButton />
<aside className={styles.container}>
<form className={styles.form}>
<div ref={formRef}>
<ArrowButton onClick={setOpenForm} isOpenForm={isOpenForm} />
<aside
className={clsx(styles.container, {
[styles.container_open]: isOpenForm,
})}>
<form className={styles.form} onSubmit={onSubmitForm}>
<Text weight={800} size={31} align={'left'} uppercase={true}>
Задайте параметры
</Text>

<Select
title='шрифт'
options={fontFamilyOptions}
selected={isOptionForm.fontFamilyOption}
onChange={(isOptionForm) => {
onChangeSelected('fontFamilyOption', isOptionForm);
}}
/>

<RadioGroup
title='размер шрифта'
options={fontSizeOptions}
selected={isOptionForm.fontSizeOption}
name={'font-size'}
onChange={(isOptionForm) => {
onChangeSelected('fontSizeOption', isOptionForm);
}}
/>

<Select
title='цвет шрифта'
options={fontColors}
selected={isOptionForm.fontColor}
onChange={(isOptionForm) => {
onChangeSelected('fontColor', isOptionForm);
}}
/>

<Separator />

<Select
title='цвет фона'
options={backgroundColors}
selected={isOptionForm.backgroundColor}
onChange={(isOptionForm) => {
onChangeSelected('backgroundColor', isOptionForm);
}}
/>

<Select
title='ширина контента'
options={contentWidthArr}
selected={isOptionForm.contentWidth}
onChange={(isOptionForm) => {
onChangeSelected('contentWidth', isOptionForm);
}}
/>

<div className={styles.bottomContainer}>
<Button title='Сбросить' type='reset' />
<Button
title='Сбросить'
type='reset'
onClick={() => {
setOptionForm(defaultArticleState);
onSubmitState(defaultArticleState);
}}
/>
<Button title='Применить' type='submit' />
</div>
</form>
</aside>
</>
</div>
);
};
2 changes: 1 addition & 1 deletion src/components/radio-group/RadioGroup.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

.label:hover,
.item[data-checked='true'] .label:hover {
background: var(--gold, #ffc802);
background: var(--gold, #ffedab);
}

.item[data-checked='true'] .label {
Expand Down
6 changes: 5 additions & 1 deletion src/components/select/Select.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

.selectWrapper:not([data-is-active='true'])
.placeholder:not([data-status='invalid']):hover {
outline: 3px solid #000000;
outline: 3px solid #ffc802;
}

.select {
Expand Down Expand Up @@ -81,6 +81,10 @@
background: var(--grey, #c4c4c4);
}

.option:active {
background: #d7d7d7;
}

@mixin option-color-before {
content: '';
width: 35px;
Expand Down
4 changes: 2 additions & 2 deletions src/components/select/hooks/useOutsideClickClose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ export const useOutsideClickClose = ({
}
};

window.addEventListener('click', handleClick);
window.addEventListener('mousedown', handleClick);

return () => {
window.removeEventListener('click', handleClick);
window.removeEventListener('mousedown', handleClick);
};
}, [onClose, onChange, isOpen]);
};
2 changes: 1 addition & 1 deletion src/components/separator/index.module.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.separator {
width: 100%;
height: 1px;
background: #000000;
background: #d7d7d7;
}
2 changes: 2 additions & 0 deletions src/constants/articleProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,6 @@ export const defaultArticleState = {
fontSizeOption: fontSizeOptions[0],
};

console.log('start');

export type ArticleStateType = typeof defaultArticleState;
25 changes: 17 additions & 8 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { createRoot } from 'react-dom/client';
import { StrictMode, CSSProperties } from 'react';
import { StrictMode, CSSProperties, useState } from 'react';
import clsx from 'clsx';

import { Article } from './components/article/Article';
import { ArticleParamsForm } from './components/article-params-form/ArticleParamsForm';
import { defaultArticleState } from './constants/articleProps';
import {
defaultArticleState,
ArticleStateType,
} from './constants/articleProps';

import './styles/index.scss';
import styles from './styles/index.module.scss';
Expand All @@ -13,19 +16,25 @@ const domNode = document.getElementById('root') as HTMLDivElement;
const root = createRoot(domNode);

const App = () => {

Choose a reason for hiding this comment

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

Можно лучше

  • Лучше выделить компонент App в отдельный файл, чтобы не смешивать все в index.js

const [articleState, setArticleState] =
useState<ArticleStateType>(defaultArticleState);

return (
<div

Choose a reason for hiding this comment

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

Можно лучше

  • По семантике нужно помещать весь главный контент страницы после хэдера в тег main.

className={clsx(styles.main)}

Choose a reason for hiding this comment

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

Можно лучше

  • clsx можно не использовать, если только один селектор передается

style={
{
'--font-family': defaultArticleState.fontFamilyOption.value,
'--font-size': defaultArticleState.fontSizeOption.value,
'--font-color': defaultArticleState.fontColor.value,
'--container-width': defaultArticleState.contentWidth.value,
'--bg-color': defaultArticleState.backgroundColor.value,
'--font-family': articleState.fontFamilyOption.value,
'--font-size': articleState.fontSizeOption.value,
'--font-color': articleState.fontColor.value,
'--container-width': articleState.contentWidth.value,
'--bg-color': articleState.backgroundColor.value,
} as CSSProperties
}>
<ArticleParamsForm />
<ArticleParamsForm
articleState={articleState}
onSubmitState={setArticleState}
/>
<Article />
</div>
);
Expand Down
Loading