npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cloud-ru/ds-button

v1.0.5

Published

Пакет кнопок дизайн-системы — компоненты Button и ButtonGroup с едиными токенами размеров, appearance и view.

Readme

Button

@cloud-ru/ds-button — Пакет кнопок дизайн-системы — компоненты Button и ButtonGroup с едиными токенами размеров, appearance и view.

Пакет @cloud-ru/ds-button предоставляет два компонента для действий и навигации: одиночную кнопку Button и контейнер связанных действий ButtonGroup. Оба компонента используют общие токены — размеры s/m/l, appearance primary/neutral/critical и view filled/outline/tonal/simple/elevated/function — и пересекаются по типам пропсов.

  • Button — одиночная кнопка для действий и навигации с полным набором view/appearance/size и полиморфизмом через as.
  • ButtonGroup — контейнер связанных действий с едиными токенами и согласованным layout'ом по горизонтали и вертикали.

Установка

pnpm add @cloud-ru/ds-button
import { Button, ButtonGroup } from '@cloud-ru/ds-button'

Figma

Оба компонента следуют одному мастер-файлу Figma. Cсылки на конкретные узлы — на страницах компонентов.

Смотри также

Button

Полиморфная кнопка дизайн-системы — шесть видов оформления, три семантических appearance, три размера, icon/counter/loading/disabled и рендер как button / a / произвольный компонент.

Основной инструмент для действий и навигации. Рендерится как <button> (по умолчанию), <a> или произвольный компонент через проп as — без потери типизации пропсов целевого элемента.

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

  • Для инициации действий (сохранить, удалить, применить).
  • Для навигации, оформленной как кнопка — через as="a".
  • Для toolbar-иконок без текста — icon без label + обязательный aria-label.

Когда не нужен Button: для обычных inline-ссылок используйте <a> или навигационный компонент, а не as="a" с view="function".

Анатомия

Appearance

Семантическая роль действия: primary — основное действие на экране (максимум одно), neutral — вторичные действия, critical — деструктивные (удаление, отмена подписки).

View

Визуальная подача: filled — сплошная заливка (ключевое CTA), tonal — мягкая заливка токеном appearance, outline — с границей, simple — плоский фон, elevated — с тенью, function — максимально ненавязчивая подача (тулбары, инлайны).

Size

Размерный ряд: s — для плотных поверхностей (тулбары, таблицы), m — дефолт, l — для крупных форм и CTA.

Icon position

Положение иконки относительно лейбла: before — слева, after — справа. Для icon-only варианта label не задаётся.

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

Минимум, который покрывает 80% реальных случаев. Каждый пример — отдельный файл в packages/button/demos/examples/, который можно скопировать целиком.

Три appearance в ряд

Сравнение семантических ролей на одном размере и view

import { Button } from '@cloud-ru/ds-button';

export function Appearances() {
  return (
    <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center' }}>
      <Button appearance='primary' label='Primary' />
      <Button appearance='neutral' label='Neutral' />
      <Button appearance='critical' label='Critical' />
    </div>
  );
}

Все шесть view

appearance=primary, size=m

import { Button } from '@cloud-ru/ds-button';

export function Views() {
  return (
    <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center' }}>
      <Button view='filled' label='Filled' />
      <Button view='outline' label='Outline' />
      <Button view='tonal' label='Tonal' />
      <Button view='simple' label='Simple' />
      <Button view='elevated' label='Elevated' />
      <Button view='function' label='Function' />
    </div>
  );
}

Три размера в ряд

import { Button } from '@cloud-ru/ds-button';

export function Sizes() {
  return (
    <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center' }}>
      <Button size='s' label='Small' />
      <Button size='m' label='Medium' />
      <Button size='l' label='Large' />
    </div>
  );
}

1. Пара главное + вторичное

Типичный футер формы: filled primary + simple neutral

import { Button } from '@cloud-ru/ds-button';

export function Actions() {
  return (
    <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center' }}>
      <Button appearance='primary' view='filled' label='Сохранить' />
      <Button appearance='neutral' view='simple' label='Отмена' />
    </div>
  );
}

2. Деструктивное действие

Critical + иконка — визуально подкрепляет риск

