From 8346801e51baa2d00f9d678d2200c245d594f2c7 Mon Sep 17 00:00:00 2001 From: Maria Rushkova <66270386+mrushkova@users.noreply.github.com> Date: Tue, 5 Oct 2021 09:55:43 +0200 Subject: [PATCH] Add narrow mode (channels) (#35) --- .../react-chat/src/components/Channels.tsx | 29 ++++++-- packages/react-chat/src/components/Chat.tsx | 3 + .../src/components/Chat/ChatBody.tsx | 48 +++++++++++-- .../src/components/Chat/ChatInput.tsx | 4 ++ .../src/components/Chat/ChatMessages.tsx | 6 +- .../src/components/CommunityIdentity.tsx | 1 + .../src/components/Icons/BackIcon.tsx | 31 ++++++++ .../src/components/Icons/TagIcon.tsx | 37 ++++++++++ .../react-chat/src/components/Members.tsx | 12 +++- .../components/NarrowMode/NarrowChannels.tsx | 61 ++++++++++++++++ .../components/NarrowMode/NarrowTopbar.tsx | 70 +++++++++++++++++++ .../src/contexts/narrowProvider.tsx | 2 +- .../react-chat/src/styles/GlobalStyle.tsx | 1 - 13 files changed, 288 insertions(+), 17 deletions(-) create mode 100644 packages/react-chat/src/components/Icons/BackIcon.tsx create mode 100644 packages/react-chat/src/components/Icons/TagIcon.tsx create mode 100644 packages/react-chat/src/components/NarrowMode/NarrowChannels.tsx create mode 100644 packages/react-chat/src/components/NarrowMode/NarrowTopbar.tsx diff --git a/packages/react-chat/src/components/Channels.tsx b/packages/react-chat/src/components/Channels.tsx index acc6a2ba..5ce3461e 100644 --- a/packages/react-chat/src/components/Channels.tsx +++ b/packages/react-chat/src/components/Channels.tsx @@ -1,6 +1,7 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useMemo } from "react"; import styled from "styled-components"; +import { useNarrow } from "../contexts/narrowProvider"; import { ChannelData, channels } from "../helpers/channelsMock"; import { CommunityData } from "../helpers/communityMock"; import { Theme } from "../styles/themes"; @@ -81,6 +82,12 @@ export function Channel({ onClick, notification, }: ChannelProps) { + const narrow = useNarrow(); + const className = useMemo( + () => (narrow && !activeView ? "narrow" : activeView ? "active" : ""), + [narrow] + ); + return ( {!channel.icon && channel.name.slice(0, 1).toUpperCase()} @@ -134,6 +141,7 @@ interface ThemeProps { const ChannelsWrapper = styled.div` width: 21%; height: 100%; + min-width: 196px; background-color: ${({ theme }) => theme.sectionBackgroundColor}; padding: 10px 0.6%; display: flex; @@ -141,7 +149,7 @@ const ChannelsWrapper = styled.div` `; const StyledCommunity = styled(Community)` - padding-left: 0 0 0 10px; + padding: 0 0 0 10px; margin: 0 0 16px; `; @@ -152,10 +160,14 @@ const MembersAmount = styled.p` color: ${({ theme }) => theme.secondary}; `; -const ChannelList = styled.div` +export const ChannelList = styled.div` display: flex; flex-direction: column; - margin-top: 16px; + overflow-y: scroll; + + &::-webkit-scrollbar { + width: 0; + } `; const ChannelWrapper = styled.div` @@ -203,6 +215,13 @@ const ChannelLogo = styled.div` font-size: 20px; line-height: 20px; } + + &.narrow { + width: 40px; + height: 40px; + font-size: 20px; + line-height: 20px; + } `; const ChannelName = styled.p` diff --git a/packages/react-chat/src/components/Chat.tsx b/packages/react-chat/src/components/Chat.tsx index b2b63410..04c34df1 100644 --- a/packages/react-chat/src/components/Chat.tsx +++ b/packages/react-chat/src/components/Chat.tsx @@ -52,6 +52,9 @@ export function Chat({ theme, community }: ChatProps) { channel={activeChannel} messages={messages} sendMessage={sendMessage} + notifications={notifications} + setActiveChannel={setActiveChannel} + activeChannelId={activeChannel.id} onClick={() => setShowMembers(!showMembers)} showMembers={showMembers} community={community} diff --git a/packages/react-chat/src/components/Chat/ChatBody.tsx b/packages/react-chat/src/components/Chat/ChatBody.tsx index 80c99fd8..8fd89542 100644 --- a/packages/react-chat/src/components/Chat/ChatBody.tsx +++ b/packages/react-chat/src/components/Chat/ChatBody.tsx @@ -1,6 +1,7 @@ -import React from "react"; +import React, { useState } from "react"; import styled from "styled-components"; +import { useNarrow } from "../../contexts/narrowProvider"; import { ChannelData } from "../../helpers/channelsMock"; import { CommunityData } from "../../helpers/communityMock"; import { ChatMessage } from "../../models/ChatMessage"; @@ -8,6 +9,8 @@ import { Theme } from "../../styles/themes"; import { Channel } from "../Channels"; import { Community } from "../Community"; import { MembersIcon } from "../Icons/MembersIcon"; +import { NarrowChannels } from "../NarrowMode/NarrowChannels"; +import { NarrowTopbar } from "../NarrowMode/NarrowTopbar"; import { ChatInput } from "./ChatInput"; import { ChatMessages } from "./ChatMessages"; @@ -21,6 +24,9 @@ interface ChatBodyProps { onClick: () => void; showMembers: boolean; showCommunity: boolean; + notifications: { [id: string]: number }; + setActiveChannel: (val: ChannelData) => void; + activeChannelId: number; } export function ChatBody({ @@ -32,12 +38,19 @@ export function ChatBody({ onClick, showMembers, showCommunity, + notifications, + setActiveChannel, + activeChannelId, }: ChatBodyProps) { + const narrow = useNarrow(); + const [showChannelsList, setShowChannels] = useState(false); + const [showMembersList, setShowMembersList] = useState(false); + return ( - {showCommunity && ( + {(showCommunity || narrow) && ( @@ -48,18 +61,41 @@ export function ChatBody({ isActive={true} activeView={true} isMuted={false} + onClick={() => (narrow ? setShowChannels(true) : undefined)} /> setShowMembersList(true) : onClick} className={showMembers ? "active" : ""} theme={theme} > - - + {!showChannelsList && !showMembersList && ( + <> + + + + )} + {showChannelsList && narrow && ( + + )} + {showMembersList && narrow && ( + setShowMembersList(false)} + /> + )} ); } @@ -100,7 +136,7 @@ const CommunityWrap = styled.div` height: 24px; transform: translateY(-50%); border-radius: 1px; - background: ${({ theme }) => theme.textPrimaryColor}; + background: ${({ theme }) => theme.primary}; opacity: 0.1; } `; diff --git a/packages/react-chat/src/components/Chat/ChatInput.tsx b/packages/react-chat/src/components/Chat/ChatInput.tsx index 58454e54..26f732ca 100644 --- a/packages/react-chat/src/components/Chat/ChatInput.tsx +++ b/packages/react-chat/src/components/Chat/ChatInput.tsx @@ -125,6 +125,10 @@ const Input = styled.textarea` outline: none; caret-color: ${({ theme }) => theme.notificationColor}; } + + &::-webkit-scrollbar { + width: 0; + } `; const AddPictureBtn = styled.label` diff --git a/packages/react-chat/src/components/Chat/ChatMessages.tsx b/packages/react-chat/src/components/Chat/ChatMessages.tsx index 1808b53b..9a78790e 100644 --- a/packages/react-chat/src/components/Chat/ChatMessages.tsx +++ b/packages/react-chat/src/components/Chat/ChatMessages.tsx @@ -69,6 +69,10 @@ const MessagesWrapper = styled.div` height: calc(100% - 44px); overflow: auto; padding: 8px 16px 0; + + &::-webkit-scrollbar { + width: 0; + } `; const MessageWrapper = styled.div` @@ -142,6 +146,6 @@ const TimeWrapper = styled.div` const MessageText = styled.div` overflow-wrap: anywhere; width: 100%; - white-space: pre; + white-space: pre-wrap; color: ${({ theme }) => theme.primary}; `; diff --git a/packages/react-chat/src/components/CommunityIdentity.tsx b/packages/react-chat/src/components/CommunityIdentity.tsx index 41e4eb4e..2e6d7391 100644 --- a/packages/react-chat/src/components/CommunityIdentity.tsx +++ b/packages/react-chat/src/components/CommunityIdentity.tsx @@ -43,6 +43,7 @@ const Logo = styled.img` `; const Name = styled.p` + font-family: "Inter", sans-serif; font-weight: 500; color: ${({ theme }) => theme.primary}; diff --git a/packages/react-chat/src/components/Icons/BackIcon.tsx b/packages/react-chat/src/components/Icons/BackIcon.tsx new file mode 100644 index 00000000..7fdb97dc --- /dev/null +++ b/packages/react-chat/src/components/Icons/BackIcon.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import styled from "styled-components"; + +import { Theme } from "../../styles/themes"; + +interface ThemeProps { + theme: Theme; +} + +export const BackIcon = ({ theme }: ThemeProps) => { + return ( + + + + ); +}; + +const Icon = styled.svg` + & > path { + fill: ${({ theme }) => theme.primary}; + } +`; diff --git a/packages/react-chat/src/components/Icons/TagIcon.tsx b/packages/react-chat/src/components/Icons/TagIcon.tsx new file mode 100644 index 00000000..b567b481 --- /dev/null +++ b/packages/react-chat/src/components/Icons/TagIcon.tsx @@ -0,0 +1,37 @@ +import React from "react"; +import styled from "styled-components"; + +import { Theme } from "../../styles/themes"; + +interface ThemeProps { + theme: Theme; +} + +export const TagIcon = ({ theme }: ThemeProps) => { + return ( + + + + + ); +}; + +const Icon = styled.svg` + & > path { + fill: ${({ theme }) => theme.secondary}; + } +`; diff --git a/packages/react-chat/src/components/Members.tsx b/packages/react-chat/src/components/Members.tsx index 7742ef5b..49f47f13 100644 --- a/packages/react-chat/src/components/Members.tsx +++ b/packages/react-chat/src/components/Members.tsx @@ -96,6 +96,7 @@ interface ThemeProps { const MembersWrapper = styled.div` width: 18%; height: 100%; + min-width: 164px; display: flex; flex-direction: column; background-color: ${({ theme }) => theme.sectionBackgroundColor}; @@ -106,7 +107,7 @@ const MemberHeading = styled.h2` font-weight: 500; font-size: 15px; line-height: 22px; - color: ${({ theme }) => theme.textPrimaryColor}; + color: ${({ theme }) => theme.primary}; margin-bottom: 16px; `; @@ -114,7 +115,7 @@ const MemberCategoryName = styled.h3` font-weight: normal; font-size: 13px; line-height: 18px; - color: ${({ theme }) => theme.textSecondaryColor}; + color: ${({ theme }) => theme.secondary}; margin-bottom: 8px; `; @@ -122,7 +123,7 @@ const MemberName = styled.p` font-weight: 500; font-size: 15px; line-height: 22px; - color: ${({ theme }) => theme.textPrimaryColor}; + color: ${({ theme }) => theme.primary}; opacity: 0.7; margin-left: 8px; text-overflow: ellipsis; @@ -133,6 +134,11 @@ const MemberName = styled.p` const MembersList = styled.div` display: flex; flex-direction: column; + overflow-y: scroll; + + &::-webkit-scrollbar { + width: 0; + } `; const MemberCategory = styled.div` diff --git a/packages/react-chat/src/components/NarrowMode/NarrowChannels.tsx b/packages/react-chat/src/components/NarrowMode/NarrowChannels.tsx new file mode 100644 index 00000000..0cf191ef --- /dev/null +++ b/packages/react-chat/src/components/NarrowMode/NarrowChannels.tsx @@ -0,0 +1,61 @@ +import React from "react"; +import styled from "styled-components"; + +import { ChannelData, channels } from "../../helpers/channelsMock"; +import { Theme } from "../../styles/themes"; +import { Channel, ChannelList } from "../Channels"; + +import { NarrowTopbar } from "./NarrowTopbar"; + +interface NarrowChannelsProps { + theme: Theme; + community: string; + notifications: { [id: string]: number }; + setActiveChannel: (val: ChannelData) => void; + activeChannelId: number; + setShowChannels: (val: boolean) => void; +} + +export function NarrowChannels({ + theme, + community, + notifications, + setActiveChannel, + activeChannelId, + setShowChannels, +}: NarrowChannelsProps) { + return ( + + setShowChannels(false)} + /> + + {channels.map((channel) => ( + 0 && !channel.isMuted + ? notifications[channel.name] + : undefined + } + onClick={() => { + setActiveChannel(channel); + setShowChannels(false); + }} + /> + ))} + + + ); +} + +const ListWrapper = styled.div` + padding: 18px; +`; diff --git a/packages/react-chat/src/components/NarrowMode/NarrowTopbar.tsx b/packages/react-chat/src/components/NarrowMode/NarrowTopbar.tsx new file mode 100644 index 00000000..05bd6e86 --- /dev/null +++ b/packages/react-chat/src/components/NarrowMode/NarrowTopbar.tsx @@ -0,0 +1,70 @@ +import React from "react"; +import styled from "styled-components"; + +import { Theme } from "../../styles/themes"; +import { BackIcon } from "../Icons/BackIcon"; + +interface NarrowTopbarProps { + theme: Theme; + list: string; + community: string; + onClick: () => void; +} + +export function NarrowTopbar({ + theme, + list, + community, + onClick, +}: NarrowTopbarProps) { + return ( + + + + + + + {list} + {community} + + + ); +} + +interface ThemeProps { + theme: Theme; +} + +const TopbarWrapper = styled.div` + display: flex; + justify-content: center; + background-color: ${({ theme }) => theme.bodyBackgroundColor}; + padding: 14px 0; + position: relative; +`; + +const HeadingWrapper = styled.div` + display: flex; + flex-direction: column; + text-align: center; +`; + +const Heading = styled.p` + font-weight: 500; + color: ${({ theme }) => theme.primary}; +`; + +const SubHeading = styled.p` + font-weight: 500; + color: ${({ theme }) => theme.secondary}; +`; + +const GoBackBtn = styled.button` + width: 24px; + height: 24px; + margin-right: 18px; + position: absolute; + left: 0; + top: 50%; + transform: translateY(-50%); +`; diff --git a/packages/react-chat/src/contexts/narrowProvider.tsx b/packages/react-chat/src/contexts/narrowProvider.tsx index 0c5d3c28..9b52d6e4 100644 --- a/packages/react-chat/src/contexts/narrowProvider.tsx +++ b/packages/react-chat/src/contexts/narrowProvider.tsx @@ -14,6 +14,6 @@ interface NarrowProviderProps { } export function NarrowProvider({ children, myRef }: NarrowProviderProps) { - const narrow = useRefWidthBreak(myRef, 735); + const narrow = useRefWidthBreak(myRef, 736); return ; } diff --git a/packages/react-chat/src/styles/GlobalStyle.tsx b/packages/react-chat/src/styles/GlobalStyle.tsx index 588d3ae2..95492ef4 100644 --- a/packages/react-chat/src/styles/GlobalStyle.tsx +++ b/packages/react-chat/src/styles/GlobalStyle.tsx @@ -13,7 +13,6 @@ export const GlobalStyle = createGlobalStyle` font-weight: normal; font-size: 15px; line-height: 22px; - overflow-x: hidden; } html,