Skip to content

Commit

Permalink
feat(plasma-new-hope): add header as separate components
Browse files Browse the repository at this point in the history
  • Loading branch information
TitanKuzmich committed Dec 3, 2023
1 parent b830b16 commit de6b826
Show file tree
Hide file tree
Showing 54 changed files with 1,400 additions and 1 deletion.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions packages/plasma-new-hope/src/components/Header/Header.tokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export const classes = {
headerLogoImage: 'header-logo-image',
headerArrow: 'header-arrow',
headerArrowIcon: 'header-arrow-icon',
headerArrowIconMinimize: 'header-arrow-icon-minimize',
headerRoot: 'header-root',
headerWithGradient: 'header-with-gradient',
headerWithDefaultSizes: 'header-with-default-sizes',
};

export const tokens = {
headerHeight: '--plasma-header-height',
headerPaddingTop: '--plasma-header-padding-top',
headerPaddingBottom: '--plasma-header-padding-bottom',

headerLogoMarginRight: '--plasma-header-logo-margin-right',

headerArrowTransition: '--plasma-header-arrow-transition',
headerArrowMarginRight: '--plasma-header-arrow-margin-right',
headerArrowIconSize: '--plasma-header-arrow-icon-size',

headerTitleMargin: '--plasma-header-title-margin',
headerBigTitleMargin: '--plasma-header-big-title-margin',
headerBiggerTitleMargin: '--plasma-header-bigger-title-margin',
headerLabelMargin: '--plasma-header-label-margin',
headerSubTitleMargin: '--plasma-header-subtitle-margin',
headerCaptionMargin: '--plasma-header-caption-margin',

headerTitleColor: '--plasma-header-title-color',
headerBigTitleColor: '--plasma-header-big-title-color',
headerBiggerTitleColor: '--plasma-header-bigger-title-color',
headerLabelColor: '--plasma-header-label-color',
headerSubTitleColor: '--plasma-header-subtitle-color',
headerCaptionColor: '--plasma-header-caption-color',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import { styled } from '@linaria/react';

const StyledHeaderContent = styled.div`
display: flex;
justify-content: flex-end;
flex: 1 0 max-content;
margin-left: auto;
padding-left: 0.75rem;
`;

/**
* Контейнер для контента шапки.
*/
export const HeaderContent = ({ children, ...rest }: React.HTMLAttributes<HTMLDivElement>) => (
<StyledHeaderContent {...rest}>{children}</StyledHeaderContent>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { styled } from '@linaria/react';

import { mediaQuery } from '../../../mixins';
import { classes, tokens } from '../Header.tokens';

import type { StyledHeaderRootProps } from './HeaderRoot.types';
import { sizes } from './HeaderRoot';

export const StyledHeaderRoot = styled.header<StyledHeaderRootProps>`
box-sizing: content-box;
width: 100%;
height: var(${tokens.headerHeight});
padding-top: var(${tokens.headerPaddingTop});
padding-bottom: var(${tokens.headerPaddingBottom});
--header_private-gradient-color: ${({ $gradientColor }) => $gradientColor};
&.${String(classes.headerWithGradient)} {
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: calc(
var(${tokens.headerHeight}) + var(${tokens.headerPaddingTop}) + var(${tokens.headerPaddingBottom})
);
background-image: linear-gradient(180deg, var(--header_private-gradient-color), rgba(0, 0, 0, 0));
}
};
&.${String(classes.headerWithDefaultSizes)} {
${mediaQuery('S', 1)(sizes.s)}
${mediaQuery('M')(sizes.m)}
${mediaQuery('L')(sizes.l)}
${mediaQuery('XL')(sizes.l)}
}
`;

export const StyledInner = styled.div`
position: relative;
display: flex;
align-items: center;
flex-direction: row;
width: 100%;
height: 100%;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React, { forwardRef } from 'react';

import type { RootProps } from '../../../engines';
import { classes, tokens } from '../Header.tokens';
import { cx } from '../../../utils';

import type { HeaderRootProps } from './HeaderRoot.types';
import { base as sizeCSS } from './variations/_size/base';
import { StyledHeaderRoot, StyledInner } from './HeaderRoot.styles';

export const sizes = {
/* sberBox */
l: `
${tokens.headerHeight}: 2.25rem; /* 36px */
${tokens.headerPaddingTop}: 1.875rem; /* 30px */
${tokens.headerPaddingBottom}: 0.875rem; /* 14px */
`,
/* sberPortal */
m: `
${tokens.headerHeight}: 2.25rem; /* 36px */
${tokens.headerPaddingTop}: 1.625rem; /* 26px */
${tokens.headerPaddingBottom}: 0.625rem; /* 10px */
`,
/* mobile */
s: `
${tokens.headerHeight}: 2.25rem; /* 36px */
${tokens.headerPaddingTop}: 0.375rem; /* 6px */
${tokens.headerPaddingBottom}: 0.375rem; /* 6px */
`,
};

/**
* Корневой узел для шапки.
*/
export const headerRoot = (Root: RootProps<HTMLDivElement, HeaderRootProps>) =>
forwardRef<HTMLDivElement, HeaderRootProps>((props, outerRootRef) => {
const { children, size, view, gradientColor, ...rest } = props;

const gradientColorClass = gradientColor ? classes.headerWithGradient : undefined;
const defaultSizesClass = size !== 'xk' ? classes.headerWithDefaultSizes : undefined;

return (
<Root ref={outerRootRef} size={size} view={view}>
<StyledHeaderRoot
className={cx(classes.headerRoot, gradientColorClass, defaultSizesClass)}
{...rest}
$gradientColor={gradientColor}
>
<StyledInner>{children}</StyledInner>
</StyledHeaderRoot>
</Root>
);
});

export const headerRootConfig = {
name: 'HeaderRoot',
tag: 'div',
layout: headerRoot,
base: '',
variations: {
size: {
css: sizeCSS,
},
},
defaults: {
size: 'm',
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { HtmlHTMLAttributes } from 'react';

import { sizes } from './HeaderRoot';

export type StyledHeaderRootProps = {
$size?: string;
$gradientColor?: string;
};

type HeaderRootCustomProps = {
/**
* Задать размер, зависимый от устройства.
* Если не задан, на каждом брейкпоинте будет свой размер.
*/
size?: keyof typeof sizes;
/**
* Цвет для создания градиента сверху вниз.
* Указаный цвет займет верхнюю точку градента,
* а его, рассчитываемая программно, прозрачная версия - нижнюю.
* Можно использовать hex, rgb и rgba значения цвета.
*/
gradientColor?: string;

view?: string;
};

export type HeaderRootProps = HtmlHTMLAttributes<HTMLDivElement> & HeaderRootCustomProps;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { css } from '@linaria/core';

export const base = css``;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
["--plasma-header-height", "--plasma-header-padding-top", "--plasma-header-padding-bottom"]
9 changes: 9 additions & 0 deletions packages/plasma-new-hope/src/components/Header/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export { headerLogoConfig, headerArrowConfig, headerTitleWrapperConfig, HeaderTitle } from './ui';
export type { HeaderLogoProps, HeaderArrowProps, HeaderTitleWrapperProps } from './ui';

export { HeaderContent } from './HeaderContent/HeaderContent';

export { headerRootConfig } from './HeaderRoot/HeaderRoot';
export type { HeaderRootProps } from './HeaderRoot/HeaderRoot.types';

export { tokens as headerTokens, classes as headerClasses } from './Header.tokens';
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { css } from '@linaria/core';

export const base = css`
position: absolute;
top: 0;
bottom: 0;
margin-top: auto;
margin-bottom: auto;
right: 100%;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React, { forwardRef } from 'react';
import type { HTMLAttributes } from 'react';

import { component, mergeConfig } from '../../../../engines';
import type { RootProps } from '../../../../engines';
import { buttonConfig } from '../../../Button';
import { classes, tokens } from '../../Header.tokens';
import { IconChevronLeft } from '../../../_Icon';
import { cx } from '../../../../utils';

import type { HeaderArrowProps } from './HeaderArrow.types';
import { base } from './HeaderArrow.styles';
import { base as sizeCSS } from './variations/_size/base';
import { base as viewCSS } from './variations/_view/base';

const mergedButtonConfig = mergeConfig(buttonConfig);
const Button = component(mergedButtonConfig);

/**
* Кнопка-стрелка с возможностью отображения в двух типах - "назад" или "свернуть".
*/
export const headerArrowRoot = (Root: RootProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>>) =>
forwardRef<HTMLDivElement, HeaderArrowProps>((props, outerRootRef) => {
const { arrow, iconSize = 's', ...rest } = props;

const minimizeClass = arrow === 'minimize' ? classes.headerArrowIconMinimize : undefined;

return (
<Root ref={outerRootRef}>
<Button view="clear" size="s" tabIndex={-1} className={classes.headerArrow} {...rest}>
<IconChevronLeft
size={iconSize}
sizeCustomProperty={tokens.headerArrowIconSize}
className={cx(classes.headerArrowIcon, minimizeClass)}
color="inherit"
{...props}
/>
</Button>
</Root>
);
});

export const headerArrowConfig = {
name: 'HeaderArrow',
tag: 'div',
layout: headerArrowRoot,
base,
variations: {
view: {
css: viewCSS,
},
size: {
css: sizeCSS,
},
},
defaults: {
view: 'primary',
size: 'm',
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { ButtonHTMLAttributes } from 'react';

import type { IconSize } from '../../../_Icon/IconRoot';

export type HeaderArrowProps = ButtonHTMLAttributes<HTMLButtonElement> & {
/**
* Тип стрелки.
*/
arrow?: 'back' | 'minimize';
iconSize?: IconSize;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { css } from '@linaria/core';

import { mediaQuery } from '../../../../../../mixins';
import { classes, tokens } from '../../../../Header.tokens';

export const base = css`
.${String(classes.headerArrow)} {
margin-right: var(${tokens.headerArrowMarginRight});
${mediaQuery('S')(`
position: static;
width: auto;
height: calc(var(${tokens.headerPaddingTop}) + var(${tokens.headerHeight}) + var(${tokens.headerPaddingBottom}));
padding: 0;
margin-right: 1rem;
margin-top: calc(var(${tokens.headerPaddingTop}) * -1);
`)}
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
["--plasma-header-arrow-margin-right", "--plasma-header-arrow-icon-size"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { css } from '@linaria/core';

import { classes, tokens } from '../../../../Header.tokens';

export const base = css`
.${String(classes.headerArrowIcon)} {
transition: var(${tokens.headerArrowTransition});
}
.${String(classes.headerArrowIconMinimize)} {
transform: rotate(-90deg);
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
["--plasma-header-arrow-transition"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { css } from '@linaria/core';

import { classes, tokens } from '../../Header.tokens';

export const base = css`
.${String(classes.headerLogoImage)} {
--plasma_private-header-size: var(${tokens.headerHeight});
width: var(--plasma_private-header-size);
height: var(--plasma_private-header-size);
flex: 0 0 var(--plasma_private-header-size);
margin-right: var(${tokens.headerLogoMarginRight});
}
`;
Loading

0 comments on commit de6b826

Please sign in to comment.