diff --git a/packages/plasma-new-hope/src/components/Segment/index.ts b/packages/plasma-new-hope/src/components/Segment/index.ts index d059c37b5af..3ba082385ca 100644 --- a/packages/plasma-new-hope/src/components/Segment/index.ts +++ b/packages/plasma-new-hope/src/components/Segment/index.ts @@ -1,5 +1,12 @@ -export { segmentItemConfig, segmentItemRoot, segmentGroupConfig, segmentGroupRoot } from './ui'; -export type { SegmentItemProps, SegmentGroupProps } from './ui'; +export { + segmentItemConfig, + segmentItemRoot, + segmentGroupConfig, + segmentGroupRoot, + segmentIconItemConfig, + segmentIconItemRoot, +} from './ui'; +export type { SegmentItemProps, SegmentGroupProps, SegmentIconItemProps } from './ui'; export { SegmentProvider, useSegment } from './SegmentProvider'; export type { SegmentProviderProps } from './SegmentProvider'; diff --git a/packages/plasma-new-hope/src/components/Segment/tokens.ts b/packages/plasma-new-hope/src/components/Segment/tokens.ts index b192b422f0b..8aa9b044acf 100644 --- a/packages/plasma-new-hope/src/components/Segment/tokens.ts +++ b/packages/plasma-new-hope/src/components/Segment/tokens.ts @@ -42,6 +42,7 @@ export const tokens = { itemPilledPadding: '--plasma-segment-item-pilled-padding', itemMarginLeft: '--plasma-segment-item-margin-left', itemContentPadding: '--plasma-segment-item-content-padding', + iconItemContentPadding: '--plasma-segment-icon-item-content-padding', itemIconMargin: '--plasma-segment-item-content-icon-margin', itemColor: '--plasma-segment-item-color', diff --git a/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/SegmentIconItem.styles.ts b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/SegmentIconItem.styles.ts new file mode 100644 index 00000000000..c58ff7096e2 --- /dev/null +++ b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/SegmentIconItem.styles.ts @@ -0,0 +1,51 @@ +import { styled } from '@linaria/react'; +import { css } from '@linaria/core'; + +import { addFocus } from '../../../../mixins'; +import { tokens } from '../../tokens'; + +export const StyledIcon = styled.div` + display: inline-flex; + align-items: center; + justify-content: center; + width: fit-content; + padding: var(${tokens.iconItemContentPadding}); +`; + +export const base = css` + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + box-sizing: border-box; + min-width: 0; + white-space: nowrap; + + appearance: none; + border: none; + outline: none; + cursor: pointer; + margin-left: var(${tokens.itemMarginLeft}); + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + + &:first-child { + margin-left: 0; + } + + ${addFocus({ + outlineSize: '0.063rem', + outlineOffset: 'var(--plasma_private-clip-outline-offset)', + outlineColor: `var(${tokens.outlineFocusColor})`, + outlineRadius: 'calc(var(--plasma_private-outline-radius) + var(--plasma_private-clip-outline-radius))', + customFocusRules: ` + &.focus-visible:focus, + &[data-focus-visible-added] { + &::before { + z-index: 1; + outline: none; + box-shadow: 0 0 0 0.063rem var(${tokens.outlineFocusColor}); + } + } + `, + })}; +`; diff --git a/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/SegmentIconItem.tsx b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/SegmentIconItem.tsx new file mode 100644 index 00000000000..fd1405be3a0 --- /dev/null +++ b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/SegmentIconItem.tsx @@ -0,0 +1,96 @@ +import React, { forwardRef } from 'react'; +import type { MouseEvent } from 'react'; +import type { RootProps } from 'src/engines/types'; +import { cx, safeUseId } from 'src/utils'; + +import { classes } from '../../tokens'; +import { useSegmentInner } from '../../SegmentProvider/SegmentProvider'; + +import { base as sizeCSS } from './variations/_size/base'; +import { base as viewCSS } from './variations/_view/base'; +import { base as disabledCSS } from './variations/_disabled/base'; +import { base as pilledCSS } from './variations/_pilled/base'; +import type { SegmentIconItemProps } from './SegmentIconItem.types'; +import { StyledIcon, base } from './SegmentIconItem.styles'; + +export const segmentIconItemRoot = (Root: RootProps) => + forwardRef((props, outerRef) => { + const { + style, + size, + view = 'default', + className, + id, + icon, + value, + pilled, + customHandleSelect, + 'aria-label': ariaLabelExternal, + ...rest + } = props; + const { disabledGroup, handleSelect, selectedSegmentItems } = useSegmentInner(); + + const uniqId = safeUseId(); + const segmentId = id || `label-${uniqId}`; + + const pilledClass = pilled ? classes.segmentPilled : undefined; + + const isSelected = selectedSegmentItems?.includes(value); + const selectedClass = isSelected ? classes.selectedSegmentItem : undefined; + + const handleSelectSegment = (event: MouseEvent) => { + if (disabledGroup) { + return; + } + + customHandleSelect?.(event); + handleSelect?.(value); + }; + + return ( + + {icon} + + ); + }); + +export const segmentIconItemConfig = { + name: 'SegmentIconItem', + tag: 'button', + layout: segmentIconItemRoot, + base, + variations: { + size: { + css: sizeCSS, + }, + view: { + css: viewCSS, + }, + disabled: { + css: disabledCSS, + attrs: true, + }, + pilled: { + css: pilledCSS, + attrs: true, + }, + }, + defaults: { + view: 'default', + size: 'xs', + }, +}; diff --git a/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/SegmentIconItem.types.ts b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/SegmentIconItem.types.ts new file mode 100644 index 00000000000..643f5d6d298 --- /dev/null +++ b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/SegmentIconItem.types.ts @@ -0,0 +1,35 @@ +import type { MouseEvent, ButtonHTMLAttributes } from 'react'; + +type CustomSegmentIconItemProps = { + /** + * Значение сегмента + */ + value: string; + /** + * Уникальный идентификатор контрола + */ + id?: string; + /** + * Иконка + */ + icon?: React.ReactNode; + /** + * Сегмент c округлым border-radius + */ + pilled?: boolean; + /** + * Коллбек для обработки выбора сегмента + */ + customHandleSelect?: (e: MouseEvent) => void; + /** + * Размер сегмента + */ + size?: string; + /** + * Вид сегмента + * @default 'default' + */ + view?: string; +}; + +export type SegmentIconItemProps = ButtonHTMLAttributes & CustomSegmentIconItemProps; diff --git a/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/index.ts b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/index.ts new file mode 100644 index 00000000000..24bd12bcd54 --- /dev/null +++ b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/index.ts @@ -0,0 +1,2 @@ +export { segmentIconItemConfig, segmentIconItemRoot } from './SegmentIconItem'; +export type { SegmentIconItemProps } from './SegmentIconItem.types'; diff --git a/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_disabled/base.ts b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_disabled/base.ts new file mode 100644 index 00000000000..b53063fa2d7 --- /dev/null +++ b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_disabled/base.ts @@ -0,0 +1,19 @@ +import { css } from '@linaria/core'; + +import { classes, tokens } from '../../../../tokens'; + +export const base = css` + &[disabled] { + cursor: not-allowed; + + &:hover { + color: var(${tokens.itemColor}); + background-color: var(${tokens.itemBackgroundColor}); + } + + &.${String(classes.selectedSegmentItem)}:hover { + color: var(${tokens.itemSelectedColor}); + background-color: var(${tokens.itemSelectedBackgroundColor}); + } + } +`; diff --git a/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_disabled/tokens.json b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_disabled/tokens.json new file mode 100644 index 00000000000..aa806dc7cf3 --- /dev/null +++ b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_disabled/tokens.json @@ -0,0 +1,4 @@ +{ + "type": "boolean", + "tokens": ["--plasma-segment-disabled-opacity"] +} diff --git a/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_pilled/base.ts b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_pilled/base.ts new file mode 100644 index 00000000000..4cec279b010 --- /dev/null +++ b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_pilled/base.ts @@ -0,0 +1,12 @@ +import { css } from '@linaria/core'; + +import { classes, tokens } from '../../../../tokens'; + +export const base = css` + &.${String(classes.segmentPilled)} { + --plasma_private-outline-radius: var(${tokens.itemPilledBorderRadius}); + border-radius: var(${tokens.itemPilledBorderRadius}); + + padding: var(${tokens.itemPilledPadding}); + } +`; diff --git a/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_pilled/tokens.json b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_pilled/tokens.json new file mode 100644 index 00000000000..ae63509bc33 --- /dev/null +++ b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_pilled/tokens.json @@ -0,0 +1,4 @@ +{ + "type": "boolean", + "tokens": ["--plasma-segment-item-pilled-border-radius"] +} diff --git a/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_size/base.ts b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_size/base.ts new file mode 100644 index 00000000000..350e860b981 --- /dev/null +++ b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_size/base.ts @@ -0,0 +1,17 @@ +import { css } from '@linaria/core'; + +import { classes, tokens } from '../../../../tokens'; + +export const base = css` + --plasma_private-outline-radius: var(${tokens.itemBorderRadius}); + border-radius: var(${tokens.itemBorderRadius}); + + width: var(${tokens.itemWidth}); + height: var(${tokens.itemHeight}); + + padding: var(${tokens.itemPadding}); + + &.${classes.selectedSegmentItem} { + font-weight: var(${tokens.fontWeightSelectedItem}, var(${tokens.fontWeight})); + } +`; diff --git a/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_size/tokens.json b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_size/tokens.json new file mode 100644 index 00000000000..3e058c33716 --- /dev/null +++ b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_size/tokens.json @@ -0,0 +1,6 @@ +[ + "--plasma-segment-item-border-radius", + "--plasma-segment-item-width", + "--plasma-segment-item-height", + "--plasma-segment-item-padding" +] diff --git a/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_view/base.ts b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_view/base.ts new file mode 100644 index 00000000000..daa51c97353 --- /dev/null +++ b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_view/base.ts @@ -0,0 +1,23 @@ +import { css } from '@linaria/core'; + +import { classes, tokens } from '../../../../tokens'; + +export const base = css` + color: var(${tokens.itemColor}); + background-color: var(${tokens.itemBackgroundColor}); + + &:hover { + color: var(${tokens.itemColorHover}); + background-color: var(${tokens.itemBackgroundColorHover}); + } + + &.${classes.selectedSegmentItem} { + color: var(${tokens.itemSelectedColor}); + background-color: var(${tokens.itemSelectedBackgroundColor}); + + &:hover { + color: var(${tokens.itemSelectedColorHover}); + background-color: var(${tokens.itemSelectedBackgroundColorHover}); + } + } +`; diff --git a/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_view/tokens.json b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_view/tokens.json new file mode 100644 index 00000000000..7742d8186d9 --- /dev/null +++ b/packages/plasma-new-hope/src/components/Segment/ui/SegmentIconItem/variations/_view/tokens.json @@ -0,0 +1,10 @@ +[ + "--plasma-segment-item-color", + "--plasma-segment-item-background-color", + "--plasma-segment-item-color-hover", + "--plasma-segment-item-background-color-hover", + "--plasma-segment-item-selected-color", + "--plasma-segment-item-selected-background-color", + "--plasma-segment-item-selected-color-hover", + "--plasma-segment-item-selected-background-color-hover" +] diff --git a/packages/plasma-new-hope/src/components/Segment/ui/index.ts b/packages/plasma-new-hope/src/components/Segment/ui/index.ts index ee29c903d96..6c236b7580f 100644 --- a/packages/plasma-new-hope/src/components/Segment/ui/index.ts +++ b/packages/plasma-new-hope/src/components/Segment/ui/index.ts @@ -2,3 +2,5 @@ export { segmentGroupConfig, segmentGroupRoot } from './SegmentGroup'; export type { SegmentGroupProps } from './SegmentGroup'; export { segmentItemConfig, segmentItemRoot } from './SegmentItem'; export type { SegmentItemProps } from './SegmentItem'; +export { segmentIconItemConfig, segmentIconItemRoot } from './SegmentIconItem'; +export type { SegmentIconItemProps } from './SegmentIconItem'; diff --git a/packages/plasma-new-hope/src/examples/components/Segment/Segment.stories.tsx b/packages/plasma-new-hope/src/examples/components/Segment/Segment.stories.tsx index e52552c742f..67fccccfe96 100644 --- a/packages/plasma-new-hope/src/examples/components/Segment/Segment.stories.tsx +++ b/packages/plasma-new-hope/src/examples/components/Segment/Segment.stories.tsx @@ -7,13 +7,14 @@ import { Counter } from '../Counter/Counter'; import { WithTheme } from '../../_helpers'; import { config } from './SegmentGroup.config'; -import { SegmentItem, SegmentGroup } from './Segment'; +import { SegmentItem, SegmentGroup, SegmentIconItem } from './Segment'; type SegmentGroupProps = ComponentProps; -const { meta: META, Default } = getSegmentStories({ +const { meta: META, Default, IconItem } = getSegmentStories({ SegmentGroup, SegmentItem, + SegmentIconItem, SegmentProvider, componentConfig: config, CounterComponent: Counter, @@ -28,4 +29,4 @@ const meta: Meta = { export default meta; -export { Default }; +export { Default, IconItem }; diff --git a/packages/plasma-new-hope/src/examples/components/Segment/Segment.ts b/packages/plasma-new-hope/src/examples/components/Segment/Segment.ts index ff673ea5275..3ea2dca0280 100644 --- a/packages/plasma-new-hope/src/examples/components/Segment/Segment.ts +++ b/packages/plasma-new-hope/src/examples/components/Segment/Segment.ts @@ -1,11 +1,14 @@ -import { segmentItemConfig, segmentGroupConfig } from '../../../components/Segment'; +import { segmentItemConfig, segmentGroupConfig, segmentIconItemConfig } from '../../../components/Segment'; import { component, mergeConfig } from '../../../engines'; import { config as groupConfig } from './SegmentGroup.config'; import { config as itemConfig } from './SegmentItem.config'; +import { config as iconItemConfig } from './SegmentIconItem.config'; const mergedSegmentGroupConfig = mergeConfig(segmentGroupConfig, groupConfig); const mergedSegmentItemConfig = mergeConfig(segmentItemConfig, itemConfig); +const mergedSegmentIconItemConfig = mergeConfig(segmentIconItemConfig, iconItemConfig); export const SegmentGroup = component(mergedSegmentGroupConfig); export const SegmentItem = component(mergedSegmentItemConfig); +export const SegmentIconItem = component(mergedSegmentIconItemConfig); diff --git a/packages/plasma-new-hope/src/examples/components/Segment/SegmentIconItem.config.ts b/packages/plasma-new-hope/src/examples/components/Segment/SegmentIconItem.config.ts new file mode 100644 index 00000000000..ad6b4dbbf4b --- /dev/null +++ b/packages/plasma-new-hope/src/examples/components/Segment/SegmentIconItem.config.ts @@ -0,0 +1,120 @@ +import { css } from '@linaria/core'; + +import { segmentTokens } from '../../../components/Segment'; + +export const config = { + defaults: { + view: 'clear', + size: 'xs', + }, + variations: { + view: { + clear: css` + ${segmentTokens.itemColor}: var(--text-secondary); + ${segmentTokens.itemBackgroundColor}: transparent; + ${segmentTokens.itemColorHover}: var(--text-primary-hover); + ${segmentTokens.itemBackgroundColorHover}: transparent; + ${segmentTokens.itemSelectedColor}: var(--text-primary-hover); + ${segmentTokens.itemSelectedBackgroundColor}: transparent; + ${segmentTokens.itemSelectedColorHover}: var(--text-primary); + ${segmentTokens.itemSelectedBackgroundColorHover}: transparent; + + ${segmentTokens.outlineFocusColor}: var(--text-accent); + `, + secondary: css` + ${segmentTokens.itemColor}: var(--text-primary); + ${segmentTokens.itemBackgroundColor}: transparent; + ${segmentTokens.itemColorHover}: var(--text-primary-hover); + ${segmentTokens.itemBackgroundColorHover}: transparent; + ${segmentTokens.itemSelectedColor}: var(--text-primary); + ${segmentTokens.itemSelectedBackgroundColor}: var(--surface-transparent-card); + ${segmentTokens.itemSelectedColorHover}: var(--text-primary-hover); + ${segmentTokens.itemSelectedBackgroundColorHover}: var(--surface-transparent-card); + + ${segmentTokens.outlineFocusColor}: var(--text-accent); + `, + default: css` + ${segmentTokens.itemColor}: var(--text-primary); + ${segmentTokens.itemBackgroundColor}: transparent; + ${segmentTokens.itemColorHover}: var(--text-primary-hover); + ${segmentTokens.itemBackgroundColorHover}: transparent; + ${segmentTokens.itemSelectedColor}: var(--inverse-text-primary); + ${segmentTokens.itemSelectedBackgroundColor}: var(--surface-solid-default); + ${segmentTokens.itemSelectedColorHover}: var(--inverse-text-primary-hover); + ${segmentTokens.itemSelectedBackgroundColorHover}: var(--surface-solid-default); + + ${segmentTokens.outlineFocusColor}: var(--text-accent); + `, + accent: css` + ${segmentTokens.itemColor}: var(--text-primary); + ${segmentTokens.itemBackgroundColor}: transparent; + ${segmentTokens.itemColorHover}: var(--text-primary-hover); + ${segmentTokens.itemBackgroundColorHover}: transparent; + ${segmentTokens.itemSelectedColor}: var(--on-dark-text-primary); + ${segmentTokens.itemSelectedBackgroundColor}: var(--surface-accent); + ${segmentTokens.itemSelectedColorHover}: var(--on-dark-text-primary-hover); + ${segmentTokens.itemSelectedBackgroundColorHover}: var(--surface-accent); + + ${segmentTokens.groupFilledBackgroundColor}: var(--text-accent); + `, + }, + size: { + xs: css` + ${segmentTokens.itemBorderRadius}: 0.5rem; + ${segmentTokens.itemWidth}: auto; + ${segmentTokens.itemHeight}: 2rem; + ${segmentTokens.itemPadding}: 0.5rem; + ${segmentTokens.itemPilledPadding}: 0.5rem; + ${segmentTokens.iconItemContentPadding}: 0.0625rem 0.125rem; + ${segmentTokens.itemMarginLeft}: 0; + `, + s: css` + ${segmentTokens.itemBorderRadius}: 0.625rem; + ${segmentTokens.itemWidth}: auto; + ${segmentTokens.itemHeight}: 2.5rem; + ${segmentTokens.itemPadding}: 0.5rem; + ${segmentTokens.itemPilledPadding}: 0.5rem; + ${segmentTokens.iconItemContentPadding}: 0.1875rem 0.125rem; + ${segmentTokens.itemMarginLeft}: 0rem; + `, + m: css` + ${segmentTokens.itemBorderRadius}: 0.75rem; + ${segmentTokens.itemWidth}: auto; + ${segmentTokens.itemHeight}: 3rem; + ${segmentTokens.itemPadding}: 0.75rem; + ${segmentTokens.itemPilledPadding}: 0.75rem; + ${segmentTokens.iconItemContentPadding}: 0.125rem; + ${segmentTokens.itemMarginLeft}: 0rem; + `, + l: css` + ${segmentTokens.itemBorderRadius}: 0.875rem; + ${segmentTokens.itemWidth}: auto; + ${segmentTokens.itemHeight}: 3.5rem; + ${segmentTokens.itemPadding}: 1rem; + ${segmentTokens.itemPilledPadding}: 1rem; + ${segmentTokens.iconItemContentPadding}: 0.0625rem 0.125rem; + ${segmentTokens.itemMarginLeft}: 0; + `, + xl: css` + ${segmentTokens.itemBorderRadius}: 1rem; + ${segmentTokens.itemWidth}: auto; + ${segmentTokens.itemHeight}: 4rem; + ${segmentTokens.itemPadding}: 1.25rem; + ${segmentTokens.itemPilledPadding}: 1.25rem; + ${segmentTokens.iconItemContentPadding}: 0.0625rem 0.125rem; + ${segmentTokens.itemMarginLeft}: 0; + `, + }, + disabled: { + true: css` + ${segmentTokens.disabledOpacity}: 0.4; + `, + }, + pilled: { + true: css` + // NOTE: change on token when added + ${segmentTokens.itemPilledBorderRadius}: 1000px; + `, + }, + }, +}; diff --git a/packages/sdds-finai/src/components/Segment/Segment.stories.tsx b/packages/sdds-finai/src/components/Segment/Segment.stories.tsx index 9bf6406d0c8..13be9b954e2 100644 --- a/packages/sdds-finai/src/components/Segment/Segment.stories.tsx +++ b/packages/sdds-finai/src/components/Segment/Segment.stories.tsx @@ -9,9 +9,10 @@ import { SegmentProvider, SegmentItem, SegmentGroup, useSegment } from './Segmen type SegmentGroupProps = ComponentProps; -const { meta: META, Default } = getSegmentStories({ +const { meta: META, Default, IconItem } = getSegmentStories({ SegmentGroup, SegmentItem, + SegmentIconItem, SegmentProvider, componentConfig: config, CounterComponent: Counter, @@ -25,4 +26,4 @@ const meta: Meta = { export default meta; -export { Default }; +export { Default, IconItem }; diff --git a/packages/sdds-finai/src/components/Segment/Segment.ts b/packages/sdds-finai/src/components/Segment/Segment.ts index 021f8276835..adc6bd36754 100644 --- a/packages/sdds-finai/src/components/Segment/Segment.ts +++ b/packages/sdds-finai/src/components/Segment/Segment.ts @@ -7,6 +7,7 @@ import { import { config as configSegmentItem } from './SegmentItem.config'; import { config as configSegmentGroup } from './SegmentGroup.config'; +import { config as iconItemConfig } from './SegmentIconItem.config'; /** * Провайдер контекста для группы сегментов и хук для доступа к контексту. @@ -14,6 +15,7 @@ import { config as configSegmentGroup } from './SegmentGroup.config'; export { SegmentProvider, useSegment } from '@salutejs/plasma-new-hope/styled-components'; const mergedSegmentItemConfig = mergeConfig(segmentItemConfig, configSegmentItem); +const mergedSegmentIconItemConfig = mergeConfig(segmentIconItemConfig, iconItemConfig); const mergedSegmentGroupConfig = mergeConfig(segmentGroupConfig, configSegmentGroup); /** @@ -24,3 +26,7 @@ export const SegmentGroup = component(mergedSegmentGroupConfig); * Компонент сегмента. */ export const SegmentItem = component(mergedSegmentItemConfig); +/** + * Компонент сегмента с иконкой. + */ +export const SegmentIconItem = component(mergedSegmentIconItemConfig); diff --git a/packages/sdds-finai/src/components/Segment/SegmentIconItem.config.ts b/packages/sdds-finai/src/components/Segment/SegmentIconItem.config.ts new file mode 100644 index 00000000000..1bb42fa732e --- /dev/null +++ b/packages/sdds-finai/src/components/Segment/SegmentIconItem.config.ts @@ -0,0 +1,118 @@ +import { css, segmentTokens } from '@salutejs/plasma-new-hope/styled-components'; + +export const config = { + defaults: { + view: 'clear', + size: 'xs', + }, + variations: { + view: { + clear: css` + ${segmentTokens.itemColor}: var(--text-secondary); + ${segmentTokens.itemBackgroundColor}: transparent; + ${segmentTokens.itemColorHover}: var(--text-primary-hover); + ${segmentTokens.itemBackgroundColorHover}: transparent; + ${segmentTokens.itemSelectedColor}: var(--text-primary-hover); + ${segmentTokens.itemSelectedBackgroundColor}: transparent; + ${segmentTokens.itemSelectedColorHover}: var(--text-primary); + ${segmentTokens.itemSelectedBackgroundColorHover}: transparent; + + ${segmentTokens.outlineFocusColor}: var(--text-accent); + `, + secondary: css` + ${segmentTokens.itemColor}: var(--text-primary); + ${segmentTokens.itemBackgroundColor}: transparent; + ${segmentTokens.itemColorHover}: var(--text-primary-hover); + ${segmentTokens.itemBackgroundColorHover}: transparent; + ${segmentTokens.itemSelectedColor}: var(--text-primary); + ${segmentTokens.itemSelectedBackgroundColor}: var(--surface-transparent-card); + ${segmentTokens.itemSelectedColorHover}: var(--text-primary-hover); + ${segmentTokens.itemSelectedBackgroundColorHover}: var(--surface-transparent-card); + + ${segmentTokens.outlineFocusColor}: var(--text-accent); + `, + default: css` + ${segmentTokens.itemColor}: var(--text-primary); + ${segmentTokens.itemBackgroundColor}: transparent; + ${segmentTokens.itemColorHover}: var(--text-primary-hover); + ${segmentTokens.itemBackgroundColorHover}: transparent; + ${segmentTokens.itemSelectedColor}: var(--inverse-text-primary); + ${segmentTokens.itemSelectedBackgroundColor}: var(--surface-solid-default); + ${segmentTokens.itemSelectedColorHover}: var(--inverse-text-primary-hover); + ${segmentTokens.itemSelectedBackgroundColorHover}: var(--surface-solid-default); + + ${segmentTokens.outlineFocusColor}: var(--text-accent); + `, + accent: css` + ${segmentTokens.itemColor}: var(--text-primary); + ${segmentTokens.itemBackgroundColor}: transparent; + ${segmentTokens.itemColorHover}: var(--text-primary-hover); + ${segmentTokens.itemBackgroundColorHover}: transparent; + ${segmentTokens.itemSelectedColor}: var(--on-dark-text-primary); + ${segmentTokens.itemSelectedBackgroundColor}: var(--surface-accent); + ${segmentTokens.itemSelectedColorHover}: var(--on-dark-text-primary-hover); + ${segmentTokens.itemSelectedBackgroundColorHover}: var(--surface-accent); + + ${segmentTokens.groupFilledBackgroundColor}: var(--text-accent); + `, + }, + size: { + xs: css` + ${segmentTokens.itemBorderRadius}: 0.5rem; + ${segmentTokens.itemWidth}: auto; + ${segmentTokens.itemHeight}: 2rem; + ${segmentTokens.itemPadding}: 0.5rem; + ${segmentTokens.itemPilledPadding}: 0.5rem; + ${segmentTokens.iconItemContentPadding}: 0.0625rem 0.125rem; + ${segmentTokens.itemMarginLeft}: 0; + `, + s: css` + ${segmentTokens.itemBorderRadius}: 0.625rem; + ${segmentTokens.itemWidth}: auto; + ${segmentTokens.itemHeight}: 2.5rem; + ${segmentTokens.itemPadding}: 0.5rem; + ${segmentTokens.itemPilledPadding}: 0.5rem; + ${segmentTokens.iconItemContentPadding}: 0.1875rem 0.125rem; + ${segmentTokens.itemMarginLeft}: 0rem; + `, + m: css` + ${segmentTokens.itemBorderRadius}: 0.75rem; + ${segmentTokens.itemWidth}: auto; + ${segmentTokens.itemHeight}: 3rem; + ${segmentTokens.itemPadding}: 0.75rem; + ${segmentTokens.itemPilledPadding}: 0.75rem; + ${segmentTokens.iconItemContentPadding}: 0.125rem; + ${segmentTokens.itemMarginLeft}: 0rem; + `, + l: css` + ${segmentTokens.itemBorderRadius}: 0.875rem; + ${segmentTokens.itemWidth}: auto; + ${segmentTokens.itemHeight}: 3.5rem; + ${segmentTokens.itemPadding}: 1rem; + ${segmentTokens.itemPilledPadding}: 1rem; + ${segmentTokens.iconItemContentPadding}: 0.0625rem 0.125rem; + ${segmentTokens.itemMarginLeft}: 0; + `, + xl: css` + ${segmentTokens.itemBorderRadius}: 1rem; + ${segmentTokens.itemWidth}: auto; + ${segmentTokens.itemHeight}: 4rem; + ${segmentTokens.itemPadding}: 1.25rem; + ${segmentTokens.itemPilledPadding}: 1.25rem; + ${segmentTokens.iconItemContentPadding}: 0.0625rem 0.125rem; + ${segmentTokens.itemMarginLeft}: 0; + `, + }, + disabled: { + true: css` + ${segmentTokens.disabledOpacity}: 0.4; + `, + }, + pilled: { + true: css` + // NOTE: change on token when added + ${segmentTokens.itemPilledBorderRadius}: 1000px; + `, + }, + }, +}; diff --git a/utils/plasma-sb-utils/src/components/Segment/Segment.tsx b/utils/plasma-sb-utils/src/components/Segment/Segment.tsx index 78ebd6c2c3d..74b60a44831 100644 --- a/utils/plasma-sb-utils/src/components/Segment/Segment.tsx +++ b/utils/plasma-sb-utils/src/components/Segment/Segment.tsx @@ -3,11 +3,12 @@ import React from 'react'; import { getConfigVariations } from '../../helpers'; import { createMeta } from './meta'; -import { createDefaultStory } from './stories'; +import { createDefaultStory, createIconItemStory } from './stories'; type CreateSegmentStoriesProps = { SegmentGroup: any; SegmentItem: any; + SegmentIconItem?: any; SegmentProvider: any; componentConfig: any; CounterComponent?: any; @@ -33,6 +34,7 @@ export const getSegmentStories = (config: CreateSegmentStoriesProps) => { const { SegmentGroup, SegmentItem, + SegmentIconItem, SegmentProvider, componentConfig, CounterComponent, @@ -62,13 +64,23 @@ export const getSegmentStories = (config: CreateSegmentStoriesProps) => { customGetContentLeft, customGetContentRight, }); + const IconItemStoryComponent = createIconItemStory({ + SegmentGroup, + SegmentIconItem, + SegmentProvider, + }); const Default = { render: (args: any) => , }; + const IconItem = { + render: (args: any) => , + }; + return { meta, Default, + IconItem, }; }; diff --git a/utils/plasma-sb-utils/src/components/Segment/stories.tsx b/utils/plasma-sb-utils/src/components/Segment/stories.tsx index 07f8c3ca128..e479479b7b4 100644 --- a/utils/plasma-sb-utils/src/components/Segment/stories.tsx +++ b/utils/plasma-sb-utils/src/components/Segment/stories.tsx @@ -1,6 +1,7 @@ import React, { useState } from 'react'; +import { IconPlasma } from '@salutejs/plasma-icons'; -import { getContentLeft, getContentRight } from './helpers'; +import { getContentLeft, getContentRight, getContentSize } from './helpers'; type CreateDefaultStoryProps = { SegmentGroup: any; @@ -137,3 +138,85 @@ export const createDefaultStory = ({ ); }; }; + +type CreateIconItemStoryProps = { + SegmentGroup: any; + SegmentIconItem: any; + SegmentProvider: any; +}; + +export const createIconItemStory = ({ SegmentGroup, SegmentIconItem, SegmentProvider }: CreateIconItemStoryProps) => { + const SegmentGroupContent = ({ + items, + stretch, + disabled, + size, + orientation, + segmentItemView, + hasBackground, + args, + }: any) => { + const iconSize = getContentSize(size); + + return ( + + {items.map((_: any, i: number) => ( + } + {...args} + /> + ))} + + ); + }; + + return (props: any) => { + const { + singleSelectedRequired, + disabled, + itemQuantity, + size, + stretch, + orientation, + segmentItemView, + ...args + } = props; + + const items = Array(itemQuantity).fill(0); + const [selected, setSelected] = useState([]); + + const handleChangeSelected = (selectedSegment: string) => { + setSelected([selectedSegment]); + }; + + return ( + + + + ); + }; +}; diff --git a/website/sdds-finai-docs/docs/components/Segment.mdx b/website/sdds-finai-docs/docs/components/Segment.mdx index 60dde393225..e8cce339da8 100644 --- a/website/sdds-finai-docs/docs/components/Segment.mdx +++ b/website/sdds-finai-docs/docs/components/Segment.mdx @@ -252,6 +252,49 @@ export function App() { } ``` +### Сегменты только с иконкой + +Для отображения сегментов с только иконкой, необходимо использовать `SegmentIconItem` + +```tsx live +import React from 'react'; +import { IconPlasma } from '@salutejs/plasma-icons' +import { SegmentGroup, SegmentIconItem, SegmentProvider, useSegment } from '@salutejs/sdds-finai'; + +export function App() { + const items = Array(4).fill(0); + + const SegmentTemplate = () => { + const {selectedSegmentItems} = useSegment(); + + return ( + <> +
Выбранный элемент: {selectedSegmentItems.join(', ')}
+
+ + {items.map((_, i) => ( + } + value={`label_${i}`} + key={`label_${i}`} + view='default' + /> + ))} + + + ) + } + + return ( +
+ + + +
+ ); +} +``` + ## Таблица свойств ### SegmentGroup