react-miui 0.23.6 → 0.23.7-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/preview.tsx +1 -0
- package/CHANGELOG.md +8 -0
- package/dist/components/icons/Icon.d.ts +1 -0
- package/dist/components/icons/Icon.d.ts.map +1 -1
- package/dist/components/layout/header/Header.d.ts +1 -1
- package/dist/components/layout/header/Header.d.ts.map +1 -1
- package/dist/components/layout/header/Header.js +7 -14
- package/dist/components/layout/header/Header.js.map +1 -1
- package/dist/components/layout/header/Header.stories.d.ts +11 -0
- package/dist/components/layout/header/Header.stories.d.ts.map +1 -0
- package/dist/components/layout/header/Header.stories.js +65 -0
- package/dist/components/layout/header/Header.stories.js.map +1 -0
- package/dist/components/layout/header/Header.styled.d.ts +326 -0
- package/dist/components/layout/header/Header.styled.d.ts.map +1 -0
- package/dist/components/layout/header/Header.styled.js +98 -0
- package/dist/components/layout/header/Header.styled.js.map +1 -0
- package/dist/components/layout/header/HeaderIconAction.d.ts +1 -2
- package/dist/components/layout/header/HeaderIconAction.d.ts.map +1 -1
- package/dist/components/layout/header/HeaderIconAction.js +6 -11
- package/dist/components/layout/header/HeaderIconAction.js.map +1 -1
- package/dist/components/layout/header/HeaderIconAction.stories.d.ts +9 -0
- package/dist/components/layout/header/HeaderIconAction.stories.d.ts.map +1 -0
- package/dist/components/layout/header/HeaderIconAction.stories.js +43 -0
- package/dist/components/layout/header/HeaderIconAction.stories.js.map +1 -0
- package/dist/components/layout/header/HeaderIconAction.styled.d.ts +243 -0
- package/dist/components/layout/header/HeaderIconAction.styled.d.ts.map +1 -0
- package/dist/components/layout/header/HeaderIconAction.styled.js +35 -0
- package/dist/components/layout/header/HeaderIconAction.styled.js.map +1 -0
- package/dist/components/layout/header/StickyHeader.d.ts +2 -2
- package/dist/components/layout/header/StickyHeader.d.ts.map +1 -1
- package/dist/components/layout/header/StickyHeader.js +17 -8
- package/dist/components/layout/header/StickyHeader.js.map +1 -1
- package/dist/components/layout/header/StickyHeader.stories.d.ts +8 -0
- package/dist/components/layout/header/StickyHeader.stories.d.ts.map +1 -0
- package/dist/components/layout/header/StickyHeader.stories.js +30 -0
- package/dist/components/layout/header/StickyHeader.stories.js.map +1 -0
- package/dist/components/layout/header/StickyHeader.styled.d.ts +166 -0
- package/dist/components/layout/header/StickyHeader.styled.d.ts.map +1 -0
- package/dist/components/layout/header/StickyHeader.styled.js +40 -0
- package/dist/components/layout/header/StickyHeader.styled.js.map +1 -0
- package/docs/assets/search.js +1 -1
- package/docs/classes/Drawer.html +14 -14
- package/docs/classes/Pop.html +14 -14
- package/docs/classes/ToasterProvider.html +10 -10
- package/docs/enums/ICON.html +14 -14
- package/docs/functions/Action.html +5 -4
- package/docs/functions/Button.html +5 -4
- package/docs/functions/Card.html +5 -4
- package/docs/functions/Checkbox.html +5 -4
- package/docs/functions/Choice.html +6 -5
- package/docs/functions/CoveringLoader.html +5 -4
- package/docs/functions/DirectionPad.html +5 -4
- package/docs/functions/EqualActions.html +5 -4
- package/docs/functions/FullLoader.html +5 -4
- package/docs/functions/HandleEsc.html +5 -4
- package/docs/functions/Header.html +5 -4
- package/docs/functions/HeaderIconAction.html +8 -4
- package/docs/functions/Icon-1.html +7 -6
- package/docs/functions/If.html +5 -4
- package/docs/functions/Input.html +6 -5
- package/docs/functions/KeyValue.html +5 -4
- package/docs/functions/Label.html +5 -4
- package/docs/functions/List-1.html +5 -4
- package/docs/functions/Loader.html +5 -4
- package/docs/functions/Loading.html +5 -4
- package/docs/functions/Message.html +5 -4
- package/docs/functions/Modal-1.html +5 -4
- package/docs/functions/ModalButtons.html +5 -4
- package/docs/functions/PopLoader.html +5 -4
- package/docs/functions/PopOption.html +5 -4
- package/docs/functions/SearchContainer.html +5 -4
- package/docs/functions/Section.html +5 -4
- package/docs/functions/Select.html +5 -4
- package/docs/functions/Selector.html +6 -5
- package/docs/functions/Spacer.html +5 -4
- package/docs/functions/Stats.html +5 -4
- package/docs/functions/StickyHeader-1.html +5 -4
- package/docs/functions/StickyHeader.Content.html +5 -5
- package/docs/functions/Table.html +5 -4
- package/docs/functions/TextArea.html +5 -4
- package/docs/functions/Toggle.html +5 -4
- package/docs/functions/getCssText.html +5 -4
- package/docs/functions/styled.html +5 -4
- package/docs/functions/useToaster.html +6 -5
- package/docs/index.html +5 -4
- package/docs/interfaces/ActionProps.html +13 -13
- package/docs/interfaces/ChoiceProps.html +11 -11
- package/docs/interfaces/IconProps.html +79 -0
- package/docs/interfaces/InputCustomProps.html +10 -10
- package/docs/modules/List.html +7 -7
- package/docs/modules/Modal.html +6 -6
- package/docs/modules/StickyHeader.html +6 -6
- package/docs/modules.html +6 -4
- package/docs/pages/tutorials/Test.html +5 -4
- package/docs/types/InputProps.html +6 -5
- package/docs/types/ThemeCSS.html +6 -5
- package/docs/variables/List.Header.html +5 -5
- package/docs/variables/List.Item.html +5 -5
- package/docs/variables/Modal.RemovePadding.html +5 -5
- package/docs/variables/cssReset.html +6 -5
- package/docs/variables/miuiScrollbars.html +6 -5
- package/esm/components/icons/Icon.d.ts +1 -0
- package/esm/components/icons/Icon.d.ts.map +1 -1
- package/esm/components/layout/header/Header.d.ts +1 -1
- package/esm/components/layout/header/Header.d.ts.map +1 -1
- package/esm/components/layout/header/Header.js +7 -14
- package/esm/components/layout/header/Header.js.map +1 -1
- package/esm/components/layout/header/Header.stories.d.ts +11 -0
- package/esm/components/layout/header/Header.stories.d.ts.map +1 -0
- package/esm/components/layout/header/Header.stories.js +56 -0
- package/esm/components/layout/header/Header.stories.js.map +1 -0
- package/esm/components/layout/header/Header.styled.d.ts +326 -0
- package/esm/components/layout/header/Header.styled.d.ts.map +1 -0
- package/esm/components/layout/header/Header.styled.js +112 -0
- package/esm/components/layout/header/Header.styled.js.map +1 -0
- package/esm/components/layout/header/HeaderIconAction.d.ts +1 -2
- package/esm/components/layout/header/HeaderIconAction.d.ts.map +1 -1
- package/esm/components/layout/header/HeaderIconAction.js +6 -11
- package/esm/components/layout/header/HeaderIconAction.js.map +1 -1
- package/esm/components/layout/header/HeaderIconAction.stories.d.ts +9 -0
- package/esm/components/layout/header/HeaderIconAction.stories.d.ts.map +1 -0
- package/esm/components/layout/header/HeaderIconAction.stories.js +24 -0
- package/esm/components/layout/header/HeaderIconAction.stories.js.map +1 -0
- package/esm/components/layout/header/HeaderIconAction.styled.d.ts +243 -0
- package/esm/components/layout/header/HeaderIconAction.styled.d.ts.map +1 -0
- package/esm/components/layout/header/HeaderIconAction.styled.js +30 -0
- package/esm/components/layout/header/HeaderIconAction.styled.js.map +1 -0
- package/esm/components/layout/header/StickyHeader.d.ts +2 -2
- package/esm/components/layout/header/StickyHeader.d.ts.map +1 -1
- package/esm/components/layout/header/StickyHeader.js +6 -8
- package/esm/components/layout/header/StickyHeader.js.map +1 -1
- package/esm/components/layout/header/StickyHeader.stories.d.ts +8 -0
- package/esm/components/layout/header/StickyHeader.stories.d.ts.map +1 -0
- package/esm/components/layout/header/StickyHeader.stories.js +24 -0
- package/esm/components/layout/header/StickyHeader.stories.js.map +1 -0
- package/esm/components/layout/header/StickyHeader.styled.d.ts +166 -0
- package/esm/components/layout/header/StickyHeader.styled.d.ts.map +1 -0
- package/esm/components/layout/header/StickyHeader.styled.js +36 -0
- package/esm/components/layout/header/StickyHeader.styled.js.map +1 -0
- package/package.json +3 -3
- package/src/components/icons/Icon.tsx +4 -0
- package/src/components/layout/header/Header.stories.tsx +86 -0
- package/src/components/layout/header/Header.styled.ts +134 -0
- package/src/components/layout/header/Header.tsx +22 -19
- package/src/components/layout/header/HeaderIconAction.stories.tsx +47 -0
- package/src/components/layout/header/HeaderIconAction.styled.ts +40 -0
- package/src/components/layout/header/HeaderIconAction.tsx +30 -16
- package/src/components/layout/header/StickyHeader.stories.tsx +34 -0
- package/src/components/layout/header/StickyHeader.styled.ts +43 -0
- package/src/components/layout/header/StickyHeader.tsx +10 -19
- package/src/demo/componentsMap.ts +1 -67
- package/dist/components/layout/header/Header.module.scss +0 -108
- package/dist/components/layout/header/HeaderIconAction.module.scss +0 -26
- package/dist/components/layout/header/StickyHeader.module.scss +0 -18
- package/esm/components/layout/header/Header.module.scss +0 -108
- package/esm/components/layout/header/HeaderIconAction.module.scss +0 -26
- package/esm/components/layout/header/StickyHeader.module.scss +0 -18
- package/src/components/layout/header/Header.module.scss +0 -108
- package/src/components/layout/header/HeaderIconAction.module.scss +0 -26
- package/src/components/layout/header/StickyHeader.module.scss +0 -18
- package/src/demo/components/layout/header/Header.tsx +0 -118
- package/src/demo/components/layout/header/StickyHeader.module.scss +0 -14
- package/src/demo/components/layout/header/StickyHeader.tsx +0 -112
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import type { StoryObj, Meta } from "@storybook/react";
|
|
4
|
+
|
|
5
|
+
import { ICON } from "../../icons/Icon";
|
|
6
|
+
|
|
7
|
+
import { Header } from "./Header";
|
|
8
|
+
import { HeaderIconAction } from "./HeaderIconAction";
|
|
9
|
+
|
|
10
|
+
const meta: Meta = {
|
|
11
|
+
title: "Components/Layout/Header/Header",
|
|
12
|
+
component: Header,
|
|
13
|
+
tags: ["autodocs", "layout"],
|
|
14
|
+
|
|
15
|
+
argTypes: {
|
|
16
|
+
before: {
|
|
17
|
+
control: {
|
|
18
|
+
type: "text",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
after: {
|
|
22
|
+
control: {
|
|
23
|
+
type: "text",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
args: {
|
|
28
|
+
before: "Left side",
|
|
29
|
+
children: "Title",
|
|
30
|
+
after: "[Icons]",
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type Story = StoryObj<typeof Header>;
|
|
35
|
+
|
|
36
|
+
const Primary: Story = {};
|
|
37
|
+
const LongContent: Story = {
|
|
38
|
+
render: (args) => {
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-magic-numbers,react/no-array-index-key
|
|
40
|
+
const longContent = new Array(1000).fill(null).map((_, key) => <div key={key}>content</div>);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<>
|
|
44
|
+
<Header {...args} />
|
|
45
|
+
{longContent}
|
|
46
|
+
|
|
47
|
+
</>
|
|
48
|
+
);
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const handleClick = () => { alert(1); };
|
|
53
|
+
|
|
54
|
+
const WithButtons: Story = {
|
|
55
|
+
args: {
|
|
56
|
+
before: (
|
|
57
|
+
<>
|
|
58
|
+
<HeaderIconAction icon={ICON.back} onClick={handleClick} />
|
|
59
|
+
<HeaderIconAction icon={ICON.checkmark} onClick={handleClick} />
|
|
60
|
+
</>
|
|
61
|
+
),
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const Vertical: Story = {
|
|
66
|
+
args: {
|
|
67
|
+
before: (
|
|
68
|
+
<>
|
|
69
|
+
<HeaderIconAction icon={ICON.back} onClick={handleClick} />
|
|
70
|
+
<HeaderIconAction icon={ICON.checkmark} onClick={handleClick} />
|
|
71
|
+
</>
|
|
72
|
+
),
|
|
73
|
+
after: null,
|
|
74
|
+
position: "left",
|
|
75
|
+
children: "M",
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export {
|
|
80
|
+
Primary,
|
|
81
|
+
LongContent,
|
|
82
|
+
WithButtons,
|
|
83
|
+
Vertical,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default meta;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import type { ThemeCSS } from "../../../theme";
|
|
2
|
+
|
|
3
|
+
import { dimensionsPxToRem, pxToRem, styled } from "../../../theme";
|
|
4
|
+
import { EqualActions } from "../../ui/action/EqualActions";
|
|
5
|
+
|
|
6
|
+
const Contents = styled("div", {
|
|
7
|
+
flex: 1,
|
|
8
|
+
display: "flex",
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const Before = styled("div", {
|
|
12
|
+
display: "flex",
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const After = styled("div", {
|
|
16
|
+
display: "flex",
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const topBottomBeforeAfter: ThemeCSS = {
|
|
20
|
+
height: "100%",
|
|
21
|
+
padding: "7px 0",
|
|
22
|
+
boxSizing: "border-box",
|
|
23
|
+
display: "flex",
|
|
24
|
+
alignItems: "center",
|
|
25
|
+
justifyContent: "center",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const leftRightBeforeAfter: ThemeCSS = {
|
|
29
|
+
width: "100%",
|
|
30
|
+
padding: "0 7px",
|
|
31
|
+
boxSizing: "border-box",
|
|
32
|
+
display: "flex",
|
|
33
|
+
alignItems: "center",
|
|
34
|
+
justifyContent: "center",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const topBottomShared: ThemeCSS = {
|
|
38
|
+
padding: "0 16.666px",
|
|
39
|
+
height: "44px",
|
|
40
|
+
|
|
41
|
+
[`& ${Before.toString()}`]: topBottomBeforeAfter,
|
|
42
|
+
[`& ${After.toString()}`]: topBottomBeforeAfter,
|
|
43
|
+
|
|
44
|
+
[`& ${EqualActions.toString()}`]: {
|
|
45
|
+
margin: `${dimensionsPxToRem(56)} 0`,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const leftRightShared: ThemeCSS = {
|
|
50
|
+
padding: "16.666px 0",
|
|
51
|
+
width: "44px",
|
|
52
|
+
flexDirection: "column",
|
|
53
|
+
|
|
54
|
+
[`& ${Contents.toString()}`]: {
|
|
55
|
+
flexDirection: "column",
|
|
56
|
+
alignItems: "center",
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
[`& ${Before.toString()}`]: {
|
|
60
|
+
flexDirection: "column",
|
|
61
|
+
...leftRightBeforeAfter,
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
[`& ${After.toString()}`]: {
|
|
65
|
+
flexDirection: "column",
|
|
66
|
+
...leftRightBeforeAfter,
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
[`& ${EqualActions.toString()}`]: {
|
|
70
|
+
margin: `0 ${dimensionsPxToRem(56)}`,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const StyledHeader = styled("div", {
|
|
75
|
+
"--border-color": "$colors$headerBorder",
|
|
76
|
+
"--background-color": "$colors$headerBg",
|
|
77
|
+
"backgroundClip": "padding-box",
|
|
78
|
+
"background": "var(--background-color)",
|
|
79
|
+
"display": "flex",
|
|
80
|
+
"alignItems": "center",
|
|
81
|
+
"fontSize": pxToRem(15),
|
|
82
|
+
"fontWeight": "bold",
|
|
83
|
+
"boxSizing": "border-box",
|
|
84
|
+
"color": "$headerText",
|
|
85
|
+
"gap": dimensionsPxToRem(50),
|
|
86
|
+
|
|
87
|
+
"variants": {
|
|
88
|
+
variant: {
|
|
89
|
+
toolbar: {
|
|
90
|
+
"--border-color": "$colors$toolbarBorder",
|
|
91
|
+
"--background-color": "$colors$toolbarBg",
|
|
92
|
+
},
|
|
93
|
+
colored: {
|
|
94
|
+
"--border-color": "var(--custom-header-color)",
|
|
95
|
+
"--background-color": "var(--custom-header-color)",
|
|
96
|
+
"color": "var(--custom-text-color)",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
position: {
|
|
100
|
+
top: {
|
|
101
|
+
borderBottom: "0.37px solid var(--border-color)",
|
|
102
|
+
...topBottomShared,
|
|
103
|
+
},
|
|
104
|
+
bottom: {
|
|
105
|
+
borderTop: "0.37px solid var(--border-color)",
|
|
106
|
+
order: 2,
|
|
107
|
+
...topBottomShared,
|
|
108
|
+
},
|
|
109
|
+
left: {
|
|
110
|
+
borderRight: "0.37px solid var(--border-color)",
|
|
111
|
+
...leftRightShared,
|
|
112
|
+
},
|
|
113
|
+
right: {
|
|
114
|
+
borderLeft: "0.37px solid var(--border-color)",
|
|
115
|
+
order: 2,
|
|
116
|
+
...leftRightShared,
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
center: {
|
|
120
|
+
true: {
|
|
121
|
+
[`& ${Contents.toString()}`]: {
|
|
122
|
+
justifyContent: "center",
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
export {
|
|
130
|
+
StyledHeader,
|
|
131
|
+
Contents,
|
|
132
|
+
Before,
|
|
133
|
+
After,
|
|
134
|
+
};
|
|
@@ -1,32 +1,41 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import type { Div } from "../../native";
|
|
5
5
|
|
|
6
6
|
import { Action } from "../../ui/action/Action";
|
|
7
7
|
import { EqualActions } from "../../ui/action/EqualActions";
|
|
8
|
-
import { Div } from "../../native";
|
|
9
8
|
|
|
10
|
-
import
|
|
9
|
+
import { After, Before, Contents, StyledHeader } from "./Header.styled";
|
|
11
10
|
|
|
12
11
|
interface Props {
|
|
12
|
+
/**
|
|
13
|
+
* Should the main content (children) be centered?
|
|
14
|
+
*/
|
|
13
15
|
center?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Styling variant.
|
|
18
|
+
*/
|
|
14
19
|
variant?: "toolbar" | "colored";
|
|
15
20
|
/**
|
|
16
21
|
* This indicates just how the borders are drawn and how content is aligned, not the actual position on the screen.
|
|
17
22
|
* To set up position on the screen, you need to properly style the parent element.
|
|
18
23
|
*/
|
|
19
24
|
position?: "top" | "left" | "right" | "bottom"; // @TODO disallow left/right if not inside StickyHeader?
|
|
25
|
+
/**
|
|
26
|
+
* Content to be displayed before the main content.
|
|
27
|
+
*/
|
|
20
28
|
before?: ReactNode;
|
|
29
|
+
/**
|
|
30
|
+
* Content to be displayed after the main content.
|
|
31
|
+
*/
|
|
21
32
|
after?: ReactNode;
|
|
22
33
|
}
|
|
23
34
|
|
|
24
35
|
const Header: React.FC<React.ComponentProps<typeof Div> & Props> = (props) => {
|
|
25
36
|
const {
|
|
26
|
-
center,
|
|
27
|
-
variant,
|
|
28
37
|
position = "top",
|
|
29
|
-
|
|
38
|
+
before: _before, after: _after,
|
|
30
39
|
children,
|
|
31
40
|
...rest
|
|
32
41
|
} = props;
|
|
@@ -36,36 +45,30 @@ const Header: React.FC<React.ComponentProps<typeof Div> & Props> = (props) => {
|
|
|
36
45
|
return c && typeof c === "object" && "type" in c && c.type === Action;
|
|
37
46
|
});
|
|
38
47
|
|
|
39
|
-
const cls = classnames(styles.header, {
|
|
40
|
-
[styles["header--center"] as string]: center,
|
|
41
|
-
[styles["header--toolbar"] as string]: variant === "toolbar",
|
|
42
|
-
[styles["header--colored"] as string]: variant === "colored",
|
|
43
|
-
}, styles[`header--${position}`], props.className);
|
|
44
|
-
|
|
45
48
|
let contents = children;
|
|
46
49
|
if (justActions) {
|
|
47
50
|
const mode = position === "top" || position === "bottom" ? "horizontal" : "vertical";
|
|
48
|
-
contents = <EqualActions
|
|
51
|
+
contents = <EqualActions mode={mode}>{contents}</EqualActions>;
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
let before: ReactNode;
|
|
52
55
|
if (props.before != null) {
|
|
53
|
-
before = <
|
|
56
|
+
before = <Before>{props.before}</Before>;
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
let after: ReactNode;
|
|
57
60
|
if (props.after != null) {
|
|
58
|
-
after = <
|
|
61
|
+
after = <After>{props.after}</After>;
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
return (
|
|
62
|
-
<
|
|
65
|
+
<StyledHeader {...rest} position={position} data-header-position={position}>
|
|
63
66
|
{before}
|
|
64
|
-
<
|
|
67
|
+
<Contents>
|
|
65
68
|
{contents}
|
|
66
|
-
</
|
|
69
|
+
</Contents>
|
|
67
70
|
{after}
|
|
68
|
-
</
|
|
71
|
+
</StyledHeader>
|
|
69
72
|
);
|
|
70
73
|
};
|
|
71
74
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import type { StoryObj, Meta } from "@storybook/react";
|
|
4
|
+
|
|
5
|
+
import { Header } from "./Header";
|
|
6
|
+
import { HeaderIconAction } from "./HeaderIconAction";
|
|
7
|
+
|
|
8
|
+
const meta: Meta = {
|
|
9
|
+
title: "Components/Layout/Header/HeaderIconAction",
|
|
10
|
+
component: HeaderIconAction,
|
|
11
|
+
tags: ["autodocs", "layout"],
|
|
12
|
+
render: (args) => {
|
|
13
|
+
return (
|
|
14
|
+
<Header before={<HeaderIconAction {...args} icon={<>i</>} />}>
|
|
15
|
+
On the left you can see the icon
|
|
16
|
+
</Header>
|
|
17
|
+
);
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type Story = StoryObj<typeof Header>;
|
|
22
|
+
|
|
23
|
+
const Primary: Story = {};
|
|
24
|
+
|
|
25
|
+
const MultipleIcons: Story = {
|
|
26
|
+
render: ({ onClick: _onClick, ...args }) => {
|
|
27
|
+
const after = (
|
|
28
|
+
<>
|
|
29
|
+
<div>some text</div>
|
|
30
|
+
<HeaderIconAction {...args} icon={<>i</>} />
|
|
31
|
+
<HeaderIconAction {...args} icon={<>i</>} />
|
|
32
|
+
</>
|
|
33
|
+
);
|
|
34
|
+
return (
|
|
35
|
+
<Header after={after}>
|
|
36
|
+
On the left you can see the icon
|
|
37
|
+
</Header>
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export {
|
|
43
|
+
Primary,
|
|
44
|
+
MultipleIcons,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default meta;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ThemeCSS } from "../../../theme";
|
|
2
|
+
|
|
3
|
+
import { styled } from "../../../theme";
|
|
4
|
+
import { Icon } from "../../icons/Icon";
|
|
5
|
+
|
|
6
|
+
const sharedStyles: ThemeCSS = {
|
|
7
|
+
"blockSize": "100%",
|
|
8
|
+
"aspectRatio": "1",
|
|
9
|
+
"background": "none",
|
|
10
|
+
"borderRadius": "666px",
|
|
11
|
+
"display": "inline-flex",
|
|
12
|
+
"alignItems": "center",
|
|
13
|
+
"justifyContent": "center",
|
|
14
|
+
"border": "calc(2px / var(--ratio-border)) solid transparent",
|
|
15
|
+
"color": "currentColor",
|
|
16
|
+
|
|
17
|
+
"&:hover": {
|
|
18
|
+
background: "#00000022",
|
|
19
|
+
},
|
|
20
|
+
"&:active": {
|
|
21
|
+
background: "#00000011",
|
|
22
|
+
color: "currentColor",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const Btn = styled("button", sharedStyles);
|
|
27
|
+
const A = styled("a", sharedStyles);
|
|
28
|
+
|
|
29
|
+
const StyledIcon = styled(Icon, {
|
|
30
|
+
width: "16px",
|
|
31
|
+
height: "16px",
|
|
32
|
+
display: "block",
|
|
33
|
+
fill: "currentColor",
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
Btn,
|
|
38
|
+
A,
|
|
39
|
+
StyledIcon,
|
|
40
|
+
};
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
3
|
|
|
4
|
-
import classnames from "classnames";
|
|
5
|
-
|
|
6
4
|
import type { ICON } from "../../icons/Icon";
|
|
7
5
|
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
import styles from "./HeaderIconAction.module.scss";
|
|
6
|
+
import { A, Btn, StyledIcon } from "./HeaderIconAction.styled";
|
|
11
7
|
|
|
12
8
|
interface LinkProps { // @TODO extract? - same on list item
|
|
13
9
|
href: string;
|
|
@@ -15,21 +11,42 @@ interface LinkProps { // @TODO extract? - same on list item
|
|
|
15
11
|
}
|
|
16
12
|
|
|
17
13
|
interface Props {
|
|
14
|
+
/**
|
|
15
|
+
* Icon to display. Can be a string (for build in icons) or a ReactNode (any icon component).
|
|
16
|
+
*/
|
|
18
17
|
icon?: ICON | Exclude<ReactNode, string>;
|
|
18
|
+
/**
|
|
19
|
+
* Function to call when the icon is clicked.
|
|
20
|
+
*/
|
|
19
21
|
onClick?: () => void;
|
|
22
|
+
/**
|
|
23
|
+
* If given it will make the icon a native link.
|
|
24
|
+
*/
|
|
20
25
|
href?: string;
|
|
26
|
+
/**
|
|
27
|
+
* If given it will make the icon a custom link. `to` will be passed to given `Link` component as `href`.
|
|
28
|
+
*/
|
|
21
29
|
to?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Custom link component to use. Use with `to` prop.
|
|
32
|
+
*/
|
|
22
33
|
Link?: React.ComponentClass<LinkProps> | React.FC<LinkProps>;
|
|
23
|
-
|
|
24
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Additional class name to apply.
|
|
36
|
+
*/
|
|
37
|
+
className?: string | undefined;
|
|
25
38
|
}
|
|
26
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Use this component if you need a clickable icon that stylistically fits the header.
|
|
42
|
+
* It can be a simple link, a button or a custom link component.
|
|
43
|
+
*/
|
|
27
44
|
const HeaderIconAction: React.FC<Props> = (props) => {
|
|
28
|
-
const { icon,
|
|
45
|
+
const { icon, href, to, Link, className, ...restProps } = props;
|
|
29
46
|
|
|
30
47
|
let content: ReactNode = icon;
|
|
31
48
|
if (typeof icon === "string") {
|
|
32
|
-
content = <
|
|
49
|
+
content = <StyledIcon name={icon as ICON} />;
|
|
33
50
|
}
|
|
34
51
|
|
|
35
52
|
if (to) {
|
|
@@ -37,20 +54,17 @@ const HeaderIconAction: React.FC<Props> = (props) => {
|
|
|
37
54
|
throw new TypeError("`to` prop given without `Link` component");
|
|
38
55
|
}
|
|
39
56
|
|
|
40
|
-
|
|
41
|
-
return <Link href={to} {...restProps}><a className={aCls}>{content}</a></Link>;
|
|
57
|
+
return <Link href={to} {...restProps}><A className={props.className}>{content}</A></Link>;
|
|
42
58
|
}
|
|
43
59
|
|
|
44
60
|
if (href) {
|
|
45
|
-
|
|
46
|
-
return <a href={href} className={aCls} {...restProps}>{content}</a>;
|
|
61
|
+
return <A href={href} className={props.className} {...restProps}>{content}</A>;
|
|
47
62
|
}
|
|
48
63
|
|
|
49
|
-
const btnCls = classnames(props.className, styles.btn);
|
|
50
64
|
return (
|
|
51
|
-
<
|
|
65
|
+
<Btn className={props.className} onClick={props.onClick}>
|
|
52
66
|
{content}
|
|
53
|
-
</
|
|
67
|
+
</Btn>
|
|
54
68
|
);
|
|
55
69
|
};
|
|
56
70
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import type { StoryObj, Meta } from "@storybook/react";
|
|
4
|
+
|
|
5
|
+
import { StickyHeader } from "./StickyHeader";
|
|
6
|
+
import { Header } from "./Header";
|
|
7
|
+
|
|
8
|
+
const meta: Meta = {
|
|
9
|
+
title: "Components/Layout/Header/StickyHeader",
|
|
10
|
+
component: StickyHeader,
|
|
11
|
+
tags: ["autodocs", "layout"],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type Story = StoryObj<typeof StickyHeader>;
|
|
15
|
+
|
|
16
|
+
const Primary: Story = {
|
|
17
|
+
render: (args) => {
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-magic-numbers,react/no-array-index-key
|
|
19
|
+
const longContent = new Array(1000).fill(null).map((_, key) => <div key={key}>content</div>);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<StickyHeader {...args}>
|
|
23
|
+
<Header>x<br />x<br />x</Header>
|
|
24
|
+
<StickyHeader.Content>{longContent}</StickyHeader.Content>
|
|
25
|
+
</StickyHeader>
|
|
26
|
+
);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
Primary,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default meta;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { styled } from "../../../theme";
|
|
2
|
+
|
|
3
|
+
const StyledStickyHeader = styled("div", {
|
|
4
|
+
height: "100%",
|
|
5
|
+
display: "flex",
|
|
6
|
+
flexDirection: "column",
|
|
7
|
+
|
|
8
|
+
variants: {
|
|
9
|
+
position: {
|
|
10
|
+
top: {},
|
|
11
|
+
left: {
|
|
12
|
+
flexDirection: "row",
|
|
13
|
+
},
|
|
14
|
+
bottom: {},
|
|
15
|
+
right: {
|
|
16
|
+
flexDirection: "row",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const Content = styled("div", {
|
|
23
|
+
flex: 1,
|
|
24
|
+
overflow: "auto",
|
|
25
|
+
|
|
26
|
+
variants: {
|
|
27
|
+
position: {
|
|
28
|
+
top: {},
|
|
29
|
+
bottom: {
|
|
30
|
+
order: 1,
|
|
31
|
+
},
|
|
32
|
+
left: {},
|
|
33
|
+
right: {
|
|
34
|
+
order: 1,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
Content,
|
|
42
|
+
StyledStickyHeader,
|
|
43
|
+
};
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
-
import classnames from "classnames";
|
|
4
|
-
|
|
5
3
|
import { Header } from "./Header";
|
|
6
|
-
|
|
7
|
-
import styles from "./StickyHeader.module.scss";
|
|
4
|
+
import { Content, StyledStickyHeader } from "./StickyHeader.styled";
|
|
8
5
|
|
|
9
6
|
const err = new TypeError("StickyHeader needs two children - Header and StickyHeader.Content");
|
|
10
7
|
|
|
11
|
-
interface
|
|
8
|
+
interface ContentComponent {
|
|
12
9
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
13
10
|
Content: React.FC<ContentProps>;
|
|
14
11
|
}
|
|
@@ -24,10 +21,10 @@ interface Props {
|
|
|
24
21
|
children: React.ReactNode;
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
const StickyHeader: React.FC<Props> &
|
|
28
|
-
const
|
|
24
|
+
const StickyHeader: React.FC<Props> & ContentComponent = (props) => {
|
|
25
|
+
const { children: _children, position = "top", ...rest } = props;
|
|
29
26
|
|
|
30
|
-
const children = React.Children.toArray(
|
|
27
|
+
const children = React.Children.toArray(_children);
|
|
31
28
|
|
|
32
29
|
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
33
30
|
if (children.length !== 2) {
|
|
@@ -44,21 +41,15 @@ const StickyHeader: React.FC<Props> & Content = (props) => {
|
|
|
44
41
|
header = header as never; // @TODO find a better way to silence TS on cloneElement
|
|
45
42
|
content = content as never;
|
|
46
43
|
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
const contentCls = classnames(
|
|
50
|
-
styles.stickyHeader__content,
|
|
51
|
-
styles[`stickyHeader__content--${position}`],
|
|
52
|
-
(content as { props: ContentProps }).props.className,
|
|
53
|
-
);
|
|
44
|
+
const contentCls = (content as { props: ContentProps }).props.className;
|
|
54
45
|
|
|
55
46
|
return (
|
|
56
|
-
<
|
|
47
|
+
<StyledStickyHeader {...rest} position={position}>
|
|
57
48
|
{React.cloneElement(header, { position })}
|
|
58
|
-
<
|
|
49
|
+
<Content className={contentCls} position={position}>
|
|
59
50
|
{content}
|
|
60
|
-
</
|
|
61
|
-
</
|
|
51
|
+
</Content>
|
|
52
|
+
</StyledStickyHeader>
|
|
62
53
|
);
|
|
63
54
|
};
|
|
64
55
|
// eslint-disable-next-line react/no-multi-comp
|