cetirizine

An experimental matrix client written in reactjs utilizing tailwind and storybook
git clone git://archive.git.mtrnord.blog/MTRNord/cetirizine.git
Log | Files | Refs | README | LICENSE

commit 9ff9b3af1cd6bd2e8a0ddf7932e6349b218ca6f7
parent 6757ef8429b2ec6bcaf48abb8e1e65bba9edd16f
Author: MTRNord <mtrnord1@gmail.com>
Date:   Tue,  6 Jun 2023 13:11:26 +0200

Initial conversion to a grid layout

Diffstat:
Msrc/components/input/chat/input.scss | 1+
Msrc/components/input/chat/input.tsx | 5+++--
Msrc/components/roomList/roomList.scss | 19+++++++++++++++++++
Msrc/components/roomList/roomList.tsx | 4++--
Msrc/pages/MainPage.scss | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/pages/MainPage.tsx | 31++++++++++++++++---------------
6 files changed, 106 insertions(+), 19 deletions(-)

diff --git a/src/components/input/chat/input.scss b/src/components/input/chat/input.scss @@ -2,6 +2,7 @@ @apply text-black relative font-normal; line-height: 20px; text-align: left; + height: 100%; } .editor-inner { diff --git a/src/components/input/chat/input.tsx b/src/components/input/chat/input.tsx @@ -81,6 +81,7 @@ type ChatInputProps = { * The current Room */ room: Room + id?: string }; function Placeholder() { @@ -265,7 +266,7 @@ const RoomChangePlugin: FC<RoomChangeProps> = ({ room }) => { return <></> } -const ChatInput: FC<ChatInputProps> = memo(({ namespace, room }: ChatInputProps) => { +const ChatInput: FC<ChatInputProps> = memo(({ namespace, room, id }: ChatInputProps) => { const [sending, setSending] = useState(false); const initialConfig: InitialConfigType = { @@ -295,7 +296,7 @@ const ChatInput: FC<ChatInputProps> = memo(({ namespace, room }: ChatInputProps) ] } return ( - <div className='flex flex-row items-end'> + <div id={id} className='flex flex-row items-end'> <LexicalComposer initialConfig={initialConfig}> <div className="editor-container flex-1"> <ToolbarPlugin /> diff --git a/src/components/roomList/roomList.scss b/src/components/roomList/roomList.scss @@ -14,4 +14,23 @@ background-color: rgba(155, 155, 155, 0.5); border-radius: 5px; border: transparent; +} + +#roomlist { + @apply p-2 px-4 overflow-y-auto overflow-x-hidden scrollbarSmall gap-1; + grid-area: roomlist; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + align-items: flex-start; + justify-content: flex-start; + height: 100%; + + .room-section { + user-select: none; + display: flex; + flex-direction: column; + width: 100%; + row-gap: 0.5rem; + } } \ No newline at end of file diff --git a/src/components/roomList/roomList.tsx b/src/components/roomList/roomList.tsx @@ -135,7 +135,7 @@ const RoomSection: FC<{ section: Section, onRoomClick: (roomID: string) => void, } }, [hidden]) return ( - <div ref={ref} key={section.roomID} className="flex flex-col gap-1 pl-4 select-none"> + <div ref={ref} key={section.roomID} className='room-section'> { inView && <div className="flex flex-row gap-2 py-1 items-center justify-start cursor-pointer h-8 text-slate-600" onClick={() => setHidden(prev => !prev)}> {hidden ? <ChevronRight size={14} /> : <ChevronDown size={14} />} @@ -169,7 +169,7 @@ const RoomList: FC<RoomListProps> = memo(({ sections, rooms, dmRooms }: RoomList const navigate = useNavigate(); return ( - <div className="flex flex-col gap-1 flex-1 p-2 min-w-[30ch] overflow-y-auto overflow-x-hidden scrollbarSmall max-w-[33ch]"> + <div id='roomlist'> <RoomSection section={{ sectionName: "DMs", diff --git a/src/pages/MainPage.scss b/src/pages/MainPage.scss @@ -0,0 +1,64 @@ +#main-container { + display: grid; + grid-template-areas: + "sidebar header" + "sidebar main" + "sidebar editor"; + grid-template-columns: 40ch 1fr; + grid-template-rows: 60px 2fr 1fr; + grid-auto-flow: column; + row-gap: 0.5rem; + column-gap: 0.1rem; + + #sidebar { + grid-area: sidebar; + @apply bg-gradient-to-br from-slate-100 via-gray-200 to-orange-200 border-r-[1px] border-slate-300; + display: grid; + grid-auto-flow: column; + grid-template-rows: 60px 1fr; + grid-template-areas: + "user-info" + "roomlist"; + height: 100vh; + + #user-info { + @apply p-3 items-center border-b-2; + grid-area: user-info; + column-gap: 0.5rem; + display: grid; + grid-auto-flow: row; + grid-template-columns: minmax(0, 1fr) 7fr; + grid-template-areas: + "avatar username"; + flex-direction: row; + align-items: center; + justify-self: flex-start; + width: 100%; + + #username-container { + grid-area: username; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + } + } + } + + #room-wrapper { + grid-area: header / header / editor-end / editor-end; + } + + #room-info { + @apply pb-2 flex flex-row items-center border-b-2 pt-4 pl-2; + grid-area: header; + } + + #chat-view { + grid-area: main; + } + + #chat-editor { + grid-area: editor; + } +} +\ No newline at end of file diff --git a/src/pages/MainPage.tsx b/src/pages/MainPage.tsx @@ -25,10 +25,11 @@ type ChatViewProps = { * If the roomID is valid, but the room is not joined, the ChatView will display a placeholder * If the roomID is valid, but the room is not loaded, the ChatView will display a placeholder */ - room?: Room + room?: Room, + id?: string }; -const ChatView: FC<ChatViewProps> = memo(({ room, }) => { +const ChatView: FC<ChatViewProps> = memo(({ room, id }) => { const client = useContext(MatrixContext); const [events, setEvents] = useState<IRoomEvent[]>([]); const [eventsFull, setEventsFull] = useState<IRoomEvent[]>([]); @@ -254,6 +255,7 @@ const ChatView: FC<ChatViewProps> = memo(({ room, }) => { return ( <Virtuoso + id={id} alignToBottom className='flex overflow-y-auto overflow-x-hidden scrollbarSmall' data={events} @@ -470,11 +472,11 @@ const MainPage = memo(() => { className: "text-blue-500 hover:text-blue-700 active:text-blue-700 visited:text-blue-500" } - return <div className='flex flex-row gap-2 min-h-screen h-screen'> - <div className='flex flex-col bg-gradient-to-br from-slate-100 via-gray-200 to-orange-200 border-r-[1px] border-slate-300'> - <div className='flex flex-row gap-2 m-2 p-1 items-center border-b-2'> - <Avatar displayname={profile.displayname || client.mxid!} avatarUrl={profile?.avatar_url} dm={false} online={OnlineState.Unknown} /> - <div className='flex flex-row justify-between items-center w-full'> + return <div id='main-container'> + <div id='sidebar'> + <div id="user-info"> + <Avatar displayname={profile.displayname || client.mxid!} avatarUrl={profile?.avatar_url} dm={false} online={OnlineState.Unknown} isBot={false} /> + <div id='username-container'> <span className='text-base font-semibold'>{profile?.displayname}</span> <Settings size={28} stroke='unset' className='stroke-slate-600 rounded-full hover:bg-slate-300 p-1 cursor-pointer' /> </div> @@ -482,19 +484,18 @@ const MainPage = memo(() => { <RoomList sections={sections} rooms={otherRooms} dmRooms={dmRooms} /> </div> { - room ? <div className='flex-1 flex flex-col' id='room-wrapper'> - <div className='pb-2 flex flex-row items-center border-b-2 mt-4 ml-2'> - <Avatar displayname={room.getName()} avatarUrl={room.getAvatarURL()} dm={room.isDM()} online={room.presence} /> + room ? <> + <div id="room-wrapper"></div> + <div id='room-info'> + <Avatar displayname={room.getName()} avatarUrl={room.getAvatarURL()} dm={room.isDM()} online={room.presence} isBot={false} /> <div className='flex flex-row items-start'> <h1 className='text-black font-semibold text-lg flex-shrink-0'>{room.getName()}</h1> <Linkify options={linkifyOptions} as='p' className="ml-4 text-slate-700 font-normal text-base line-clamp-2 text-ellipsis">{room.getTopic()}</Linkify> </div> </div> - <div className='my-1 flex-1 flex flex-col'> - <ChatView room={room} /> - </div> - <ChatInput namespace='Editor' room={room} /> - </div> : <></> + <ChatView id='chat-view' room={room} /> + <ChatInput id='chat-editor' namespace='Editor' room={room} /> + </> : <></> } </div> })