Merge pull request 'DropDownMenu without Storybook' (#74) from DropDownMenu into develop
Reviewed-on: http://85.143.176.51:3000/free-land/front-end/pulls/74
This commit is contained in:
commit
43163a19b2
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