Skip to content

Commit 044ced8

Browse files
authored
feat(FormBlock): add content labels, stub, update background (#1314)
* feat(FormBlock): add content labels, add stub * chore: fix tests * fix: label sizes * feat: background-support * fix: requsted changes
1 parent 34e422b commit 044ced8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+493
-63
lines changed

memory-bank/usage/content.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -444,10 +444,11 @@ The Content component is composed of several key parts:
444444

445445
1. **Title**: Displays the content title using the Title component
446446
2. **Text**: Displays the main text content using the YFMWrapper component
447-
3. **Content List**: Displays a list of content items using the ContentList component
448-
4. **Additional Info**: Displays additional information using the YFMWrapper component
449-
5. **Links**: Displays links using the Links component
450-
6. **Buttons**: Displays buttons using the Buttons component
447+
3. **Labels**: Displays labels using the ContentLabels component
448+
4. **Content List**: Displays a list of content items using the ContentList component
449+
5. **Additional Info**: Displays additional information using the YFMWrapper component
450+
6. **Links**: Displays links using the Links component
451+
7. **Buttons**: Displays buttons using the Buttons component
451452

452453
### Internal Structure
453454

@@ -469,6 +470,11 @@ The Content component is composed of several key parts:
469470
/>
470471
</div>
471472
)}
473+
{labels?.length ? (
474+
<div className={b('labels')}>
475+
<ContentLabels labels={labels} theme={theme} />
476+
</div>
477+
) : null}
472478
{list?.length ? (
473479
<div className={b('list')}>
474480
<ContentList list={list} size={size} qa={qaAttributes.list} theme={theme} />

src/blocks/Form/Form.scss

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ $largeBorderRadius: 32px;
106106
}
107107
}
108108

109+
$labelsBlock: '.#{$ns}content-labels';
109110
@media (min-width: map-get($gridBreakpoints, 'lg')) {
110111
&_form-type_yandex {
111112
#{$root}__row {
@@ -133,7 +134,7 @@ $largeBorderRadius: 32px;
133134
}
134135
}
135136

136-
@media (max-width: map-get($gridBreakpoints, 'lg')) and (min-width: map-get($gridBreakpoints, 'md')) {
137+
@media (max-width: calc(map-get($gridBreakpoints, 'lg') - 1px)) and (min-width: map-get($gridBreakpoints, 'md')) {
137138
&__row {
138139
flex-direction: column;
139140
}
@@ -161,6 +162,10 @@ $largeBorderRadius: 32px;
161162
#{$root}__content-wrapper {
162163
text-align: center;
163164
padding-bottom: $indentM;
165+
166+
#{$labelsBlock} {
167+
justify-content: center;
168+
}
164169
}
165170
}
166171
}
@@ -172,7 +177,7 @@ $largeBorderRadius: 32px;
172177
}
173178
}
174179

