Chips

Описание

Chips помогают людям вводить информацию, делать выбор, фильтровать содержимое или запускать действия

Подробнее об использовании элемента читайте на официальном сайте

AssistChip

Примеры

Без иконкиС иконкойElevatedOutlined

Компонент

Компонент можно сохранить в src/shared/ui/Chips/AssistChip.tsx. Обратите внимание на необходимые зависимости: Label и UIStateLayer

import React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import Label from "@/shared/typography/Label"
import UIStateLayer from "../UIStateLayer"
import { cn } from "@/lib/cn"
const assistChipVariants = cva(
"group w-fit rounded-lg h-8 outline-none select-none",
{
variants: {
appearance: {
outlined: "border border-outline focus-visible:border-onSurface",
elevated:
"bg-surfaceContainerLow shadow-elevation1 hover:shadow-elevation2 active:shadow-elevation1",
},
},
}
)
interface AssistChipProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
Required<Pick<VariantProps<typeof assistChipVariants>, "appearance">> {
icon?: React.ReactNode
}
const AssistChip = React.forwardRef<HTMLButtonElement, AssistChipProps>(
({ className, appearance, children, icon, ...props }, forwardedRef) => {
return (
<button
className={cn(assistChipVariants({ appearance }), className)}
{...props}
ref={forwardedRef}
>
<UIStateLayer
className={cn(
"flex items-center gap-2 px-4 rounded-lg bg-onSurface group-focus-visible:bg-onSurface group-focus-visible:bg-opacity-[0.12]",
icon && "pl-2"
)}
>
{icon && <span className="text-primary">{icon}</span>}
<Label size="large" className="text-onSurface">
{children}
</Label>
</UIStateLayer>
</button>
)
}
)
AssistChip.displayName = "AssistChip"
export default AssistChip

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

Обратите внимание, что по стайл гайдам размеры иконок уменьшены с 24x24 до 18x18. Вам придётся делать это вручную.

import AssistChip from "@/shared/ui/Chips/AssistChip""
...
// Без иконки | стиль elevated
<AssistChip appearance="elevated">Elevated</AssistChip>
// Без иконки | стиль outlined
<AssistChip appearance="outlined">Outlined</AssistChip>
// С иконкой | стиль elevated
<AssistChip
appearance="elevated"
icon={<Calendar width={18} height={18} />}
>
Elevated
</AssistChip>
// С иконкой | стиль outlined
<AssistChip
appearance="outlined"
icon={<Calendar width={18} height={18} />}
>
Outlined
</AssistChip>

FilterChip

Примеры

Без иконкиLeading iconTrailing iconОбе иконкиElevatedOutlined

Компонент

Компонент можно сохранить в src/shared/ui/Chips/FilterChip.tsx. Обратите внимание на необходимые зависимости: Label и UIStateLayer

Так же данный компонент использует @radix-ui/react-toggle компонент.

yarn add @radix-ui/react-toggle
"use client"
import React from "react"
import * as Toggle from "@radix-ui/react-toggle"
import { cva, type VariantProps } from "class-variance-authority"
import { Check } from "iconoir-react"
import Label from "@/shared/typography/Label"
import UIStateLayer from "../UIStateLayer"
import { cn } from "@/lib/cn"
const filterChipVariants = cva(
"group w-fit rounded-lg h-8 outline-none select-none",
{
variants: {
appearance: {
outlined:
"border border-outline focus-visible:border-onSurface data-[state=on]:bg-secondaryContainer data-[state=on]:border-0",
elevated:
"bg-surfaceContainerLow shadow-elevation1 data-[state=on]:bg-secondaryContainer hover:shadow-elevation2 active:shadow-elevation1",
},
},
}
)
interface FilterChipProps
extends React.ComponentPropsWithoutRef<typeof Toggle.Root>,
Required<Pick<VariantProps<typeof filterChipVariants>, "appearance">> {
leadingIcon?: React.ReactNode
trailingIcon?: React.ReactNode
}
const FilterChip = React.forwardRef<
React.ElementRef<typeof Toggle.Root>,
FilterChipProps
>(
(
{
className,
appearance,
children,
leadingIcon,
trailingIcon,
pressed,
...props
},
forwardedRef
) => {
return (
<Toggle.Root
className={cn(filterChipVariants({ appearance }), className)}
{...props}
ref={forwardedRef}
>
<UIStateLayer
className={cn(
"flex items-center gap-2 px-4 rounded-lg bg-onSurfaceVariant group-focus-visible:bg-onSurfaceVariant group-data-[state=on]:bg-onSecondaryContainer group-data-[state=on]:group-focus-visible:bg-onSecondaryContainer group-focus-visible:bg-opacity-[0.12] group-data-[state=on]:bg-opacity-0 group-data-[state=on]:group-hover:bg-opacity-[0.08] group-data-[state=on]:group-focus-visible:bg-opacity-[0.12]",
(leadingIcon || pressed) && "pl-2",
trailingIcon && "pr-2"
)}
>
{pressed ? (
<span className="text-primary group-data-[state=on]:text-onSecondaryContainer">
<Check width={18} height={18} />
</span>
) : (
leadingIcon && (
<span className="text-primary group-data-[state=on]:text-onSecondaryContainer">
{leadingIcon}
</span>
)
)}
<Label
size="large"
className="text-onSurfaceVariant group-hover:text-onSurface group-focus-visible:text-onSurface group-data-[state=on]:text-onSecondaryContainer"
>
{children}
</Label>
{trailingIcon && (
<span className="text-onSurface group-data-[state=on]:text-onSecondaryContainer">
{trailingIcon}
</span>
)}
</UIStateLayer>
</Toggle.Root>
)
}
)
FilterChip.displayName = "FilterChip"
export default FilterChip

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

