Giter VIP home page Giter VIP logo

frontend-hw-2's Introduction

Начинающий React разработчик. Домашнее задание №2

В данном домашнем задании вам необходимо реализовать React-компоненты для вашего будущего проекта.

Общие требования:

  1. Если в требованиях к компоненту указано, что он должен принимать пропс className, в таком случае переданные css-классы должны дополнять текущие css-классы, но не заменять их.
  2. При реализации className необходимо воспользоваться библиотекой classnames
  3. Именование css-классов должно осуществляться согласно Методологии БЭМ
  4. Компоненты должны быть реактивными, то есть реагировать на изменение любых пропсов
  5. Контролы должны быть управляемым (то есть не хранить состояние внутри, а лишь сообщать об изменениях наверх. А также соответствовать переданным пропсам со значением, даже если они не изменяются после действий)
  6. Компоненты, которые принимают в качестве пропсов React.InputHTMLAttributes<HTMLElement> должны уметь их пробрасывать в нативные элементы
  7. Из существующих файлов обязательно должны экспортироваться одноименные компоненты через обычный export, не default.

1. Loader

Реализуйте компонент Лоадер

Макеты лоадера: GitHub, E-commerce, Food, Crypto

Требования:

/** Возможные значения размера лоадера */
enum LoaderSize {
    s = 's',
    m = 'm',
    l = 'l'
}

/** Пропсы, которые принимает компонент Loader */
type LoaderProps = {
    /**
     * Идет ли загрузка.
     * По умолчанию - true, для удобства использования
     * Если false, то лоадер не должен отображаться
     */
    loading?: boolean;
    /**
     * Размер лоадера. При передаче данного пропса, должен добавляться css-класс loader_size-{size}
     * По умолчанию: размер - LoaderSize.m, css-класс - loader_size-m
     */
    size?: LoaderSize;
    /**
     * Дополнительные CSS-классы.
     */
    className?: string;
};

Примеры использования:

<Loader />  // стандартный лоадер

<Loader size={LoaderSize.l} />  // лоадер размера L

<Loader loading={isLoading} />  // лоадер, который отображается только при isLoading=false

2. WithLoader

Реализуйте компонент WithLoader.

Требования:

  1. Всегда отображает вложенные элементы (children)
  2. При передаче loading=true поверх контента отображает Loader
  3. Должен переиспользовать компонент Loader
/** Пропсы, которые принимает компонент WithLoader */
export type WithLoaderProps = React.PropsWithChildren<{
  loading: boolean;
}>;

Примеры использования:

<WithLoader loading={isLoading}>
  <div>Семантическая верстка наше все!</div>
</WithLoader>

3. Button

Реализуйте компонент Кнопка.

Макеты кнопки: GitHub, E-commerce, Food, Crypto

Требования:

  1. Кнопка использует html-тег button и принимает все его нативные html-атрибуты
  2. Кнопка принимает пропсы ButtonProps и удовлетворяет их требованиям, описанным ниже
  3. Текст кнопки/дочерний элемент передается в качестве children
  4. Именование css-классов:
    • Базовый класс кнопки: .button
    • Класс-модификатор заблокированной кнопки: .button_disabled
    • Класс-модификатор, отвечающий за раскраску кнопки: .button_color-primary, .button_color-secondary
/** Возможные раскраски кнопки */
enum ButtonColor {
    /** Основная, акцентная кнопка */
    primary = 'primary',
    /** Второстепенная кнопка */
    secondary = 'secondary'
}
 
 /** Пропсы, который принимает компонент Button */
export type ButtonProps = React.PropsWithChildren<{
    /**
     * Если true, то внутри кнопки вместе с children отображается компонент Loader
     * Также кнопка должна переходить в состояние disabled
     * По умолчанию - false
     */
    loading?: boolean;
    /** Цвет кнопки, по умолчанию -  ButtonColor.primary*/
    color?: ButtonColor;
}> & React.ButtonHTMLAttributes<HTMLButtonElement>;

Примеры использования:

// Кнопка с текстом "Отправить", логирующая в консоль "Письмо отправлено" при клике 
<Button onClick={() => console.log('Письмо отправлено')}>
  Отправить
</Button>

// Второстепенная кнопка, отображающая компонент Loader при загрузке каких-то данных
<Button
  color={ButtonColor.secondary}
  loading={isLoading}
>
  Отправить
</Button>

// Кнопка с элементом в качестве содержимого
<Button>
  <span>Модная кнопка</span>
</Button>

// Заблокированная кнопка с дополнительным классом
<Button className="some-outer-class" disabled>
  Отправить
</Button>

// Кнопка с пропсом нативной кнопки
<Button onMouseOver={() => console.log('Убери от меня курсор!')}>
  Отправить
