Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Header): add props before, beforeTitle, afterTitle, beforeSubtitle, afterSubtitle #7202

Merged
merged 10 commits into from
Aug 27, 2024
Merged
44 changes: 44 additions & 0 deletions packages/vkui/src/components/Header/Header.e2e-playground.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
import {
Icon12Fire,
Icon12Tag,
Icon16LockOutline,
Icon16UnlockOutline,
Icon28UserCircleFillBlue,
} from '@vkontakte/icons';
import { ComponentPlayground, type ComponentPlaygroundProps } from '@vkui-e2e/playground-helpers';
import { Counter } from '../Counter/Counter';
import { Link } from '../Link/Link';
Expand Down Expand Up @@ -49,6 +56,43 @@ export const HeaderPlayground = (props: ComponentPlaygroundProps) => {
mode: ['primary'],
size: ['regular', 'large'],
},
{
mode: ['primary'],
children: ['Кто может оставлять записи на моей странице'],
before: [<Icon28UserCircleFillBlue key="user" />],
},
{
mode: ['primary'],
children: ['Кто может оставлять записи на моей странице'],
beforeTitle: [<Icon16LockOutline key="beforeTitle" />],
},
{
mode: ['primary'],
children: ['Кто может оставлять записи на моей странице'],
afterTitle: [<Icon16UnlockOutline key="afterTitle" />],
},
{
mode: ['primary'],
children: ['Кто может оставлять записи на моей странице'],
subtitle: ['SOHN — Conrad'],
beforeSubtitle: [<Icon12Tag key="beforeSubtitle" />],
},
{
mode: ['primary'],
children: ['Кто может оставлять записи на моей странице'],
subtitle: ['SOHN — Conrad'],
afterSubtitle: [<Icon12Fire key="afterSubtitle" />],
},
{
mode: ['primary', 'secondary', 'tertiary'],
children: ['Кто может оставлять записи на моей странице'],
before: [<Icon28UserCircleFillBlue key="user" />],
beforeTitle: [<Icon16LockOutline key="beforeTitle" />],
afterTitle: [<Icon16UnlockOutline key="afterTitle" />],
beforeSubtitle: [<Icon12Tag key="beforeSubtitle" />],
afterSubtitle: [<Icon12Fire key="afterSubtitle" />],
subtitle: ['SOHN — Conrad'],
mendrew marked this conversation as resolved.
Show resolved Hide resolved
},
]}
>
{({ children, ...restProps }: HeaderProps) => (
Expand Down
51 changes: 46 additions & 5 deletions packages/vkui/src/components/Header/Header.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,46 @@
font-family: var(--vkui--font_family_base);
}

.Header__before,
.Header__subtitleBefore,
.Header__subtitleAfter,
.Header__content__before,
.Header__content__after {
display: flex;
flex-shrink: 0;
}

.Header__before {
align-self: center;
margin-inline-end: var(--vkui--spacing_size_m);
margin-block-start: var(--vkui--spacing_size_3xs);
}

.Header__before--withSubtitle {
margin-block-start: var(--vkui--spacing_size_s);
}

.Header__subtitleWrapper {
display: flex;
align-items: center;
}

.Header__subtitleBefore {
margin-inline-end: var(--vkui--spacing_size_xs);
}

.Header__subtitleAfter {
margin-inline-start: var(--vkui--spacing_size_xs);
}

.Header__content__before {
margin-inline-end: var(--vkui--spacing_size_xs);
}

.Header__content__after {
margin-inline-start: var(--vkui--spacing_size_xs);
}

.Header__main {
flex: 1 0 0;
min-inline-size: 0;
Expand All @@ -27,6 +67,7 @@
.Header__content--multiline {
white-space: initial;
word-break: break-word;
flex-grow: 1;
EldarMuhamethanov marked this conversation as resolved.
Show resolved Hide resolved
}

.Header__subtitle {
Expand All @@ -41,7 +82,7 @@

.Header__indicator {
color: var(--vkui--color_text_secondary);
margin-inline-start: 6px;
margin-inline-start: var(--vkui--spacing_size_xs);
flex-shrink: 0;
}

Expand Down Expand Up @@ -104,12 +145,12 @@
margin-block-end: 9px;
}

.Header__subtitle {
.Header__subtitleWrapper {
margin-block-end: 7px;
}

/* Компенсируем 1 пиксель из-за паддинга в .Header--mode-primary */
.Header--mode-primary .Header__subtitle {
.Header--mode-primary .Header__subtitleWrapper {
margin-block-end: 6px;
}

Expand Down Expand Up @@ -147,7 +188,7 @@
:global(.vkuiInternalGroup--mode-card)
> :global(.vkuiInternalTappable):first-child
> .Header:not(.Header--mode-tertiary) {
margin-block-start: -4px;
margin-block-start: calc(-1 * var(--vkui--spacing_size_xs));
}

@media (--sizeX-regular) {
Expand All @@ -157,7 +198,7 @@
:global(.vkuiInternalGroup--sizeX-none.vkuiInternalGroup--mode-none)
> :global(.vkuiInternalTappable):first-child
> .Header:not(.Header--mode-tertiary) {
margin-block-start: -4px;
margin-block-start: calc(-1 * var(--vkui--spacing_size_xs));
}
}

Expand Down
21 changes: 21 additions & 0 deletions packages/vkui/src/components/Header/Header.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Meta, StoryObj } from '@storybook/react';
import {
Icon12Fire,
Icon12Tag,
Icon16LockOutline,
Icon16UnlockOutline,
Icon28UserCircleFillBlue,
} from '@vkontakte/icons';
import { withSinglePanel, withVKUILayout } from '../../storybook/VKUIDecorators';
import { CanvasFullLayout, DisableCartesianParam } from '../../storybook/constants';
import { Counter } from '../Counter/Counter';
Expand Down Expand Up @@ -67,3 +74,17 @@ export const WithCounter: Story = {
withVKUILayout,
],
};

export const WithAllFeatures: Story = {
...Playground,
args: {
...Playground.args,
before: <Icon28UserCircleFillBlue />,
beforeTitle: <Icon16LockOutline />,
afterTitle: <Icon16UnlockOutline />,
beforeSubtitle: <Icon12Tag />,
afterSubtitle: <Icon12Fire />,
subtitle: 'SOHN — Conrad',
aside: <Link>Показать все</Link>,
},
};
62 changes: 53 additions & 9 deletions packages/vkui/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,26 @@
*/
indicator?: React.ReactNode;
multiline?: boolean;
/**
* Иконка слева (рекомендуется использовать размер 28px)
*/
before?: React.ReactElement;
/**
* Иконка слева от title (рекомендуется использовать размер 16px)
*/
beforeTitle?: React.ReactElement;
/**
* Иконка справа от title (рекомендуется использовать размер 16px)
*/
afterTitle?: React.ReactElement;
/**
* Иконка слева от subtitle (рекомендуется использовать размер 12px)
*/
beforeSubtitle?: React.ReactElement;
/**
* Иконка справа от subtitle (рекомендуется использовать размер 12px)
*/
afterSubtitle?: React.ReactElement;
}

type HeaderContentProps = Pick<HeaderProps, 'children' | 'mode' | 'size' | 'className'> &
Expand Down Expand Up @@ -83,6 +103,11 @@
indicator,
aside,
multiline,
before,
beforeTitle,
afterTitle,
beforeSubtitle,
afterSubtitle,
...restProps
}: HeaderProps): React.ReactNode => {
return (
Expand All @@ -96,13 +121,24 @@
hasReactNode(subtitle) && styles['Header--with-subtitle'],
)}
>
{before && (
<div
className={classNames(
styles['Header__before'],
subtitle && styles['Header__before--withSubtitle'],

Check warning on line 128 in packages/vkui/src/components/Header/Header.tsx

View check run for this annotation

Codecov / codecov/patch

packages/vkui/src/components/Header/Header.tsx#L128

Added line #L128 was not covered by tests
)}
>
{before}
</div>
)}
<div className={styles['Header__main']}>
<HeaderContent
className={styles['Header__content']}
Component={Component}
mode={mode}
size={size}
>
{beforeTitle && <div className={styles['Header__content__before']}>{beforeTitle}</div>}
<span
className={classNames(
styles['Header__content-in'],
Expand All @@ -111,23 +147,31 @@
>
{children}
</span>
{afterTitle && <div className={styles['Header__content__after']}>{afterTitle}</div>}
{hasReactNode(indicator) && (
<Footnote className={styles['Header__indicator']} weight="2">
{indicator}
</Footnote>
)}
</HeaderContent>

{hasReactNode(subtitle) && (
<Subhead
className={classNames(
styles['Header__subtitle'],
multiline && styles['Header__content--multiline'],
<div className={styles['Header__subtitleWrapper']}>
{beforeSubtitle && (
<div className={styles['Header__subtitleBefore']}>{beforeSubtitle}</div>
)}
Component={subtitleComponent}
>
{subtitle}
</Subhead>
<Subhead
className={classNames(
styles['Header__subtitle'],
multiline && styles['Header__content--multiline'],
)}
Component={subtitleComponent}
>
{subtitle}
</Subhead>
{afterSubtitle && (
<div className={styles['Header__subtitleAfter']}>{afterSubtitle}</div>
)}
</div>
)}
</div>

Expand Down
49 changes: 49 additions & 0 deletions packages/vkui/src/components/Header/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,55 @@ const Example = () => {
Большой заголовок
</Header>
</Group>
<Group>
<Header
mode="primary"
before={<Icon28UserCircleFillBlue />}
beforeTitle={<Icon16LockOutline />}
afterTitle={<Icon16UnlockOutline />}
beforeSubtitle={<Icon12Tag />}
afterSubtitle={<Icon12Fire />}
subtitle="SOHN — Conrad"
subtitleComponent="h3"
indicator={
<Counter size="s" mode="prominent">
3
</Counter>
}
aside={
<Link>
Показать все
{platform === 'vkcom' && <Icon12ChevronOutline />}
</Link>
}
>
Плейлисты
</Header>
<Header
mode="primary"
before={<Icon28UserCircleFillBlue />}
beforeTitle={<Icon16LockOutline />}
afterTitle={<Icon16UnlockOutline />}
beforeSubtitle={<Icon12Tag />}
afterSubtitle={<Icon12Fire />}
subtitle="SOHN — Conrad"
subtitleComponent="h3"
multiline
indicator={
<Counter size="s" mode="prominent">
3
</Counter>
}
aside={
<Link>
Показать все
{platform === 'vkcom' && <Icon12ChevronOutline />}
</Link>
}
>
Плейлисты
</Header>
</Group>
</Panel>
</View>
);
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading