TogglesPredefined

Предзаготовленный паттерн выбора: ToggleCard — кликабельная карточка с иконкой, заголовком и описанием, ToggleGroup — провайдер выбора и grid-раскладка карточек. Визуальный chrome (фон, state-layer выбора, outline, focus-ring) приходит из @cloud-ru/ds-card; выбор управляется контекстом @cloud-ru/ds-toggles.

Когда использовать

  • Выбор тарифа, конфигурации, плана — когда варианты крупные и им нужны иконка + заголовок + описание.
  • Single-выбор (один вариант из набора) или multiple-выбор (несколько опций-аддонов).
  • Когда нужна увеличенная hit-area: вся карточка кликабельна и операбельна с клавиатуры.

Когда не нужен TogglesPredefined:

  • Компактный список бинарных опций со Switch:
  • Один inline-чекбокс или радио без описания:

Анатомия

Size (default m)

Ось size масштабирует анатомию карточки целиком (как в продуктовом ките) — padding, gap, типографику заголовка/описания и радиус контейнера @cloud-ru/ds-card:

  • s — padding 8, gap 4, заголовок title/s, описание body/m.
  • m — padding 16, gap 8, заголовок title/m, описание body/m.
  • l — padding 24, gap 16, заголовок title/l, описание body/l.

Эмблема масштабируется вместе с карточкой автоматически: size встроенного IconPredefined выводится из size карточки (s → m, m → l, l → 5xl).

Orientation (default vertical)

Ось раскладки ToggleGroup:

  • vertical — карточки в колонку.
  • horizontal — карточки в авто-колонки repeat(auto-fit, minmax(breakpoint, 1fr)).

Gap (default s)

Расстояние между карточками — density spacing interval:

  • s — 8px.
  • m — 16px.
  • l — 24px.

SelectionMode (default single)

Режим выбора ToggleGroup (из @cloud-ru/ds-toggles):

  • single — выбран один вариант; карточки получают role='radio'.
  • multiple — выбрано несколько; карточки получают role='checkbox'.

Слоты ToggleCard

  • title — обязательный заголовок карточки.
  • description — опциональное описание под заголовком.
  • emblem — ведущая эмблема. IconPredefined встроен в компонент — передаются только его параметры (icon, appearance, decor, shape) либо картинка (src / alt).
  • promoBadge — промо-бейдж в правом верхнем углу (string или { text, appearance? } для PromoTag).
  • truncate — максимум строк title и/или description (по умолчанию title: 1, description: 2).

Установка

pnpm add @cloud-ru/ds-uikit-product-toggles-predefined
import { ToggleCard, ToggleGroup, useToggleGroup } from '@cloud-ru/ds-uikit-product-toggles-predefined'

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

Базовый single-выбор

Базовый single-выбор
tsx
import { ToggleCard, ToggleGroup } from '@cloud-ru/ds-uikit-product-toggles-predefined';

export function Basic() {
  return (
    <ToggleGroup defaultValue='pro'>
      <ToggleCard value='start' title='Тариф Start' description='10 ГБ хранилища' />
      <ToggleCard value='pro' title='Тариф Pro' description='100 ГБ хранилища, приоритетная поддержка' />
      <ToggleCard value='enterprise' title='Тариф Enterprise' description='Безлимит и выделенный менеджер' />
    </ToggleGroup>
  );
}

С иконками

С иконками
tsx
import { PlaceholderSVG } from '@cloud-ru/ds-icons/interface/system';
import { ToggleCard, ToggleGroup } from '@cloud-ru/ds-uikit-product-toggles-predefined';

export function WithIcon() {
  return (
    <ToggleGroup defaultValue='cpu'>
      <ToggleCard value='cpu' emblem={{ icon: PlaceholderSVG }} title='CPU' description='4 vCPU, 8 ГБ RAM' />
      <ToggleCard value='gpu' emblem={{ icon: PlaceholderSVG }} title='GPU' description='1× A100, 80 ГБ' />
    </ToggleGroup>
  );
}

С промо-тегами

С промо-тегамиpromoBadge — строка или объект для PromoTag в правом верхнем углу карточки.
tsx
import { PlaceholderSVG } from '@cloud-ru/ds-icons/interface/system';
import { ToggleCard, ToggleGroup } from '@cloud-ru/ds-uikit-product-toggles-predefined';

