Skip to content
Merged
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
15 changes: 15 additions & 0 deletions memory-bank/usage/headerBlock.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The HeaderBlock now supports multiple className props for fine-grained styling c
### Props Evolution

- **Props Refactoring**: Renamed `containerFluidClassName` to `contentWrapperClassName` for better semantic clarity
- **Props Added/Modified**: Added option to use `videoIframe` to embed iframe-based video content as media

### Enhanced Content Structure

Expand All @@ -33,6 +34,7 @@ The HeaderBlock now supports multiple className props for fine-grained styling c
### Background and Media Features

- **`fullWidthMedia`**: Support for full-width media backgrounds
- **`videoIframe`**: Support for embedding iframe-based video content as media
- **`mediaView`**: Control over media display mode ('full' by default)
- **Component Composition**: Separate `Background` and `FullWidthBackground` components for better maintainability

Expand Down Expand Up @@ -159,6 +161,18 @@ The HeaderBlock uses a sophisticated layout structure:
/>
```

### With Iframe Video

```tsx
<HeaderBlock
title="Video Header"
description="Header with iframe video"
videoIframe={{
src: 'https://example.com/video-iframe',
}}
/>
```

### With Full-Width Background

```tsx
Expand Down Expand Up @@ -285,6 +299,7 @@ const FullWidthBackground = ({background}: FullWidthBackgroundProps) => (
1. **Image Optimization**: Use appropriately sized and optimized images
2. **Theme Support**: Provide both light and dark theme variants when needed
3. **Mobile Adaptation**: Consider how media displays on mobile devices
4. **Video Iframe**: When using videoIframe, ensure the source URL is properly formatted and accessible

### Background Implementation

Expand Down
17 changes: 17 additions & 0 deletions src/blocks/Header/Header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ $backgroundWidth: 1440px;
border-radius: $borderRadius;
}

&__video-iframe {
position: absolute;
top: 50%;
right: 0;
left: 0;
transform: translateY(-50%);
}

&__breadcrumbs {
position: absolute;
top: $indentXS;
Expand Down Expand Up @@ -255,6 +263,15 @@ $backgroundWidth: 1440px;
}
}

&_media-view_full {
#{$block}__video-iframe {
top: 0;
bottom: 0;
height: auto !important; /* stylelint-disable-line declaration-no-important */ // we have to override contents of the style tag
transform: none;
}
}

@media (max-width: $backgroundWidth) {
&__background,
&__background#{$block}__background_media {
Expand Down
7 changes: 5 additions & 2 deletions src/blocks/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export const HeaderBlock = (props: React.PropsWithChildren<HeaderBlockFullProps>
buttons,
image,
video,
videoIframe,
width = 'm',
imageSize,
offset = 'default',
Expand All @@ -102,7 +103,7 @@ export const HeaderBlock = (props: React.PropsWithChildren<HeaderBlockFullProps>
const windowWidth = useWindowWidth();
const isMobile = windowWidth <= BREAKPOINTS.sm;
const theme = useTheme();
const hasRightSideImage = Boolean((image || video) && !centered);
const hasRightSideImage = Boolean((image || video || videoIframe) && !centered);
const curImageSize = imageSize || getImageSize(width);
const titleSizes = hasRightSideImage ? titleWithImageSizes(curImageSize) : getTitleSizes(width);
let curVerticalOffset = verticalOffset;
Expand All @@ -114,8 +115,9 @@ export const HeaderBlock = (props: React.PropsWithChildren<HeaderBlockFullProps>
const backgroundThemed = background && getThemedValue(background, theme);
const imageThemed = image && getThemedValue(image, theme);
const videoThemed = video && getThemedValue(video, theme);
const {src: videoIframeSrc, ...videoIframeProps} = videoIframe ?? {};
const mediaWithMicrodata = mergeVideoMicrodata(
{video: videoThemed, image: imageThemed},
{video: videoThemed, image: imageThemed, videoIframe: videoIframeSrc, ...videoIframeProps},
{name: title, description},
);
const fullWidth = backgroundThemed?.fullWidth || backgroundThemed?.fullWidthMedia;
Expand Down Expand Up @@ -235,6 +237,7 @@ export const HeaderBlock = (props: React.PropsWithChildren<HeaderBlockFullProps>
className={b('media', {[curImageSize]: true}, mediaClassName)}
videoClassName={b('video')}
imageClassName={b('image')}
youtubeClassName={b('video-iframe')}
{...mediaWithMicrodata}
/>
)}
Expand Down
6 changes: 6 additions & 0 deletions src/blocks/Header/__stories__/Header.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ There could be only one one Header block on the page.
- `start: number`
- `end: number`

`videoIframe?:`
- `src: string`
- `autoplay?: boolean`
- `previewImg?: string`
- `height?: number`

`backLink?: 'url' | 'title'`

`imageSize?: 's' | 'm'` — Image size.
Expand Down
6 changes: 6 additions & 0 deletions src/blocks/Header/__stories__/Header.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ export const FullWidthMediaBackground = FullWidthMediaBackgroundTemplate.bind({}
export const DarkTheme = DefaultTemplate.bind({});
export const Breadcrumbs = BreadCrumbsTemplate.bind({});
export const MediaViewFit = FitTemplate.bind({});
export const VideoIframe = DefaultTemplate.bind([]);

Default.args = {...DefaultArgs} as HeaderBlockProps;

Expand Down Expand Up @@ -260,3 +261,8 @@ MediaViewFit.args = {
...data.image.content,
mediaView: 'fit',
} as HeaderBlockProps;

VideoIframe.args = {
...DefaultArgs,
...data.videoIframe.content,
} as HeaderBlockProps;
9 changes: 9 additions & 0 deletions src/blocks/Header/__stories__/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@
}
}
},
"videoIframe": {
"content": {
"videoIframe": {
"src": "https://runtime.video.cloud.yandex.net/player/video/vplvmyqsxi7dlwndvb4y",
"autoplay": false,
"previewImg": "/story-assets/header-img_0-12_light.png"
}
}
},
"size": {
"title": "Header size {{size}}"
}
Expand Down
13 changes: 13 additions & 0 deletions src/blocks/Header/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ import {
} from '../../schema/validators/common';
import {filteredArray} from '../../schema/validators/utils';

export const HeaderVideoIframeProps = {
type: 'object',
additionalProperties: false,
required: ['src'],
properties: {
src: {type: 'string'},
autoplay: {type: 'boolean'},
previewImg: {type: 'string'},
height: {type: 'number'},
},
};

export const HeaderBackgroundProps = {
type: 'object',
additionalProperties: false,
Expand Down Expand Up @@ -50,6 +62,7 @@ export const HeaderProperties = {
},
image: withTheme(ImageProps),
video: withTheme(VideoProps),
videoIframe: withTheme(HeaderVideoIframeProps),
mediaView: {
type: 'string',
enum: mediaView,
Expand Down
8 changes: 8 additions & 0 deletions src/models/constructor-items/blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ export interface HeaderBlockBackground extends Partial<HeaderBackgroundProps>, P

export type ThemedHeaderBlockBackground = ThemeSupporting<HeaderBlockBackground>;

export interface HeaderBlockVideoIframe {
src: string;
autoplay?: boolean;
previewImg?: string;
height?: number;
}

export interface HeaderBlockProps {
title: string;
overtitle?: string | JSX.Element;
Expand All @@ -182,6 +189,7 @@ export interface HeaderBlockProps {
offset?: HeaderOffset;
image?: ThemedImage;
video?: ThemedMediaVideoProps;
videoIframe?: HeaderBlockVideoIframe;
mediaView?: MediaView;
centered?: boolean;
background?: ThemedHeaderBlockBackground;
Expand Down