diff --git a/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _size.snap.png b/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _size.snap.png
new file mode 100644
index 0000000000..2ace0c8cbe
Binary files /dev/null and b/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _size.snap.png differ
diff --git a/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _type.snap.png b/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _type.snap.png
new file mode 100644
index 0000000000..8b299c1c7d
Binary files /dev/null and b/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _type.snap.png differ
diff --git a/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _viewclear.snap.png b/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _viewclear.snap.png
new file mode 100644
index 0000000000..e10225a93a
Binary files /dev/null and b/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _viewclear.snap.png differ
diff --git a/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- animation.snap.png b/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- animation.snap.png
new file mode 100644
index 0000000000..3b4daa25f4
Binary files /dev/null and b/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- animation.snap.png differ
diff --git a/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- simple.snap.png b/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- simple.snap.png
new file mode 100644
index 0000000000..ad98162a99
Binary files /dev/null and b/cypress/snapshots/b2c/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- simple.snap.png differ
diff --git a/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _size.snap.png b/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _size.snap.png
new file mode 100644
index 0000000000..15dd871e30
Binary files /dev/null and b/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _size.snap.png differ
diff --git a/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _type.snap.png b/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _type.snap.png
new file mode 100644
index 0000000000..0b84fdd887
Binary files /dev/null and b/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _type.snap.png differ
diff --git a/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _viewclear.snap.png b/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _viewclear.snap.png
new file mode 100644
index 0000000000..5c0175397e
Binary files /dev/null and b/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- _viewclear.snap.png differ
diff --git a/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- animation.snap.png b/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- animation.snap.png
new file mode 100644
index 0000000000..d5f6662447
Binary files /dev/null and b/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- animation.snap.png differ
diff --git a/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- simple.snap.png b/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- simple.snap.png
new file mode 100644
index 0000000000..693d319db2
Binary files /dev/null and b/cypress/snapshots/web/components/Accordion/Accordion.component-test.tsx/plasma-web Accordion -- simple.snap.png differ
diff --git a/packages/plasma-b2c/api/plasma-b2c.api.md b/packages/plasma-b2c/api/plasma-b2c.api.md
index 76da048d43..732cf021a0 100644
--- a/packages/plasma-b2c/api/plasma-b2c.api.md
+++ b/packages/plasma-b2c/api/plasma-b2c.api.md
@@ -6,6 +6,8 @@
///
+import { AccordionItem } from '@salutejs/plasma-new-hope/styled-components';
+import { AccordionProps } from '@salutejs/plasma-new-hope/styled-components';
import { addFocus } from '@salutejs/plasma-core';
import { addNotification } from '@salutejs/plasma-new-hope/styled-components';
import { AlignProp } from '@salutejs/plasma-new-hope/types/components/Cell/Cell.types';
@@ -279,6 +281,38 @@ import { WithAutoFocusProps } from '@salutejs/plasma-core';
import { withSkeleton } from '@salutejs/plasma-new-hope/styled-components';
import { WithSkeletonProps } from '@salutejs/plasma-new-hope/styled-components';
+// @public
+export const Accordion: FunctionComponent & {
+view: string;
+size?: string | undefined;
+singleActive?: boolean | undefined;
+defaultActiveEventKey?: number[] | undefined;
+disabled?: boolean | undefined;
+stretching?: "fixed" | "filled" | undefined;
+onChange?: ((index?: number | undefined, value?: boolean | undefined) => void) | undefined;
+children?: ReactNode;
+className?: string | undefined;
+} & RefAttributes>;
+
+export { AccordionItem }
+
+export { AccordionProps }
+
export { addFocus }
export { addNotification }
@@ -825,11 +859,11 @@ l: string;
view: {
default: string;
};
-}> & ((Omit, "onChange" | "value" | "type" | "target" | "size" | "checked" | "minLength" | "maxLength"> & CustomComboboxProps & {
+}> & ((Omit, "onChange" | "size" | "value" | "type" | "target" | "checked" | "minLength" | "maxLength"> & CustomComboboxProps & {
valueType?: "single" | undefined;
value?: ComboboxPrimitiveValue | undefined;
onChangeValue?: ((value?: ComboboxPrimitiveValue | undefined) => void) | undefined;
-} & RefAttributes) | (Omit, "onChange" | "value" | "type" | "target" | "size" | "checked" | "minLength" | "maxLength"> & CustomComboboxProps & {
+} & RefAttributes) | (Omit, "onChange" | "size" | "value" | "type" | "target" | "checked" | "minLength" | "maxLength"> & CustomComboboxProps & {
valueType: "multiple";
value?: ComboboxPrimitiveValue[] | undefined;
onChangeValue?: ((value?: ComboboxPrimitiveValue[] | undefined) => void) | undefined;
diff --git a/packages/plasma-b2c/src/components/Accordion/Accordion.component-test.tsx b/packages/plasma-b2c/src/components/Accordion/Accordion.component-test.tsx
new file mode 120000
index 0000000000..12574f0698
--- /dev/null
+++ b/packages/plasma-b2c/src/components/Accordion/Accordion.component-test.tsx
@@ -0,0 +1 @@
+../../../../plasma-web/src/components/Accordion/Accordion.component-test.tsx
\ No newline at end of file
diff --git a/packages/plasma-b2c/src/components/Accordion/Accordion.config.ts b/packages/plasma-b2c/src/components/Accordion/Accordion.config.ts
new file mode 100644
index 0000000000..4818c3cb31
--- /dev/null
+++ b/packages/plasma-b2c/src/components/Accordion/Accordion.config.ts
@@ -0,0 +1,121 @@
+import { css, accordionTokens } from '@salutejs/plasma-new-hope/styled-components';
+
+export const config = {
+ defaults: {
+ view: 'default',
+ size: 'm',
+ },
+ variations: {
+ view: {
+ default: css`
+ ${accordionTokens.accordionGap}: 0.125rem;
+ ${accordionTokens.accordionWidth}: 20rem;
+ ${accordionTokens.accordionItemPadding}: var(${accordionTokens.accordionItemPaddingVertical}) var(${accordionTokens.accordionItemPaddingHorizontal});
+ ${accordionTokens.accordionItemBackground}: var(--surface-solid-card);
+ ${accordionTokens.accordionItemTitleColor}: var(--text-primary);
+ ${accordionTokens.accordionItemTextColor}: var(--text-primary);
+ ${accordionTokens.accordionItemFocus}: var(--surface-accent);
+ ${accordionTokens.accordionBackground}: var(--surface-clear);
+ ${accordionTokens.accordionItemBorderBottom}: 0;
+ `,
+ clear: css`
+ ${accordionTokens.accordionGap}: 0.125rem;
+ ${accordionTokens.accordionWidth}: 20rem;
+ ${accordionTokens.accordionItemPadding}: var(${accordionTokens.accordionItemPaddingVertical}) 0rem;
+ ${accordionTokens.accordionItemBackground}: var(--surface-clear);
+ ${accordionTokens.accordionItemTitleColor}: var(--text-primary);
+ ${accordionTokens.accordionItemTextColor}: var(--text-primary);
+ ${accordionTokens.accordionItemFocus}: var(--surface-accent);
+ ${accordionTokens.accordionItemBorderRadius}: 0rem !important;
+ ${accordionTokens.accordionBackground}: var(--surface-clear);
+ ${accordionTokens.accordionItemBorderBottom}: 0.125rem solid var(--surface-solid-tertiary);
+ `,
+ },
+ size: {
+ l: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 1.0625rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 1.25rem;
+ ${accordionTokens.accordionItemGap}: 0.5rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.875rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-l-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-l-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-l-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-l-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-l-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-l-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-l-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-l-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-l-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-l-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-l-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-l-line-height);
+ `,
+ m: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 0.875rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 1.125rem;
+ ${accordionTokens.accordionItemGap}: 0.375rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.75rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-m-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-m-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-m-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-m-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-m-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-m-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-m-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-m-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-m-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-m-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-m-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-m-line-height);
+ `,
+ s: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 0.6875rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 0.875rem;
+ ${accordionTokens.accordionItemGap}: 0.375rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.625rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-s-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-s-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-s-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-s-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-s-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-s-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-s-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-s-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-s-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-s-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-s-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-s-line-height);
+ `,
+ xs: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 0.5rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 0.75rem;
+ ${accordionTokens.accordionItemGap}: 0.25rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.5rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-xs-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-xs-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-xs-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-xs-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-xs-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-xs-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-xs-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-xs-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-xs-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-xs-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-xs-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-xs-line-height);
+ `,
+ },
+ stretching: {
+ filled: css``,
+ fixed: css``,
+ },
+ },
+};
diff --git a/packages/plasma-b2c/src/components/Accordion/Accordion.stories.tsx b/packages/plasma-b2c/src/components/Accordion/Accordion.stories.tsx
new file mode 100644
index 0000000000..7c9abfa2f3
--- /dev/null
+++ b/packages/plasma-b2c/src/components/Accordion/Accordion.stories.tsx
@@ -0,0 +1,58 @@
+import * as React from 'react';
+import type { ComponentProps } from 'react';
+import type { StoryObj, Meta } from '@storybook/react';
+import { disableProps } from '@salutejs/plasma-sb-utils';
+
+import { Accordion, AccordionItem } from '.';
+
+const meta: Meta = {
+ title: 'Content/Accordion',
+ component: Accordion,
+ args: {
+ singleActive: false,
+ view: 'default',
+ size: 'm',
+ stretching: 'filled',
+ type: 'arrow',
+ title: 'Как оплатить заправку бонусами СберСпасибо?',
+ body:
+ 'После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива',
+ },
+ argTypes: {
+ ...disableProps(['text']),
+ stretching: {
+ options: ['filled', 'fixed'],
+ control: {
+ type: 'select',
+ },
+ },
+ type: {
+ options: ['arrow', 'sign', 'clear'],
+ control: {
+ type: 'select',
+ },
+ },
+ },
+};
+
+export default meta;
+
+export const Default: StoryObj> = {
+ render: (props: ComponentProps) => {
+ const args = { ...props, text: undefined };
+
+ return (
+
+
+ {args.body}
+
+
+ {args.body}
+
+
+ {args.body}
+
+
+ );
+ },
+};
diff --git a/packages/plasma-b2c/src/components/Accordion/Accordion.tsx b/packages/plasma-b2c/src/components/Accordion/Accordion.tsx
new file mode 100644
index 0000000000..d56bbf45e0
--- /dev/null
+++ b/packages/plasma-b2c/src/components/Accordion/Accordion.tsx
@@ -0,0 +1,11 @@
+import { accordionConfig, component, mergeConfig } from '@salutejs/plasma-new-hope/styled-components';
+
+import { config } from './Accordion.config';
+
+const mergedConfig = mergeConfig(accordionConfig, config);
+const AccordionComponent = component(mergedConfig);
+
+/**
+ * Accordion
+ */
+export const Accordion = AccordionComponent;
diff --git a/packages/plasma-b2c/src/components/Accordion/index.ts b/packages/plasma-b2c/src/components/Accordion/index.ts
new file mode 100644
index 0000000000..8a291f450d
--- /dev/null
+++ b/packages/plasma-b2c/src/components/Accordion/index.ts
@@ -0,0 +1,4 @@
+export { AccordionItem } from '@salutejs/plasma-new-hope/styled-components';
+export { Accordion } from './Accordion';
+
+export type { AccordionProps } from '@salutejs/plasma-new-hope/styled-components';
diff --git a/packages/plasma-b2c/src/index.ts b/packages/plasma-b2c/src/index.ts
index f1d57b5ddb..745315f580 100644
--- a/packages/plasma-b2c/src/index.ts
+++ b/packages/plasma-b2c/src/index.ts
@@ -1,3 +1,4 @@
+export * from './components/Accordion';
export * from './components/AudioPlayer';
export * from './components/Badge';
export * from './components/Button';
diff --git a/packages/plasma-new-hope/src/components/Accordion/Accordion.styles.ts b/packages/plasma-new-hope/src/components/Accordion/Accordion.styles.ts
new file mode 100644
index 0000000000..bd01dca854
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/Accordion.styles.ts
@@ -0,0 +1,19 @@
+import { css } from '@linaria/core';
+
+import { classes, tokens } from './Accordion.tokens';
+
+export const base = css`
+ display: flex;
+ flex-direction: column;
+ gap: var(${tokens.accordionGap});
+ align-items: stretch;
+ height: auto;
+ background: var(${tokens.accordionBackground});
+
+ &.${classes.fixedStretching} {
+ width: var(${tokens.accordionWidth});
+ }
+ &.${classes.filledStretching} {
+ width: 100%;
+ }
+`;
diff --git a/packages/plasma-new-hope/src/components/Accordion/Accordion.tokens.ts b/packages/plasma-new-hope/src/components/Accordion/Accordion.tokens.ts
new file mode 100644
index 0000000000..53510b3333
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/Accordion.tokens.ts
@@ -0,0 +1,41 @@
+export const classes = {
+ filledStretching: 'accordion-stretching-filled',
+ fixedStretching: 'accordion-stretching-fixed',
+ accordionRoot: 'accordion-root',
+ accordionItem: 'accordion-item',
+ clearAccordionItem: 'clear-accordion-item',
+ accordionItemShowBody: 'accordion-item-show-body',
+ accordionPlusAnimationElement: 'accordion-plus-animation-element',
+ accordionDisabled: 'accordion-disabled',
+};
+
+export const tokens = {
+ accordionGap: '--plasma-accordion-gap',
+ accordionWidth: '--plasma-accordion-width',
+ accordionBackground: '--plasma-accordion-background',
+
+ accordionItemBackground: '--plasma-accordion-item-background',
+ accordionItemBorderRadius: '--plasma-accordion-item-border-radius',
+ accordionItemPadding: '--plasma-accordion-item-padding',
+ accordionItemPaddingVertical: '--plasma-accordion-item-padding-vertical',
+ accordionItemPaddingHorizontal: '--plasma-accordion-item-padding-horizontal',
+ accordionItemGap: '--plasma-accordion-item-gap',
+ accordionItemFocus: '--plasma-accordion-item-focus',
+ accordionItemBorderBottom: '--plasma-accordion-item-border-bottom',
+
+ accordionItemTitleColor: '--plasma-accordion-item-title-color',
+ accordionItemTitleFontFamily: '--plasma-accordion-item-title-font-family',
+ accordionItemTitleFontSize: '--plasma-accordion-item-title-font-size',
+ accordionItemTitleFontStyle: '--plasma-accordion-item-title-font-style',
+ accordionItemTitleFontWeight: '--plasma-accordion-item-title-font-weight',
+ accordionItemTitleLetterSpacing: '--plasma-accordion-item-title-letter-spacing',
+ accordionItemTitleLineHeight: '--plasma-accordion-item-title-line-height',
+
+ accordionItemTextColor: '--plasma-accordion-item-text-color',
+ accordionItemTextFontFamily: '--plasma-accordion-item-text-font-family',
+ accordionItemTextFontSize: '--plasma-accordion-item-text-font-size',
+ accordionItemTextFontStyle: '--plasma-accordion-item-text-font-style',
+ accordionItemTextFontWeight: '--plasma-accordion-item-text-font-weight',
+ accordionItemTextLetterSpacing: '--plasma-accordion-item-text-letter-spacing',
+ accordionItemTextLineHeight: '--plasma-accordion-item-text-line-height',
+};
diff --git a/packages/plasma-new-hope/src/components/Accordion/Accordion.tsx b/packages/plasma-new-hope/src/components/Accordion/Accordion.tsx
new file mode 100644
index 0000000000..cf8cc923bf
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/Accordion.tsx
@@ -0,0 +1,82 @@
+import React, { Children, forwardRef, useState } from 'react';
+
+import { RootPropsOmitOnChange } from '../../engines';
+import { cx } from '../../utils';
+
+import type { AccordionProps } from './Accordion.types';
+import { base } from './Accordion.styles';
+import { classes } from './Accordion.tokens';
+import { base as viewCSS } from './variations/_view/base';
+import { base as sizeCSS } from './variations/_size/base';
+import { getChildren } from './utils';
+
+export const accordionRoot = (Root: RootPropsOmitOnChange) =>
+ forwardRef(
+ (
+ {
+ size,
+ view,
+ stretching = 'filled',
+ defaultActiveEventKey = [],
+ children,
+ disabled,
+ className,
+ singleActive,
+ onChange,
+ },
+ outerRootRef,
+ ) => {
+ const stretchingClass = classes[`${stretching}Stretching` as keyof typeof classes];
+
+ const [activeIndex, setActiveIndex] = useState(defaultActiveEventKey);
+
+ const updateValue = (index: number, value?: boolean) => {
+ if (onChange) {
+ onChange(index, value);
+ }
+ if (singleActive) {
+ if (value) {
+ setActiveIndex([index]);
+ } else {
+ setActiveIndex([]);
+ }
+ } else if (value) {
+ setActiveIndex([index, ...activeIndex]);
+ } else {
+ const updatedActiveIndex = activeIndex.filter((i) => i !== index);
+ setActiveIndex(updatedActiveIndex);
+ }
+ };
+
+ const childrenArray = Children.toArray(children) as React.ReactElement[];
+ return (
+
+ {getChildren(childrenArray, activeIndex, disabled, updateValue)}
+
+ );
+ },
+ );
+
+export const accordionConfig = {
+ name: 'Accordion',
+ tag: 'div',
+ layout: accordionRoot,
+ base,
+ variations: {
+ view: {
+ css: viewCSS,
+ },
+ size: {
+ css: sizeCSS,
+ },
+ },
+ defaults: {
+ view: 'default',
+ size: 'm',
+ },
+};
diff --git a/packages/plasma-new-hope/src/components/Accordion/Accordion.types.ts b/packages/plasma-new-hope/src/components/Accordion/Accordion.types.ts
new file mode 100644
index 0000000000..02588fac74
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/Accordion.types.ts
@@ -0,0 +1,43 @@
+import type { ReactNode } from 'react';
+
+type CustomAccordionProps = {
+ /**
+ * Тип аккордеона
+ */
+ view: string;
+
+ /**
+ * Размер
+ */
+ size?: string;
+
+ /**
+ * Возможность раскрытия всех элементов или только одногo
+ */
+ singleActive?: boolean;
+
+ /**
+ * Индекс элемента, который должен быть изначально раскрыт
+ */
+ defaultActiveEventKey?: number[];
+
+ /**
+ * Блокировка всех элементов
+ */
+ disabled?: boolean;
+
+ /**
+ * Ширина
+ */
+ stretching?: 'fixed' | 'filled';
+
+ /**
+ * Коллбэк при открытии или закрытии элемента аккордеона
+ */
+ onChange?: (index?: number, value?: boolean) => void;
+
+ children?: ReactNode;
+ className?: string;
+};
+
+export type AccordionProps = CustomAccordionProps;
diff --git a/packages/plasma-new-hope/src/components/Accordion/index.ts b/packages/plasma-new-hope/src/components/Accordion/index.ts
new file mode 100644
index 0000000000..24e2eefab6
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/index.ts
@@ -0,0 +1,5 @@
+export { accordionRoot, accordionConfig } from './Accordion';
+export type { AccordionProps } from './Accordion.types';
+
+export { AccordionItem } from './ui/AccordionItem/AccordionItem';
+export { tokens as accordionTokens, classes as accordionClasses } from './Accordion.tokens';
diff --git a/packages/plasma-new-hope/src/components/Accordion/ui/AccordionItem/AccordionItem.styles.ts b/packages/plasma-new-hope/src/components/Accordion/ui/AccordionItem/AccordionItem.styles.ts
new file mode 100644
index 0000000000..a1191e1985
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/ui/AccordionItem/AccordionItem.styles.ts
@@ -0,0 +1,147 @@
+import styled from 'styled-components';
+
+import { IconChevronDownFill, IconMinus } from '../../../_Icon';
+import { classes, tokens } from '../../Accordion.tokens';
+import { addFocus } from '../../../../mixins';
+
+export const StyledAccordionItem = styled.div`
+ background: var(${tokens.accordionItemBackground});
+ border-bottom: var(${tokens.accordionItemBorderBottom});
+
+ &:last-child {
+ border-bottom: none;
+ }
+`;
+
+export const StyledAccordionHeader = styled.button`
+ width: 100%;
+ border: none;
+ padding: var(${tokens.accordionItemPadding});
+ display: flex;
+ gap: var(${tokens.accordionItemGap});
+ justify-content: space-between;
+ align-items: center;
+ background: none;
+ box-sizing: border-box;
+ cursor: pointer;
+
+ &.${classes.accordionDisabled} {
+ opacity: 0.4;
+ cursor: not-allowed;
+ }
+
+ &:focus {
+ outline: none;
+ }
+
+ ${addFocus({
+ outlineOffset: '0.125rem',
+ outlineSize: '0.125rem',
+ outlineRadius: '0',
+ outlineColor: `var(${tokens.accordionItemFocus})`,
+ })}
+`;
+
+export const StyledAccordionHeaderLeft = styled.div`
+ display: flex;
+ gap: var(${tokens.accordionItemGap});
+ justify-content: space-between;
+ align-items: center;
+`;
+
+export const StyledAccordionContentRight = styled.div`
+ transition: 0.2s;
+ transform: rotate(90deg);
+
+ &.${classes.accordionItemShowBody} {
+ transition: 0.2s;
+ transform: rotate(0deg);
+ }
+`;
+
+export const StyledAccordionContentLeft = styled.div`
+ transition: 0.2s;
+ display: flex;
+ align-items: center;
+
+ &.${classes.accordionItemShowBody} {
+ transition: 0.2s;
+ transform: rotate(180deg);
+ }
+`;
+
+export const StyledAccordionTitle = styled.div`
+ color: var(${tokens.accordionItemTitleColor});
+ font-family: var(${tokens.accordionItemTitleFontFamily});
+ font-size: var(${tokens.accordionItemTitleFontSize});
+ font-weight: var(${tokens.accordionItemTitleFontWeight});
+ font-style: var(${tokens.accordionItemTitleFontStyle});
+ letter-spacing: var(${tokens.accordionItemTitleLetterSpacing});
+ line-height: var(${tokens.accordionItemTitleLineHeight});
+`;
+
+export const StyledAccordionBodyAnimate = styled.div`
+ display: grid;
+ grid-template-rows: 0fr;
+ transition: grid-template-rows 0.2s ease-out;
+ overflow: hidden;
+
+ &.${classes.accordionItemShowBody} {
+ grid-template-rows: 1fr;
+ padding-bottom: var(${tokens.accordionItemPaddingVertical});
+
+ &.${classes.accordionPlusAnimationElement} {
+ transition: 0.2s;
+ transform: rotate(0deg);
+ }
+ }
+`;
+
+export const StyledAccordionBody = styled.div`
+ color: var(${tokens.accordionItemTextColor});
+ font-family: var(${tokens.accordionItemTextFontFamily});
+ font-size: var(${tokens.accordionItemTextFontSize});
+ font-weight: var(${tokens.accordionItemTextFontWeight});
+ font-style: var(${tokens.accordionItemTextFontStyle});
+ letter-spacing: var(${tokens.accordionItemTextLetterSpacing});
+ line-height: var(${tokens.accordionItemTextLineHeight});
+ overflow: hidden;
+ padding-right: var(${tokens.accordionItemPaddingHorizontal});
+ padding-left: var(${tokens.accordionItemPaddingHorizontal});
+`;
+
+export const StyledArrow = styled(IconChevronDownFill)`
+ pointer-events: none;
+ user-select: none;
+ color: var(${tokens.accordionItemTextColor});
+`;
+
+export const StyledMinus = styled(IconMinus)`
+ pointer-events: none;
+ user-select: none;
+ color: var(${tokens.accordionItemTextColor});
+ display: flex;
+ align-items: center;
+ position: absolute;
+ top: 0;
+ left: 0;
+
+ &.${classes.accordionPlusAnimationElement} {
+ transition: 0.2s;
+ transform: rotate(90deg);
+ }
+
+ &.${classes.accordionItemShowBody} {
+ transition: 0.2s;
+ transform: rotate(0deg);
+ }
+`;
+
+export const StyledPlus = styled.div`
+ position: relative;
+ height: 1rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 1rem;
+`;
diff --git a/packages/plasma-new-hope/src/components/Accordion/ui/AccordionItem/AccordionItem.tsx b/packages/plasma-new-hope/src/components/Accordion/ui/AccordionItem/AccordionItem.tsx
new file mode 100644
index 0000000000..38003473bf
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/ui/AccordionItem/AccordionItem.tsx
@@ -0,0 +1,116 @@
+import React, { HTMLAttributes, useState, useRef, useEffect } from 'react';
+
+import { convertRoundnessMatrix } from '../../../../utils/roundness';
+import { classes, tokens } from '../../Accordion.tokens';
+
+import {
+ StyledAccordionItem,
+ StyledAccordionHeader,
+ StyledAccordionBody,
+ StyledAccordionTitle,
+ StyledAccordionContentLeft,
+ StyledAccordionHeaderLeft,
+ StyledAccordionContentRight,
+ StyledArrow,
+ StyledMinus,
+ StyledPlus,
+ StyledAccordionBodyAnimate,
+} from './AccordionItem.styles';
+import type { AccordionItemProps } from './AccordionItem.types';
+
+export const AccordionItem: React.FC & AccordionItemProps> = ({
+ value,
+ contentRight,
+ contentLeft,
+ title,
+ pin = 'square-square',
+ children,
+ type = 'sign',
+ index,
+ eventKey,
+ disabled,
+ onChange,
+}) => {
+ const key = eventKey ?? index;
+
+ const [leftPadding, setLeftPadding] = useState();
+
+ const handleOpen = () => {
+ if (disabled) {
+ return;
+ }
+ if (onChange) {
+ onChange(key, !value);
+ }
+ };
+
+ const leftContentRef = useRef(null);
+
+ useEffect(() => {
+ const leftContentWidth = leftContentRef?.current?.offsetWidth ?? 0;
+ const leftPaddingBody = leftContentWidth ? `calc(${leftContentWidth}px + var(${tokens.accordionItemGap}))` : 0;
+ setLeftPadding(leftPaddingBody);
+ }, [value, type, leftContentRef, setLeftPadding]);
+
+ const openedBodyClass = value ? classes.accordionItemShowBody : undefined;
+
+ const StyledAnimationPLus = () => (
+
+
+
+
+ );
+
+ const accordionBorderRadius = convertRoundnessMatrix(pin, `var(${tokens.accordionItemBorderRadius})`, '1.5rem');
+ const disabledClass = disabled ? classes.accordionDisabled : '';
+
+ const leftContent = contentLeft ?? (type === 'arrow' ? : undefined);
+ const leftContentRotate = type === 'arrow' && value ? classes.accordionItemShowBody : undefined;
+
+ const rightContent = contentRight ?? (type === 'sign' ? : undefined);
+ const rightContentRotate = type === 'sign' && value ? classes.accordionItemShowBody : undefined;
+
+ return (
+
+
+
+ {leftContent && (
+
+ {leftContent}
+
+ )}
+ {title}
+
+
+
+ {rightContent && rightContent}
+
+
+
+ {children}
+
+
+ );
+};
diff --git a/packages/plasma-new-hope/src/components/Accordion/ui/AccordionItem/AccordionItem.types.ts b/packages/plasma-new-hope/src/components/Accordion/ui/AccordionItem/AccordionItem.types.ts
new file mode 100644
index 0000000000..7759730f7a
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/ui/AccordionItem/AccordionItem.types.ts
@@ -0,0 +1,66 @@
+import type { ReactNode } from 'react';
+
+import type { Pin } from '../../../../utils/roundness';
+
+type CustomAccordionItemProps = {
+ /**
+ * Значение раскрытия аккордеона
+ */
+ value?: boolean;
+
+ /**
+ * Тип анимации раскрытия
+ */
+ type?: 'clear' | 'arrow' | 'sign';
+
+ /**
+ * Контент слева
+ */
+ contentLeft?: ReactNode;
+
+ /**
+ * Контент справа
+ */
+ contentRight?: ReactNode;
+
+ /**
+ * Скругление аккордеона
+ */
+ pin?: Pin;
+
+ /**
+ * Заголовок аккордеона
+ */
+ title: ReactNode;
+
+ /**
+ * Контент аккордеона
+ */
+ children: ReactNode;
+
+ /**
+ * Функция при открытии аккардеона
+ */
+ onChange: (index: number, value: boolean) => void;
+
+ /**
+ * Блокировка элемента
+ */
+ disabled?: boolean;
+
+ //
+ // Свойства которые автоматически добавляется Accordion'ом
+ //
+
+ /**
+ * Индекс элемента
+ */
+ eventKey?: number;
+
+ /**
+ * Индекс элемента
+ */
+ index: number;
+};
+
+export type AccordionItemProps = CustomAccordionItemProps;
diff --git a/packages/plasma-new-hope/src/components/Accordion/utils/index.ts b/packages/plasma-new-hope/src/components/Accordion/utils/index.ts
new file mode 100644
index 0000000000..f96d91e0a5
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/utils/index.ts
@@ -0,0 +1,33 @@
+import { Children, ReactElement, ReactNode, cloneElement, isValidElement } from 'react';
+
+import { AccordionItemProps } from '../ui/AccordionItem/AccordionItem.types';
+
+export const updatePropsRecursively = (
+ children?: ReactElement[],
+ activeIndex?: number[],
+ disabled?: boolean,
+ updateValue?: (index: number, value?: boolean) => void,
+): ReactNode[] =>
+ Children.map(children || [], (child, index) => {
+ if (!isValidElement(child)) {
+ return child;
+ }
+
+ const props = {
+ index,
+ value: !!(activeIndex?.findIndex((i: number) => i === (child.props.eventKey ?? index)) !== -1),
+ disabled,
+ onChange: updateValue,
+ };
+
+ return cloneElement(child, props);
+ });
+
+export const getChildren = (
+ children: ReactElement[],
+ activeIndex?: number[],
+ disabled?: boolean,
+ updateValue?: (index: number, value?: boolean) => void,
+) => {
+ return updatePropsRecursively(children, activeIndex, disabled, updateValue);
+};
diff --git a/packages/plasma-new-hope/src/components/Accordion/variations/_size/base.ts b/packages/plasma-new-hope/src/components/Accordion/variations/_size/base.ts
new file mode 100644
index 0000000000..cd585b76c4
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/variations/_size/base.ts
@@ -0,0 +1,3 @@
+import { css } from '@linaria/core';
+
+export const base = css``;
diff --git a/packages/plasma-new-hope/src/components/Accordion/variations/_size/tokens.json b/packages/plasma-new-hope/src/components/Accordion/variations/_size/tokens.json
new file mode 100644
index 0000000000..802d8646a9
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/variations/_size/tokens.json
@@ -0,0 +1,6 @@
+[
+ "--plasma-accordion-item-padding-vertical",
+ "--plasma-accordion-item-padding-horizontal",
+ "--plasma-accordion-item-gap",
+ "--plasma-accordion-item-border-radius"
+]
diff --git a/packages/plasma-new-hope/src/components/Accordion/variations/_stretching/base.ts b/packages/plasma-new-hope/src/components/Accordion/variations/_stretching/base.ts
new file mode 100644
index 0000000000..cd585b76c4
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/variations/_stretching/base.ts
@@ -0,0 +1,3 @@
+import { css } from '@linaria/core';
+
+export const base = css``;
diff --git a/packages/plasma-new-hope/src/components/Accordion/variations/_stretching/tokens.json b/packages/plasma-new-hope/src/components/Accordion/variations/_stretching/tokens.json
new file mode 100644
index 0000000000..fe51488c70
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/variations/_stretching/tokens.json
@@ -0,0 +1 @@
+[]
diff --git a/packages/plasma-new-hope/src/components/Accordion/variations/_view/base.ts b/packages/plasma-new-hope/src/components/Accordion/variations/_view/base.ts
new file mode 100644
index 0000000000..cd585b76c4
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/variations/_view/base.ts
@@ -0,0 +1,3 @@
+import { css } from '@linaria/core';
+
+export const base = css``;
diff --git a/packages/plasma-new-hope/src/components/Accordion/variations/_view/tokens.json b/packages/plasma-new-hope/src/components/Accordion/variations/_view/tokens.json
new file mode 100644
index 0000000000..205cee632c
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/Accordion/variations/_view/tokens.json
@@ -0,0 +1,8 @@
+[
+ "--plasma-accordion-width",
+ "--plasma-accordion-gap",
+ "--plasma-accordion-item-padding",
+ "--plasma-accordion-background",
+ "--plasma-accordion-item-background",
+ "--plasma-accordion-item-border-bottom"
+]
diff --git a/packages/plasma-new-hope/src/components/_Icon/Icon.assets/ChevronDownFill.tsx b/packages/plasma-new-hope/src/components/_Icon/Icon.assets/ChevronDownFill.tsx
new file mode 100644
index 0000000000..8290d80d5a
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/_Icon/Icon.assets/ChevronDownFill.tsx
@@ -0,0 +1,15 @@
+import React from 'react';
+
+import { IconProps } from '../IconRoot';
+
+export const ChevronDownFill: React.FC = (props) => (
+
+
+
+);
diff --git a/packages/plasma-new-hope/src/components/_Icon/Icon.assets/Minus.tsx b/packages/plasma-new-hope/src/components/_Icon/Icon.assets/Minus.tsx
new file mode 100644
index 0000000000..b0ab2a83ea
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/_Icon/Icon.assets/Minus.tsx
@@ -0,0 +1,13 @@
+import React from 'react';
+
+import { IconProps } from '../IconRoot';
+
+export const Minus: React.FC = (props) => (
+
+
+
+);
diff --git a/packages/plasma-new-hope/src/components/_Icon/Icons/IconChevronDownFill.tsx b/packages/plasma-new-hope/src/components/_Icon/Icons/IconChevronDownFill.tsx
new file mode 100644
index 0000000000..4fe3da595f
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/_Icon/Icons/IconChevronDownFill.tsx
@@ -0,0 +1,8 @@
+import React from 'react';
+
+import { ChevronDownFill } from '../Icon.assets/ChevronDownFill';
+import { IconRoot, IconProps } from '../IconRoot';
+
+export const IconChevronDownFill: React.FC = ({ size = 'xs', color, className }) => {
+ return ;
+};
diff --git a/packages/plasma-new-hope/src/components/_Icon/Icons/IconMinus.tsx b/packages/plasma-new-hope/src/components/_Icon/Icons/IconMinus.tsx
new file mode 100644
index 0000000000..e7911283eb
--- /dev/null
+++ b/packages/plasma-new-hope/src/components/_Icon/Icons/IconMinus.tsx
@@ -0,0 +1,8 @@
+import React from 'react';
+
+import { Minus } from '../Icon.assets/Minus';
+import { IconRoot, IconProps } from '../IconRoot';
+
+export const IconMinus: React.FC = ({ size = 's', color, className }) => {
+ return ;
+};
diff --git a/packages/plasma-new-hope/src/components/_Icon/index.tsx b/packages/plasma-new-hope/src/components/_Icon/index.tsx
index a386e46458..cf8b1e70a0 100644
--- a/packages/plasma-new-hope/src/components/_Icon/index.tsx
+++ b/packages/plasma-new-hope/src/components/_Icon/index.tsx
@@ -4,6 +4,8 @@ export { IconMic } from './Icons/IconMic';
export { IconChevronLeft } from './Icons/IconChevronLeft';
export { IconChevronDoubleLeft } from './Icons/IconChevronDoubleLeft';
export { IconChevronDown } from './Icons/IconChevronDown';
+export { IconChevronDownFill } from './Icons/IconChevronDownFill';
export { IconClose } from './Icons/IconClose';
export { IconCross } from './Icons/IconCross';
export { IconDone } from './Icons/IconDone';
+export { IconMinus } from './Icons/IconMinus';
diff --git a/packages/plasma-new-hope/src/examples/plasma_b2c/components/Accordion/Accordion.config.ts b/packages/plasma-new-hope/src/examples/plasma_b2c/components/Accordion/Accordion.config.ts
new file mode 100644
index 0000000000..f2b295d92f
--- /dev/null
+++ b/packages/plasma-new-hope/src/examples/plasma_b2c/components/Accordion/Accordion.config.ts
@@ -0,0 +1,122 @@
+import { css } from '@linaria/core';
+
+import { accordionTokens } from '../../../../components/Accordion';
+
+export const config = {
+ defaults: {
+ view: 'default',
+ size: 'm',
+ },
+ variations: {
+ view: {
+ default: css`
+ ${accordionTokens.accordionGap}: 0.125rem;
+ ${accordionTokens.accordionWidth}: 20rem;
+ ${accordionTokens.accordionItemPadding}: var(${accordionTokens.accordionItemPaddingVertical}) var(${accordionTokens.accordionItemPaddingHorizontal});
+ ${accordionTokens.accordionItemBackground}: var(--surface-solid-card);
+ ${accordionTokens.accordionItemTitleColor}: var(--text-primary);
+ ${accordionTokens.accordionItemTextColor}: var(--text-primary);
+ ${accordionTokens.accordionItemFocus}: var(--surface-accent);
+ ${accordionTokens.accordionBackground}: var(--surface-clear);
+ ${accordionTokens.accordionItemBorderBottom}: 0;
+ `,
+ clear: css`
+ ${accordionTokens.accordionGap}: 0;
+ ${accordionTokens.accordionWidth}: 20rem;
+ ${accordionTokens.accordionItemPadding}: var(${accordionTokens.accordionItemPaddingVertical}) 0rem;
+ ${accordionTokens.accordionItemBackground}: var(--surface-clear);
+ ${accordionTokens.accordionItemTitleColor}: var(--text-primary);
+ ${accordionTokens.accordionItemTextColor}: var(--text-primary);
+ ${accordionTokens.accordionItemFocus}: var(--surface-accent);
+ ${accordionTokens.accordionItemBorderRadius}: 0rem !important;
+ ${accordionTokens.accordionBackground}: var(--surface-clear);
+ ${accordionTokens.accordionItemBorderBottom}: 0.125rem solid var(--surface-solid-tertiary);
+ `,
+ },
+ size: {
+ l: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 1.0625rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 1.25rem;
+ ${accordionTokens.accordionItemGap}: 0.5rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.875rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-l-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-l-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-l-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-l-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-l-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-l-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-l-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-l-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-l-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-l-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-l-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-l-line-height);
+ `,
+ m: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 0.875rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 1.125rem;
+
+ ${accordionTokens.accordionItemGap}: 0.375rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.75rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-m-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-m-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-m-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-m-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-m-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-m-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-m-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-m-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-m-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-m-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-m-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-m-line-height);
+ `,
+ s: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 0.6875rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 0.875rem;
+
+ ${accordionTokens.accordionItemGap}: 0.375rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.625rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-s-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-s-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-s-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-s-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-s-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-s-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-s-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-s-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-s-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-s-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-s-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-s-line-height);
+ `,
+ xs: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 0.5rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 0.75rem;
+
+ ${accordionTokens.accordionItemGap}: 0.25rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.5rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-xs-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-xs-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-xs-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-xs-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-xs-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-xs-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-xs-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-xs-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-xs-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-xs-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-xs-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-xs-line-height);
+ `,
+ },
+ },
+};
diff --git a/packages/plasma-new-hope/src/examples/plasma_b2c/components/Accordion/Accordion.stories.tsx b/packages/plasma-new-hope/src/examples/plasma_b2c/components/Accordion/Accordion.stories.tsx
new file mode 100644
index 0000000000..6f113abdf9
--- /dev/null
+++ b/packages/plasma-new-hope/src/examples/plasma_b2c/components/Accordion/Accordion.stories.tsx
@@ -0,0 +1,66 @@
+import * as React from 'react';
+import type { ComponentProps } from 'react';
+import type { StoryObj, Meta } from '@storybook/react';
+import { disableProps } from '@salutejs/plasma-sb-utils';
+
+import { mergeConfig } from '../../../../engines';
+import { WithTheme, argTypesFromConfig } from '../../../_helpers';
+import { accordionConfig } from '../../../../components/Accordion';
+
+import { config } from './Accordion.config';
+import { Accordion, AccordionItem } from './Accordion';
+
+const meta: Meta = {
+ title: 'plasma_b2c/Accordion',
+ decorators: [WithTheme],
+ component: Accordion,
+ args: {
+ singleActive: false,
+ view: 'default',
+ size: 'm',
+ stretching: 'filled',
+ type: 'arrow',
+ disabled: false,
+ title: 'Как оплатить заправку бонусами СберСпасибо?',
+ body:
+ 'После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива',
+ },
+ argTypes: {
+ ...argTypesFromConfig(mergeConfig(accordionConfig, config)),
+ ...disableProps(['text']),
+ stretching: {
+ options: ['filled', 'fixed'],
+ control: {
+ type: 'select',
+ },
+ },
+ type: {
+ options: ['arrow', 'sign', 'clear'],
+ control: {
+ type: 'select',
+ },
+ },
+ },
+};
+
+export default meta;
+
+export const Default: StoryObj> = {
+ render: (props: ComponentProps) => {
+ const args = { ...props, text: undefined };
+
+ return (
+
+
+ {args.body}
+
+
+ {args.body}
+
+
+ {args.body}
+
+
+ );
+ },
+};
diff --git a/packages/plasma-new-hope/src/examples/plasma_b2c/components/Accordion/Accordion.ts b/packages/plasma-new-hope/src/examples/plasma_b2c/components/Accordion/Accordion.ts
new file mode 100644
index 0000000000..fbae3a6c54
--- /dev/null
+++ b/packages/plasma-new-hope/src/examples/plasma_b2c/components/Accordion/Accordion.ts
@@ -0,0 +1,9 @@
+import { accordionConfig, AccordionItem } from '../../../../components/Accordion';
+import { component, mergeConfig } from '../../../../engines';
+
+import { config } from './Accordion.config';
+
+const mergedConfig = mergeConfig(accordionConfig, config);
+
+export const Accordion = component(mergedConfig);
+export { AccordionItem };
diff --git a/packages/plasma-new-hope/src/examples/plasma_web/components/Accordion/Accordion.config.ts b/packages/plasma-new-hope/src/examples/plasma_web/components/Accordion/Accordion.config.ts
new file mode 100644
index 0000000000..8282213aa6
--- /dev/null
+++ b/packages/plasma-new-hope/src/examples/plasma_web/components/Accordion/Accordion.config.ts
@@ -0,0 +1,123 @@
+import { css } from '@linaria/core';
+
+import { accordionTokens } from '../../../../components/Accordion';
+
+export const config = {
+ defaults: {
+ view: 'default',
+ size: 'm',
+ },
+ variations: {
+ view: {
+ default: css`
+ ${accordionTokens.accordionGap}: 0.125rem;
+ ${accordionTokens.accordionWidth}: 20rem;
+ ${accordionTokens.accordionItemPadding}: var(${accordionTokens.accordionItemPaddingVertical}) var(${accordionTokens.accordionItemPaddingHorizontal});
+ ${accordionTokens.accordionItemBackground}: var(--surface-solid-card);
+ ${accordionTokens.accordionItemTitleColor}: var(--text-primary);
+ ${accordionTokens.accordionItemTextColor}: var(--text-primary);
+ ${accordionTokens.accordionItemFocus}: var(--surface-accent);
+ ${accordionTokens.accordionBackground}: var(--surface-clear);
+ ${accordionTokens.accordionItemBorderBottom}: 0;
+ `,
+ clear: css`
+ ${accordionTokens.accordionGap}: 0.125rem;
+ ${accordionTokens.accordionWidth}: 20rem;
+ ${accordionTokens.accordionItemPadding}: var(${accordionTokens.accordionItemPaddingVertical}) 0rem;
+ ${accordionTokens.accordionItemBackground}: var(--surface-clear);
+ ${accordionTokens.accordionItemTitleColor}: var(--text-primary);
+ ${accordionTokens.accordionItemTextColor}: var(--text-primary);
+ ${accordionTokens.accordionItemFocus}: var(--surface-accent);
+ ${accordionTokens.accordionItemBorderRadius}: 0rem !important;
+ ${accordionTokens.accordionBackground}: var(--surface-clear);
+ ${accordionTokens.accordionItemBorderBottom}: 0.125rem solid var(--surface-solid-tertiary);
+ `,
+ },
+ size: {
+ l: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 1.0625rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 1.25rem;
+ ${accordionTokens.accordionItemGap}: 0.5rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.875rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-l-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-l-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-l-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-l-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-l-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-l-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-l-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-l-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-l-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-l-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-l-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-l-line-height);
+ `,
+ m: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 0.875rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 1.125rem;
+ ${accordionTokens.accordionItemGap}: 0.375rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.75rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-m-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-m-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-m-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-m-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-m-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-m-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-m-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-m-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-m-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-m-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-m-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-m-line-height);
+ `,
+ s: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 0.6875rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 0.875rem;
+ ${accordionTokens.accordionItemGap}: 0.375rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.625rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-s-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-s-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-s-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-s-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-s-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-s-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-s-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-s-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-s-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-s-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-s-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-s-line-height);
+ `,
+ xs: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 0.5rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 0.75rem;
+ ${accordionTokens.accordionItemGap}: 0.25rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.5rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-xs-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-xs-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-xs-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-xs-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-xs-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-xs-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-xs-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-xs-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-xs-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-xs-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-xs-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-xs-line-height);
+ `,
+ },
+ stretching: {
+ filled: css``,
+ fixed: css``,
+ },
+ },
+};
diff --git a/packages/plasma-new-hope/src/examples/plasma_web/components/Accordion/Accordion.stories.tsx b/packages/plasma-new-hope/src/examples/plasma_web/components/Accordion/Accordion.stories.tsx
new file mode 100644
index 0000000000..68bc73a979
--- /dev/null
+++ b/packages/plasma-new-hope/src/examples/plasma_web/components/Accordion/Accordion.stories.tsx
@@ -0,0 +1,65 @@
+import * as React from 'react';
+import type { ComponentProps } from 'react';
+import type { StoryObj, Meta } from '@storybook/react';
+import { disableProps } from '@salutejs/plasma-sb-utils';
+
+import { mergeConfig } from '../../../../engines';
+import { WithTheme, argTypesFromConfig } from '../../../_helpers';
+import { accordionConfig } from '../../../../components/Accordion';
+
+import { config } from './Accordion.config';
+import { Accordion, AccordionItem } from './Accordion';
+
+const meta: Meta = {
+ title: 'plasma_web/Accordion',
+ decorators: [WithTheme],
+ component: Accordion,
+ args: {
+ singleActive: false,
+ view: 'default',
+ size: 'm',
+ stretching: 'filled',
+ type: 'arrow',
+ title: 'Как оплатить заправку бонусами СберСпасибо?',
+ body:
+ 'После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива',
+ },
+ argTypes: {
+ ...argTypesFromConfig(mergeConfig(accordionConfig, config)),
+ ...disableProps(['text']),
+ stretching: {
+ options: ['filled', 'fixed'],
+ control: {
+ type: 'select',
+ },
+ },
+ type: {
+ options: ['arrow', 'sign', 'clear'],
+ control: {
+ type: 'select',
+ },
+ },
+ },
+};
+
+export default meta;
+
+export const Default: StoryObj> = {
+ render: (props: ComponentProps) => {
+ const args = { ...props, text: undefined };
+
+ return (
+
+
+ {args.body}
+
+
+ {args.body}
+
+
+ {args.body}
+
+
+ );
+ },
+};
diff --git a/packages/plasma-new-hope/src/examples/plasma_web/components/Accordion/Accordion.ts b/packages/plasma-new-hope/src/examples/plasma_web/components/Accordion/Accordion.ts
new file mode 100644
index 0000000000..fbae3a6c54
--- /dev/null
+++ b/packages/plasma-new-hope/src/examples/plasma_web/components/Accordion/Accordion.ts
@@ -0,0 +1,9 @@
+import { accordionConfig, AccordionItem } from '../../../../components/Accordion';
+import { component, mergeConfig } from '../../../../engines';
+
+import { config } from './Accordion.config';
+
+const mergedConfig = mergeConfig(accordionConfig, config);
+
+export const Accordion = component(mergedConfig);
+export { AccordionItem };
diff --git a/packages/plasma-new-hope/src/index.ts b/packages/plasma-new-hope/src/index.ts
index 79922ab55b..f66d520310 100644
--- a/packages/plasma-new-hope/src/index.ts
+++ b/packages/plasma-new-hope/src/index.ts
@@ -48,3 +48,4 @@ export * from './components/Divider';
export * from './components/Toolbar';
export * from './components/Slider';
export * from './components/Range';
+export * from './components/Accordion';
diff --git a/packages/plasma-web/api/plasma-web.api.md b/packages/plasma-web/api/plasma-web.api.md
index af9e27202d..af0062b310 100644
--- a/packages/plasma-web/api/plasma-web.api.md
+++ b/packages/plasma-web/api/plasma-web.api.md
@@ -6,6 +6,8 @@
///
+import { AccordionItem } from '@salutejs/plasma-new-hope/styled-components';
+import { AccordionProps } from '@salutejs/plasma-new-hope/styled-components';
import { addFocus } from '@salutejs/plasma-core';
import { addNotification } from '@salutejs/plasma-new-hope/styled-components';
import { AlignProp } from '@salutejs/plasma-new-hope/types/components/Cell/Cell.types';
@@ -279,6 +281,38 @@ import { WithAutoFocusProps } from '@salutejs/plasma-core';
import { withSkeleton } from '@salutejs/plasma-new-hope/styled-components';
import { WithSkeletonProps } from '@salutejs/plasma-new-hope/styled-components';
+// @public
+export const Accordion: FunctionComponent & {
+view: string;
+size?: string | undefined;
+singleActive?: boolean | undefined;
+defaultActiveEventKey?: number[] | undefined;
+disabled?: boolean | undefined;
+stretching?: "fixed" | "filled" | undefined;
+onChange?: ((index?: number | undefined, value?: boolean | undefined) => void) | undefined;
+children?: ReactNode;
+className?: string | undefined;
+} & RefAttributes>;
+
+export { AccordionItem }
+
+export { AccordionProps }
+
export { addFocus }
export { addNotification }
@@ -826,11 +860,11 @@ l: string;
view: {
default: string;
};
-}> & ((Omit, "onChange" | "value" | "type" | "target" | "size" | "checked" | "minLength" | "maxLength"> & CustomComboboxProps & {
+}> & ((Omit, "onChange" | "size" | "value" | "type" | "target" | "checked" | "minLength" | "maxLength"> & CustomComboboxProps & {
valueType?: "single" | undefined;
value?: ComboboxPrimitiveValue | undefined;
onChangeValue?: ((value?: ComboboxPrimitiveValue | undefined) => void) | undefined;
-} & RefAttributes) | (Omit, "onChange" | "value" | "type" | "target" | "size" | "checked" | "minLength" | "maxLength"> & CustomComboboxProps & {
+} & RefAttributes) | (Omit, "onChange" | "size" | "value" | "type" | "target" | "checked" | "minLength" | "maxLength"> & CustomComboboxProps & {
valueType: "multiple";
value?: ComboboxPrimitiveValue[] | undefined;
onChangeValue?: ((value?: ComboboxPrimitiveValue[] | undefined) => void) | undefined;
diff --git a/packages/plasma-web/src/components/Accordion/Accordion.component-test.tsx b/packages/plasma-web/src/components/Accordion/Accordion.component-test.tsx
new file mode 100644
index 0000000000..82777d9ea5
--- /dev/null
+++ b/packages/plasma-web/src/components/Accordion/Accordion.component-test.tsx
@@ -0,0 +1,114 @@
+import React from 'react';
+import type { FC, PropsWithChildren } from 'react';
+import { CypressTestDecorator, getComponent, mount, PadMe } from '@salutejs/plasma-cy-utils';
+import { standard as standardTypo } from '@salutejs/plasma-typo';
+import { createGlobalStyle } from 'styled-components';
+
+const StandardTypoStyle = createGlobalStyle(standardTypo);
+
+describe('plasma-web: Accordion', () => {
+ const Accordion = getComponent('Accordion');
+ const AccordionItem = getComponent('AccordionItem');
+
+ const title = 'Как оплатить заправку бонусами СберСпасибо?';
+ const body =
+ 'После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топливa';
+
+ const CypressTestDecoratorWithTypo: FC = ({ children }) => (
+
+
+ {children}
+
+ );
+
+ it('simple', () => {
+ mount(
+
+
+ {body}
+
+ ,
+ );
+ cy.matchImageSnapshot();
+ });
+
+ it('_view:clear', () => {
+ mount(
+
+
+ {body}
+ {body}
+
+ ,
+ );
+ cy.matchImageSnapshot();
+ });
+
+ it('_size', () => {
+ mount(
+
+
+ {body}
+
+ {body}
+
+
+
+
+ {body}
+
+ {body}
+
+
+
+
+ {body}
+
+ {body}
+
+
+
+
+ {body}
+
+ {body}
+
+
+
+ ,
+ );
+ cy.matchImageSnapshot();
+ });
+
+ it('_type', () => {
+ mount(
+
+
+
+ {body}
+
+
+ {body}
+
+
+ {body}
+
+
+ ,
+ );
+ cy.matchImageSnapshot();
+ });
+
+ it('animation', () => {
+ mount(
+
+
+ {body}
+
+ ,
+ );
+
+ cy.get('.accordion-root').last().trigger('click', { waitForAnimations: true });
+ cy.matchImageSnapshot();
+ });
+});
diff --git a/packages/plasma-web/src/components/Accordion/Accordion.config.ts b/packages/plasma-web/src/components/Accordion/Accordion.config.ts
new file mode 100644
index 0000000000..4818c3cb31
--- /dev/null
+++ b/packages/plasma-web/src/components/Accordion/Accordion.config.ts
@@ -0,0 +1,121 @@
+import { css, accordionTokens } from '@salutejs/plasma-new-hope/styled-components';
+
+export const config = {
+ defaults: {
+ view: 'default',
+ size: 'm',
+ },
+ variations: {
+ view: {
+ default: css`
+ ${accordionTokens.accordionGap}: 0.125rem;
+ ${accordionTokens.accordionWidth}: 20rem;
+ ${accordionTokens.accordionItemPadding}: var(${accordionTokens.accordionItemPaddingVertical}) var(${accordionTokens.accordionItemPaddingHorizontal});
+ ${accordionTokens.accordionItemBackground}: var(--surface-solid-card);
+ ${accordionTokens.accordionItemTitleColor}: var(--text-primary);
+ ${accordionTokens.accordionItemTextColor}: var(--text-primary);
+ ${accordionTokens.accordionItemFocus}: var(--surface-accent);
+ ${accordionTokens.accordionBackground}: var(--surface-clear);
+ ${accordionTokens.accordionItemBorderBottom}: 0;
+ `,
+ clear: css`
+ ${accordionTokens.accordionGap}: 0.125rem;
+ ${accordionTokens.accordionWidth}: 20rem;
+ ${accordionTokens.accordionItemPadding}: var(${accordionTokens.accordionItemPaddingVertical}) 0rem;
+ ${accordionTokens.accordionItemBackground}: var(--surface-clear);
+ ${accordionTokens.accordionItemTitleColor}: var(--text-primary);
+ ${accordionTokens.accordionItemTextColor}: var(--text-primary);
+ ${accordionTokens.accordionItemFocus}: var(--surface-accent);
+ ${accordionTokens.accordionItemBorderRadius}: 0rem !important;
+ ${accordionTokens.accordionBackground}: var(--surface-clear);
+ ${accordionTokens.accordionItemBorderBottom}: 0.125rem solid var(--surface-solid-tertiary);
+ `,
+ },
+ size: {
+ l: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 1.0625rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 1.25rem;
+ ${accordionTokens.accordionItemGap}: 0.5rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.875rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-l-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-l-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-l-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-l-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-l-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-l-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-l-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-l-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-l-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-l-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-l-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-l-line-height);
+ `,
+ m: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 0.875rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 1.125rem;
+ ${accordionTokens.accordionItemGap}: 0.375rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.75rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-m-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-m-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-m-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-m-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-m-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-m-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-m-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-m-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-m-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-m-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-m-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-m-line-height);
+ `,
+ s: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 0.6875rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 0.875rem;
+ ${accordionTokens.accordionItemGap}: 0.375rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.625rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-s-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-s-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-s-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-s-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-s-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-s-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-s-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-s-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-s-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-s-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-s-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-s-line-height);
+ `,
+ xs: css`
+ ${accordionTokens.accordionItemPaddingVertical}: 0.5rem;
+ ${accordionTokens.accordionItemPaddingHorizontal}: 0.75rem;
+ ${accordionTokens.accordionItemGap}: 0.25rem;
+ ${accordionTokens.accordionItemBorderRadius}: 0.5rem;
+
+ ${accordionTokens.accordionItemTitleFontFamily}: var(--plasma-typo-body-xs-font-family);
+ ${accordionTokens.accordionItemTitleFontSize}: var(--plasma-typo-body-xs-font-size);
+ ${accordionTokens.accordionItemTitleFontStyle}: var(--plasma-typo-body-xs-font-style);
+ ${accordionTokens.accordionItemTitleFontWeight}: var(--plasma-typo-body-xs-bold-font-weight);
+ ${accordionTokens.accordionItemTitleLetterSpacing}: var(--plasma-typo-body-xs-letter-spacing);
+ ${accordionTokens.accordionItemTitleLineHeight}: var(--plasma-typo-body-xs-line-height);
+
+ ${accordionTokens.accordionItemTextFontFamily}: var(--plasma-typo-body-xs-font-family);
+ ${accordionTokens.accordionItemTextFontSize}: var(--plasma-typo-body-xs-font-size);
+ ${accordionTokens.accordionItemTextFontStyle}: var(--plasma-typo-body-xs-font-style);
+ ${accordionTokens.accordionItemTextFontWeight}: var(--plasma-typo-body-xs-font-weight);
+ ${accordionTokens.accordionItemTextLetterSpacing}: var(--plasma-typo-body-xs-letter-spacing);
+ ${accordionTokens.accordionItemTextLineHeight}: var(--plasma-typo-body-xs-line-height);
+ `,
+ },
+ stretching: {
+ filled: css``,
+ fixed: css``,
+ },
+ },
+};
diff --git a/packages/plasma-web/src/components/Accordion/Accordion.stories.tsx b/packages/plasma-web/src/components/Accordion/Accordion.stories.tsx
new file mode 100644
index 0000000000..7c9abfa2f3
--- /dev/null
+++ b/packages/plasma-web/src/components/Accordion/Accordion.stories.tsx
@@ -0,0 +1,58 @@
+import * as React from 'react';
+import type { ComponentProps } from 'react';
+import type { StoryObj, Meta } from '@storybook/react';
+import { disableProps } from '@salutejs/plasma-sb-utils';
+
+import { Accordion, AccordionItem } from '.';
+
+const meta: Meta = {
+ title: 'Content/Accordion',
+ component: Accordion,
+ args: {
+ singleActive: false,
+ view: 'default',
+ size: 'm',
+ stretching: 'filled',
+ type: 'arrow',
+ title: 'Как оплатить заправку бонусами СберСпасибо?',
+ body:
+ 'После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива',
+ },
+ argTypes: {
+ ...disableProps(['text']),
+ stretching: {
+ options: ['filled', 'fixed'],
+ control: {
+ type: 'select',
+ },
+ },
+ type: {
+ options: ['arrow', 'sign', 'clear'],
+ control: {
+ type: 'select',
+ },
+ },
+ },
+};
+
+export default meta;
+
+export const Default: StoryObj> = {
+ render: (props: ComponentProps) => {
+ const args = { ...props, text: undefined };
+
+ return (
+
+
+ {args.body}
+
+
+ {args.body}
+
+
+ {args.body}
+
+
+ );
+ },
+};
diff --git a/packages/plasma-web/src/components/Accordion/Accordion.tsx b/packages/plasma-web/src/components/Accordion/Accordion.tsx
new file mode 100644
index 0000000000..d56bbf45e0
--- /dev/null
+++ b/packages/plasma-web/src/components/Accordion/Accordion.tsx
@@ -0,0 +1,11 @@
+import { accordionConfig, component, mergeConfig } from '@salutejs/plasma-new-hope/styled-components';
+
+import { config } from './Accordion.config';
+
+const mergedConfig = mergeConfig(accordionConfig, config);
+const AccordionComponent = component(mergedConfig);
+
+/**
+ * Accordion
+ */
+export const Accordion = AccordionComponent;
diff --git a/packages/plasma-web/src/components/Accordion/index.ts b/packages/plasma-web/src/components/Accordion/index.ts
new file mode 100644
index 0000000000..8a291f450d
--- /dev/null
+++ b/packages/plasma-web/src/components/Accordion/index.ts
@@ -0,0 +1,4 @@
+export { AccordionItem } from '@salutejs/plasma-new-hope/styled-components';
+export { Accordion } from './Accordion';
+
+export type { AccordionProps } from '@salutejs/plasma-new-hope/styled-components';
diff --git a/packages/plasma-web/src/index.ts b/packages/plasma-web/src/index.ts
index 7b163a8a86..d31e26e420 100644
--- a/packages/plasma-web/src/index.ts
+++ b/packages/plasma-web/src/index.ts
@@ -1,3 +1,4 @@
+export * from './components/Accordion';
export * from './components/AudioPlayer';
export * from './components/Badge';
export * from './components/Button';
diff --git a/website/plasma-web-docs/docs/components/Accordion.mdx b/website/plasma-web-docs/docs/components/Accordion.mdx
new file mode 100644
index 0000000000..794ace7554
--- /dev/null
+++ b/website/plasma-web-docs/docs/components/Accordion.mdx
@@ -0,0 +1,238 @@
+---
+id: accordion
+title: Accordion
+---
+
+import { PropsTable, Description, StorybookLink } from '@site/src/components';
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+
+# Accordion
+Компонент выпадающей информации
+
+
+
+# AccordionItem
+Компонент выпадающей информации
+
+
+
+Компонент представляет собой заголовок и контент, который раскрывается при нажатии.
+
+## Примеры Accordion
+
+
+
+ ```tsx live
+ import React from 'react';
+ import { Accordion, AccordionItem } from '@salutejs/plasma-web';
+
+ export function App() {
+ return (
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+ );
+ }
+ ```
+
+
+ ```tsx live
+ import React from 'react';
+ import { Accordion, AccordionItem } from '@salutejs/plasma-web';
+
+ export function App() {
+ return (
+
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+
+ );
+ }
+ ```
+
+
+ ```tsx live
+ import React from 'react';
+ import { Accordion, AccordionItem } from '@salutejs/plasma-web';
+
+ export function App() {
+ return (
+
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+
+ );
+ }
+ ```
+
+
+ ```tsx live
+ import React from 'react';
+ import { Accordion, AccordionItem } from '@salutejs/plasma-web';
+
+ export function App() {
+ return (
+
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+
+ );
+ }
+ ```
+
+
+
+### Использование Accorion SignleActive
+
+```tsx live
+ import React from 'react';
+ import { Accordion, AccordionItem } from '@salutejs/plasma-web';
+
+ export function App() {
+ return (
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+ );
+ }
+ ```
+
+### Использование Accorion с eventKey и defaultActiveEventKey
+
+```tsx live
+ import React from 'react';
+ import { Accordion, AccordionItem } from '@salutejs/plasma-web';
+
+ export function App() {
+ return (
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+ );
+ }
+ ```
+
+
+### Использование AccorionItem атрибута Type
+
+
+
+ ```tsx live
+ import React from 'react';
+ import { Accordion, AccordionItem } from '@salutejs/plasma-web';
+
+ export function App() {
+ return (
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+ );
+ }
+ ```
+
+
+ ```tsx live
+ import React from 'react';
+ import { Accordion, AccordionItem } from '@salutejs/plasma-web';
+
+ export function App() {
+ return (
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+ );
+ }
+ ```
+
+
+ ```tsx live
+ import React from 'react';
+ import { Accordion, AccordionItem } from '@salutejs/plasma-web';
+
+ export function App() {
+ return (
+
+
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+ После указания деталей заправки нажмите кнопку «К оплате». Откроется окно оплаты, где вы сможете списать бонусы и оплатить ими до 99% стоимости топлива
+
+
+ );
+ }
+ ```
+
+
+