Skip to content

Commit 3115ece

Browse files
feat(Media,Map): expand title prop type (#1280)
* feat(Media,Map): expand title prop type * chore: update storybook and memory-bank * fix: add onClick in media story
1 parent 4e9088b commit 3115ece

File tree

10 files changed

+223
-5
lines changed

10 files changed

+223
-5
lines changed

memory-bank/usage/map.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,58 @@ graph TD
9595
- **Properties**:
9696
- `type`: MapType enum value (Yandex or Google)
9797

98+
## MapBlockProps Interface
99+
100+
Map blocks use the same enhanced title support as Media blocks through MediaContentProps:
101+
102+
- **Description**: Map blocks extend MediaBaseBlockProps, which includes MediaContentProps with enhanced title support.
103+
- **File**: `src/models/constructor-items/blocks.ts`
104+
- **Key Properties**:
105+
- `title`: TitleItemBaseProps | string - Enhanced title support with object or string format
106+
- `description`: string - Optional description text with YFM support
107+
- `map`: MapProps - Map configuration (required)
108+
- Inherits all MediaContentProps properties: `additionalInfo`, `links`, `buttons`, `size`, `list`, `controlPosition`
109+
110+
### Enhanced Title Support for Maps
111+
112+
Map blocks support the same enhanced title functionality as Media blocks:
113+
114+
**Usage Examples**:
115+
116+
```typescript
117+
// Map with custom title size
118+
{
119+
type: 'map-block',
120+
title: {
121+
text: 'Our Location',
122+
textSize: 'l'
123+
},
124+
map: { /* map config */ }
125+
}
126+
127+
// Map with clickable title
128+
{
129+
type: 'map-block',
130+
title: {
131+
text: 'View on Google Maps',
132+
url: 'https://maps.google.com/...',
133+
urlTitle: 'Open in Google Maps'
134+
},
135+
map: { /* map config */ }
136+
}
137+
138+
// Map with custom content
139+
{
140+
type: 'map-block',
141+
title: {
142+
text: 'Office Location',
143+
custom: '📍',
144+
textSize: 'm'
145+
},
146+
map: { /* map config */ }
147+
}
148+
```
149+
98150
## Usage Patterns
99151

100152
> **Note**: In the code examples below, `b()` is a utility function used throughout the page-constructor project for BEM (Block Element Modifier) class naming. It generates CSS class names following the BEM methodology, making the code more maintainable and consistent.
@@ -249,6 +301,7 @@ The Map component includes Storybook stories demonstrating:
249301
- Yandex Maps integration with coordinate-based markers
250302
- Different zoom levels and configurations
251303
- API key input for development/testing
304+
- Enhanced title support
252305

253306
Stories are located in `src/components/Map/__stories__/Map.stories.tsx` with example data in `data.json`.
254307

memory-bank/usage/media.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,69 @@ graph TD
9696
- Supports `color` for background color
9797
- Includes `videoMicrodata` for SEO structured data
9898

99+
### MediaContentProps Interface
100+
101+
- **Description**: Defines the content properties for Media and Map blocks, extending ContentBlockProps with media-specific properties.
102+
- **File**: `src/models/constructor-items/blocks.ts`
103+
- **Key Properties**:
104+
- `title`: TitleItemBaseProps | string - Enhanced title support with object or string format
105+
- `description`: string - Optional description text with YFM support
106+
- `button`: ButtonProps - Deprecated, use buttons array from ContentBlockProps instead
107+
- Inherits from ContentBlockProps: `additionalInfo`, `links`, `buttons`, `size`, `list`, `controlPosition`
108+
109+
#### Enhanced Title Support
110+
111+
The `title` property in MediaContentProps now supports both simple strings and rich title objects:
112+
113+
**String Format (Legacy)**:
114+
115+
```typescript
116+
title: 'Simple Title Text';
117+
```
118+
119+
**Object Format (Enhanced)**:
120+
121+
```typescript
122+
title: {
123+
text: "Title Text", // Required: The title text
124+
textSize?: TextSize, // Optional: 'xs' | 's' | 'sm' | 'm' | 'l'
125+
url?: string, // Optional: Makes title clickable
126+
urlTitle?: string, // Optional: Link title attribute
127+
custom?: string | ReactNode, // Optional: Custom content (e.g., emoji)
128+
onClick?: () => void, // Optional: Click handler
129+
}
130+
```
131+
132+
**Usage Examples**:
133+
134+
```typescript
135+
// Title with custom size
136+
title: {
137+
text: 'Large Title',
138+
textSize: 'l'
139+
}
140+
141+
// Clickable title
142+
title: {
143+
text: 'Visit Our Site',
144+
url: 'https://example.com',
145+
urlTitle: 'Open example.com'
146+
}
147+
148+
// Interactive title
149+
title: {
150+
text: 'Click Me',
151+
onClick: () => alert('Title clicked!')
152+
}
153+
154+
// Title with custom content
155+
title: {
156+
text: 'Featured Content',
157+
custom: '',
158+
textSize: 'm'
159+
}
160+
```
161+
99162
### Media Sub-components
100163

101164
The Media component internally uses specialized sub-components:
@@ -569,6 +632,7 @@ The Media component includes comprehensive Storybook stories demonstrating:
569632
- Theme variations
570633
- Analytics integration
571634
- Responsive behavior
635+
- Enhanced title support
572636

573637
Stories are located in `src/components/Media/__stories__/Media.stories.tsx` with example data in `data.json`.
574638

src/blocks/Map/__stories__/Map.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import * as MapStories from './Map.stories.tsx';
1010

1111
`type: map-block`
1212

13-
`title: string` — Title.
13+
`title: string | TitleItemBaseProps` — Title. Can be a simple string or an object with additional properties like `textSize`, `url`, `urlTitle`, `custom`, and `onClick`.
1414

1515
`description: string` — Description.
1616

src/blocks/Map/__stories__/Map.stories.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,43 @@ const MapsTypesTemplate: StoryFn<MapBlockModel> = (args) => (
183183
</React.Fragment>
184184
);
185185

186+
const EnhancedTitleTemplate: StoryFn<MapBlockModel> = (args) => (
187+
<MapProvider
188+
scriptSrc={scriptsSrc[MapType.Yandex]}
189+
apiKey={ymapApiKeyForStorybook}
190+
type={MapType.Yandex}
191+
>
192+
<PageConstructor
193+
content={{
194+
blocks: [
195+
{
196+
...args,
197+
...data.enhancedTitle.largeClickable,
198+
map: data.ymap,
199+
},
200+
{
201+
...args,
202+
...data.enhancedTitle.interactiveWithIcon,
203+
title: {
204+
...data.enhancedTitle.interactiveWithIcon.title,
205+
onClick: () => alert('Map title clicked!'),
206+
},
207+
map: {
208+
...data.ymap,
209+
id: 'interactive-title-map',
210+
},
211+
},
212+
],
213+
}}
214+
/>
215+
</MapProvider>
216+
);
217+
186218
export const Default = DefaultTemplate.bind({});
187219
export const Size = SizeTemplate.bind({});
188220
export const Direction = DirectionTemplate.bind({});
189221
export const MapsTypes = MapsTypesTemplate.bind({});
222+
export const EnhancedTitle = EnhancedTitleTemplate.bind({});
190223

191224
const DefaultArgs = {
192225
...data.default.content,
@@ -201,3 +234,8 @@ Size.args = DefaultArgs as MapBlockProps;
201234
Direction.args = DefaultArgs as MapBlockProps;
202235

203236
MapsTypes.args = DefaultArgs as MapBlockProps;
237+
238+
EnhancedTitle.args = {
239+
...DefaultArgs,
240+
...data.enhancedTitle.largeClickable,
241+
} as MapBlockProps;

src/blocks/Map/__stories__/data.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,24 @@
6161
"direction": {
6262
"defaultDirectionTitle": "Default Direction",
6363
"ReverseDirectionTitle": "Reverse Direction"
64+
},
65+
"enhancedTitle": {
66+
"largeClickable": {
67+
"title": {
68+
"text": "Large Clickable Media Title",
69+
"textSize": "l",
70+
"url": "https://example.com",
71+
"urlTitle": "Open media example"
72+
},
73+
"description": "Example with title object using custom size and clickable link"
74+
},
75+
"interactiveWithIcon": {
76+
"title": {
77+
"text": "Interactive Media Title",
78+
"textSize": "m",
79+
"custom": "🗺️"
80+
},
81+
"description": "Example with title object using onClick handler and custom content (emoji)"
82+
}
6483
}
6584
}

src/blocks/Media/Media.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const MediaBlock = (props: MediaBlockProps) => {
2323
const theme = useTheme();
2424
const mediaThemed = getThemedValue(media, theme);
2525
const mediaWithMicrodata = mergeVideoMicrodata(mediaThemed, {
26-
name: title,
26+
name: typeof title === 'object' ? title.text : title,
2727
description,
2828
});
2929

src/blocks/Media/__stories__/Media.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import * as MediaStories from './Media.stories.tsx';
99

1010
`type: media-block`
1111

12-
`title: string` — Title.
12+
`title: string | TitleItemBaseProps` — Title. Can be a simple string or an object with additional properties like `textSize`, `url`, `urlTitle`, `custom`, and `onClick`.
1313

1414
`description: string` — Description.
1515

src/blocks/Media/__stories__/Media.stories.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,27 @@ const IframeTemplate: StoryFn<MediaBlockModel> = (args) => (
198198
/>
199199
);
200200

201+
const EnhancedTitleTemplate: StoryFn<MediaBlockModel> = (args) => (
202+
<PageConstructor
203+
content={{
204+
blocks: [
205+
{
206+
...args,
207+
...data.enhancedTitle.largeClickable,
208+
},
209+
{
210+
...args,
211+
...data.enhancedTitle.interactiveWithIcon,
212+
title: {
213+
...data.enhancedTitle.interactiveWithIcon.title,
214+
onClick: () => alert('Media title clicked!'),
215+
},
216+
},
217+
],
218+
}}
219+
/>
220+
);
221+
201222
export const Default = DefaultTemplate.bind({});
202223
export const ImageSlider = ImageSliderTemplate.bind({});
203224
export const Video = VideoTemplate.bind({});
@@ -208,6 +229,7 @@ export const WithoutShadowDeprecated = ImageSliderTemplate.bind({});
208229
export const WithoutShadow = ImageSliderTemplate.bind({});
209230
export const WithBorder = ImageSliderTemplate.bind({});
210231
export const Iframe = IframeTemplate.bind({});
232+
export const EnhancedTitle = EnhancedTitleTemplate.bind({});
211233

212234
const DefaultArgs = {
213235
...data.default.content,
@@ -245,3 +267,7 @@ WithBorder.args = {
245267
Iframe.args = {
246268
...DefaultArgs,
247269
} as MediaBlockProps;
270+
EnhancedTitle.args = {
271+
...DefaultArgs,
272+
...data.enhancedTitle.largeClickable,
273+
} as MediaBlockProps;

src/blocks/Media/__stories__/data.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,25 @@
330330
"defaultDirectionTitle": "Default Direction",
331331
"ReverseDirectionTitle": "Reverse Direction"
332332
},
333+
"enhancedTitle": {
334+
"largeClickable": {
335+
"title": {
336+
"text": "Large Clickable Media Title",
337+
"textSize": "l",
338+
"url": "https://example.com",
339+
"urlTitle": "Open media example"
340+
},
341+
"description": "Example with title object using custom size and clickable link"
342+
},
343+
"interactiveWithIcon": {
344+
"title": {
345+
"text": "Interactive Media Title",
346+
"textSize": "m",
347+
"custom": "🎬"
348+
},
349+
"description": "Example with title object using onClick handler and custom content (emoji)"
350+
}
351+
},
333352
"withoutShadow": {
334353
"content": {
335354
"type": "media-block",

src/models/constructor-items/blocks.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,7 @@ export interface MediaBaseBlockProps extends Animatable, MediaContentProps {
281281
}
282282

283283
export interface MediaContentProps
284-
extends Omit<ContentBlockProps, 'colSizes' | 'text' | 'title' | 'theme' | 'centered'> {
285-
title: string;
284+
extends Omit<ContentBlockProps, 'colSizes' | 'text' | 'theme' | 'centered'> {
286285
description?: string;
287286
/** @deprecated Use array of buttons from ContentBlockProps instead**/
288287
button?: ButtonProps;

0 commit comments

Comments
 (0)