Skip to content

Commit 7790d8c

Browse files
feat(PageLayout): support function type for topAlert prop (#491)
* feat(PageLayout): support function type for topAlert prop * feat(PageLayout): retain TopAlert height logic for custom renderers * feat(PageLayout): rollback TopAlert props type * feat(PageLayout): refine TopAlert props type
1 parent f5f364b commit 7790d8c

10 files changed

+83
-8
lines changed
Loading
Loading
Loading
Loading

src/components/AsideHeader/__stories__/AsideHeader.stories.tsx

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22

3+
import {Xmark} from '@gravity-ui/icons';
34
import {Button, Flex, Icon, Text, spacing} from '@gravity-ui/uikit';
45
import type {Meta, StoryFn} from '@storybook/react';
56

@@ -8,7 +9,7 @@ import {AsideFallback} from '../components/PageLayout/AsideFallback';
89
import {PageLayout} from '../components/PageLayout/PageLayout';
910
import {PageLayoutAside} from '../components/PageLayout/PageLayoutAside';
1011

11-
import {AsideHeaderShowcase} from './AsideHeaderShowcase';
12+
import {AsideHeaderShowcase, AsideHeaderShowcaseProps} from './AsideHeaderShowcase';
1213
import {DEFAULT_LOGO, menuItemsClamped, menuItemsShowcase} from './moc';
1314

1415
import logoIcon from '../../../../.storybook/assets/logo.svg';
@@ -126,7 +127,9 @@ AdvancedUsage.args = {
126127
initialCompact: true,
127128
};
128129

129-
const TopAlertTemplate: StoryFn = (args) => <AsideHeaderShowcase {...args} />;
130+
const TopAlertTemplate: StoryFn<AsideHeaderShowcaseProps> = (args) => (
131+
<AsideHeaderShowcase {...args} />
132+
);
130133
export const HeaderAlert = TopAlertTemplate.bind({});
131134
HeaderAlert.args = {
132135
topAlert: {
@@ -148,6 +151,44 @@ HeaderAlertCentered.args = {
148151
},
149152
};
150153

154+
export const HeaderAlertCustom = TopAlertTemplate.bind({});
155+
HeaderAlertCustom.args = {
156+
topAlert: {
157+
render: ({handleClose}) => (
158+
<Flex
159+
direction="row"
160+
justifyContent="center"
161+
alignItems="center"
162+
gap={4}
163+
style={{
164+
position: 'relative',
165+
padding: '8px',
166+
background:
167+
' linear-gradient(120deg, #191654, #43cea2 40%, #185a9d 70%, #f857a6 100%)',
168+
}}
169+
>
170+
<Text variant="subheader-2" style={{color: 'var(--g-color-text-light-primary)'}}>
171+
We&apos;ve got something new for you to try!
172+
</Text>
173+
<Button view="normal-contrast" size="m">
174+
Try Now
175+
</Button>
176+
<Button view="outlined-contrast" size="m">
177+
Learn More
178+
</Button>
179+
<Button
180+
style={{position: 'absolute', right: '8px'}}
181+
view="flat-contrast"
182+
aria-label="Close"
183+
onClick={handleClose}
184+
>
185+
<Icon data={Xmark} size={18} />
186+
</Button>
187+
</Flex>
188+
),
189+
},
190+
};
191+
151192
const fallbackArgs = {
152193
headerDecoration: true,
153194
subheaderItemsCount: 2,

src/components/AsideHeader/__stories__/AsideHeaderShowcase.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import {
1111
eventBroker,
1212
} from '@gravity-ui/uikit';
1313

14-
import {AsideHeader, AsideHeaderProps, FooterItem, TopAlertProps} from '../..';
14+
import {AsideHeader, AsideHeaderProps, FooterItem} from '../..';
1515
import {ASIDE_HEADER_ICON_SIZE} from '../../constants';
16-
import {OpenModalSubscriber} from '../../types';
16+
import {OpenModalSubscriber, TopAlertProps} from '../../types';
1717
import {cn} from '../../utils/cn';
1818

1919
import {menuItemsShowcase, text as placeholderText} from './moc';
@@ -36,7 +36,7 @@ enum Panel {
3636
Components = 'components',
3737
}
3838

39-
interface AsideHeaderShowcaseProps {
39+
export interface AsideHeaderShowcaseProps {
4040
multipleTooltip?: boolean;
4141
initialCompact?: boolean;
4242
topAlert?: TopAlertProps;

src/components/AsideHeader/__tests__/AsideHeader.visual.test.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ test.describe('AsideHeader', () => {
6868
await expectScreenshot();
6969
});
7070

71+
test('render story: <HeaderAlertCustom>', async ({mount, expectScreenshot}) => {
72+
await mount(<AsideHeaderStories.HeaderAlertCustom />, undefined, {
73+
width: 1200,
74+
height: 720,
75+
});
76+
77+
await expectScreenshot();
78+
});
79+
7180
test('render story: <MultipleTooltip>', async ({mount, expectScreenshot}) => {
7281
await mount(<AsideHeaderStories.MultipleTooltip />, undefined, {
7382
width: 1200,

src/components/AsideHeader/types.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import * as React from 'react';
2+
13
import {QAProps} from '@gravity-ui/uikit';
24

35
import {RenderContentType} from '../Content';

src/components/TopAlert/TopAlert.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ export const TopAlert = ({alert, className, mobileView = false}: Props) => {
2424

2525
const handleClose = React.useCallback(() => {
2626
setOpened(false);
27-
alert?.onCloseTopAlert?.();
27+
28+
if (alert && 'onCloseTopAlert' in alert) {
29+
alert.onCloseTopAlert?.();
30+
}
2831
}, [alert]);
2932

3033
React.useEffect(() => {
@@ -33,10 +36,23 @@ export const TopAlert = ({alert, className, mobileView = false}: Props) => {
3336
}
3437
}, [opened, updateTopSize]);
3538

36-
if (!alert || !alert.message) {
39+
if (!alert) {
3740
return null;
3841
}
3942

43+
const {render} = alert;
44+
45+
if (typeof render === 'function') {
46+
return (
47+
<div
48+
ref={alertRef}
49+
className={b('wrapper', {'with-bottom-border': !mobileView && opened}, className)}
50+
>
51+
{opened && render({handleClose})}
52+
</div>
53+
);
54+
}
55+
4056
return (
4157
<div
4258
ref={alertRef}

src/components/types.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export interface LogoProps {
7777
'aria-labelledby'?: string;
7878
}
7979

80-
export interface TopAlertProps {
80+
interface TopAlertBaseProps {
8181
align?: AlertProps['align'];
8282
message: AlertProps['message'];
8383
title?: AlertProps['title'];
@@ -89,4 +89,11 @@ export interface TopAlertProps {
8989
centered?: boolean;
9090
dense?: boolean;
9191
onCloseTopAlert?: () => void;
92+
render?: never;
9293
}
94+
95+
export type TopAlertProps =
96+
| TopAlertBaseProps
97+
| {
98+
render: (params: {handleClose: () => void}) => React.ReactElement;
99+
};

0 commit comments

Comments
 (0)