Common Buttons

Описание

Есть 5 видов кнопок: Elevated, Filled, Tonal, Outlined, Text. Подробно об использовании каждой из кнопок можете почитать на официальном сайте. Здесь же я опишу применение кратко.

Примеры

Elevated

Elevated кнопки - это, по сути, tonal кнопки с тенью. Чтобы предотвратить расползание теней, используйте их только в случае крайней необходимости, например, когда кнопка требует визуального отделения от фона с рисунком.

Filled

Filled кнопки оказывают наибольшее визуальное воздействие после FAB и должны использоваться для важных, завершающих действий, таких как Сохранить, Присоединиться или Подтвердить.

Filled Tonal

Tonal кнопка - это альтернативная середина между кнопками filled и outlined. Они полезны в контекстах, где кнопка с более низким приоритетом требует немного большего внимания, чем outlined может предоставить, например, Далее в настройке профиля. Tonal кнопки используют secondary цветовое отображение.

Outlined

Outlined кнопки - это кнопки со средним акцентом. Они содержат действия, которые важны, но не являются основным действием в приложении.

Outlined кнопки хорошо сочетаются с filled кнопками, указывая на альтернативное, второстепенное действие.

Text

Text кнопки используются для действий с наименьшим приоритетом, особенно при представлении нескольких вариантов. Например, в форме опроса, где ответами являются Да, Нет и Возможно.

Компонент

Скопируйте и вставьте код в свой проект.

Обратите внимание, что компонент имеет зависимости таких компонентов как Label и UIStateLayer. Если вы еще не добавили их в свой проект, следует заняться сперва ими.

Можно сохранить компонент в файл src/shared/ui/Button.tsx:

import React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import Label from "@/shared/typography/Label"
import UIStateLayer from "@/shared/ui/UIStateLayer"
import { cn } from "@/lib/cn"
const buttonVariants = cva(
"group h-10 rounded-full w-fit disabled:bg-opacity-[0.12] disabled:cursor-not-allowed disabled:shadow-none disabled:text-onSurface disabled:text-opacity-[0.38] transition-shadow duration-short2 ease-standard",
{
variants: {
appearance: {
elevated:
"bg-surfaceContainerLow shadow-elevation1 disabled:bg-primary hover:shadow-elevation2 active:shadow-elevation1 text-primary",
filled:
"bg-primary disabled:bg-onSurface hover:shadow-elevation1 active:shadow-none text-onPrimary",
tonal:
"bg-secondaryContainer disabled:bg-onSurface hover:shadow-elevation1 active:shadow-none text-onSecondaryContainer",
outlined:
"border border-outline disabled:border-onSurface disabled:border-opacity-[0.12] text-primary",
text: "text-primary",
},
},
defaultVariants: {},
}
)
// Для стилей State Layer
// (Необходим, так как Button и State Layer в разных состояниях имеют разные свойства background)
const uiStateLayerVariants = cva("rounded-full flex justify-center items-center gap-2 px-6", {
variants: {
appearance: {
elevated: "bg-primary",
filled: "bg-onPrimary",
tonal: "bg-onSecondaryContainer",
outlined: "bg-primary",
text: "bg-primary px-3",
},
},
})
interface Props
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
Required<Pick<VariantProps<typeof buttonVariants>, "appearance">> {
icon?: React.ReactNode
}
const Button = React.forwardRef<HTMLButtonElement, Props>(
({ icon, children, className, appearance, ...props }, forwardedRef) => {
return (
<button
className={cn(buttonVariants({ appearance }), className)}
{...props}
ref={forwardedRef}
>
<UIStateLayer
className={cn(
uiStateLayerVariants({ appearance }),
icon && "pl-4",
icon && appearance === "text" && "pl-3 pr-4"
)}
>
{icon && <span>{icon}</span>}
<Label size="large">{children}</Label>
</UIStateLayer>
</button>
)
}
)
Button.displayName = "Button"
export default Button

Использование

import Button from "@/components/ui/Button"
...
{/* elevated */}
<Button appearance='elevated'>Elevated button</Button>
{/* filled */}
<Button appearance='filled'>Filled button</Button>
{/* disabled tonal */}
<Button appearance='tonal' disabled>Tonal button</Button>
{/* with onClick */}
<Button appearance='outlined' onClick={() => {}}>Outlined button</Button>
{/* button type (submit by default as regular html) */}
<Button appearance='text' type="button">Text button</Button>

Иконки

Также можно использовать кнопки с иконками. Лично я использую Iconoir библиотеку. Можете выбрать свою любимую.

import { Plus } from "iconoir-react"
...
<Button appearance="filled" icon={<Plus />}>
Filled
</Button>