</Button>

4. Card

Реализуйте компонент Карточка (Элемент списка).

Макеты карточки: GitHub, E-commerce, Food, Crypto

Требования:

  1. Для изображения используется html-тег img
/** Пропсы, которые принимает компонент Card */
type CardProps = {
    /** URL изображения */
    image: string;
    /** Заголовок карточки */
    title: React.ReactNode;
    /** Подзаголовок карточки */
    subtitle: React.ReactNode;
    /** Содержимое карточки (футер/боковая часть), может быть пустым */
    content?: React.ReactNode;
    /** Клик на карточку */
    onClick?: React.MouseEventHandler;
};

Примеры использования:

// Простая карточка 
<Card
    image="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg"
    title="Мандарин"
    subtitle="Марокко"
    onClick={() => console.log('Мандарин куплен!')}
/>

// Карточка с доп.контентом и подзаголовком-ссылкой
<Card
    image="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg"
    title="Мандарин"
    subtitle={<a href="/morocco">Марокко</a>}
    content={<span><b>299р</b><i>5 отзывов</i><span>}
/>

5. Input

Реализуйте компонент Поле ввода.

Макеты инпута: GitHub, E-commerce, Food, Crypto

Требования:

  1. Необходимо использовать html-тег input
/** Пропсы, которые принимает компонент Input */
export type InputProps = Omit<
  React.InputHTMLAttributes<HTMLInputElement>,
  'onChange'
> & {
  /** Значение поля */
  value: string;
  /** Callback, вызываемый при вводе данных в поле */
  onChange: (value: string) => void;
};

Примеры использования:

// Простое поле 
<Input
    value="Кто такой биткоин?"
    onChange={(value: string) => console.log(value)}
/>

// Заблокированное поле с плейсхолдером
<Input
    value=""
    onChange={(value: string) => console.log(value)}
    placeholder="Начните набирать свой вопрос"
    disabled
/>

6. MultiDropdown

Реализуйте компонент Выпадающий список с множественным выбором (Фильтр).

Макеты мультидропдауна: GitHub, E-commerce, Food, Crypto,

Требования:

  1. Не должен использовать html-элемент select
/** Вариант для выбора в фильтре */
type Option = {
    /** Ключ варианта, используется для отправки на бек/использования в коде */
    key: string;
    /** Значение варианта, отображается пользователю */
    value: string;
};

/** Пропсы, которые принимает компонент Dropdown */
type MultiDropdownProps = {
    /** Массив возможных вариантов для выбора */
    options: Option[];
    /** Текущие выбранные значения поля, массив может быть пустым */
    value: Option[];
    /** Callback, вызываемый при выборе варианта */
    onChange: (value: Option[]) => void;
    /** Заблокирован ли дропдаун */
    disabled?: boolean;
    /** Преобразовать выбранные значения в строку. Отображается в дропдауне в качестве выбранного значения */
    pluralizeOptions: (value: Option[]) => string;
}

Примеры использования:

// Простой фильтр 
<MultiDropdown
    options={[
        { key: 'msk', value: 'Москва' },
        { key: 'spb', value: 'Санкт-Петербург' },
        { key: 'ekb', value: 'Екатеринбург' }
    ]}
    value={[{ key: 'msk', value: 'Москва' }]}
    onChange={(selected: Option[]) => console.log('Выбрано:', JSON.stringify(selected))}
    pluralizeOptions={() => ''}
/>

// Заблокированный фильтр
<MultiDropdown
    disabled
    options={someOptions}
    value={currentValue}
    onChange={onChange}
    pluralizeOptions={(values: Option[]) => values.length === 0 ? 'Выберите город' : `Выбрано: ${values.length}`}
/>

// Фильтр, отображающий количество выбранных вариантов
<MultiDropdown
    options={someOptions}
    value={currentValue}
    onChange={onChange}
    pluralizeOptions={(values: Option[]) => `Выбрано: ${values.length}`}
/>

7. CheckBox

Реализуйте компонент Чекбокс.

Макеты чекбокса: GitHub, E-commerce, Food, Crypto

Требования:

  1. Необходимо использовать html-тег input
/** Пропсы, которые принимает компонент CheckBox */
type CheckBoxProps = Omit<
  React.InputHTMLAttributes<HTMLInputElement>,
  'onChange'
> & {
    /** Вызывается при клике на чекбокс */
    onChange: (value: boolean) => void;
};

Примеры использования:

// Простой чекбокс 
<CheckBox
  checked={checked}
  onChange={setChecked}
/>

// Заблокированный чекбокс 
<CheckBox
  disabled
  checked={checked}
  onChange={setChecked}
/>

frontend-hw-2's People

Contributors

kirill-gadzhiev avatar sodapng avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.