From 5174ef666c3fa4961f8c234c0fa54408fc9e722b Mon Sep 17 00:00:00 2001 From: berdysheva Date: Fri, 25 Nov 2022 10:55:46 +0300 Subject: [PATCH 1/5] feat(Tabs): use custom tabs buttons --- src/blocks/Tabs/Tabs.scss | 58 +++++-- src/blocks/Tabs/Tabs.tsx | 153 +++++++++++-------- src/blocks/Tabs/__stories__/Tabs.stories.tsx | 93 +++++++++-- src/blocks/Tabs/__stories__/data.json | 121 +++++++-------- src/components/ButtonTabs/ButtonTabs.scss | 17 +++ src/components/ButtonTabs/ButtonTabs.tsx | 66 ++++++++ src/components/ButtonTabs/README.md | 15 ++ src/components/Image/Image.scss | 7 + src/components/Image/Image.tsx | 7 +- src/components/VideoBlock/VideoBlock.tsx | 2 +- src/models/constructor-items/blocks.ts | 12 +- src/text-transform/blocks.ts | 21 ++- 12 files changed, 404 insertions(+), 168 deletions(-) create mode 100644 src/components/ButtonTabs/ButtonTabs.scss create mode 100644 src/components/ButtonTabs/ButtonTabs.tsx create mode 100644 src/components/ButtonTabs/README.md create mode 100644 src/components/Image/Image.scss diff --git a/src/blocks/Tabs/Tabs.scss b/src/blocks/Tabs/Tabs.scss index 524896e4f..9281db677 100644 --- a/src/blocks/Tabs/Tabs.scss +++ b/src/blocks/Tabs/Tabs.scss @@ -1,20 +1,33 @@ @import '../../../styles/mixins'; @import '../../../styles/variables'; -$block: '.#{$ns}TabsBlock'; +$block: '.#{$ns}tabs-block'; #{$block} { $class: &; &__block-title { - margin-bottom: 12px; + margin-bottom: $indentXXS; + + &_centered { + margin: 0 auto $indentXXS; + text-align: center; + } } &__tabs { - @include add-specificity(&) { - flex-wrap: nowrap; - overflow-x: auto; - margin-bottom: $indentM; + &_centered { + display: flex; + justify-content: center; + } + } + + &__row_reverse { + flex-direction: row-reverse; + + #{$class}__content-wrapper { + margin-right: $indentM; + margin-left: 0; } } @@ -40,6 +53,16 @@ $block: '.#{$ns}TabsBlock'; &__content { display: flex; flex-direction: column; + + &_centered { + margin: 0 auto; + } + } + + &__col { + &_centered { + margin: 0 auto; + } } &__content-wrapper { @@ -58,17 +81,30 @@ $block: '.#{$ns}TabsBlock'; } } - &__tabs, - &__link { - @include text-size(body-2); - } - @media (max-width: map-get($gridBreakpoints, 'md')) { + &__tabs { + display: flex; + overflow: auto; + margin-left: -$indentSM; + margin-right: -$indentSM; + padding-left: $indentSM; + padding-right: $indentXS; + } + &__content-wrapper { &_margin { margin: 0 0 $contentMargin 0; } } + + &__row_reverse { + flex-direction: column-reverse; + + #{$class}__content > * { + margin-top: $indentM; + padding-bottom: 0; + } + } } @include animate(#{$class}__media); diff --git a/src/blocks/Tabs/Tabs.tsx b/src/blocks/Tabs/Tabs.tsx index a8af243f4..08ec5a158 100644 --- a/src/blocks/Tabs/Tabs.tsx +++ b/src/blocks/Tabs/Tabs.tsx @@ -1,101 +1,124 @@ import React, {Fragment, useContext, useState} from 'react'; -import {Tabs} from '@gravity-ui/uikit'; import {block, getThemedValue} from '../../utils'; import {Row, Col, GridColumnOrderClasses} from '../../grid'; -import YFMWrapper from '../../components/YFMWrapper/YFMWrapper'; import {TabsBlockProps} from '../../models'; import AnimateBlock from '../../components/AnimateBlock/AnimateBlock'; import BlockHeader from '../../components/BlockHeader/BlockHeader'; import FullScreenImage from '../../components/FullscreenImage/FullscreenImage'; import Media from '../../components/Media/Media'; -import Links from '../../components/Link/Links'; import {ThemeValueContext} from '../../context/theme/ThemeValueContext'; import {getMediaImage} from '../../components/Media/Image/utils'; +import ButtonTabs, {ButtonTabsItemProps} from '../../components/ButtonTabs/ButtonTabs'; +import {Content} from '../../sub-blocks'; import './Tabs.scss'; -const b = block('TabsBlock'); +const b = block('tabs-block'); -export const TabsBlock = ({items, title, description, animated}: TabsBlockProps) => { +export const TabsBlock = ({ + items, + title, + description, + animated, + tabsColSizes, + centered, + direction = 'media-content', +}: TabsBlockProps) => { const [activeTab, setActiveTab] = useState(items[0].tabName); const [play, setPlay] = useState(false); const {themeValue: theme} = useContext(ThemeValueContext); - const tabs = items.map(({tabName}) => ({title: tabName, id: tabName})); + const tabs: ButtonTabsItemProps[] = items.map(({tabName}) => ({title: tabName, id: tabName})); const activeTabData = items.find(({tabName}) => tabName === activeTab); + const isReverse = direction === 'content-media'; let imageProps; if (activeTabData) { const themedImage = getThemedValue(activeTabData.image, theme); + imageProps = themedImage && getMediaImage(themedImage); } const showMedia = Boolean(activeTabData?.media || imageProps); + const showText = Boolean(activeTabData?.text); + + const textContent = activeTabData && showText && ( + +
+ +
+ + ); + + const mediaContent = showMedia && ( + + {activeTabData?.media && ( + + )} + {imageProps && ( + + + {activeTabData?.caption && ( +

{activeTabData.caption}

+ )} +
+ )} + + ); return ( setPlay(true)} animate={animated}> - - + + + + + {activeTabData && ( - - {showMedia && ( - - {activeTabData?.media && ( - - )} - {imageProps && ( - - - {activeTabData && ( -

{activeTabData.caption}

- )} -
- )} - - )} - -
-

- -

- - -
- + + {mediaContent} + {textContent} )}
diff --git a/src/blocks/Tabs/__stories__/Tabs.stories.tsx b/src/blocks/Tabs/__stories__/Tabs.stories.tsx index 3d92991f5..59db6ed25 100644 --- a/src/blocks/Tabs/__stories__/Tabs.stories.tsx +++ b/src/blocks/Tabs/__stories__/Tabs.stories.tsx @@ -1,9 +1,9 @@ -import React from 'react'; +import React, {Fragment} from 'react'; import {Meta, Story} from '@storybook/react/types-6-0'; import {yfmTransform} from '../../../../.storybook/utils'; -import {TabsBlockModel} from '../../../models'; +import {TabsBlockModel, TabsBlockProps} from '../../../models'; import Tabs from '../Tabs'; -import {PageConstructor} from '../../../containers/PageConstructor/PageConstructor'; +import {PageConstructor} from '../../../containers/PageConstructor'; import data from './data.json'; @@ -19,17 +19,92 @@ const DefaultTemplate: Story = (args) => ( ); +const ButtonsColSizesTemplate: Story = (args) => ( + + + + +); + +const DirectionTemplate: Story = (args) => ( + + + + +); + export const Default = DefaultTemplate.bind({}); -export const WithTheme = DefaultTemplate.bind({}); -export const Media = DefaultTemplate.bind({}); +export const OnlyMedia = DefaultTemplate.bind({}); +export const OnlyText = DefaultTemplate.bind({}); +export const TabsButtonsColSizes = ButtonsColSizesTemplate.bind({}); +export const Centered = DefaultTemplate.bind({}); +export const Direction = DirectionTemplate.bind({}); +export const Caption = DefaultTemplate.bind({}); -Default.args = { +const DefaultArgs = { ...data.default.content, items: data.default.content.items.map((item) => ({ ...item, - title: yfmTransform(item.title), text: yfmTransform(item.text), + additionalInfo: item.additionalInfo && yfmTransform(item.additionalInfo), + })), +}; + +Default.args = {...DefaultArgs} as TabsBlockProps; + +OnlyMedia.args = { + ...DefaultArgs, + items: DefaultArgs.items.map((item) => ({ + ...item, + text: undefined, + })), +} as TabsBlockModel; + +OnlyText.args = { + ...DefaultArgs, + items: DefaultArgs.items.map((item) => ({ + ...item, + media: undefined, + })), +} as TabsBlockModel; + +TabsButtonsColSizes.args = { + ...data.default.content, + items: DefaultArgs.items.concat( + DefaultArgs.items.map((item, index) => { + return { + ...item, + tabName: `${item.tabName} ${index}`, + }; + }), + DefaultArgs.items.map((item, index) => { + return { + ...item, + tabName: `${item.tabName} ${index} ${index}`, + }; + }), + ), +} as TabsBlockModel; + +Centered.args = { + ...DefaultArgs, + centered: true, +} as TabsBlockModel; + +Direction.args = {...DefaultArgs} as TabsBlockModel; + +Caption.args = { + ...DefaultArgs, + items: DefaultArgs.items.map((item) => ({ + ...item, + caption: item.title, })), } as TabsBlockModel; -WithTheme.args = data.theme.content as TabsBlockModel; -Media.args = data.media.content as TabsBlockModel; diff --git a/src/blocks/Tabs/__stories__/data.json b/src/blocks/Tabs/__stories__/data.json index 67270ea73..f276096c3 100644 --- a/src/blocks/Tabs/__stories__/data.json +++ b/src/blocks/Tabs/__stories__/data.json @@ -8,77 +8,28 @@ "items": [ { "tabName": "Dolor sit amet", - "title": "Dolor sit amet", - "text": "* Ut enim ad minim veniam\n* Ut enim ad minim veniam", - "link": { - "url": "https://example.com", - "text": "Link", - "theme": "normal", - "arrow": true - } - }, - { - "tabName": "Consectetur adipiscing elit", - "title": "Consectetur adipiscing elit", - "text": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.", - "link": { - "url": "https://example.com", - "text": "Link", - "theme": "normal" - } - } - ] - } - }, - "theme": { - "content": { - "type": "tabs-block", - "title": { - "text": "Lorem ipsum" - }, - "items": [ - { - "tabName": "Dolor sit amet", - "title": "Dolor sit amet", - "image": { - "light": { - "src": "https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/img_8-12_light.png", - "disableCompress": true + "title": "Lorem ipsum dolor sit amet", + "text": "**Ut enim ad minim veniam** [quis nostrud](https://example.com) exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", + "buttons": [ + { + "text": "Button\r", + "theme": "action", + "url": "https://example.com" }, - "dark": { - "src": "https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/img_8-12_dark.png" + { + "text": "Button", + "theme": "outlined", + "url": "https://example.com" } - }, - "caption": "Dolor sit amet", - "text": "* Ut enim ad minim veniam\n* Ut enim ad minim veniam" - }, - { - "tabName": "Consectetur adipiscing elit", - "title": "Consectetur adipiscing elit", + ], "image": { - "light": { - "src": "https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/img_8-12_light.png" - }, - "dark": { - "src": "https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/img_8-12_dark.png" - } - }, - "caption": "Consectetur adipiscing elit", - "text": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." - } - ] - } - }, - "media": { - "content": { - "type": "tabs-block", - "title": { - "text": "Lorem ipsum" - }, - "items": [ + "light": "https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/img_8-12_white.png", + "dark": "https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/img_8-12_dark.png" + } + }, { - "tabName": "Dolor sit amet", - "title": "Dolor sit amet", + "tabName": "Lorem ipsum", + "title": "Lorem ipsum", "media": { "light": { "video": { @@ -108,19 +59,49 @@ } }, "caption": "Dolor sit amet", - "text": "* Ut enim ad minim veniam\n* Ut enim ad minim veniam" + "text": "* Ut enim ad minim veniam\n* Ut enim ad minim veniam", + "links": [ + { + "url": "https://example.com", + "text": "Link", + "theme": "normal", + "arrow": true + } + ] }, { "tabName": "Consectetur adipiscing elit", "title": "Consectetur adipiscing elit", + "additionalInfo": "Duis aute irure dolor in [reprehenderit](https://example.com) n voluptate velit esse cillum dolore eu fugiat nulla pariatur.", "media": { - "youtube": "https://youtu.be/0Qd3T6skprA", - "previewImg": "https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/video_8-12_dark.png" + "light": { + "youtube": "https://youtu.be/0Qd3T6skprA", + "previewImg": "https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/video_8-12_light.png" + }, + "dark": { + "youtube": "https://youtu.be/0Qd3T6skprA", + "previewImg": "https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/video_8-12_dark.png" + } }, "caption": "Consectetur adipiscing elit", "text": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." } ] } + }, + "buttonsColSizes": { + "wide": { + "title": "Tabs buttons with col sizes 12 columns", + "colSizes": { + "all": 12 + } + }, + "narrow": { + "title": "Tabs buttons with col sizes 8 columns", + "colSizes": { + "all": 12, + "md": 8 + } + } } } diff --git a/src/components/ButtonTabs/ButtonTabs.scss b/src/components/ButtonTabs/ButtonTabs.scss new file mode 100644 index 000000000..05d01cebc --- /dev/null +++ b/src/components/ButtonTabs/ButtonTabs.scss @@ -0,0 +1,17 @@ +@import '../../../styles/variables'; +@import '../../../styles/mixins'; + +$block: '.#{$ns}button-tabs'; + +#{$block} { + margin-bottom: $indentS; + + &__item { + margin-right: $indentXXXS; + margin-bottom: $indentXXS; + + &_active { + pointer-events: none; + } + } +} diff --git a/src/components/ButtonTabs/ButtonTabs.tsx b/src/components/ButtonTabs/ButtonTabs.tsx new file mode 100644 index 000000000..8e655af5e --- /dev/null +++ b/src/components/ButtonTabs/ButtonTabs.tsx @@ -0,0 +1,66 @@ +import React, {useCallback, useMemo} from 'react'; +import {block} from '../../utils'; + +// import {MobileContext} from '../../context/mobileContext'; +import {ButtonProps} from '../../models'; +import {Button} from '../index'; + +import './ButtonTabs.scss'; + +const b = block('button-tabs'); + +export interface ButtonTabsItemProps + extends Omit { + id: string; + title: string; +} + +export interface ButtonTabsProps { + className?: string; + items: ButtonTabsItemProps[]; + activeTab?: string; + onSelectTab?: (tabId: string) => void; +} + +const ButtonTabs = (props: ButtonTabsProps) => { + const {className, items, activeTab, onSelectTab} = props; + // const isMobile = useContext(MobileContext); + + const activeTabId: string = useMemo(() => { + if (activeTab) { + return activeTab; + } + + return items[0].id; + }, [activeTab, items]); + + const handleClick = useCallback( + (tabId) => { + if (onSelectTab) { + onSelectTab(tabId); + } + }, + [onSelectTab], + ); + + return ( +
+ {items.map((item) => { + const isActive = item.id === activeTabId; + + return ( +
+ ); +}; + +export default ButtonTabs; diff --git a/src/components/ButtonTabs/README.md b/src/components/ButtonTabs/README.md new file mode 100644 index 000000000..358050467 --- /dev/null +++ b/src/components/ButtonTabs/README.md @@ -0,0 +1,15 @@ +`type: "title"` + +`text: text` — Title text + +`textSize?: 's' | 'm' | 'l'` — Title font size + +`url?: string` — URL for a redirect on clicking the title, an arrow is automatically added at the end. + +**Margins:** + +`textSize s - top: m` + +`textSize m - top: l` + +`textSize l - top: xl` diff --git a/src/components/Image/Image.scss b/src/components/Image/Image.scss new file mode 100644 index 000000000..ca641bcd0 --- /dev/null +++ b/src/components/Image/Image.scss @@ -0,0 +1,7 @@ +@import '../../../styles/variables.scss'; + +$block: '.#{$ns}Image'; + +#{$block} { + height: 100%; +} diff --git a/src/components/Image/Image.tsx b/src/components/Image/Image.tsx index 0998f6923..bcf3da30c 100644 --- a/src/components/Image/Image.tsx +++ b/src/components/Image/Image.tsx @@ -2,6 +2,11 @@ import React, {CSSProperties, MouseEventHandler, useContext, useState, Fragment} import {ProjectSettingsContext} from '../../context/projectSettingsContext'; import {BREAKPOINTS} from '../../constants'; import {ImageDeviceProps, ImageObjectProps} from '../../models'; +import {block} from '../../utils'; + +import './Image.scss'; + +const b = block('Image'); export interface ImageProps extends Partial, Partial { style?: CSSProperties; @@ -32,7 +37,7 @@ const Image = (props: ImageProps) => { imgLoadingError; return ( - + {mobile && ( {!disableWebp && ( diff --git a/src/components/VideoBlock/VideoBlock.tsx b/src/components/VideoBlock/VideoBlock.tsx index 2258bb6b5..25af30a7a 100644 --- a/src/components/VideoBlock/VideoBlock.tsx +++ b/src/components/VideoBlock/VideoBlock.tsx @@ -76,7 +76,7 @@ const VideoBlock = (props: VideoBlockProps) => { useEffect(() => { const updateSize = _.debounce(() => { - setHeight(ref.current ? Math.round(getHeight(ref.current.offsetWidth)) : undefined); + setHeight(ref.current ? Math.floor(getHeight(ref.current.offsetWidth)) : undefined); }, 100); updateSize(); diff --git a/src/models/constructor-items/blocks.ts b/src/models/constructor-items/blocks.ts index 2ef8f2d12..e93e211f8 100644 --- a/src/models/constructor-items/blocks.ts +++ b/src/models/constructor-items/blocks.ts @@ -286,19 +286,23 @@ export interface TableBlockProps { table: TableProps; } -export interface TabsBlockItem { +export interface TabsBlockItem + extends Omit { tabName: string; - title: string; - text: string; + /** + * @deprecated Use array links from ContentBlockProps instead + */ link?: LinkProps; image?: ThemedImage; disableCompress?: boolean; caption?: string; media?: ThemedMediaProps; - links?: LinkProps[]; } export interface TabsBlockProps extends BlockHeaderProps, Animatable { + tabsColSizes?: GridColumnSizesType; + centered?: boolean; + direction?: MediaDirection; items: TabsBlockItem[]; } diff --git a/src/text-transform/blocks.ts b/src/text-transform/blocks.ts index d56fd19b5..abb359734 100644 --- a/src/text-transform/blocks.ts +++ b/src/text-transform/blocks.ts @@ -2,7 +2,6 @@ import _ from 'lodash'; import { Block, BlockType, - SubBlockType, ContentBlockProps, ExtendedFeaturesItem, PriceDetailedProps, @@ -10,6 +9,7 @@ import { PriceDetailsSettingsProps, PromoFeaturesItem, SliderProps, + SubBlockType, TableProps, TitleProps, } from '../models'; @@ -46,8 +46,6 @@ export const createItemsParser = (fields: string[]) => (transformer: Transformer } }); -const parseItems = createItemsParser(['title', 'text']); - function parseTableBlock(transformer: Transformer, content: TableProps) { const legend = content?.legend; @@ -89,10 +87,16 @@ const parseTitle = (transformer: Transformer, title: TitleProps | string) => ? {...title, text: transformer(title.text)} : title && transformer(title); +const parseItemsTitle = (transformer: Transformer, items: ExtendedFeaturesItem[]) => + items.map(({title, ...rest}) => ({ + title: title && parseTitle(transformer, title), + ...rest, + })); + function parsePriceDetailedBlock(transformer: Transformer, block: PriceDetailedProps) { const {priceType} = block; - const transformedBlockItems = block.items.map((item) => { + block.items = block.items.map((item) => { const {description, items: details = []} = item; if (priceType === 'marked-list') { @@ -114,8 +118,6 @@ function parsePriceDetailedBlock(transformer: Transformer, block: PriceDetailedP return item; }); - block.items = transformedBlockItems; - return block; } @@ -291,7 +293,12 @@ const config: BlocksConfig = { { fields: ['items'], transformer: yfmTransformer, - parser: parseItems, + parser: createItemsParser(['text', 'additionalInfo']), + }, + { + fields: ['items'], + transformer: typografTransformer, + parser: parseItemsTitle, }, ], [BlockType.TableBlock]: [ From cb8c6641cddc5acba2048fd651f955c9d2520c12 Mon Sep 17 00:00:00 2001 From: berdysheva Date: Tue, 29 Nov 2022 19:34:22 +0300 Subject: [PATCH 2/5] fix(Tabs): indents --- package.json | 3 ++ src/blocks/ContentLayout/README.md | 2 +- src/blocks/Tabs/README.md | 30 ++++++++++++++------ src/blocks/Tabs/Tabs.scss | 22 +++++++++----- src/blocks/Tabs/__stories__/Tabs.stories.tsx | 6 +++- src/blocks/Tabs/__stories__/data.json | 3 +- src/blocks/Tabs/schema.ts | 26 +++++++++++------ src/components/ButtonTabs/ButtonTabs.tsx | 3 +- src/components/Image/Image.scss | 3 +- src/components/Image/Image.tsx | 2 +- src/models/constructor-items/blocks.ts | 1 - src/sub-blocks/Content/README.md | 14 +++++++++ 12 files changed, 84 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index f3bcd57b1..55b82139f 100644 --- a/package.json +++ b/package.json @@ -121,5 +121,8 @@ "*.{json,yaml,yml,md}": [ "prettier --write" ] + }, + "publishConfig": { + "tag": "alpha" } } diff --git a/src/blocks/ContentLayout/README.md b/src/blocks/ContentLayout/README.md index c628f5ea8..1004cc57c 100644 --- a/src/blocks/ContentLayout/README.md +++ b/src/blocks/ContentLayout/README.md @@ -1,6 +1,6 @@ `properties:` — Content cube properties (optional) -- `size?: 's' | 'l'` — Cube size that defines font sizes (defaults to l) +- `size?: 's' | 'l'` — Cube size that defines font sizes ('l' by default) - `background?: BackgroundImage` — Special background properties described in the **Content blocks** section. - `centered?: false | true` — Indicates if text is centered (false by default). - `theme?: 'default' | 'dark' | 'light'` — Cube theme: default, dark, or monochrome light ('default' by default). diff --git a/src/blocks/Tabs/README.md b/src/blocks/Tabs/README.md index a1caabe1c..ad68e3c9a 100644 --- a/src/blocks/Tabs/README.md +++ b/src/blocks/Tabs/README.md @@ -1,17 +1,31 @@ Tabs block -`type: tabs-block` — Title +`type: tabs-block` -`title: Title` — Subtitle +`title?: Title | string` - `items: TabsBlockItem[]` — Tab description +`description?: string` - > `tabName: string` — Tab title. +`animated?: boolean` — Enables/disables animation for the block (enabled by default). - > `image: string` — Image. +`centered?: false | true` - Aligns all content to the center ('false' by default) - > `caption?: string` — Image caption. +`tabsColSizes?: Object` — Width of buttons tabs, the value ranges from 1 to 12 columns. If 12 columns, buttons takes up the entire width of the row. - > `text: string` —Text. +- `all: number` — On all screens. +- `sm: number` — On a screen wider than 577px. +- `md: number` — On a screen wider than 769px. +- `lg: number` — On a screen wider than 1081px. +- `xl: number` — On a screen wider than 1185px. - > `link?: Link` — Link below the text. +`items: TabsBlockItem[]` — Tab description + +- `tabName: string` — Tab title. +- `title?: string` — Item's title +- `text?: string` — Item's text (with YFM support) +- `additionalInfo?: string` — Gray text (with YFM support) +- `links?: Link[]` — An array with link objects (see [Content blocks](?path=/story/information--common-types&viewMode=docs)) +- `buttons?: Button[]` — An array with button objects (see [Content blocks](?path=/story/information--common-types&viewMode=docs)) +- `image?: string | ImageObjectProps` — Image. +- [`media: Media` — Media description](?path=/story/information--common-types&viewMode=docs#media---picvideodatalens) +- `caption?: string` — Image caption. diff --git a/src/blocks/Tabs/Tabs.scss b/src/blocks/Tabs/Tabs.scss index 9281db677..00dd19bb2 100644 --- a/src/blocks/Tabs/Tabs.scss +++ b/src/blocks/Tabs/Tabs.scss @@ -7,7 +7,7 @@ $block: '.#{$ns}tabs-block'; $class: &; &__block-title { - margin-bottom: $indentXXS; + margin-bottom: $indentSM; &_centered { margin: 0 auto $indentXXS; @@ -26,8 +26,7 @@ $block: '.#{$ns}tabs-block'; flex-direction: row-reverse; #{$class}__content-wrapper { - margin-right: $indentM; - margin-left: 0; + margin: $indentSM $indentM 0 0; } } @@ -85,10 +84,10 @@ $block: '.#{$ns}tabs-block'; &__tabs { display: flex; overflow: auto; - margin-left: -$indentSM; - margin-right: -$indentSM; - padding-left: $indentSM; - padding-right: $indentXS; + margin-left: -$indentL; + margin-right: -$indentL; + padding-left: $indentL; + padding-right: $indentL - $indentXXXS; } &__content-wrapper { @@ -107,6 +106,15 @@ $block: '.#{$ns}tabs-block'; } } + @media (max-width: map-get($gridBreakpoints, 'sm')) { + &__tabs { + margin-left: -$indentSM; + margin-right: -$indentSM; + padding-left: $indentSM; + padding-right: $indentXS; + } + } + @include animate(#{$class}__media); @include animate(#{$class}__image); } diff --git a/src/blocks/Tabs/__stories__/Tabs.stories.tsx b/src/blocks/Tabs/__stories__/Tabs.stories.tsx index 59db6ed25..75e020c23 100644 --- a/src/blocks/Tabs/__stories__/Tabs.stories.tsx +++ b/src/blocks/Tabs/__stories__/Tabs.stories.tsx @@ -58,7 +58,10 @@ const DefaultArgs = { })), }; -Default.args = {...DefaultArgs} as TabsBlockProps; +Default.args = { + ...DefaultArgs, + description: yfmTransform(data.description), +} as TabsBlockProps; OnlyMedia.args = { ...DefaultArgs, @@ -73,6 +76,7 @@ OnlyText.args = { items: DefaultArgs.items.map((item) => ({ ...item, media: undefined, + image: undefined, })), } as TabsBlockModel; diff --git a/src/blocks/Tabs/__stories__/data.json b/src/blocks/Tabs/__stories__/data.json index f276096c3..63cd88a8e 100644 --- a/src/blocks/Tabs/__stories__/data.json +++ b/src/blocks/Tabs/__stories__/data.json @@ -103,5 +103,6 @@ "md": 8 } } - } + }, + "description": "**Ut enim ad minim veniam** [quis nostrud](https://example.com) exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." } diff --git a/src/blocks/Tabs/schema.ts b/src/blocks/Tabs/schema.ts index 7dc44b57e..036f7627e 100644 --- a/src/blocks/Tabs/schema.ts +++ b/src/blocks/Tabs/schema.ts @@ -5,23 +5,25 @@ import { BlockBaseProps, TitleProps, MediaProps, + containerSizesArray, + sizeNumber, + mediaDirection, } from '../../schema/validators/common'; import {ImageProps} from '../../components/Image/schema'; +import _ from 'lodash'; +import {ContentBase} from '../../sub-blocks/Content/schema'; + +const TabsItemContentProps = _.omit(ContentBase, ['size', 'colSizes', 'centered', 'theme']); export const tabsItem = { type: 'object', additionalProperties: false, - required: ['tabName', 'text'], + required: ['tabName'], properties: { + ...TabsItemContentProps, tabName: { type: 'string', }, - title: { - type: 'string', - }, - text: { - type: 'string', - }, caption: { type: 'string', }, @@ -31,7 +33,6 @@ export const tabsItem = { }), //TODO deprecated link: LinkProps, - links: filteredArray(LinkProps), image: withTheme(ImageProps), }, }; @@ -46,6 +47,15 @@ export const TabsBlock = { description: { type: 'string', }, + tabsColSizes: containerSizesArray.reduce( + (acc, size) => ({...acc, [size]: sizeNumber}), + {}, + ), + direction: { + type: 'string', + enum: mediaDirection, + }, + centered: {type: 'boolean'}, items: filteredArray(tabsItem), }, }, diff --git a/src/components/ButtonTabs/ButtonTabs.tsx b/src/components/ButtonTabs/ButtonTabs.tsx index 8e655af5e..346a05917 100644 --- a/src/components/ButtonTabs/ButtonTabs.tsx +++ b/src/components/ButtonTabs/ButtonTabs.tsx @@ -24,7 +24,6 @@ export interface ButtonTabsProps { const ButtonTabs = (props: ButtonTabsProps) => { const {className, items, activeTab, onSelectTab} = props; - // const isMobile = useContext(MobileContext); const activeTabId: string = useMemo(() => { if (activeTab) { @@ -35,7 +34,7 @@ const ButtonTabs = (props: ButtonTabsProps) => { }, [activeTab, items]); const handleClick = useCallback( - (tabId) => { + (tabId: string) => { if (onSelectTab) { onSelectTab(tabId); } diff --git a/src/components/Image/Image.scss b/src/components/Image/Image.scss index ca641bcd0..e02bdef46 100644 --- a/src/components/Image/Image.scss +++ b/src/components/Image/Image.scss @@ -1,7 +1,8 @@ @import '../../../styles/variables.scss'; -$block: '.#{$ns}Image'; +$block: '.#{$ns}image'; #{$block} { height: 100%; + width: 100%; } diff --git a/src/components/Image/Image.tsx b/src/components/Image/Image.tsx index bcf3da30c..aab83b3bc 100644 --- a/src/components/Image/Image.tsx +++ b/src/components/Image/Image.tsx @@ -6,7 +6,7 @@ import {block} from '../../utils'; import './Image.scss'; -const b = block('Image'); +const b = block('image'); export interface ImageProps extends Partial, Partial { style?: CSSProperties; diff --git a/src/models/constructor-items/blocks.ts b/src/models/constructor-items/blocks.ts index e93e211f8..36bd39747 100644 --- a/src/models/constructor-items/blocks.ts +++ b/src/models/constructor-items/blocks.ts @@ -294,7 +294,6 @@ export interface TabsBlockItem */ link?: LinkProps; image?: ThemedImage; - disableCompress?: boolean; caption?: string; media?: ThemedMediaProps; } diff --git a/src/sub-blocks/Content/README.md b/src/sub-blocks/Content/README.md index 9c08683f4..7063d49c4 100644 --- a/src/sub-blocks/Content/README.md +++ b/src/sub-blocks/Content/README.md @@ -7,3 +7,17 @@ [`links?: Link[]` — An array with link objects](?path=/story/information--common-types&viewMode=docs#link---link) [`buttons?: Button[]` — An array with button objects](?path=/story/information--common-types&viewMode=docs#button---button) + +`centered?: false | true` - Aligns all content to the center ('false' by default) + +`theme?: 'default' | 'dark' | 'light'` — Component's theme: default, dark, or monochrome light ('default' by default). + +- `size?: 's' | 'l'` — Component's size that defines font sizes ('l' by default) + +`сolSizes?: Object` — Width of buttons tabs, the value ranges from 1 to 12 columns. If 12 columns, buttons takes up the entire width of the row. + +- `all: number` — On all screens. +- `sm: number` — On a screen wider than 577px. +- `md: number` — On a screen wider than 769px. +- `lg: number` — On a screen wider than 1081px. +- `xl: number` — On a screen wider than 1185px. From d9d34db61eecafec57915d432f9836c40e86512b Mon Sep 17 00:00:00 2001 From: berdysheva Date: Thu, 1 Dec 2022 18:52:00 +0300 Subject: [PATCH 3/5] fix(Tabs): centered tabs --- package.json | 3 --- src/blocks/Tabs/Tabs.scss | 9 ++++++++- src/blocks/Tabs/Tabs.tsx | 1 - src/blocks/Tabs/__stories__/Tabs.stories.tsx | 1 + 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 55b82139f..f3bcd57b1 100644 --- a/package.json +++ b/package.json @@ -121,8 +121,5 @@ "*.{json,yaml,yml,md}": [ "prettier --write" ] - }, - "publishConfig": { - "tag": "alpha" } } diff --git a/src/blocks/Tabs/Tabs.scss b/src/blocks/Tabs/Tabs.scss index 00dd19bb2..77c44fa76 100644 --- a/src/blocks/Tabs/Tabs.scss +++ b/src/blocks/Tabs/Tabs.scss @@ -10,7 +10,11 @@ $block: '.#{$ns}tabs-block'; margin-bottom: $indentSM; &_centered { - margin: 0 auto $indentXXS; + display: flex; + justify-content: center; + flex-wrap: wrap; + margin-left: auto; + margin-right: auto; text-align: center; } } @@ -19,6 +23,7 @@ $block: '.#{$ns}tabs-block'; &_centered { display: flex; justify-content: center; + flex-wrap: wrap; } } @@ -83,6 +88,8 @@ $block: '.#{$ns}tabs-block'; @media (max-width: map-get($gridBreakpoints, 'md')) { &__tabs { display: flex; + flex-wrap: nowrap; + justify-content: flex-start; overflow: auto; margin-left: -$indentL; margin-right: -$indentL; diff --git a/src/blocks/Tabs/Tabs.tsx b/src/blocks/Tabs/Tabs.tsx index 08ec5a158..59f6c8da5 100644 --- a/src/blocks/Tabs/Tabs.tsx +++ b/src/blocks/Tabs/Tabs.tsx @@ -103,7 +103,6 @@ export const TabsBlock = ({ title={title} description={description} className={b('block-title', {centered: centered})} - colSizes={centered ? {all: 12} : {all: 12, sm: 8}} /> diff --git a/src/blocks/Tabs/__stories__/Tabs.stories.tsx b/src/blocks/Tabs/__stories__/Tabs.stories.tsx index 75e020c23..333f9b879 100644 --- a/src/blocks/Tabs/__stories__/Tabs.stories.tsx +++ b/src/blocks/Tabs/__stories__/Tabs.stories.tsx @@ -100,6 +100,7 @@ TabsButtonsColSizes.args = { Centered.args = { ...DefaultArgs, + description: yfmTransform(data.description), centered: true, } as TabsBlockModel; From 5a0e15986ba86597d76ff854f7d5e02fe16a21b6 Mon Sep 17 00:00:00 2001 From: berdysheva Date: Mon, 5 Dec 2022 14:38:34 +0300 Subject: [PATCH 4/5] fix(Tabs): remove unnecessary text in storybook data --- src/blocks/Tabs/__stories__/data.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blocks/Tabs/__stories__/data.json b/src/blocks/Tabs/__stories__/data.json index 63cd88a8e..f78d6cc4f 100644 --- a/src/blocks/Tabs/__stories__/data.json +++ b/src/blocks/Tabs/__stories__/data.json @@ -12,7 +12,7 @@ "text": "**Ut enim ad minim veniam** [quis nostrud](https://example.com) exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", "buttons": [ { - "text": "Button\r", + "text": "Button", "theme": "action", "url": "https://example.com" }, From f9d6f25199c1fb75a20415f3119401c213c68539 Mon Sep 17 00:00:00 2001 From: berdysheva Date: Mon, 5 Dec 2022 14:44:34 +0300 Subject: [PATCH 5/5] fix: remove comments --- src/components/ButtonTabs/ButtonTabs.tsx | 1 - src/components/ButtonTabs/README.md | 15 --------------- src/components/VideoBlock/VideoBlock.tsx | 2 +- 3 files changed, 1 insertion(+), 17 deletions(-) delete mode 100644 src/components/ButtonTabs/README.md diff --git a/src/components/ButtonTabs/ButtonTabs.tsx b/src/components/ButtonTabs/ButtonTabs.tsx index 346a05917..3b2515d4c 100644 --- a/src/components/ButtonTabs/ButtonTabs.tsx +++ b/src/components/ButtonTabs/ButtonTabs.tsx @@ -1,7 +1,6 @@ import React, {useCallback, useMemo} from 'react'; import {block} from '../../utils'; -// import {MobileContext} from '../../context/mobileContext'; import {ButtonProps} from '../../models'; import {Button} from '../index'; diff --git a/src/components/ButtonTabs/README.md b/src/components/ButtonTabs/README.md deleted file mode 100644 index 358050467..000000000 --- a/src/components/ButtonTabs/README.md +++ /dev/null @@ -1,15 +0,0 @@ -`type: "title"` - -`text: text` — Title text - -`textSize?: 's' | 'm' | 'l'` — Title font size - -`url?: string` — URL for a redirect on clicking the title, an arrow is automatically added at the end. - -**Margins:** - -`textSize s - top: m` - -`textSize m - top: l` - -`textSize l - top: xl` diff --git a/src/components/VideoBlock/VideoBlock.tsx b/src/components/VideoBlock/VideoBlock.tsx index 25af30a7a..2258bb6b5 100644 --- a/src/components/VideoBlock/VideoBlock.tsx +++ b/src/components/VideoBlock/VideoBlock.tsx @@ -76,7 +76,7 @@ const VideoBlock = (props: VideoBlockProps) => { useEffect(() => { const updateSize = _.debounce(() => { - setHeight(ref.current ? Math.floor(getHeight(ref.current.offsetWidth)) : undefined); + setHeight(ref.current ? Math.round(getHeight(ref.current.offsetWidth)) : undefined); }, 100); updateSize();