diff --git a/packages/sdds-serv/src/components/IconButton/IconButton.config.ts b/packages/sdds-serv/src/components/IconButton/IconButton.config.ts new file mode 100644 index 0000000000..efaa4588c8 --- /dev/null +++ b/packages/sdds-serv/src/components/IconButton/IconButton.config.ts @@ -0,0 +1,217 @@ +import { css, iconButtonTokens } from '@salutejs/plasma-new-hope/styled-components'; + +export const config = { + defaults: { + view: 'default', + focused: 'true', + size: 'm', + }, + variations: { + view: { + default: css` + ${iconButtonTokens.iconButtonColor}: var(--inverse-text-primary); + ${iconButtonTokens.iconButtonBackgroundColor}: var(--surface-solid-default); + ${iconButtonTokens.iconButtonColorHover}: var(--inverse-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorHover}: var(--surface-solid-default-hover); + ${iconButtonTokens.iconButtonColorActive}: var(--inverse-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorActive}: var(--surface-solid-default-active); + `, + accent: css` + ${iconButtonTokens.iconButtonColor}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColor}: var(--surface-accent); + ${iconButtonTokens.iconButtonColorHover}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorHover}: var(--surface-accent-hover); + ${iconButtonTokens.iconButtonColorActive}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorActive}: var(--surface-accent-active); + `, + secondary: css` + ${iconButtonTokens.iconButtonColor}: var(--text-primary); + ${iconButtonTokens.iconButtonBackgroundColor}: var(--surface-transparent-secondary); + ${iconButtonTokens.iconButtonColorHover}: var(--text-primary); + ${iconButtonTokens.iconButtonBackgroundColorHover}: var(--surface-transparent-secondary-hover); + ${iconButtonTokens.iconButtonColorActive}: var(--text-primary); + ${iconButtonTokens.iconButtonBackgroundColorActive}: var(--surface-transparent-secondary-active); + `, + clear: css` + ${iconButtonTokens.iconButtonColor}: var(--text-primary); + ${iconButtonTokens.iconButtonBackgroundColor}: var(--surface-clear); + ${iconButtonTokens.iconButtonColorHover}: var(--text-primary-hover); + ${iconButtonTokens.iconButtonBackgroundColorHover}: var(--surface-clear); + ${iconButtonTokens.iconButtonColorActive}: var(--text-primary-active); + ${iconButtonTokens.iconButtonBackgroundColorActive}: var(--surface-clear); + `, + success: css` + ${iconButtonTokens.iconButtonColor}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColor}: var(--surface-positive); + ${iconButtonTokens.iconButtonColorHover}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorHover}: var(--surface-positive-hover); + ${iconButtonTokens.iconButtonColorActive}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorActive}: var(--surface-positive-active); + `, + warning: css` + ${iconButtonTokens.iconButtonColor}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColor}: var(--surface-warning); + ${iconButtonTokens.iconButtonColorHover}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorHover}: var(--surface-warning-hover); + ${iconButtonTokens.iconButtonColorActive}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorActive}: var(--surface-warning-active); + `, + critical: css` + ${iconButtonTokens.iconButtonColor}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColor}: var(--surface-negative); + ${iconButtonTokens.iconButtonColorHover}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorHover}: var(--surface-negative-hover); + ${iconButtonTokens.iconButtonColorActive}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorActive}: var(--surface-negative-active); + `, + dark: css` + ${iconButtonTokens.iconButtonColor}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColor}: var(--on-light-surface-transparent-deep); + ${iconButtonTokens.iconButtonColorHover}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorHover}: var(--on-light-surface-transparent-deep-hover); + ${iconButtonTokens.iconButtonColorActive}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorActive}: var(--on-light-surface-transparent-deep-active); + `, + black: css` + ${iconButtonTokens.iconButtonColor}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColor}: var(--on-light-surface-solid-default); + ${iconButtonTokens.iconButtonColorHover}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorHover}: var(--on-light-surface-solid-default-hover); + ${iconButtonTokens.iconButtonColorActive}: var(--on-dark-text-primary); + ${iconButtonTokens.iconButtonBackgroundColorActive}: var(--on-light-surface-solid-default-active); + `, + white: css` + ${iconButtonTokens.iconButtonColor}: var(--on-light-text-primary); + ${iconButtonTokens.iconButtonBackgroundColor}: var(--on-dark-surface-solid-default); + ${iconButtonTokens.iconButtonColorHover}: var(--on-light-text-primary-hover); + ${iconButtonTokens.iconButtonBackgroundColorHover}: var(--on-dark-surface-solid-default-hover); + ${iconButtonTokens.iconButtonColorActive}: var(--on-light-text-primary-active); + ${iconButtonTokens.iconButtonBackgroundColorActive}: var(--on-dark-surface-solid-default-active); + `, + }, + size: { + l: css` + ${iconButtonTokens.iconButtonHeight}: 3.5rem; + ${iconButtonTokens.iconButtonWidth}: 3.5rem; + ${iconButtonTokens.iconButtonPadding}: 1.5rem; + ${iconButtonTokens.iconButtonRadius}: 0.875rem; + ${iconButtonTokens.iconButtonFontFamily}: var(--plasma-typo-body-l-font-family); + ${iconButtonTokens.iconButtonFontSize}: var(--plasma-typo-body-l-font-size); + ${iconButtonTokens.iconButtonFontStyle}: var(--plasma-typo-body-l-font-style); + ${iconButtonTokens.iconButtonFontWeight}: var(--plasma-typo-body-l-bold-font-weight); + ${iconButtonTokens.iconButtonLetterSpacing}: var(--plasma-typo-body-l-letter-spacing); + ${iconButtonTokens.iconButtonLineHeight}: var(--plasma-typo-body-l-line-height); + + ${iconButtonTokens.iconButtonSpinnerSize}: 1.375rem; + ${iconButtonTokens.iconButtonSpinnerColor}: inherit; + `, + lr: css` + ${iconButtonTokens.iconButtonHeight}: 3.5rem; + ${iconButtonTokens.iconButtonWidth}: 3.5rem; + ${iconButtonTokens.iconButtonFontFamily}: var(--plasma-typo-body-l-font-family); + ${iconButtonTokens.iconButtonFontSize}: var(--plasma-typo-body-l-font-size); + ${iconButtonTokens.iconButtonFontStyle}: var(--plasma-typo-body-l-font-style); + ${iconButtonTokens.iconButtonFontWeight}: var(--plasma-typo-body-l-bold-font-weight); + ${iconButtonTokens.iconButtonLetterSpacing}: var(--plasma-typo-body-l-letter-spacing); + ${iconButtonTokens.iconButtonLineHeight}: var(--plasma-typo-body-l-line-height); + + ${iconButtonTokens.iconButtonSpinnerSize}: 1.375rem; + ${iconButtonTokens.iconButtonSpinnerColor}: inherit; + `, + m: css` + ${iconButtonTokens.iconButtonHeight}: 3rem; + ${iconButtonTokens.iconButtonWidth}: 3rem; + ${iconButtonTokens.iconButtonPadding}: 1.25rem; + ${iconButtonTokens.iconButtonRadius}: 0.75rem; + ${iconButtonTokens.iconButtonFontFamily}: var(--plasma-typo-body-m-font-family); + ${iconButtonTokens.iconButtonFontSize}: var(--plasma-typo-body-m-font-size); + ${iconButtonTokens.iconButtonFontStyle}: var(--plasma-typo-body-m-font-style); + ${iconButtonTokens.iconButtonFontWeight}: var(--plasma-typo-body-m-bold-font-weight); + ${iconButtonTokens.iconButtonLetterSpacing}: var(--plasma-typo-body-m-letter-spacing); + ${iconButtonTokens.iconButtonLineHeight}: var(--plasma-typo-body-m-line-height); + + ${iconButtonTokens.iconButtonSpinnerSize}: 1.375rem; + ${iconButtonTokens.iconButtonSpinnerColor}: inherit; + `, + mr: css` + ${iconButtonTokens.iconButtonHeight}: 3rem; + ${iconButtonTokens.iconButtonWidth}: 3rem; + ${iconButtonTokens.iconButtonFontFamily}: var(--plasma-typo-body-m-font-family); + ${iconButtonTokens.iconButtonFontSize}: var(--plasma-typo-body-m-font-size); + ${iconButtonTokens.iconButtonFontStyle}: var(--plasma-typo-body-m-font-style); + ${iconButtonTokens.iconButtonFontWeight}: var(--plasma-typo-body-m-bold-font-weight); + ${iconButtonTokens.iconButtonLetterSpacing}: var(--plasma-typo-body-m-letter-spacing); + ${iconButtonTokens.iconButtonLineHeight}: var(--plasma-typo-body-m-line-height); + + ${iconButtonTokens.iconButtonSpinnerSize}: 1.375rem; + ${iconButtonTokens.iconButtonSpinnerColor}: inherit; + `, + s: css` + ${iconButtonTokens.iconButtonHeight}: 2.5rem; + ${iconButtonTokens.iconButtonWidth}: 2.5rem; + ${iconButtonTokens.iconButtonPadding}: 1rem; + ${iconButtonTokens.iconButtonRadius}: 0.625rem; + ${iconButtonTokens.iconButtonFontFamily}: var(--plasma-typo-body-s-font-family); + ${iconButtonTokens.iconButtonFontSize}: var(--plasma-typo-body-s-font-size); + ${iconButtonTokens.iconButtonFontStyle}: var(--plasma-typo-body-s-font-style); + ${iconButtonTokens.iconButtonFontWeight}: var(--plasma-typo-body-s-bold-font-weight); + ${iconButtonTokens.iconButtonLetterSpacing}: var(--plasma-typo-body-s-letter-spacing); + ${iconButtonTokens.iconButtonLineHeight}: var(--plasma-typo-body-s-line-height); + + ${iconButtonTokens.iconButtonSpinnerSize}: 1.375rem; + ${iconButtonTokens.iconButtonSpinnerColor}: inherit; + `, + sr: css` + ${iconButtonTokens.iconButtonHeight}: 2.5rem; + ${iconButtonTokens.iconButtonWidth}: 2.5rem; + ${iconButtonTokens.iconButtonFontFamily}: var(--plasma-typo-body-s-font-family); + ${iconButtonTokens.iconButtonFontSize}: var(--plasma-typo-body-s-font-size); + ${iconButtonTokens.iconButtonFontStyle}: var(--plasma-typo-body-s-font-style); + ${iconButtonTokens.iconButtonFontWeight}: var(--plasma-typo-body-s-bold-font-weight); + ${iconButtonTokens.iconButtonLetterSpacing}: var(--plasma-typo-body-s-letter-spacing); + ${iconButtonTokens.iconButtonLineHeight}: var(--plasma-typo-body-s-line-height); + + ${iconButtonTokens.iconButtonSpinnerSize}: 1.375rem; + ${iconButtonTokens.iconButtonSpinnerColor}: inherit; + `, + xs: css` + ${iconButtonTokens.iconButtonHeight}: 2rem; + ${iconButtonTokens.iconButtonWidth}: 2rem; + ${iconButtonTokens.iconButtonPadding}: 0.75rem; + ${iconButtonTokens.iconButtonRadius}: 0.5rem; + ${iconButtonTokens.iconButtonFontFamily}: var(--plasma-typo-body-xs-font-family); + ${iconButtonTokens.iconButtonFontSize}: var(--plasma-typo-body-xs-font-size); + ${iconButtonTokens.iconButtonFontStyle}: var(--plasma-typo-body-xs-font-style); + ${iconButtonTokens.iconButtonFontWeight}: var(--plasma-typo-body-xs-bold-font-weight); + ${iconButtonTokens.iconButtonLetterSpacing}: var(--plasma-typo-body-xs-letter-spacing); + ${iconButtonTokens.iconButtonLineHeight}: var(--plasma-typo-body-xs-line-height); + + ${iconButtonTokens.iconButtonSpinnerSize}: 1rem; + ${iconButtonTokens.iconButtonSpinnerColor}: inherit; + `, + xsr: css` + ${iconButtonTokens.iconButtonHeight}: 2rem; + ${iconButtonTokens.iconButtonWidth}: 2rem; + ${iconButtonTokens.iconButtonFontFamily}: var(--plasma-typo-body-xs-font-family); + ${iconButtonTokens.iconButtonFontSize}: var(--plasma-typo-body-xs-font-size); + ${iconButtonTokens.iconButtonFontStyle}: var(--plasma-typo-body-xs-font-style); + ${iconButtonTokens.iconButtonFontWeight}: var(--plasma-typo-body-xs-bold-font-weight); + ${iconButtonTokens.iconButtonLetterSpacing}: var(--plasma-typo-body-xs-letter-spacing); + ${iconButtonTokens.iconButtonLineHeight}: var(--plasma-typo-body-xs-line-height); + + ${iconButtonTokens.iconButtonSpinnerSize}: 1rem; + ${iconButtonTokens.iconButtonSpinnerColor}: inherit; + `, + }, + disabled: { + true: css` + ${iconButtonTokens.iconButtonDisabledOpacity}: 0.4; + `, + }, + focused: { + true: css` + ${iconButtonTokens.iconButtonFocusColor}: var(--surface-accent); + `, + }, + }, +}; diff --git a/packages/sdds-serv/src/components/IconButton/IconButton.stories.tsx b/packages/sdds-serv/src/components/IconButton/IconButton.stories.tsx new file mode 100644 index 0000000000..dfb92906be --- /dev/null +++ b/packages/sdds-serv/src/components/IconButton/IconButton.stories.tsx @@ -0,0 +1,83 @@ +import React, { ComponentProps } from 'react'; +import type { StoryObj, Meta } from '@storybook/react'; +import { IconClose } from '@salutejs/plasma-icons'; +import { disableProps, InSpacingDecorator } from '@salutejs/plasma-sb-utils'; + +import { IconButton } from './IconButton'; + +type StoryButtonProps = ComponentProps & { contentType: string; isLoading: boolean }; + +const views = ['default', 'accent', 'secondary', 'success', 'warning', 'critical', 'clear', 'dark', 'black', 'white']; +const sizes = ['l', 'm', 's', 'xs']; +const pins = [ + 'square-square', + 'square-clear', + 'clear-square', + 'clear-clear', + 'clear-circle', + 'circle-clear', + 'circle-circle', + '', +]; + +const meta: Meta = { + title: 'Controls/IconButton', + decorators: [InSpacingDecorator], + argTypes: { + size: { + options: sizes, + control: { + type: 'inline-radio', + }, + }, + view: { + options: views, + control: { + type: 'select', + }, + }, + pin: { + options: pins, + control: { + type: 'select', + }, + table: { defaultValue: { summary: 'bottom' } }, + }, + ...disableProps(['children', 'theme', 'loader', 'onClick', 'onFocus', 'onBlur', 'contentLeft', 'contentRight']), + }, +}; + +export default meta; + +const getSizeForIcon = (size) => { + const map = { + mr: 's', + lr: 's', + m: 's', + l: 's', + sr: 's', + xsr: 'xs', + }; + if (map[size]) { + return map[size]; + } + + return size; +}; + +export const Default: StoryObj> = { + args: { + children: , + view: 'default', + size: 'm', + disabled: false, + focused: true, + isLoading: false, + }, + argTypes: { ...disableProps(['children']) }, + render: (args) => ( + + + + ), +}; diff --git a/packages/sdds-serv/src/components/IconButton/IconButton.ts b/packages/sdds-serv/src/components/IconButton/IconButton.ts new file mode 100644 index 0000000000..6faeac7efe --- /dev/null +++ b/packages/sdds-serv/src/components/IconButton/IconButton.ts @@ -0,0 +1,11 @@ +import { iconButtonConfig, component, mergeConfig } from '@salutejs/plasma-new-hope/styled-components'; + +import { config } from './IconButton.config'; + +const mergedConfig = mergeConfig(iconButtonConfig, config); +const IconButtonComponent = component(mergedConfig); + +/** + * Кнопка с иконкой. + */ +export const IconButton = IconButtonComponent; diff --git a/packages/sdds-serv/src/components/IconButton/index.ts b/packages/sdds-serv/src/components/IconButton/index.ts new file mode 100644 index 0000000000..bd4d78d297 --- /dev/null +++ b/packages/sdds-serv/src/components/IconButton/index.ts @@ -0,0 +1 @@ +export { IconButton } from './IconButton'; diff --git a/packages/sdds-serv/src/index.ts b/packages/sdds-serv/src/index.ts index c4ec934223..6336664d4e 100644 --- a/packages/sdds-serv/src/index.ts +++ b/packages/sdds-serv/src/index.ts @@ -12,6 +12,7 @@ export * from './components/Cell'; export * from './components/Combobox'; export * from './components/Counter'; export * from './components/Dropdown'; +export * from './components/IconButton'; export * from './components/Image'; export * from './components/Indicator'; export * from './components/Link';