import { Button } from '@cloud-ru/ds-button';
import { TrashSVG } from '@cloud-ru/ds-icons/interface/system';

export function Destructive() {
  return <Button appearance='critical' view='filled' icon={<TrashSVG />} label='Удалить' />;
}

3. Icon-only в toolbar

Без label, но с aria-label для скринридеров

import { Button } from '@cloud-ru/ds-button';
import { SettingsSVG } from '@cloud-ru/ds-icons/interface/system';

export function IconOnly() {
  return <Button view='function' icon={<SettingsSVG />} aria-label='Настройки' />;
}

4. Кнопка-ссылка

as='a' + target='_blank' → rel='noopener noreferrer' добавляется автоматически

import { Button } from '@cloud-ru/ds-button'

export function LinkButton() {
  return <Button as='a' href='https://example.com' target='_blank' label='Документация' />
}

5. Кнопка с бейджем-счётчиком

iconPosition='after' + counter → счётчик превращается в badge над иконкой

import { Button } from '@cloud-ru/ds-button';
import { EmailSVG } from '@cloud-ru/ds-icons/interface/system';

export function CounterBadge() {
  return <Button icon={<EmailSVG />} iconPosition='after' label='Сообщения' counter={{ value: 12 }} />;
}

6. Загрузка

loading заменяет лейбл спиннером и проставляет aria-busy='true'

import { Button } from '@cloud-ru/ds-button';
import { DownloadSVG } from '@cloud-ru/ds-icons/interface/system';

export function Loading() {
  return <Button appearance='primary' view='filled' icon={<DownloadSVG />} label='Скачать отчёт' loading />;
}

Props

ButtonProps

| Prop | Type | Default | Description | |------|------|---------|-------------| | appearance | "critical" | "neutral" | "primary" | primary | Вариант оформления | | as | ElementType | — | Элемент или компонент для рендера: 'button' | 'a' | ComponentType (например Link из react-router-dom) | | className | string | — | Дополнительный класс | | counter | CounterProps | — | Пропсы для counter. appearance можно задать явно (по умолчанию наследуется от appearance кнопки). | | data-test-id | string | — | | | disabled | boolean | false | Отключена | | fullWidth | boolean | false | На всю ширину | | icon | ReactNode | — | Иконка | | iconPosition | "after" | "before" | before | Позиция иконки относительно текста | | innerRef | PolymorphicRef | — | Ref на реальный DOM-элемент/инстанс, который рендерится через as. Используем явный проп, чтобы не зависеть от forwardRef и не тащить type-assertions на экспорт. | | label | string | — | Текст кнопки | | loading | boolean | false | Состояние загрузки | | minWidth | boolean | true | Минимальная ширина контейнера (min-width из токена размера). По умолчанию true. false — кнопка сжимается по контенту вместо фиксированного минимума. | | size | "l" | "m" | "s" | m | Размер | | view | "elevated" | "filled" | "function" | "outline" | "simple" | "tonal" | filled | Вариант кнопки (Figma: filled, outline, function, simple, elevated) |

Related types
  • Appearance = "critical" | "neutral" | "primary"

  • IconPosition = "after" | "before"

  • PolymorphicRef = ComponentPropsWithRef<T>["ref"]

  • Size = "l" | "m" | "s"

  • View = "elevated" | "filled" | "function" | "outline" | "simple" | "tonal"

Смотри также

Здесь — что импортировать, как собрать типовые сценарии и какие пропсы доступны.

ButtonGroup

Контейнер для связанных действий формы — primary / secondary / tertiary, с модификаторами vertical, centered, break и filled.

Группирует связанные действия формы или диалога: основное (primary), вторичное (secondary) и третичное (tertiary). Задаёт единый размер, расстояние между кнопками и отвечает за порядок, выравнивание и перенос при нехватке места.

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

  • В футере формы или диалога: «Сохранить / Отмена», «Продолжить / Назад».
  • Для toolbar-действий одного уровня, которые нужно визуально связать.
  • Когда нужно одинаково растянуть все кнопки на ширину контейнера (filled).

Когда не подходит: если действий больше трёх — используйте меню или split-button. Если действия разного приоритета и логики (напр. «Удалить» + «Настройки») — оставляйте их как независимые Button.

