Skip to content

Commit

Permalink
feat(collapse): add component
Browse files Browse the repository at this point in the history
  • Loading branch information
redzumi committed Dec 21, 2020
1 parent 0499ae9 commit eea2a52
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 0 deletions.
20 changes: 20 additions & 0 deletions packages/collapse/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "@alfalab/core-components-collapse",
"version": "0.0.1",
"description": "",
"keywords": [],
"license": "ISC",
"main": "dist/index.js",
"files": [
"dist"
],
"publishConfig": {
"access": "public"
},
"peerDependencies": {
"react": "^16.9.0"
},
"dependencies": {
"classnames": "^2.2.6"
}
}
40 changes: 40 additions & 0 deletions packages/collapse/src/Component.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
import { boolean } from '@storybook/addon-knobs';
import { ComponentHeader } from 'storybook/blocks/component-header';

import { Collapse } from './Component';
import { name, version } from '../package.json';

<Meta title='Компоненты' component={Collapse} />

<!-- Canvas -->

<Story name='Collapse'>
<Collapse
collapsedLabel='Подробнее'
expandedLabel='Скрыть'
isExpanded={ true }
>
<p>
Альфа-Банк, основанный в 1990 году, является универсальным банком,
осуществляющим все основные виды банковских операций, представленных
на рынке финансовых услуг, включая обслуживание частных и корпоративных
клиентов, инвестиционный банковский бизнес, торговое финансирование и т.д.
</p>
</Collapse>
</Story>

<ComponentHeader
name='Collapse'
version={version}
package='@alfalab/core-components-collapse'
stage={1}
/>

```tsx
import { Collapse } from '@alfalab/core-components-collase';
```

Компонент для установки расстояния между компонентами.

<Props of={Collapse} />
26 changes: 26 additions & 0 deletions packages/collapse/src/Component.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import { render } from '@testing-library/react';

import { Collapse } from './index';

const paragraph = (
<p>
Альфа-Банк, основанный в 1990 году, является универсальным банком, осуществляющим все
основные виды банковских операций, представленных на рынке финансовых услуг, включая
обслуживание частных и корпоративных клиентов, инвестиционный банковский бизнес, торговое
финансирование и т.д.
</p>
);

// TODO: more tests
describe('Collapse', () => {
describe('Display tests', () => {
it('should display with children like boolean or string or others react children type correctly', () => {
expect(render(<Collapse>{paragraph}</Collapse>)).toMatchSnapshot();
});

it('should display radio group with one child correctly', () => {
expect(render(<Collapse>{paragraph}</Collapse>)).toMatchSnapshot();
});
});
});
108 changes: 108 additions & 0 deletions packages/collapse/src/Component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React, { useEffect, useRef, useState } from 'react';
import cn from 'classnames';
import { ArrowDownSBlackIcon, ArrowUpSBlackIcon } from '@alfalab/icons-classic';
import { Link } from '@alfalab/core-components-link';
import styles from './index.module.css';

export type CollapseProps = {
/**
* Первоначальное состояние компонента
*
*/
isExpanded?: boolean;

/**
* Текст ссылки в `expanded` состоянии
*
*/
collapsedLabel?: string;

/**
* Текст ссылки в `collapsed` состоянии
*
*/
expandedLabel?: string;

/**
* Дочерние элементы `Collapse`
*/
children?: React.ReactNode;

/**
* Дополнительный класс
*/
className?: string;

/**
* Идентификатор компонента в DOM
*/
id?: string;

/**
* Обработчик смены состояний `expanded/collapsed`
*/
onExpandedChange?: (isExpanded?: boolean) => void;

/**
* Идентификатор для систем автоматизированного тестирования
*/
'data-test-id'?: string;
};

export const Collapse = (props: CollapseProps) => {
const {
isExpanded,
collapsedLabel,
expandedLabel,
children,
className,
id,
onExpandedChange,
'data-test-id': dataTestId,
} = props;

const contentRef = useRef<HTMLDivElement>(null);
const contentCaseRef = useRef<HTMLDivElement>(null);
const [expanded, setExpanded] = useState(isExpanded);

useEffect(() => {
let contentHeight;

if (!contentCaseRef.current || !contentRef.current) {
return;
}

if (expanded) {
contentHeight = contentCaseRef.current.offsetHeight;
} else {
contentHeight = 0;
}

contentRef.current.style.height = `${contentHeight}px`;
}, [expanded]);

const contentClassName = cn(styles.content, {
[styles.expandedContent]: expanded,
});

const ToggledIcon = expanded ? ArrowUpSBlackIcon : ArrowDownSBlackIcon;

const handleExpandedChange = () => {
setExpanded(!expanded);
if (onExpandedChange) onExpandedChange();
};

return (
<div className={`${className} ${styles.collapse}`} id={id} data-test-id={dataTestId}>
<div ref={contentRef} className={contentClassName}>
<div ref={contentCaseRef}>{children}</div>
</div>
<Link className={styles.link} pseudo={true} onClick={handleExpandedChange}>
{expanded ? expandedLabel : collapsedLabel}
<ToggledIcon className={styles.icon} />
</Link>
</div>
);
};

export default Collapse;
34 changes: 34 additions & 0 deletions packages/collapse/src/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
@import '../../themes/src/default.css';

.collapse {
font-family: var(--font-family);
}

.collapse,
.collapse:before,
.collapse:after {
box-sizing: border-box;
}

.content {
position: relative;
overflow: hidden;
visibility: hidden;
height: 0;
transition: height 0.2s;
}

.expandedContent {
visibility: visible;
height: auto;
margin-bottom: 15px;
transition: height 0.2s;
}

.link {
outline: none;
}

.icon {
vertical-align: text-bottom;
}
1 change: 1 addition & 0 deletions packages/collapse/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Component';
23 changes: 23 additions & 0 deletions packages/collapse/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useEffect, useState } from 'react';
import debounce from 'lodash.debounce';

/*
* TODO: заменить на хук из https://github.com/alfa-laboratory/utils
* TODO: стоит ли объеденить с useWindowWidth? например в useResize?
*/
export function useWindowHeight(delay = 300) {
const isClient = typeof window === 'object';
const [height, setHeight] = useState(isClient ? window.innerHeight : 0);

useEffect(() => {
if (!isClient) return;

const handleResize = debounce(() => setHeight(window.innerHeight), delay);

window.addEventListener('resize', handleResize);
// eslint-disable-next-line consistent-return
return () => window.removeEventListener('resize', handleResize);
}, [delay, isClient]);

return height;
}
9 changes: 9 additions & 0 deletions packages/collapse/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"include": ["src", "../../typings"],
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"rootDirs": ["src"]
},
"references": [{ "path": "../link" }]
}

0 comments on commit eea2a52

Please sign in to comment.