From ac77a0ada25b927744114e7c6492a7d817b8d13d Mon Sep 17 00:00:00 2001 From: Szymon Szlachtowicz <38212223+Szymx95@users.noreply.github.com> Date: Wed, 3 Nov 2021 00:43:06 +0100 Subject: [PATCH] Refactor dropdowns (#109) --- .../src/components/Form/ChannelMenu.tsx | 116 ++++-------------- .../src/components/Form/DropdownMenu.tsx | 61 +++++++++ .../src/components/Form/ImageMenu.tsx | 56 +++------ .../src/components/Icons/CopyIcon.tsx | 23 +++- .../src/components/Icons/DownloadIcon.tsx | 23 +++- 5 files changed, 136 insertions(+), 143 deletions(-) create mode 100644 packages/react-chat/src/components/Form/DropdownMenu.tsx diff --git a/packages/react-chat/src/components/Form/ChannelMenu.tsx b/packages/react-chat/src/components/Form/ChannelMenu.tsx index 06fece5..bfd1d3c 100644 --- a/packages/react-chat/src/components/Form/ChannelMenu.tsx +++ b/packages/react-chat/src/components/Form/ChannelMenu.tsx @@ -1,5 +1,4 @@ import React from "react"; -import styled from "styled-components"; import { useMessengerContext } from "../../contexts/messengerProvider"; import { useNarrow } from "../../contexts/narrowProvider"; @@ -9,22 +8,8 @@ import { CheckSvg } from "../Icons/CheckIcon"; import { ClearSvg } from "../Icons/ClearIcon"; import { MembersSmallSvg } from "../Icons/MembersSmallIcon"; import { MuteSvg } from "../Icons/MuteIcon"; -import { textSmallStyles } from "../Text"; -type MenuItemProps = { - Svg: ({ width, height }: { width: number; height: number }) => JSX.Element; - text: string; - onClick: () => void; -}; - -function MenuItem({ Svg, text, onClick }: MenuItemProps) { - return ( - - - {text} - - ); -} +import { DropdownMenu, MenuItem, MenuText } from "./DropdownMenu"; interface ChannelMenuProps { channel: ChannelData; @@ -43,82 +28,35 @@ export const ChannelMenu = ({ const { clearNotifications } = useMessengerContext(); return ( - - - {narrow && ( - { - switchMemberList(); - setShowChannelMenu(false); - }} - Svg={MembersSmallSvg} - text="View Members" - /> - )} + + {narrow && ( { - channel.isMuted = true; + switchMemberList(); setShowChannelMenu(false); }} - Svg={MuteSvg} - text="Mute Chat" - /> - clearNotifications(channel.id)} - Svg={CheckSvg} - text="Mark as Read" - /> - messages.length === 0} - Svg={ClearSvg} - text="Clear History" - /> - - + > + + View Members + + )} + { + channel.isMuted = true; + setShowChannelMenu(false); + }} + > + + Mute Chat + + clearNotifications(channel.id)}> + + Mark as Read + + messages.length === 0}> + + Clear History + + ); }; - -const MenuBlock = styled.div` - width: 207px; - background: ${({ theme }) => theme.bodyBackgroundColor}; - box-shadow: 0px 2px 4px rgba(0, 34, 51, 0.16), - 0px 4px 12px rgba(0, 34, 51, 0.08); - borderradius: 8px; - padding: 8px 0; - position: absolute; - right: 8px; - top: calc(100% - 8px); - z-index: 2; -`; - -const MenuList = styled.ul` - list-style: none; -`; - -const Item = styled.li` - width: 100%; - display: flex; - align-items: center; - padding: 8px 14px; - cursor: pointer; - color: ${({ theme }) => theme.primary}; - - &:hover { - background: ${({ theme }) => theme.tertiary}; - color: ${({ theme }) => theme.bodyBackgroundColor}; - } - - & > svg { - fill: ${({ theme }) => theme.tertiary}; - } - - &:hover > svg { - fill: ${({ theme }) => theme.bodyBackgroundColor}; - } -`; - -const MenuText = styled.span` - margin-left: 6px; - - ${textSmallStyles} -`; diff --git a/packages/react-chat/src/components/Form/DropdownMenu.tsx b/packages/react-chat/src/components/Form/DropdownMenu.tsx new file mode 100644 index 0000000..5d46822 --- /dev/null +++ b/packages/react-chat/src/components/Form/DropdownMenu.tsx @@ -0,0 +1,61 @@ +import React, { ReactNode } from "react"; +import styled from "styled-components"; + +import { textSmallStyles } from "../Text"; + +type DropdownMenuProps = { + children: ReactNode; + className?: string; +}; + +export function DropdownMenu({ children, className }: DropdownMenuProps) { + return ( + + {children} + + ); +} + +export const MenuItem = styled.li` + width: 100%; + display: flex; + align-items: center; + padding: 8px 14px; + cursor: pointer; + color: ${({ theme }) => theme.primary}; + + &:hover { + background: ${({ theme }) => theme.tertiary}; + color: ${({ theme }) => theme.bodyBackgroundColor}; + } + + & > svg { + fill: ${({ theme }) => theme.tertiary}; + } + + &:hover > svg { + fill: ${({ theme }) => theme.bodyBackgroundColor}; + } +`; + +export const MenuText = styled.span` + margin-left: 6px; + + ${textSmallStyles} +`; +const MenuBlock = styled.div` + width: 207px; + background: ${({ theme }) => theme.bodyBackgroundColor}; + box-shadow: 0px 2px 4px rgba(0, 34, 51, 0.16), + 0px 4px 12px rgba(0, 34, 51, 0.08); + border-radius: 8px; + padding: 8px 0; + position: absolute; + right: 8px; + top: calc(100% - 8px); + z-index: 2; +`; + +const MenuList = styled.ul` + list-style: none; +`; diff --git a/packages/react-chat/src/components/Form/ImageMenu.tsx b/packages/react-chat/src/components/Form/ImageMenu.tsx index 7b2400c..e50a8c6 100644 --- a/packages/react-chat/src/components/Form/ImageMenu.tsx +++ b/packages/react-chat/src/components/Form/ImageMenu.tsx @@ -4,9 +4,10 @@ import styled from "styled-components"; import { useContextMenu } from "../../hooks/useContextMenu"; import { copyImg } from "../../utils/copyImg"; import { downloadImg } from "../../utils/downloadImg"; -import { CopyIcon } from "../Icons/CopyIcon"; -import { DownloadIcon } from "../Icons/DownloadIcon"; -import { textSmallStyles } from "../Text"; +import { CopySvg } from "../Icons/CopyIcon"; +import { DownloadSvg } from "../Icons/DownloadIcon"; + +import { DropdownMenu, MenuItem, MenuText } from "./DropdownMenu"; interface ImageMenuProps { imageId: string; @@ -16,51 +17,22 @@ export const ImageMenu = ({ imageId }: ImageMenuProps) => { const { showMenu } = useContextMenu(imageId); return showMenu ? ( - - - copyImg(imageId)}> - Copy image - - downloadImg(imageId)}> - - Download image - - - + + copyImg(imageId)}> + Copy image + + downloadImg(imageId)}> + + Download image + + ) : ( <> ); }; -const MenuBlock = styled.div` +const ImageDropdown = styled(DropdownMenu)` width: 176px; - height: 84px; - background: ${({ theme }) => theme.bodyBackgroundColor}; - box-shadow: 0px 2px 4px rgba(0, 34, 51, 0.16), - 0px 4px 12px rgba(0, 34, 51, 0.08); - border-radius: 8px; - padding: 8px 0; - position: absolute; left: 120px; top: 46px; - z-index: 2; -`; - -const MenuList = styled.ul` - list-style: none; -`; - -const MenuItem = styled.li` - width: 100%; - display: flex; - align-items: center; - padding: 8px 14px; - cursor: pointer; -`; - -const MenuText = styled.span` - margin-left: 6px; - color: ${({ theme }) => theme.primary}; - - ${textSmallStyles} `; diff --git a/packages/react-chat/src/components/Icons/CopyIcon.tsx b/packages/react-chat/src/components/Icons/CopyIcon.tsx index 3455faa..1f4a901 100644 --- a/packages/react-chat/src/components/Icons/CopyIcon.tsx +++ b/packages/react-chat/src/components/Icons/CopyIcon.tsx @@ -1,13 +1,20 @@ import React from "react"; import styled from "styled-components"; -export const CopyIcon = () => { +type CopySvgProps = { + width: number; + height: number; + className?: string; +}; + +export function CopySvg({ width, height, className }: CopySvgProps) { return ( - { clipRule="evenodd" d="M6.00016 4.00065C6.00016 2.52789 7.19407 1.33398 8.66683 1.33398H12.0002C13.4729 1.33398 14.6668 2.52789 14.6668 4.00065V7.33398C14.6668 8.80674 13.4729 10.0007 12.0002 10.0007H8.66683C7.19407 10.0007 6.00016 8.80674 6.00016 7.33398V4.00065ZM8.66683 2.33398H12.0002C12.9206 2.33398 13.6668 3.08018 13.6668 4.00065V7.33398C13.6668 8.25446 12.9206 9.00065 12.0002 9.00065H8.66683C7.74636 9.00065 7.00016 8.25446 7.00016 7.33398V4.00065C7.00016 3.08018 7.74636 2.33398 8.66683 2.33398Z" /> - + ); +} + +export const CopyIcon = () => { + return ; }; -const Icon = styled.svg` +const Icon = styled(CopySvg)` & > path { fill: ${({ theme }) => theme.tertiary}; } diff --git a/packages/react-chat/src/components/Icons/DownloadIcon.tsx b/packages/react-chat/src/components/Icons/DownloadIcon.tsx index c1afdaa..3d63c1a 100644 --- a/packages/react-chat/src/components/Icons/DownloadIcon.tsx +++ b/packages/react-chat/src/components/Icons/DownloadIcon.tsx @@ -1,21 +1,32 @@ import React from "react"; import styled from "styled-components"; -export const DownloadIcon = () => { +type DownloadSvgProps = { + width: number; + height: number; + className?: string; +}; + +export function DownloadSvg({ width, height, className }: DownloadSvgProps) { return ( - - + ); +} + +export const DownloadIcon = () => { + return ; }; -const Icon = styled.svg` +const Icon = styled(DownloadSvg)` & > path { fill: ${({ theme }) => theme.tertiary}; }