import { Callout } from 'nextra/components' # Компоненты, полиморфные компоненты ## Button ### Подготовка - Создайте папку _src/components/ui_ - Создайте папку _button_ в _src/components/ui_ со следующей структурой: {/* prettier-ignore */} ```markdown src └── components └── ui └── button └── button.tsx └── button.module.scss └── button.stories.ts └── index.ts ``` ### Дизайн и варианты После рассмотрения дизайна стало понятно, что у нас будет несколько вариантов кнопок, а именно: ![Button](./images/Button.png) - Стандартная, она же основная, она же `primary` - Второстепенная, она же `secondary` - Третьестепенная, она же `tertiary`, иногда ее называют `outlined` - Кнопка, занимающая всю ширину родителя, она же `fullWidth` - Кнопка, которая выглядит как ссылка, она же `link` - Ссылка, которая выглядит как кнопка ### Варианты реализации Какие варианты реализации у нас есть? 1. Создать один компонент, который будет принимать все возможные пропсы и в зависимости от них будет рендериться тот или иной вариант кнопки 2. Создать отдельный компонент для каждого варианта кнопки Мы отдадим предпочтение **первому варианту**, так как он более гибкий и позволит нам легко добавлять новые варианты кнопок в будущем. ### Props Опишем пропсы, которые будет принимать наш компонент: ```tsx filename="button.tsx" import { ComponentPropsWithoutRef } from 'react' export type ButtonProps = { variant?: 'primary' | 'secondary' | 'tertiary' | 'link' fullWidth?: boolean } & ComponentPropsWithoutRef<'button'> ``` `ComponentPropsWithoutRef<'button'>` - это пропсы, которые принимает стандартный html-тег button, мы их расширяем своими пропсами. ### Реализация Создадим сам компонент: ```tsx filename="button.tsx" import s from './button.module.scss' export const Button = ({ className, fullWidth, variant = 'primary', ...rest }: ButtonProps) => { return (