export function WithPromoBadge() {
  return (
    <ToggleGroup defaultValue='pro'>
      <ToggleCard value='basic' emblem={{ icon: PlaceholderSVG }} title='Basic' description='Для старта' />
      <ToggleCard
        value='pro'
        emblem={{ icon: PlaceholderSVG }}
        title='Pro'
        description='Популярный тариф'
        promoBadge='−20%'
      />
      <ToggleCard
        value='enterprise'
        emblem={{ icon: PlaceholderSVG }}
        title='Enterprise'
        description='Для команд'
        promoBadge={{ label: 'New', appearance: 'blue' }}
      />
    </ToggleGroup>
  );
}

Multiple (controlled)

Multiple (controlled)Несколько аддонов, состояние в useState.
tsx
import { ToggleCard, ToggleGroup } from '@cloud-ru/ds-uikit-product-toggles-predefined';
import { useState } from 'react';

export function Multiple() {
  const [value, setValue] = useState<string[]>(['backup']);

  return (
    <ToggleGroup selectionMode='multiple' value={value} onChange={next => setValue(next ?? [])} gap='m'>
      <ToggleCard value='backup' title='Резервное копирование' description='Ежедневные снапшоты' />
      <ToggleCard value='monitoring' title='Мониторинг' description='Алерты и метрики 24/7' />
      <ToggleCard value='cdn' title='CDN' description='Раздача статики по миру' />
    </ToggleGroup>
  );
}

Горизонтальная раскладка

Горизонтальная раскладкаorientation=horizontal + breakpoint.
tsx
import { ToggleCard, ToggleGroup } from '@cloud-ru/ds-uikit-product-toggles-predefined';

export function Horizontal() {
  return (
    <ToggleGroup orientation='horizontal' gap='m' breakpoint={200} defaultValue='month'>
      <ToggleCard value='month' title='Помесячно' description='Гибкая оплата' />
      <ToggleCard value='year' title='Годовая' description='Скидка 20%' />
    </ToggleGroup>
  );
}

Controlled single

Controlled singleОписание реагирует на выбранный вариант.
tsx
import { ToggleCard, ToggleGroup } from '@cloud-ru/ds-uikit-product-toggles-predefined';
import { useState } from 'react';

export function Controlled() {
  const [plan, setPlan] = useState<string | undefined>('pro');

  return (
    <ToggleGroup value={plan} onChange={(next: string | undefined) => setPlan(next)}>
      <ToggleCard value='start' title='Тариф Start' description={plan === 'start' ? 'Выбран' : '10 ГБ хранилища'} />
      <ToggleCard value='pro' title='Тариф Pro' description={plan === 'pro' ? 'Выбран' : '100 ГБ хранилища'} />
    </ToggleGroup>
  );
}

Props

ToggleCard

Types

PropsToggleCardProps
PropTypeDefaultRequiredDescription
classNamestringnoCSS-класс корневого элемента
data-test-idstringno
descriptionstringnoОсновной текст под заголовком
disabledbooleanfalsenoЗаблокированное состояние: интерактив отключён
emblemEmblemnoВедущая эмблема. Передаются только параметры — сам `IconPredefined` встроен в компонент; `size` эмблемы выводится из `size` карточки.
promoBadgestring | Pick<PromoTagProps, "label" | "appearance">noПромо-бейдж в правом верхнем углу карточки
size"l" | "m" | "s"mnoРазмер карточки — масштабирует padding, gap, типографику и `radius` контейнера `@cloud-ru/ds-card`
titlestringyesЗаголовок карточки
truncate{ title?: number; description?: number; } | undefined'{ title: 1; description: 2; }'noМаксимальное число строк до обрезки.
valuestringyesЗначение карточки в контексте `ToggleGroup`

Unions

Types

ToggleCardProps

Unions

ToggleGroup

Types

PropsToggleGroupProps
PropTypeDefaultRequiredDescription
breakpointnumbernoМинимальная ширина карточки для горизонтальной раскладки (px)
childrenReactNodenoДочерние карточки `ToggleCard`
classNamestringnoCSS-класс корневого элемента
data-test-idstringno
defaultValuestring | string[]noНачальное состояние
gap"l" | "m" | "s"noРасстояние между карточками
onChange((value: string) => void) | ((value: string[]) => void) | undefinednoControlled обработчик измения состояния
orientation"horizontal" | "vertical"noНаправление раскладки
selectionMode"multiple" | "single"noРежим выбора
valuestring | string[]noControlled состояние

Types

ToggleGroupProps

Storybook

Figma