DropDownMenu without Storybook
This commit is contained in:
parent
895e054e7e
commit
15b640a3f2
116
src/components/drop-down-menu/ContextMenu.tsx
Normal file
116
src/components/drop-down-menu/ContextMenu.tsx
Normal 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>
|
||||
);
|
||||
}
|
36
src/components/drop-down-menu/ContextMenuAction.tsx
Normal file
36
src/components/drop-down-menu/ContextMenuAction.tsx
Normal 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>
|
||||
|
||||
);
|
||||
}
|
||||
|
27
src/components/drop-down-menu/ContextMenuItem.tsx
Normal file
27
src/components/drop-down-menu/ContextMenuItem.tsx
Normal 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>
|
||||
);
|
||||
}
|
101
src/components/drop-down-menu/MenuIcons.tsx
Normal file
101
src/components/drop-down-menu/MenuIcons.tsx
Normal 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>
|
||||
);
|
Loading…
x
Reference in New Issue
Block a user