Initial Storybook setup (#110)

* Storybook setup

Storybook can be started using `npm run storybook`

* moved files and bugfix

Moved component files into their own directory and moved stories next to them. Fixed a bug with loading images

* prettier and bugfix

* prettier and bugfix

* Absolute Import in Header.tsx

* import fix

some imports did not work after merging

* Storybook update for chakra ui to properly work

* Prettier main.js

* comment in preview.js about hacky solution

* webpack final update and prettier update to preview

* Updated website/readme to include storybook description

* prettier...

* Delete docker-compose 2.yaml
This commit is contained in:
jojopirker
2022-12-29 10:44:14 +01:00
committed by GitHub
parent a4e5f566a8
commit cb317ebccb
15 changed files with 28990 additions and 2592 deletions
@@ -0,0 +1,24 @@
import { SessionContext } from "next-auth/react";
import React from "react";
import { Header } from "./Header";
export default {
title: "Header/Header",
component: Header,
parameters: {
layout: "fullscreen",
},
};
const Template = (args) => {
var { session } = args;
return (
<SessionContext.Provider value={session}>
<Header {...args} />
</SessionContext.Provider>
);
};
export const Default = Template.bind({});
Default.args = { session: { data: { user: { name: "StoryBook user" } }, status: "authenticated" } };
+122
View File
@@ -0,0 +1,122 @@
import { Button } from "@chakra-ui/react";
import { Popover } from "@headlessui/react";
import { AnimatePresence, motion } from "framer-motion";
import Image from "next/image";
import Link from "next/link";
import { signOut, useSession } from "next-auth/react";
import { FaUser, FaSignOutAlt } from "react-icons/fa";
import { Container } from "src/components/Container";
import { NavLinks } from "./NavLinks";
import { UserMenu } from "./UserMenu";
function MenuIcon(props) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" {...props}>
<path d="M5 6h14M5 18h14M5 12h14" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
</svg>
);
}
function ChevronUpIcon(props) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" {...props}>
<path d="M17 14l-5-5-5 5" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
</svg>
);
}
function MobileNavLink({ children, ...props }) {
return (
<Popover.Button
as={Link}
href={props.href}
className="block text-base leading-7 tracking-tight text-gray-700"
{...props}
>
{children}
</Popover.Button>
);
}
function AccountButton() {
const { data: session } = useSession();
if (session) {
return;
}
return (
<Link href="/auth/signin" aria-label="Home" className="flex items-center">
<Button variant="outline" leftIcon={<FaUser />}>
Sign in
</Button>
</Link>
);
}
export function Header() {
return (
<header className="bg-white">
<nav>
<Container className="relative z-10 flex justify-between py-8">
<div className="relative z-10 flex items-center gap-16">
<Link href="/" aria-label="Home" className="flex items-center">
<Image src="/images/logos/logo.svg" className="mx-auto object-fill" width="50" height="50" alt="logo" />
<span className="text-2xl font-bold ml-3">Open Assistant</span>
</Link>
<div className="hidden lg:flex lg:gap-10">
<NavLinks />
</div>
</div>
<div className="flex items-center gap-4">
<Popover className="lg:hidden">
{({ open }) => (
<>
<Popover.Button
className="relative z-10 inline-flex items-center rounded-lg stroke-gray-900 p-2 hover:bg-gray-200/50 hover:stroke-gray-600 active:stroke-gray-900 [&:not(:focus-visible)]:focus:outline-none"
aria-label="Toggle site navigation"
>
{({ open }) => (open ? <ChevronUpIcon className="h-6 w-6" /> : <MenuIcon className="h-6 w-6" />)}
</Popover.Button>
<AnimatePresence initial={false}>
{open && (
<>
<Popover.Overlay
static
as={motion.div}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-1 bg-gray-300/60 backdrop-blur"
/>
<Popover.Panel
static
as={motion.div}
initial={{ opacity: 0, y: -32 }}
animate={{ opacity: 1, y: 0 }}
exit={{
opacity: 0,
y: -32,
transition: { duration: 0.2 },
}}
className="absolute inset-x-0 top-0 z-0 origin-top rounded-b-2xl bg-white px-6 pb-6 pt-32 shadow-2xl shadow-gray-900/20"
>
<div className="space-y-4">
<MobileNavLink href="#join-us">Join Us</MobileNavLink>
<MobileNavLink href="#faqs">FAQs</MobileNavLink>
</div>
<div className="mt-8 flex flex-col gap-4"></div>
</Popover.Panel>
</>
)}
</AnimatePresence>
</>
)}
</Popover>
<AccountButton />
<UserMenu />
</div>
</Container>
</nav>
</header>
);
}
@@ -0,0 +1,14 @@
import { NavLinks } from "./NavLinks";
export default {
title: "Header/NavLinks",
component: NavLinks,
};
const Template = (args) => (
<div className="hidden lg:flex lg:gap-10">
<NavLinks {...args} />
</div>
);
export const Default = Template.bind({});
@@ -0,0 +1,40 @@
import { useState } from "react";
import Link from "next/link";
import { AnimatePresence, motion } from "framer-motion";
export function NavLinks(): JSX.Element {
let [hoveredIndex, setHoveredIndex] = useState(null);
return (
<>
{[
["Join Us", "#join-us"],
["FAQ", "#faq"],
].map(([label, href], index) => (
<Link
key={label}
href={href}
className="relative -my-2 -mx-3 rounded-lg px-3 py-2 text-sm text-gray-700 transition-colors delay-150 hover:text-gray-900 hover:delay-[0ms]"
onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(null)}
>
<AnimatePresence>
{hoveredIndex === index && (
<motion.span
className="absolute inset-0 rounded-lg bg-gray-100"
layoutId="hoverBackground"
initial={{ opacity: 0 }}
animate={{ opacity: 1, transition: { duration: 0.15 } }}
exit={{
opacity: 0,
transition: { duration: 0.15, delay: 0.2 },
}}
/>
)}
</AnimatePresence>
<span className="relative z-10">{label}</span>
</Link>
))}
</>
);
}
@@ -0,0 +1,25 @@
import { SessionContext } from "next-auth/react";
import React from "react";
import UserMenu from "./UserMenu";
export default {
title: "Header/UserMenu",
component: UserMenu,
};
const Template = (args) => {
var { session } = args;
return (
<SessionContext.Provider value={session}>
<div className="flex flex-col">
<div className="self-end">
<UserMenu {...args} />
</div>
</div>
</SessionContext.Provider>
);
};
export const Default = Template.bind({});
Default.args = { session: { data: { user: { name: "StoryBook user" } }, status: "authenticated" } };
@@ -0,0 +1,95 @@
import React from "react";
import { signOut, useSession } from "next-auth/react";
import Image from "next/image";
import { Popover } from "@headlessui/react";
import { AnimatePresence, motion } from "framer-motion";
import { FaCog, FaSignOutAlt, FaGithub } from "react-icons/fa";
export function UserMenu() {
const { data: session } = useSession();
if (!session) {
return <></>;
}
if (session && session.user) {
const email = session.user.email;
const accountOptions = [
{
name: "Account Settings",
href: "/account",
desc: "Account Settings",
icon: FaCog,
//For future use
},
];
return (
<Popover className="relative">
{({ open }) => (
<>
<Popover.Button aria-label="Toggle Account Options" className="flex">
<div className="flex items-center gap-4 p-1 lg:pr-6 rounded-full bg-white border border-slate-300/70 hover:bg-gray-200/50 transition-colors duration-300">
<Image
src="/images/temp-avatars/av1.jpg"
alt="Profile Picture"
width="40"
height="40"
className="rounded-full"
></Image>
<p className="hidden lg:flex">{session.user.name || session.user.email}</p>
</div>
</Popover.Button>
<AnimatePresence initial={false}>
{open && (
<>
<Popover.Panel
static
as={motion.div}
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{
opacity: 0,
y: -10,
transition: { duration: 0.2 },
}}
className="absolute right-0 mt-3 w-screen max-w-xs p-4 rounded-md bg-white border border-slate-300/70"
>
<div className="flex flex-col gap-1">
{accountOptions.map((item) => (
<a
key={item.name}
href={item.href}
aria-label={item.desc}
className="flex items-center rounded-md hover:bg-gray-200/50"
>
<div className="p-4">
<item.icon aria-hidden="true" />
</div>
<div>
<p>{item.name}</p>
</div>
</a>
))}
<a
className="flex items-center rounded-md hover:bg-gray-100 cursor-pointer"
onClick={() => signOut({ callbackUrl: "/" })}
>
<div className="p-4">
<FaSignOutAlt />
</div>
<div>
<p>Sign Out</p>
</div>
</a>
</div>
</Popover.Panel>
</>
)}
</AnimatePresence>
</>
)}
</Popover>
);
}
}
export default UserMenu;
+3
View File
@@ -0,0 +1,3 @@
export { Header } from "./Header";
export { UserMenu } from "./UserMenu";
export { NavLinks } from "./NavLinks";