Анатомия

Size

Единый размер всех кнопок в группе — задаётся на корне: s — для плотных поверхностей, m — дефолт, l — для крупных форм. Отдельные кнопки не могут переопределить размер.

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

1. Пара главное + вторичное

Типичный футер формы

import { ButtonGroup } from '@cloud-ru/ds-button';

export function ButtonGroupPrimarySecondary() {
  return (
    <ButtonGroup
      primaryAction={{ label: 'Сохранить', appearance: 'primary', view: 'filled' }}
      secondaryAction={{ label: 'Отмена', appearance: 'neutral', view: 'outline' }}
    />
  );
}

2. Три действия

tertiary / secondary / primary — порядок слева направо зафиксирован

import { ButtonGroup } from '@cloud-ru/ds-button';

export function ButtonGroupThreeActions() {
  return (
    <ButtonGroup
      primaryAction={{ label: 'Сохранить', appearance: 'primary', view: 'filled' }}
      secondaryAction={{ label: 'Отмена', appearance: 'neutral', view: 'outline' }}
      tertiaryAction={{ label: 'Помощь', appearance: 'neutral', view: 'simple' }}
    />
  );
}

3. Вертикальная группа

primary снизу — ближе к большому пальцу на мобильных

import { ButtonGroup } from '@cloud-ru/ds-button';

export function ButtonGroupVertical() {
  return (
    <ButtonGroup
      vertical
      primaryAction={{ label: 'Сохранить', appearance: 'primary', view: 'filled' }}
      secondaryAction={{ label: 'Отмена', appearance: 'neutral', view: 'outline' }}
      tertiaryAction={{ label: 'Помощь', appearance: 'neutral', view: 'simple' }}
    />
  );
}

4. Заливка (filled)

Кнопки растягиваются на всю ширину контейнера

import { ButtonGroup } from '@cloud-ru/ds-button';

export function ButtonGroupFilled() {
  return (
    <div style={{ width: 320 }}>
      <ButtonGroup
        filled
        primaryAction={{ label: 'Применить', appearance: 'primary', view: 'filled' }}
        secondaryAction={{ label: 'Сбросить', appearance: 'neutral', view: 'outline' }}
      />
    </div>
  );
}

5. Распорка через break

tertiary слева, primary справа — wizard-футер

import { ButtonGroup } from '@cloud-ru/ds-button';

export function ButtonGroupBreak() {
  return (
    <div style={{ width: 480 }}>
      <ButtonGroup
        break
        tertiaryAction={{ label: 'Назад', appearance: 'neutral', view: 'simple' }}
        primaryAction={{ label: 'Продолжить', appearance: 'primary', view: 'filled' }}
      />
    </div>
  );
}

Props

ButtonGroupProps

| Prop | Type | Default | Description | |------|------|---------|-------------| | break | boolean | false | Перенос на новую строку при нехватке места | | centered | boolean | false | Центрирование по горизонтали | | className | string | — | Дополнительный класс | | data-test-id | string | — | | | filled | boolean | false | Заливка контейнера | | primaryAction | ActionProps | — | Основное действие (filled) | | renderAction | ((button: ReactNode, slot: ButtonGroupActionSlot) => ReactNode) | — | Обёртка каждой кнопки. Получает готовый <Button> и слот действия (primary/secondary/tertiary) и возвращает узел, который встанет на место кнопки. Позволяет обернуть кнопку в Tooltip на стороне потребителя (сам @cloud-ru/ds-button не зависит от @cloud-ru/ds-tooltip). Чтобы не ломать раскладку filled, обёртка не должна добавлять лишний DOM-узел между группой и кнопкой (Tooltip — с disableSpanWrapper). | | secondaryAction | ActionProps | — | Вторичное действие (outline), опционально | | size | "l" | "m" | "s" | m | Размер кнопок | | tertiaryAction | ActionProps | — | Третичное действие (simple/text-only), опционально | | vertical | boolean | false | Вертикальное расположение |

Related types
  • ActionProps = ButtonActionProps | AnchorActionProps

  • Size = "l" | "m" | "s"

Смотри также