Обратите внимание, что по стайл гайдам размеры иконок уменьшены с 24x24 до 18x18. Вам придётся делать это вручную.

Так же обязательно придётся прокидывать пропсы pressed и onPressedChange для правильного отображения UI.

import { Calendar, NavArrowDown } from "iconoir-react"
import FilterChip from "@/shared/ui/Chips/FilterChip"
...
const [state, setState] = useState(false)
...
// Без иконки | Elevated
<FilterChip
appearance="elevated"
pressed={state}
onPressedChange={setState}
>
Elevated
</FilterChip>
// Без иконки | Outlined
<FilterChip
appearance="outlined"
pressed={state}
onPressedChange={setState}
>
Outlined
</FilterChip>
// С иконкой в начале | Elevated
<FilterChip
appearance="elevated"
leadingIcon={<Calendar width={18} height={18} />}
pressed={state}
onPressedChange={setState}
>
Elevated
</FilterChip>
// С иконкой в начале | Outlined
<FilterChip
appearance="outlined"
leadingIcon={<Calendar width={18} height={18} />}
pressed={state}
onPressedChange={setState}
>
Outlined
</FilterChip>
// С иконкой в конце | Elevated
<FilterChip
appearance="elevated"
trailingIcon={<NavArrowDown width={18} height={18} />}
pressed={state}
onPressedChange={setState}
>
Elevated
</FilterChip>
// С иконкой в конце | Outlined
<FilterChip
appearance="outlined"
trailingIcon={<NavArrowDown width={18} height={18} />}
pressed={state}
onPressedChange={setState}
>
Outlined
</FilterChip>
// Обе иконки | Elevated
<FilterChip
appearance="elevated"
leadingIcon={<Calendar width={18} height={18} />}
trailingIcon={<NavArrowDown width={18} height={18} />}
pressed={state}
onPressedChange={setState}
>
Elevated
</FilterChip>
// Обе иконки | Outlined
<FilterChip
appearance="outlined"
leadingIcon={<Calendar width={18} height={18} />}
trailingIcon={<NavArrowDown width={18} height={18} />}
pressed={state}
onPressedChange={setState}
>
Outlined
</FilterChip>

InputChip

Примеры

Без иконкиLeading iconTrailing iconОбе иконкиAvatarAvatar + trailing icon

Компонент

Компонент можно сохранить в src/shared/ui/Chips/InputChip.tsx. Обратите внимание на необходимые зависимости: Label и UIStateLayer

Так же данный компонент использует @radix-ui/react-toggle компонент.

yarn add @radix-ui/react-toggle
"use client"
import React from "react"
import * as Toggle from "@radix-ui/react-toggle"
import Label from "@/shared/typography/Label"
import UIStateLayer from "../UIStateLayer"
import { cn } from "@/lib/cn"
interface InputChipProps
extends React.ComponentPropsWithoutRef<typeof Toggle.Root> {
leadingIcon?: React.ReactNode
trailingIcon?: React.ReactNode
avatar?: React.ReactNode
}
const InputChip = React.forwardRef<
React.ElementRef<typeof Toggle.Root>,
InputChipProps
>(
(
{ className, children, leadingIcon, trailingIcon, avatar, ...props },
forwardedRef
) => {
return (
<Toggle.Root
className={cn(
"group w-fit rounded-lg h-8 outline-none select-none border border-outline focus-visible:border-onSurface data-[state=on]:bg-secondaryContainer data-[state=on]:border-0",
avatar && "rounded-full",
className
)}
{...props}
ref={forwardedRef}
>
<UIStateLayer
className={cn(
"flex items-center gap-2 px-4 rounded-lg bg-onSurfaceVariant group-focus-visible:bg-onSurfaceVariant group-data-[state=on]:bg-onSecondaryContainer group-data-[state=on]:group-focus-visible:bg-onSecondaryContainer group-focus-visible:bg-opacity-[0.12] group-data-[state=on]:bg-opacity-0 group-data-[state=on]:group-hover:bg-opacity-[0.08] group-data-[state=on]:group-focus-visible:bg-opacity-[0.12]",
avatar && "rounded-full pl-1",
leadingIcon && "pl-2",
trailingIcon && "pr-2"
)}
>
{leadingIcon && <span className="text-primary">{leadingIcon}</span>}
{avatar && avatar}
<Label
size="large"
className="text-onSurfaceVariant group-data-[state=on]:text-onSecondaryContainer"
>
{children}
</Label>
{trailingIcon && (
<span className="text-onSurfaceVariant group-hover:text-onSurface group-focus-visible:text-onSurface group-data-[state=on]:text-onSecondaryContainer">
{trailingIcon}
</span>
)}
</UIStateLayer>
</Toggle.Root>
)
}
)
InputChip.displayName = "InputChip"
export default InputChip

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

