/
Header.tsx
135 lines (127 loc) · 4.19 KB
/
Header.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import {
Divider,
Factory,
Group,
GroupProps,
Stack,
StylesApiProps,
Text,
Title,
factory,
useProps,
useStyles,
} from '@mantine/core';
import {Children, ReactElement, ReactNode} from 'react';
import {HeaderProvider} from './Header.context';
import classes from './Header.module.css';
import {HeaderActions, HeaderActionsStyleNames} from './HeaderActions/HeaderActions';
import {HeaderBreadcrumbs, HeaderBreadcrumbsStyleNames} from './HeaderBreadcrumbs/HeaderBreadcrumbs';
import {HeaderDocAnchor, HeaderDocAnchorStyleNames} from './HeaderDocAnchor/HeaderDocAnchor';
export type {HeaderActionsProps} from './HeaderActions/HeaderActions';
export type {HeaderBreadcrumbsProps} from './HeaderBreadcrumbs/HeaderBreadcrumbs';
export type {HeaderDocAnchorProps} from './HeaderDocAnchor/HeaderDocAnchor';
export type HeaderVariant = 'primary' | 'secondary';
export type HeaderStyleNames =
| 'root'
| 'title'
| 'description'
| 'divider'
| HeaderDocAnchorStyleNames
| HeaderBreadcrumbsStyleNames
| HeaderActionsStyleNames;
export interface HeaderProps extends StylesApiProps<HeaderFactory>, Omit<GroupProps, 'classNames' | 'styles' | 'vars'> {
/**
* The description text displayed inside the header underneath the title
*/
description?: ReactNode;
/**
* Whether the header should have a border on the bottom
*/
borderBottom?: boolean;
/**
* Use the primary variant for page header and secondary variant elsewhere
*
* @default 'primary'
*/
variant?: 'primary' | 'secondary';
/**
* The title of the header.
*/
children: ReactNode;
}
export type HeaderFactory = Factory<{
props: HeaderProps;
ref: HTMLDivElement;
variant: HeaderVariant;
stylesNames: HeaderStyleNames;
staticComponents: {
Breadcrumbs: typeof HeaderBreadcrumbs;
Actions: typeof HeaderActions;
DocAnchor: typeof HeaderDocAnchor;
};
}>;
const defaultProps: Partial<HeaderProps> = {
variant: 'primary',
justify: 'space-between',
wrap: 'nowrap',
};
export const Header = factory<HeaderFactory>((_props, ref) => {
const props = useProps('PlasmaHeader', defaultProps, _props);
const {
className,
description,
borderBottom,
variant,
children,
style,
classNames,
unstyled,
vars,
styles,
...others
} = props;
const getStyles = useStyles<HeaderFactory>({
name: 'PlasmaHeader',
props,
classes,
className,
style,
classNames,
styles,
unstyled,
vars,
});
const stylesApiProps = {classNames, styles};
const convertedChildren = Children.toArray(children) as ReactElement[];
const breadcrumbs = convertedChildren.find((child) => child.type === HeaderBreadcrumbs);
const actions = convertedChildren.find((child) => child.type === HeaderActions);
const docAnchor = convertedChildren.find((child) => child.type === HeaderDocAnchor);
const otherChildren = convertedChildren.filter(
(child) => child.type !== HeaderBreadcrumbs && child.type !== HeaderActions && child.type !== HeaderDocAnchor,
);
return (
<HeaderProvider value={{getStyles}}>
<Group ref={ref} variant={variant} {...getStyles('root')} {...others}>
<Stack gap={0}>
{breadcrumbs}
<Title
variant={variant}
order={variant === 'primary' ? 1 : 3}
{...getStyles('title', stylesApiProps)}
>
{otherChildren}
{docAnchor}
</Title>
<Text {...getStyles('description', stylesApiProps)} size={variant === 'primary' ? 'md' : 'sm'}>
{description}
</Text>
</Stack>
{actions}
</Group>
{borderBottom ? <Divider {...getStyles('divider', stylesApiProps)} size="xs" /> : null}
</HeaderProvider>
);
});
Header.Breadcrumbs = HeaderBreadcrumbs;
Header.Actions = HeaderActions;
Header.DocAnchor = HeaderDocAnchor;