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 333e2af39678c0d5e8f00a179419a6f6f2b90e39
parent 6757ef8429b2ec6bcaf48abb8e1e65bba9edd16f
Author: Marcel <MTRNord@users.noreply.github.com>
Date:   Wed,  7 Jun 2023 18:21:38 +0200

Merge pull request #20 from MTRNord/MTRNord/css-grid

Initial conversion to a grid layout
Diffstat:
Achangelog.d/20.misc | 2++
Msrc/components/avatar/avatar.tsx | 2+-
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/components/roomList/roomListItem/roomListItem.tsx | 4++--
Msrc/index.scss | 3++-
Msrc/pages/MainPage.scss | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/pages/MainPage.tsx | 37+++++++++++++++++++------------------
10 files changed, 121 insertions(+), 26 deletions(-)

diff --git a/changelog.d/20.misc b/changelog.d/20.misc @@ -0,0 +1 @@ +Converting the flex layout to a flatter grid layout. +\ No newline at end of file diff --git a/src/components/avatar/avatar.tsx b/src/components/avatar/avatar.tsx @@ -30,7 +30,7 @@ const Avatar: FC<AvatarProps> = memo(({ avatarUrl, displayname, dm = false, onli if (avatarUrl && !error) { return ( - <div className="flex relative min-w-[2rem] min-h-[2rem] w-[2rem] h-[2rem] justify-center items-center m-0 mr-3 text-xl rounded-full text-white"> + <div className="flex relative min-w-[2rem] min-h-[2rem] w-[2rem] h-[2rem] justify-center items-center text-xl rounded-full text-white"> <img className="rounded-full w-8 h-8 object-cover" alt={displayname} src={avatarUrl} onError={() => { setError(true) }} /> { dm ? 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/components/roomList/roomListItem/roomListItem.tsx b/src/components/roomList/roomListItem/roomListItem.tsx @@ -58,12 +58,12 @@ const RoomListItem: FC<RoomListItemProps> = memo(({ roomId, avatarUrl, displayna { inView && (active ? ( <div className="flex flex-row gap-2 p-1 bg-gray-300 hover:bg-gray-400 rounded-lg duration-200 ease-in-out items-center"> - <Avatar avatarUrl={avatarUrl} displayname={displayname} dm={dm} online={online} /> + <Avatar avatarUrl={avatarUrl} displayname={displayname} dm={dm} online={online} isBot={false} /> <span title={displayname} className='text-slate-900 font-normal text-base max-w-[32ch] overflow-hidden text-ellipsis w-full whitespace-nowrap'>{displayname}</span> </div> ) : ( <div className="flex flex-row gap-2 p-1 hover:bg-gray-300 rounded-lg duration-200 ease-in-out items-center"> - <Avatar avatarUrl={avatarUrl} displayname={displayname} dm={dm} online={online} /> + <Avatar avatarUrl={avatarUrl} displayname={displayname} dm={dm} online={online} isBot={false} /> <span title={displayname} className='text-slate-900 font-normal text-base max-w-[32ch] overflow-hidden text-ellipsis w-full whitespace-nowrap'>{displayname}</span> </div> )) diff --git a/src/index.scss b/src/index.scss @@ -44,5 +44,6 @@ pre { * Blockquote should be light grey with a thick left border */ blockquote { - @apply border-l-4 border-gray-300 p-4 py-0 bg-slate-100 rounded-md; + @apply border-l-4 border-gray-300 p-4 py-0 bg-slate-100; + border-radius: 0 0.375rem 0.375rem 0; } \ No newline at end of file diff --git a/src/pages/MainPage.scss b/src/pages/MainPage.scss @@ -0,0 +1,69 @@ +#main-container { + display: grid; + grid-template-areas: + "sidebar header" + "sidebar main" + "sidebar editor"; + grid-template-columns: 40ch auto; + grid-template-rows: 60px 2fr auto; + grid-auto-flow: column; + row-gap: 0.5rem; + column-gap: 0.15em; + + #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 auto; + 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: auto 1fr; + 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 border-b-2 pt-4 pl-2; + display: flex; + flex-direction: row; + align-items: center; + justify-content: start; + gap: 1rem; + 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} /> - <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> + 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 mr-2'> + <h1 className='text-black font-semibold text-lg'>{room.getName()}</h1> + <Linkify options={linkifyOptions} as='p' className="ml-2 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> })