From e86f4545084522bd54cf7ce1b24ba31a59dbadf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Sat, 25 Nov 2023 18:58:00 -0500 Subject: [PATCH] Create a HeaderItem component with Dropdown --- lib/components/Dropdown/Dropdown.sass | 45 +++++++++++++++++++ lib/components/Dropdown/Dropdown.tsx | 55 ++++++++++++++++++++++++ lib/components/Header/Header.sass | 17 ++++++++ lib/components/Header/Header.stories.tsx | 15 ++++++- lib/components/Header/HeaderItem.tsx | 37 ++++++++++++++++ lib/index.ts | 13 ++++++ 6 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 lib/components/Dropdown/Dropdown.sass create mode 100644 lib/components/Dropdown/Dropdown.tsx create mode 100644 lib/components/Header/HeaderItem.tsx diff --git a/lib/components/Dropdown/Dropdown.sass b/lib/components/Dropdown/Dropdown.sass new file mode 100644 index 0000000..76af86d --- /dev/null +++ b/lib/components/Dropdown/Dropdown.sass @@ -0,0 +1,45 @@ +@use "../../styles/colors" +@use "../../styles/dimensions" + +.dropdown + display: none + position: absolute + background-color: colors.$bg-secondary + border-radius: dimensions.$border-radius + border: 1px solid colors.$bg-tertiary + box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.2) + top: 100% + right: 0 + padding: 4px + min-width: 150px + + &-item + display: flex + flex-direction: row + align-items: center + gap: 8px + padding: 12px 18px + color: colors.$fg-primary + text-decoration: none + cursor: pointer + border-radius: calc(dimensions.$border-radius - 4px) + + &:hover + color: colors.$bg-accent-hover + background-color: colors.$bg-tertiary-hover + + &-red + color: colors.$red + + &:hover + color: colors.$red-hover + + & .material-icon + font-size: 20px + margin: -4px 0 + margin-left: -4px + + &-opened + display: block + z-index: 100 + animation: dropdown 0.1s ease-in-out diff --git a/lib/components/Dropdown/Dropdown.tsx b/lib/components/Dropdown/Dropdown.tsx new file mode 100644 index 0000000..d4e37e8 --- /dev/null +++ b/lib/components/Dropdown/Dropdown.tsx @@ -0,0 +1,55 @@ +import cx from "classnames"; +import "./Dropdown.sass"; +import { Fragment, HTMLProps } from "react"; +import { Overlay } from "../Overlay/Overlay.tsx"; +import { MaterialIcon } from "../MaterialIcon/MaterialIcon.tsx"; + +export type DropdownProps = HTMLProps & { + opened?: boolean; + onClose?: () => void; +}; + +export function Dropdown(props: Readonly) { + const { className, opened, onClose, ...others } = props; + + return ( + +
+ + + ); +} + +export type DropdownItemProps = HTMLProps & { + icon?: string; + red?: boolean; +}; + +export function DropdownItem(props: Readonly) { + const { className, children, icon, red, ...others } = props; + + return ( +
+ {icon && } + {children} +
+ ); +} diff --git a/lib/components/Header/Header.sass b/lib/components/Header/Header.sass index 5413412..c91878c 100644 --- a/lib/components/Header/Header.sass +++ b/lib/components/Header/Header.sass @@ -62,3 +62,20 @@ & h1 padding: 10px 0 + + &-item + display: flex + flex-direction: row + align-items: center + gap: 8px + color: colors.$fg-primary + text-decoration: none + cursor: pointer + position: relative + padding: 10px 0 + + &:hover + color: colors.$bg-accent-hover + + &-opened + z-index: 100 diff --git a/lib/components/Header/Header.stories.tsx b/lib/components/Header/Header.stories.tsx index 04365d8..e1b20bc 100644 --- a/lib/components/Header/Header.stories.tsx +++ b/lib/components/Header/Header.stories.tsx @@ -5,6 +5,8 @@ import { LinkProps } from "../Link/Link.tsx"; import { HTMLProps } from "react"; import { MaterialIcon } from "../MaterialIcon/MaterialIcon.tsx"; import { ProfilePicture } from "../ProfilePicture/ProfilePicture.tsx"; +import { HeaderItem } from "./HeaderItem.tsx"; +import { DropdownItem } from "../Dropdown/Dropdown.tsx"; const meta: Meta = { title: "Components/Header", @@ -26,13 +28,24 @@ const linkBackProps: LinkProps> = { href: "#", }; +const items = ( + + Logout + +); + export const Normal: Story = { args: { appName: "Vertex App", linkBack: linkBackProps, linkLogo: linkLogoProps, leading: , - trailing: , + trailing: ( + + Arra + + + ), }, render: (props) => (
diff --git a/lib/components/Header/HeaderItem.tsx b/lib/components/Header/HeaderItem.tsx new file mode 100644 index 0000000..cf9e41d --- /dev/null +++ b/lib/components/Header/HeaderItem.tsx @@ -0,0 +1,37 @@ +import cx from "classnames"; +import { HTMLProps, ReactNode, useState } from "react"; +import { Dropdown } from "../Dropdown/Dropdown.tsx"; + +export type HeaderItemProps = HTMLProps & { + items?: ReactNode; +}; + +export function HeaderItem(props: Readonly) { + const { className, children, items, ...others } = props; + + const [opened, setOpened] = useState(false); + + const onClick = () => setOpened((o: boolean) => !o); + const close = () => setOpened(false); + + return ( +
+ {children} + {items !== undefined && ( + + {items} + + )} +
+ ); +} diff --git a/lib/index.ts b/lib/index.ts index 71a3b67..0b9c964 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -2,7 +2,14 @@ import { Box, BoxProps, BoxType } from "./components/Box/Box"; import { Button, ButtonProps } from "./components/Button/Button"; import { Checkbox, CheckboxProps } from "./components/Checkbox/Checkbox"; import { Code, CodeProps } from "./components/Code/Code"; +import { + Dropdown, + DropdownItem, + DropdownItemProps, + DropdownProps, +} from "./components/Dropdown/Dropdown"; import { Header, HeaderProps } from "./components/Header/Header"; +import { HeaderItem, HeaderItemProps } from "./components/Header/HeaderItem"; import { InlineCode, InlineCodeProps, @@ -65,7 +72,10 @@ export type { ButtonProps, CheckboxProps, CodeProps, + DropdownProps, + DropdownItemProps, HeaderProps, + HeaderItemProps, InlineCodeProps, InputProps, LayoutProps, @@ -94,7 +104,10 @@ export { Button, Checkbox, Code, + Dropdown, + DropdownItem, Header, + HeaderItem, PageContext, PageProvider, ProfilePicture,