Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/components/ToggleArrow/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# ToggleArrow

`type: "toggle-arrow"`

The **ToggleArrow** component is a small, animated arrow icon used for collapsible sections, navigation panels, and accordions.

---

## 🔧 Props

| Prop | Type | Default | Description |
| ----------- | ---------------------------- | -------------- | --------------------------------------------- |
| `type` | `'horizontal' \| 'vertical'` | `'horizontal'` | Orientation of the arrow. |
| `iconType` | `'default' \| 'navigation'` | `'default'` | Visual icon variant. |
| `open` | `boolean` | `false` | Whether the arrow is in open (rotated) state. |
| `size` | `number` | `16` | Icon size in pixels. |
| `thin` | `boolean` | `false` | Thinner stroke style. |
| `slow` | `boolean` | `false` | Slower transition animation. |
| `className` | `string` | — | Optional custom CSS class. |

---

## 🧩 Example

```tsx
<ToggleArrow type="vertical" iconType="navigation" open size={24} thin slow />
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 8 additions & 9 deletions src/components/ToggleArrow/__stories__/ToggleArrow.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {Meta} from '@storybook/blocks';

import {StoryTemplate} from '../../../demo/StoryTemplate.mdx';
import * as ToggleArrowStories from './ToggleArrow.stories.tsx';

Expand All @@ -8,22 +7,22 @@ import * as ToggleArrowStories from './ToggleArrow.stories.tsx';

## Usage

For a detailed usage guide of the ToggleArrow component, see [ToggleArrow Usage](https://github.com/gravity-ui/page-constructor/blob/main/memory-bank/usage/toggleArrow.md).
For a detailed usage guide of the **ToggleArrow** component, see [ToggleArrow Usage](https://github.com/gravity-ui/page-constructor/blob/main/memory-bank/usage/toggleArrow.md).

## Parameters

`type?: 'horizontal' | 'vertical'` — Arrow orientation (default: 'horizontal')
`type?: 'horizontal' | 'vertical'` — Arrow orientation (default: `'horizontal'`)

`iconType?: 'default' | 'navigation'` — Icon variant (default: 'default')
`iconType?: 'default' | 'navigation'` — Icon variant (default: `'default'`)

`open?: boolean` — Boolean indicating if the toggle is in open state (default: false)
`open?: boolean` — Indicates whether the toggle is in an open state (default: `false`)

`size?: number` — Icon size in pixels (default: 16)
`size?: number` — Icon size in pixels (default: `16`)

`thin?: boolean` — Boolean for thinner stroke width (default: false)
`thin?: boolean` — Enables a thinner stroke width (default: `false`)

`slow?: boolean` — Boolean for slower animation duration (default: false)
`slow?: boolean` — Slows down animation (default: `false`)

`className?: string` — Optional CSS class name
`className?: string` — Optional CSS class name for the wrapper

</StoryTemplate>
63 changes: 57 additions & 6 deletions src/components/ToggleArrow/__stories__/ToggleArrow.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,69 @@
import {Meta, StoryFn} from '@storybook/react';
import {Meta, StoryFn, StoryObj} from '@storybook/react';

import {blockTransform} from '../../../../.storybook/utils';
import {CustomBlock} from '../../../models';
import ToggleArrow, {ToggleArrowProps} from '../ToggleArrow';

import data from './data.json';

export default {
component: ToggleArrow,
title: 'Components/ToggleArrow',
} as Meta;
component: ToggleArrow,
parameters: {
layout: 'centered',
controls: {expanded: true},
},
} as Meta<typeof ToggleArrow>;

const DefaultTemplate: StoryFn<ToggleArrowProps> = (args) => <ToggleArrow {...args} />;
const Template: StoryFn<ToggleArrowProps> = (args) => (
<ToggleArrow {...(blockTransform(args as unknown as CustomBlock) as ToggleArrowProps)} />
);

export const Horizontal = DefaultTemplate.bind({});
export const Vertical = DefaultTemplate.bind({});
export const Default: StoryObj<typeof ToggleArrow> = Template.bind({});
export const Horizontal: StoryObj<typeof ToggleArrow> = Template.bind({});
export const Vertical: StoryObj<typeof ToggleArrow> = Template.bind({});
export const OpenHorizontal: StoryObj<typeof ToggleArrow> = Template.bind({});
export const OpenVertical: StoryObj<typeof ToggleArrow> = Template.bind({});
export const Thin: StoryObj<typeof ToggleArrow> = Template.bind({});
export const Slow: StoryObj<typeof ToggleArrow> = Template.bind({});
export const ThinSlow: StoryObj<typeof ToggleArrow> = Template.bind({});
export const NavigationIcon: StoryObj<typeof ToggleArrow> = Template.bind({});
export const AllVariants: StoryObj<typeof ToggleArrow> = Template.bind({});

Default.args = {type: 'horizontal', iconType: 'default', size: 24};
Horizontal.args = data.horizontal.content as ToggleArrowProps;
Vertical.args = data.vertical.content as ToggleArrowProps;
OpenHorizontal.args = {type: 'horizontal', open: true, size: 24};
OpenVertical.args = {type: 'vertical', open: true, size: 24};
Thin.args = {type: 'horizontal', thin: true, size: 24};
Slow.args = {type: 'horizontal', slow: true, size: 24};
ThinSlow.args = {type: 'horizontal', thin: true, slow: true, size: 24};
NavigationIcon.args = {type: 'horizontal', iconType: 'navigation', size: 30};

AllVariants.args = {};
AllVariants.decorators = [
() => (
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(4, auto)',
gap: '24px',
alignItems: 'center',
justifyContent: 'center',
}}
>
<ToggleArrow type="horizontal" />
<ToggleArrow type="horizontal" open />
<ToggleArrow type="vertical" />
<ToggleArrow type="vertical" open />
<ToggleArrow type="horizontal" thin />
<ToggleArrow type="horizontal" thin open />
<ToggleArrow type="horizontal" slow />
<ToggleArrow type="horizontal" slow open />
<ToggleArrow type="horizontal" iconType="navigation" />
<ToggleArrow type="horizontal" iconType="navigation" open />
<ToggleArrow type="vertical" iconType="navigation" />
<ToggleArrow type="vertical" iconType="navigation" open />
</div>
),
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {composeStories} from '@storybook/react';

import {test} from '../../../../playwright/core/index';
import * as ToggleArrowStories from '../__stories__/ToggleArrow.stories';

const {
Default,
Horizontal,
Vertical,
OpenHorizontal,
OpenVertical,
Thin,
Slow,
ThinSlow,
NavigationIcon,
AllVariants,
} = composeStories(ToggleArrowStories);

test.describe('ToggleArrow', () => {
test('render <Default>', async ({mount, expectScreenshot, defaultDelay}) => {
await mount(<Default />);
await defaultDelay();
await expectScreenshot({skipTheme: 'dark'});
});

test('render <Horizontal>', async ({mount, expectScreenshot, defaultDelay}) => {
await mount(<Horizontal />);
await defaultDelay();
await expectScreenshot({skipTheme: 'dark'});
});

test('render <Vertical>', async ({mount, expectScreenshot, defaultDelay}) => {
await mount(<Vertical />);
await defaultDelay();
await expectScreenshot({skipTheme: 'dark'});
});

test('render <OpenHorizontal>', async ({mount, expectScreenshot, defaultDelay}) => {
await mount(<OpenHorizontal />);
await defaultDelay();
await expectScreenshot({skipTheme: 'dark'});
});

test('render <OpenVertical>', async ({mount, expectScreenshot, defaultDelay}) => {
await mount(<OpenVertical />);
await defaultDelay();
await expectScreenshot({skipTheme: 'dark'});
});

test('render <Thin>', async ({mount, expectScreenshot, defaultDelay}) => {
await mount(<Thin />);
await defaultDelay();
await expectScreenshot({skipTheme: 'dark'});
});

test('render <Slow>', async ({mount, expectScreenshot, defaultDelay}) => {
await mount(<Slow />);
await defaultDelay();
await expectScreenshot({skipTheme: 'dark'});
});

test('render <ThinSlow>', async ({mount, expectScreenshot, defaultDelay}) => {
await mount(<ThinSlow />);
await defaultDelay();
await expectScreenshot({skipTheme: 'dark'});
});

test('render <NavigationIcon>', async ({mount, expectScreenshot, defaultDelay}) => {
await mount(<NavigationIcon />);
await defaultDelay();
await expectScreenshot({skipTheme: 'dark'});
});

test('render <AllVariants>', async ({mount, expectScreenshot, defaultDelay}) => {
await mount(<AllVariants />);
await defaultDelay();
await expectScreenshot({skipTheme: 'dark'});
});
});
Loading