-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core-components-tabs): add tabs (#149)
* feat(core-components-tabs): add PrimaryTabsHeader * feat(core-components-tabs): add secondary header. some refactor * feat(core-components-tabs): add gaps props to PrimaryTabsHeader * refactor(core-components-tabs): selected -> selectedId * feat(core-components-tabs): add Tabs and useTabs * feat(core-components-tabs): use PrimaryTablist as default * refactor(core-components-tabs): move Tabs to components folder * fix(core-components-tabs): pr fixes * Feat/tabs desktop mobile split (#175) * feat(core-components-tabs): split mobile and desktop versions * feat(core-components-tabs): add responsive vartiant * docs: ✏️ update stories * refactor: 💡 fix responsive styles * docs: ✏️ replace importd * fix: 🐛 add mixins import * refactor(core-components-tabs): pr refactor * refactor(core-components-tabs): rename tablist * Feat/tabs tests (#200) * feat(core-components-tabs): add tests * test(core-components-tabs): update tests * fix(core-components-tabs): fix deps * fix(core-components-tabs): use correct font mixin
- Loading branch information
Showing
43 changed files
with
1,990 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "@alfalab/core-components-tabs", | ||
"version": "1.0.0", | ||
"description": "Tabs components", | ||
"keywords": [], | ||
"license": "ISC", | ||
"main": "dist/index.js", | ||
"types": "dist/typings.d.ts", | ||
"files": [ | ||
"dist" | ||
], | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"devDependencies": { | ||
"@types/lodash.debounce": "^4.0.6" | ||
}, | ||
"dependencies": { | ||
"@alfalab/core-components-tag": "^1.3.0", | ||
"compute-scroll-into-view": "^1.0.13", | ||
"lodash.debounce": "^4.0.8" | ||
}, | ||
"peerDependencies": { | ||
"classnames": "^2.2.6", | ||
"react": "^16.9.0", | ||
"react-dom": "^16.9.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import { Meta, Story, Props, Preview, Title } from '@storybook/addon-docs/blocks'; | ||
import { boolean, select } from '@storybook/addon-knobs'; | ||
|
||
import { | ||
TabsDesktop, | ||
TabsMobile, | ||
TabsResponsive, | ||
PrimaryTabListDesktop, | ||
PrimaryTabListMobile, | ||
SecondaryTabListDesktop, | ||
SecondaryTabListMobile, | ||
Tab, | ||
} from './index'; | ||
|
||
import { name, version } from '../package.json'; | ||
|
||
export const titles = Array(7).fill(0).map((_, i) => ({ title: `Таб ${i + 1}`, id: i + 1 })); | ||
|
||
|
||
<Meta title='Компоненты|Tabs' /> | ||
|
||
<Title> | ||
Tabs ({name}@{version}) | ||
</Title> | ||
|
||
## Описание | ||
|
||
Компоненты для построения табов. | ||
|
||
### TabsDesktop | ||
|
||
<Story name='TabsDesktop'> | ||
{React.createElement(() => { | ||
const [selectedId, setSelectedId] = React.useState('tab-1'); | ||
const handleChange = (event, { selectedId }) => setSelectedId(selectedId); | ||
return ( | ||
<TabsDesktop | ||
view={select('view', ['primary', 'secondary'], 'primary')} | ||
selectedId={selectedId} | ||
keepMounted={boolean('keepMounted')} | ||
onChange={handleChange} | ||
scrollable={boolean('scrollable')} | ||
gaps={select('gaps', ['default', 'wide'], 'default')} | ||
> | ||
<Tab title='Таб 1' id='tab-1'> | ||
Таб 1 | ||
</Tab> | ||
<Tab title='Таб 2' id='tab-2'> | ||
Таб 2 | ||
</Tab> | ||
<Tab title='Таб 3' id='tab-3'> | ||
Таб 3 | ||
</Tab> | ||
<Tab title='Таб 4' id='tab-4'> | ||
Таб 4 | ||
</Tab> | ||
<Tab title='Таб 5' id='tab-5'> | ||
Таб 5 | ||
</Tab> | ||
</TabsDesktop> | ||
); | ||
})} | ||
</Story> | ||
|
||
### TabsMobile | ||
|
||
<Story name='TabsMobile'> | ||
{React.createElement(() => { | ||
const [selectedId, setSelectedId] = React.useState('tab-1'); | ||
const handleChange = (event, { selectedId }) => setSelectedId(selectedId); | ||
return ( | ||
<TabsMobile | ||
view={select('view', ['primary', 'secondary'], 'primary')} | ||
selectedId={selectedId} | ||
keepMounted={boolean('keepMounted')} | ||
onChange={handleChange} | ||
scrollable={boolean('scrollable')} | ||
> | ||
<Tab title='Таб 1' id='tab-1'> | ||
Таб 1 | ||
</Tab> | ||
<Tab title='Таб 2' id='tab-2'> | ||
Таб 2 | ||
</Tab> | ||
<Tab title='Таб 3' id='tab-3'> | ||
Таб 3 | ||
</Tab> | ||
<Tab title='Таб 4' id='tab-4'> | ||
Таб 4 | ||
</Tab> | ||
<Tab title='Таб 5' id='tab-5'> | ||
Таб 5 | ||
</Tab> | ||
</TabsMobile> | ||
); | ||
})} | ||
</Story> | ||
|
||
### TabsResponsive | ||
|
||
Адаптивная версия табов, перестраивается при 768px | ||
|
||
<Story name='TabsResponsive'> | ||
{React.createElement(() => { | ||
const [selectedId, setSelectedId] = React.useState('tab-1'); | ||
const handleChange = (event, { selectedId }) => setSelectedId(selectedId); | ||
return ( | ||
<TabsResponsive | ||
view={select('view', ['primary', 'secondary'], 'primary')} | ||
selectedId={selectedId} | ||
keepMounted={boolean('keepMounted')} | ||
onChange={handleChange} | ||
scrollable={boolean('scrollable')} | ||
> | ||
<Tab title='Таб 1' id='tab-1'> | ||
Таб 1 | ||
</Tab> | ||
<Tab title='Таб 2' id='tab-2'> | ||
Таб 2 | ||
</Tab> | ||
<Tab title='Таб 3' id='tab-3'> | ||
Таб 3 | ||
</Tab> | ||
<Tab title='Таб 4' id='tab-4'> | ||
Таб 4 | ||
</Tab> | ||
<Tab title='Таб 5' id='tab-5'> | ||
Таб 5 | ||
</Tab> | ||
</TabsResponsive> | ||
); | ||
})} | ||
</Story> | ||
|
||
<Props components={{ | ||
TabsDesktop, | ||
TabsMobile | ||
}} /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export * from './primary-tablist'; | ||
export * from './secondary-tablist'; | ||
export * from './scrollable-container'; | ||
export * from './tab'; | ||
export * from './tabs'; |
14 changes: 14 additions & 0 deletions
14
packages/tabs/src/components/primary-tablist/Component.desktop.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import React from 'react'; | ||
import cn from 'classnames'; | ||
import { PrimaryTabList } from './Component'; | ||
import { TabListProps, Gaps } from '../../typings'; | ||
|
||
import styles from './desktop.module.css'; | ||
|
||
export const PrimaryTabListDesktop = ({ | ||
gaps = 'default', | ||
className, | ||
...restProps | ||
}: TabListProps & Gaps) => ( | ||
<PrimaryTabList {...restProps} styles={styles} className={cn(className, styles[gaps])} /> | ||
); |
9 changes: 9 additions & 0 deletions
9
packages/tabs/src/components/primary-tablist/Component.mobile.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import React from 'react'; | ||
import { PrimaryTabList } from './Component'; | ||
import { TabListProps } from '../../typings'; | ||
|
||
import styles from './mobile.module.css'; | ||
|
||
export const PrimaryTabListMobile = (props: TabListProps) => ( | ||
<PrimaryTabList {...props} styles={styles} /> | ||
); |
30 changes: 30 additions & 0 deletions
30
packages/tabs/src/components/primary-tablist/Component.responsive.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import React from 'react'; | ||
import cn from 'classnames'; | ||
import { PrimaryTabList } from './Component'; | ||
import { TabListProps, Gaps } from '../../typings'; | ||
import { useWindowWidth } from '../../utils'; | ||
|
||
import styles from './responsive.module.css'; | ||
|
||
export const PrimaryTabListResponsive = ({ | ||
gaps = 'default', | ||
className, | ||
...restProps | ||
}: TabListProps & Gaps) => { | ||
const width = useWindowWidth(); | ||
|
||
/** | ||
* Вызываем ререндер при переходе из одного вида в другой. | ||
* Это нужно, чтобы подчеркивание имело правильную ширину (lineStyles) | ||
*/ | ||
const key = width >= 768 ? 'desktop' : 'mobile'; | ||
|
||
return ( | ||
<PrimaryTabList | ||
{...restProps} | ||
styles={styles} | ||
className={cn(className, styles[gaps])} | ||
key={key} | ||
/> | ||
); | ||
}; |
70 changes: 70 additions & 0 deletions
70
packages/tabs/src/components/primary-tablist/Component.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
import cn from 'classnames'; | ||
import { useTabs } from '../../useTabs'; | ||
import { ScrollableContainer } from '../scrollable-container'; | ||
import { TabListProps, Styles } from '../../typings'; | ||
|
||
export const PrimaryTabList = ({ | ||
styles = {}, | ||
className, | ||
titles = [], | ||
selectedId = titles.length ? titles[0].id : undefined, | ||
scrollable = true, | ||
onChange, | ||
dataTestId, | ||
}: TabListProps & Styles) => { | ||
const { selectedTab, focusedTab, getTabListItemProps } = useTabs({ | ||
titles, | ||
selectedId, | ||
onChange, | ||
}); | ||
const [lineStyles, setLineStyles] = useState<{ width?: number; transform?: string }>(); | ||
|
||
useEffect(() => { | ||
if (selectedTab) { | ||
setLineStyles({ | ||
width: selectedTab.offsetWidth, | ||
transform: `translateX(${selectedTab.offsetLeft}px)`, | ||
}); | ||
} | ||
}, [selectedTab]); | ||
|
||
const renderContent = () => ( | ||
<React.Fragment> | ||
{titles.map((item, index) => ( | ||
<button | ||
{...getTabListItemProps(index)} | ||
type='button' | ||
key={item.id} | ||
className={cn(styles.title, { | ||
[styles.selected]: item.id === selectedId, | ||
})} | ||
> | ||
<span tabIndex={-1} className={styles.titleWrapper}> | ||
{item.title} | ||
</span> | ||
</button> | ||
))} | ||
|
||
<div className={styles.line} style={lineStyles} /> | ||
</React.Fragment> | ||
); | ||
|
||
return ( | ||
<div | ||
role='tablist' | ||
data-test-id={dataTestId} | ||
className={cn(styles.component, className, { | ||
[styles.scrollable]: scrollable, | ||
})} | ||
> | ||
{scrollable ? ( | ||
<ScrollableContainer activeChild={focusedTab || selectedTab}> | ||
{renderContent()} | ||
</ScrollableContainer> | ||
) : ( | ||
<div className={styles.container}>{renderContent()}</div> | ||
)} | ||
</div> | ||
); | ||
}; |
37 changes: 37 additions & 0 deletions
37
packages/tabs/src/components/primary-tablist/desktop.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
@import './index.module.css'; | ||
|
||
.component { | ||
composes: component from './index.module.css'; | ||
|
||
margin-bottom: var(--gap-2xl); | ||
margin-top: var(--gap-2xl); | ||
} | ||
|
||
.title { | ||
composes: title from './index.module.css'; | ||
|
||
@mixin system_18-22_regular; | ||
font-weight: 300; | ||
} | ||
|
||
.default .title { | ||
margin-right: var(--gap-2xl); | ||
|
||
&:last-child { | ||
margin-right: 0; | ||
} | ||
} | ||
|
||
.wide .title { | ||
margin-right: var(--gap-4xl); | ||
|
||
&:last-child { | ||
margin-right: 0; | ||
} | ||
} | ||
|
||
.titleWrapper { | ||
composes: titleWrapper from './index.module.css'; | ||
|
||
padding-bottom: var(--gap-m); | ||
} |
Oops, something went wrong.