Обратите внимание, что по стайл гайдам размеры иконок уменьшены с 24x24 до 18x18. Вам придётся делать это вручную.

Если используете проп avatar - удостоверьтесь, что помещаете туда React элемент размерами 24x24. Это может быть как иконка профиля, так и полноценное изображение пользователя.

// Без иконки
<InputChip>Input chip</InputChip>
// С иконкой спереди
<InputChip leadingIcon={<MediaImage width={18} height={18} />}>
Type: images
</InputChip>
// С иконкой в конце
<InputChip trailingIcon={<Cancel width={18} height={18} />}>
{"<$100"}
</InputChip>
// Обе иконки
<InputChip
leadingIcon={<Calendar width={18} height={18} />}
trailingIcon={<Cancel width={18} height={18} />}
>
Wed, 26.07
</InputChip>
// С аватаркой
<InputChip avatar={<ProfileCircle />}
Jack Siemens
</InputChip>
// Аватарка + иконка в конце
<InputChip
avatar={<ProfileCircle />}
trailingIcon={<Cancel width={18} height={18} />}
>
Mohammad
</InputChip>

SuggestionChip

Примеры

Без иконкиС иконкойElevatedOutlined

Компонент

Компонент можно сохранить в src/shared/ui/Chips/SuggestionChip.tsx. Обратите внимание на необходимые зависимости: Label и UIStateLayer

Так же данный компонент использует @radix-ui/react-toggle компонент.

yarn add @radix-ui/react-toggle
"use client"
import React from "react"
import * as Toggle from "@radix-ui/react-toggle"
import { cva, type VariantProps } from "class-variance-authority"
import Label from "@/shared/typography/Label"
import UIStateLayer from "../UIStateLayer"
import { cn } from "@/lib/cn"
const suggestionChipVariants = cva(
"group w-fit rounded-lg h-8 outline-none select-none",
{
variants: {
appearance: {
outlined:
"border border-outline focus-visible:border-onSurface data-[state=on]:bg-secondaryContainer data-[state=on]:border-0",
elevated:
"bg-surfaceContainerLow shadow-elevation1 data-[state=on]:bg-secondaryContainer hover:shadow-elevation2 active:shadow-elevation1",
},
},
}
)
interface SuggestionChipProps
extends React.ComponentPropsWithoutRef<typeof Toggle.Root>,
Required<Pick<VariantProps<typeof suggestionChipVariants>, "appearance">> {
icon?: React.ReactNode
}
const SuggestionChip = React.forwardRef<
React.ElementRef<typeof Toggle.Root>,
SuggestionChipProps
>(({ className, appearance, children, icon, ...props }, forwardedRef) => {
return (
<Toggle.Root
className={cn(suggestionChipVariants({ appearance }), className)}
{...props}
ref={forwardedRef}
>
<UIStateLayer
className={cn(
"flex items-center gap-2 px-4 rounded-lg bg-onSurfaceVariant group-focus-visible:bg-onSurfaceVariant group-data-[state=on]:bg-onSecondaryContainer group-data-[state=on]:group-focus-visible:bg-onSecondaryContainer group-focus-visible:bg-opacity-[0.12] group-data-[state=on]:bg-opacity-0 group-data-[state=on]:group-hover:bg-opacity-[0.08] group-data-[state=on]:group-focus-visible:bg-opacity-[0.12]",
icon && "pl-2"
)}
>
{icon && <span className="text-primary">{icon}</span>}
<Label
size="large"
className="text-onSurfaceVariant group-data-[state=on]:text-onSecondaryContainer"
>
{children}
</Label>
</UIStateLayer>
</Toggle.Root>
)
})
SuggestionChip.displayName = "SuggestionChip"
export default SuggestionChip

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

Обратите внимание, что по стайл гайдам размеры иконок уменьшены с 24x24 до 18x18. Вам придётся делать это вручную.

import SuggestionChip from "@/shared/ui/Chips/SuggestionChip""
...
// Без иконки | стиль elevated
<SuggestionChip appearance="elevated">Elevated</SuggestionChip>
// Без иконки | стиль outlined
<SuggestionChip appearance="outlined">Outlined</SuggestionChip>
// С иконкой | стиль elevated
<SuggestionChip
appearance="elevated"
icon={<Calendar width={18} height={18} />}
>
Elevated
</SuggestionChip>
// С иконкой | стиль outlined
<SuggestionChip
appearance="outlined"
icon={<Calendar width={18} height={18} />}
>
Outlined
</SuggestionChip>