DropDownMenu without Storybook

This commit is contained in:
filantrop 2022-08-15 15:18:18 +03:00
parent 895e054e7e
commit 15b640a3f2
4 changed files with 280 additions and 0 deletions

View File

@ -0,0 +1,116 @@
/* -------------------------------------------------------------------------- */
/* Imports */
/* -------------------------------------------------------------------------- */
import React, { Fragment } from "react";
import { Menu, Transition } from "@headlessui/react";
import { PropsPartion } from "./ContextMenuItem";
import classNames from "classnames";
import { ReactComponent as SelectIcon } from "assets/svg/select-arrow.svg";
type ChildType = React.ReactElement<any & PropsPartion[]>;
type ChildrenType = ChildType[] | ChildType;
/* -------------------------------------------------------------------------- */
/* Component props */
/* -------------------------------------------------------------------------- */
type MenuProps = {
emphasis?: "high" | "low";
disabled?: boolean;
className?: string | undefined;
button: React.ReactNode;
children: ChildrenType;
};
/* -------------------------------------------------------------------------- */
/* Styles */
/* -------------------------------------------------------------------------- */
const MenuButtonStyle = `
inline-flex
justify-center w-full
cursor-default
rounded
border border-gray-100
outline-8
bg-white
py-2
pl-4
pr-1
text-base`;
const MenuItemStyle = `
absolute
left-0
mt-2 w-60
origin-top-left
rounded
bg-white
shadow-lg
focus:outline-none
py-2 px-4 sm:text-sm`;
/* -------------------------------------------------------------------------- */
/* Component implementation */
/* -------------------------------------------------------------------------- */
/**
* Use width ContextMenuAction.tsx , for example:
* <ContextMenu button="MyButton" emphasis="low/high">
* <ContextMenuAction
* caption="First Menu"
* icon={icon}
* action={() => alert('click')}
* ></ContextMenuAction>
* ...
* </ContextMenu>
*/
export default function ContextMenu({
button,
children,
className,
emphasis = "low",
}: MenuProps) {
return (
<Menu as="div" className="relative inline-block text-right">
{({ open }) => (
<>
<Menu.Button
className={classNames([
`${MenuButtonStyle}`,
{ "bg-gray-100 font-bold uppercase": emphasis === "high" },
className,
])}
>
{button}
<SelectIcon
className={`${
open ? "rotate-180 transform" : "font-normal"
} my-2 mx-3 h-2 w-3 flex-center`}
aria-hidden="true"
/>
</Menu.Button>
<Transition
as={Fragment}
show={open}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
static
className={classNames([
className,
`${MenuItemStyle}`,
{ "ml-2": emphasis === "high" },
])}
>
{children}
</Menu.Items>
</Transition>
</>
)}
</Menu>
);
}

View File

@ -0,0 +1,36 @@
import classNames from "classnames";
import React from "react";
type Props = {
action: Function;
caption: string;
disabled?: boolean;
icon?: React.ReactNode;
className?: string | undefined;
};
export default function ContextMenuAction({
action,
caption,
disabled,
icon,
className,
}: Props) {
return (
<button
onClick={(e) => action(e)}
disabled={disabled}
className={classNames([
"group flex items-center text-base",
{ "opacity-50": disabled, "cursor-default": !disabled },
className,
])}
>
{icon && <div className="mr-2 h-5 w-5">{icon}</div>}
<span className="px-2 py-2">{caption}</span>
</button>
);
}

View File

@ -0,0 +1,27 @@
import {Menu} from '@headlessui/react';
import React from 'react';
export type PropsPartion = {
disabled?: boolean | undefined;
active?: boolean | undefined;
};
type Props = {
children: React.ReactElement<
any & PropsPartion
>;
} & PropsPartion;
/**
* Context menu item component
* @return {JSX.Element}
*/
export default function ContextMenuItem({children, ...props}: Props) {
return (
<Menu.Item {...props}>
{(params) => {
return React.cloneElement(children, params);
}}
</Menu.Item>
);
}

View File

@ -0,0 +1,101 @@
import React from "react";
/* -------------------------------------------------------------------------- */
/* Icons for header menu as our disign */
/* -------------------------------------------------------------------------- */
export const Publications = (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4 20V4C4 2.89543 4.89543 2 6 2H13.1716C13.702 2 14.2107 2.21071 14.5858 2.58579L19.4142 7.41421C19.7893 7.78929 20 8.29799 20 8.82843V20C20 21.1046 19.1046 22 18 22H6C4.89543 22 4 21.1046 4 20Z"
stroke="#262626"
stroke-width="2"
stroke-linecap="round"
/>
<path
d="M14 8L19 8"
stroke="#262626"
stroke-width="2"
stroke-linecap="round"
/>
<path
d="M14 3V8"
stroke="#262626"
stroke-width="2"
stroke-linecap="round"
/>
</svg>
);
export const MyFavorite = (
<svg
width="22"
height="21"
viewBox="0 0 22 21"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11 1L13.9048 7.50932L21 8.25735L15.7 13.0284L17.1803 20L11 16.4393L4.81966 20L6.3 13.0284L1 8.25735L8.09524 7.50932L11 1Z"
stroke="#262626"
stroke-width="2"
stroke-linejoin="round"
/>
</svg>
);
export const MyCollection = (
<svg
width="20"
height="16"
viewBox="0 0 20 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M18 15H2C1.44772 15 1 14.5523 1 14V2C1 1.44772 1.44772 1 2 1H6.58579C6.851 1 7.10536 1.10536 7.29289 1.29289L9.70711 3.70711C9.89464 3.89464 10.149 4 10.4142 4H18C18.5523 4 19 4.44772 19 5V14C19 14.5523 18.5523 15 18 15Z"
stroke="#262626"
stroke-width="2"
/>
<path
d="M11 7C11 6.44772 10.5523 6 10 6C9.44772 6 9 6.44772 9 7H11ZM9 12C9 12.5523 9.44772 13 10 13C10.5523 13 11 12.5523 11 12H9ZM9 7V12H11V7H9Z"
fill="#262626"
/>
<path
d="M12.5 10.5C13.0523 10.5 13.5 10.0523 13.5 9.5C13.5 8.94772 13.0523 8.5 12.5 8.5L12.5 10.5ZM7.5 8.5C6.94772 8.5 6.5 8.94771 6.5 9.5C6.5 10.0523 6.94772 10.5 7.5 10.5L7.5 8.5ZM12.5 8.5L7.5 8.5L7.5 10.5L12.5 10.5L12.5 8.5Z"
fill="#262626"
/>
</svg>
);
export const RecentViewed = (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 12C1 12 5 4 12 4C19 4 23 12 23 12C23 12 19 20 12 20C5 20 1 12 1 12Z"
stroke="#262626"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z"
stroke="#262626"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);