Skip to content

Commit 32c9e3f

Browse files
committed
Create a Header
1 parent 19808da commit 32c9e3f

File tree

4 files changed

+112
-0
lines changed

4 files changed

+112
-0
lines changed

src/Header/Header.stories.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { Meta, StoryObj } from "@storybook/react-vite";
2+
3+
import Header from ".";
4+
import { Placeholder } from "../Placeholder";
5+
import ColorSchemeToggle from "../ColorSchemeToggle";
6+
7+
const meta = {
8+
title: "Organism/Header",
9+
component: Header,
10+
} satisfies Meta<typeof Header>;
11+
12+
export default meta;
13+
type Story = StoryObj<typeof meta>;
14+
15+
export const Default = () => (
16+
<>
17+
<Header>
18+
<Header.Logo>
19+
<Placeholder height="100%" width="100px" label="Logo" />
20+
</Header.Logo>
21+
22+
<Header.Element>
23+
<ColorSchemeToggle />
24+
</Header.Element>
25+
<Header.Element>
26+
<Placeholder height="100%" width="100px" label="Primary Element" />
27+
</Header.Element>
28+
29+
<Header.Element>
30+
<Placeholder height="100%" label="Navigation Link" />
31+
</Header.Element>
32+
</Header>
33+
</>
34+
);

src/Header/index.scss

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
.header {
2+
width: 100%;
3+
height: 56px;
4+
padding: 1em;
5+
6+
align-items: center;
7+
display: flex;
8+
flex-direction: row;
9+
gap: 1em;
10+
justify-content: space-between;
11+
box-sizing: border-box;
12+
13+
.header__logo {
14+
height: 100%;
15+
display: flex;
16+
align-items: center;
17+
flex-direction: row;
18+
gap: 12px;
19+
}
20+
21+
.header__element {
22+
align-items: center;
23+
display: flex;
24+
flex-direction: row;
25+
gap: 1em;
26+
}
27+
}

src/Header/index.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { type FC } from "react";
2+
3+
import "./index.scss";
4+
import React from "react";
5+
import clsx from "clsx";
6+
7+
export interface HeaderProps {}
8+
9+
const Root: FC<React.PropsWithChildren<HeaderProps>> = ({ children }) => {
10+
let logo: React.ReactElement | undefined = undefined;
11+
let elements: React.ReactElement[] = [];
12+
13+
React.Children.forEach(children, (child) => {
14+
if (!React.isValidElement(child)) return;
15+
if (child.type === Header.Logo) {
16+
logo = child;
17+
} else if (child.type === Header.Element) {
18+
elements.push(child);
19+
} else {
20+
console.log("Dropping unknown children of Header.");
21+
}
22+
});
23+
24+
return (
25+
<div className={"header"}>
26+
{!!logo && <div className="header__logo">{logo}</div>}
27+
28+
{elements.length > 0 && <div className="header__element">{elements}</div>}
29+
</div>
30+
);
31+
};
32+
33+
export interface HeaderLogoProps {}
34+
const Logo: FC<React.PropsWithChildren<HeaderLogoProps>> = ({ children }) => {
35+
return children;
36+
};
37+
38+
export interface HeaderElementProps {}
39+
const Element: FC<React.PropsWithChildren<HeaderElementProps>> = ({
40+
children,
41+
}) => {
42+
return children;
43+
};
44+
45+
const Header = Object.assign(Root, {
46+
Logo,
47+
Element,
48+
});
49+
50+
export default Header;

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export {
4343
type GitHubButtonProps,
4444
default as GitHubButton,
4545
} from "./GitHubButton";
46+
export { type HeaderProps, default as Header } from "./Header";
4647
export {
4748
type PageLayoutProps,
4849
type PageLayoutHeaderProps,

0 commit comments

Comments
 (0)