175-
@media (max-width: map-get($gridBreakpoints, 'md')) {
180+
@media (max-width: calc(map-get($gridBreakpoints, 'md') - 1px)) {
176181
&__full-form {
177182
padding: $indentM;
178183
}

src/blocks/Form/Form.tsx

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import InnerForm from '../../components/InnerForm/InnerForm';
55
import {MobileContext} from '../../context/mobileContext';
66
import {useTheme} from '../../context/theme';
77
import {Col, Grid, GridAlignItems, GridColumnSize, Row} from '../../grid';
8+
import {useDeviceValue} from '../../hooks/useDeviceValue';
89
import type {FormBlockProps} from '../../models';
910
import {
1011
FormBlockDataTypes,
@@ -15,31 +16,42 @@ import {
1516
import {Content} from '../../sub-blocks';
1617
import {block, getThemedValue} from '../../utils';
1718

19+
import {hasBackgroundCSS} from './utils';
20+
1821
import './Form.scss';
1922

2023
const b = block('form-block');
2124

2225
const colSizes = {[GridColumnSize.Lg]: 6, [GridColumnSize.All]: 12};
2326

2427
const Form = (props: FormBlockProps) => {
25-
const {formData, title, textContent, direction = FormBlockDirection.Center, background} = props;
28+
const {
29+
formData,
30+
title,
31+
textContent,
32+
direction = FormBlockDirection.Center,
33+
background,
34+
customFormNode,
35+
} = props;
2636
const [contentLoaded, setContentLoaded] = React.useState(false);
2737
const isMobile = React.useContext(MobileContext);
2838
const theme = useTheme();
2939

3040
const themedBackground = getThemedValue(background, theme) || undefined;
41+
const themedBackgroundStyle = useDeviceValue(themedBackground?.style) || undefined;
3142

3243
const withBackground = Boolean(
3344
themedBackground &&
3445
(themedBackground.src ||
3546
themedBackground.desktop ||
36-
themedBackground.style?.backgroundColor),
47+
hasBackgroundCSS(themedBackgroundStyle ?? {})),
3748
);
49+
3850
const onContentLoad = React.useCallback(() => {
3951
setContentLoaded(true);
4052
}, []);
4153

42-
if (!formData) {
54+
if (!formData && !customFormNode) {
4355
return null;
4456
}
4557

@@ -61,6 +73,7 @@ const Form = (props: FormBlockProps) => {
6173
{themedBackground && (
6274
<BackgroundImage
6375
{...themedBackground}
76+
style={themedBackgroundStyle}
6477
className={b('media')}
6578
imageClassName={b('image')}
6679
/>
@@ -96,21 +109,25 @@ const Form = (props: FormBlockProps) => {
96109
hidden: !contentLoaded,
97110
})}
98111
>
99-
{title && (
100-
<Title
101-
title={{
102-
text: title,
103-
textSize: 's',
104-
}}
105-
className={b('title', {mobile: isMobile})}
106-
colSizes={{all: 12}}
107-
/>
112+
{customFormNode || (
113+
<React.Fragment>
114+
{title && (
115+
<Title
116+
title={{
117+
text: title,
118+
textSize: 's',
119+
}}
120+
className={b('title', {mobile: isMobile})}
121+
colSizes={{all: 12}}
122+
/>
123+
)}
124+
<InnerForm
125+
className={b('form')}
126+
formData={formData}
127+
onContentLoad={onContentLoad}
128+
/>
129+
</React.Fragment>
108130
)}
109-
<InnerForm
110-
className={b('form')}
111-
formData={formData}
112-
onContentLoad={onContentLoad}
113-
/>
114131
</div>
115132
</div>
116133
</Col>

src/blocks/Form/__stories__/Form.mdx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,21 @@ import * as FormBlockStories from './Form.stories.tsx';
1717

1818
`direction?: 'form-content' | 'content-form' | 'center'` - Direction.
1919

20-
`background?: BackgroundImage` — See [background](?path=/docs/components-pics-video-datalens-backgroundimage--docs) properties.
20+
`background?: FormBlockBackgroundProps` — Same as `BackgroundImage` (see [background](?path=/docs/components-pics-video-datalens-backgroundimage--docs) properties), but the `style` prop supports `Device` breakpoints, for example:
21+
22+
```ts
23+
{
24+
style: {
25+
desktop: {
26+
background: 'red',
27+
},
28+
mobile: {
29+
background: 'blue',
30+
},
31+
}
32+
}
33+
```
34+
35+
`customFormNode?: React.ReactNode` - A custom React node that will be rendered instead of the form.
2136

2237
</StoryTemplate>

src/blocks/Form/__stories__/Form.stories.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {blockTransform} from '../../../../.storybook/utils';
55
import {FormBlockDirection, FormBlockModel, FormBlockProps} from '../../../models';
66
import FormBlock from '../Form';
77

8+
import ExampleStub from './components/ExmapleStub';
9+
810
import data from './data.json';
911

1012
export default {
@@ -42,6 +44,7 @@ export const WithBackgroundColor = VariantsTemplate.bind([]);
4244
export const WithBackgroundImage = VariantsTemplate.bind([]);
4345
export const DarkTheme = VariantsTemplate.bind([]);
4446
export const FormData = VariantsTemplate.bind([]);
47+
export const WithCustomFormNode = DefaultTemplate.bind([]);
4548

4649
Default.args = data.default as FormBlockModel;
4750

@@ -88,3 +91,5 @@ FormData.parameters = {
8891
include: Object.keys(FormData.args),
8992
},
9093
};
94+
95+
WithCustomFormNode.args = {...data.default, customFormNode: <ExampleStub />} as FormBlockModel;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {Button} from '@gravity-ui/uikit';
2+
3+
const ExampleStub = () => {
4+
return (
5+
<div
6+
style={{
7+
display: 'flex',
8+
flexDirection: 'column',
9+
justifyContent: 'center',
10+
alignItems: 'center',
11+
gap: 24,
12+
}}
13+
>
14+
<h1>This is an example form component</h1>
15+
<p>It can be anything</p>
16+
<Button size="xl" view="action">
17+
Got it!
18+
</Button>
19+
</div>
20+
);
21+
};
22+
23+
export default ExampleStub;

src/blocks/Form/__tests__/Form.visual.test.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
FormData,
88
WithBackgroundColor,
99
WithBackgroundImage,
10+
WithCustomFormNode,
1011
} from './helpers';
1112

1213
const DEFAULT_FORM_DELAY = 20 * 1000;
@@ -48,4 +49,10 @@ test.describe('Form', () => {
4849
await delay(DEFAULT_FORM_DELAY);
4950
await expectScreenshot({skipTheme: 'dark'});
5051
});
52+
53+
test.skip('render stories <WithCustomFormNode>', async ({mount, expectScreenshot, delay}) => {
54+
await mount(<WithCustomFormNode />);
55+
await delay(DEFAULT_FORM_DELAY);
56+
await expectScreenshot({skipTheme: 'dark'});
57+
});
5158
});

src/blocks/Form/__tests__/helpers.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ export const {
99
WithBackgroundImage,
1010
DarkTheme,
1111
FormData,
12+
WithCustomFormNode,
1213
} = composeStories(FormStories);

src/blocks/Form/schema.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,7 @@ export const FormBlock = {
4242
direction: {
4343
enum: ['content-form', 'form-content', 'center'],
4444
},
45-
image: ImageProps,
46-
backgroundColor: {
47-
type: 'string',
48-
},
45+
background: ImageProps,
4946
},
5047
},
5148
};

src/blocks/Form/utils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as React from 'react';
2+
3+
export const BACKGROUND_STYLE_PROPS = [
4+
'background',
5+
'backgroundAttachment',
6+
'backgroundBlendMode',
7+
'backgroundClip',
8+
'backgroundColor',
9+
'backgroundImage',
10+
'backgroundOrigin',
11+
'backgroundPositionX',
12+
'backgroundPositionY',
13+
'backgroundRepeat',
14+
'backgroundSize',
15+
'backgroundPosition',
16+
] as const;
17+
18+
export const hasBackgroundCSS = (style: React.CSSProperties) =>
19+
BACKGROUND_STYLE_PROPS.some((backgroundStyleProp) => backgroundStyleProp in style);

0 commit comments

Comments
 (0)