1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

Add orbis floating chat

This commit is contained in:
Nuary Pradipta 2022-10-03 05:23:38 +07:00
parent e639b419d8
commit 07d69c1fb6
8 changed files with 446 additions and 19 deletions

3
src/@images/send.svg Normal file
View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.17699 1.119C1.25168 1.05563 1.34333 1.01559 1.44058 1.00386C1.53782 0.992127 1.63637 1.00921 1.72399 1.053L14.724 7.553C14.8069 7.59457 14.8767 7.6584 14.9254 7.73734C14.9741 7.81628 15 7.90723 15 8C15 8.09278 14.9741 8.18372 14.9254 8.26266C14.8767 8.34161 14.8069 8.40543 14.724 8.447L1.72399 14.947C1.63643 14.9909 1.5379 15.0081 1.44065 14.9965C1.34339 14.9849 1.25168 14.945 1.17691 14.8817C1.10213 14.8185 1.04759 14.7346 1.02005 14.6406C0.992509 14.5466 0.993183 14.4466 1.02199 14.353L2.97699 8L1.02199 1.647C0.993347 1.55348 0.992767 1.45361 1.02032 1.35976C1.04787 1.26591 1.10234 1.1822 1.17699 1.119V1.119ZM3.86899 8.5L2.32199 13.53L13.382 8L2.32199 2.47L3.86899 7.5H9.49999C9.63259 7.5 9.75977 7.55268 9.85354 7.64645C9.94731 7.74022 9.99999 7.86739 9.99999 8C9.99999 8.13261 9.94731 8.25979 9.85354 8.35355C9.75977 8.44732 9.63259 8.5 9.49999 8.5H3.86999H3.86899Z"/>
</svg>

After

Width:  |  Height:  |  Size: 996 B

View File

@ -0,0 +1,46 @@
.chatToolbar {
position: absolute;
bottom: 0;
left: 0;
right: 0;
width: 100%;
background-color: var(--background-content);
padding: calc(var(--spacer) / 2);
border-top: 1px solid var(--border-color);
border-bottom: 1px solid var(--border-color);
}
.chatMessage {
position: relative;
display: flex;
justify-content: space-between;
gap: calc(var(--spacer) / 2);
}
.chatMessage div {
width: 100%;
margin-bottom: 0;
}
.chatMessage label {
margin: 0;
}
.button {
right: calc(var(--spacer) / 4);
background-color: var(--background-content);
border: none;
cursor: pointer;
color: var(--brand-white);
font-size: var(--font-size-title);
transition: color 200ms ease;
}
.button:hover,
.button:focus {
color: var(--color-primary);
}
.sendIcon {
fill: currentColor;
}

View File

@ -0,0 +1,22 @@
import React from 'react'
import styles from './ChatToolbar.module.css'
import SendIcon from '@images/send.svg'
import Input from '@shared/FormInput'
export default function ChatToolbar() {
return (
<div className={styles.chatToolbar}>
<form className={styles.chatMessage}>
<Input
type="input"
name="message"
size="small"
placeholder="Type Message"
/>
<button className={styles.button}>
<SendIcon className={styles.sendIcon} />
</button>
</form>
</div>
)
}

View File

@ -0,0 +1,89 @@
.conversationBox {
padding: calc(var(--spacer) / 2);
height: calc(100% - (var(--spacer) * 3.5));
overflow-y: auto;
}
.conversationRecipient,
.conversationSend {
display: flex;
align-items: flex-end;
margin-bottom: calc(var(--spacer) / 2);
}
.conversationSend .chatBubbleItem {
text-align: right;
padding-left: 48px;
}
.colAvatar {
flex-shrink: 0;
padding-right: calc(var(--spacer) / 2);
}
.avatar {
aspect-ratio: 1/1;
border-radius: 100%;
border: 1px solid var(--border-color);
flex-shrink: 0;
width: calc(var(--font-size-large) * 2);
height: calc(var(--font-size-large) * 2);
}
.colBubble {
display: flex;
flex-direction: column;
width: 100%;
}
.chatBubbleItem {
display: block;
}
.chatBubbleItem + .chatBubbleItem {
margin-top: calc(var(--spacer) / 8);
}
.chatBubble {
display: inline-block;
background-color: var(--color-primary);
padding: calc(var(--spacer) / 4) calc(var(--spacer) / 2.5);
font-size: var(--font-size-base);
border-radius: 1rem;
}
.chatPrimary {
color: var(--brand-white);
background-color: var(--color-primary);
}
.chatDefault {
background-color: var(--border-color);
}
.conversationRecipient .colBubble .chatBubbleItem .chatBubble {
border-top-left-radius: 0;
border-bottom-left-radius: 0px;
}
.conversationRecipient .colBubble .chatBubbleItem:first-of-type .chatBubble {
border-top-left-radius: 1rem;
border-bottom-left-radius: 0px;
}
.conversationSend .colBubble .chatBubbleItem .chatBubble {
border-top-right-radius: 0;
border-bottom-right-radius: 0px;
text-align: left;
}
.conversationSend .colBubble .chatBubbleItem:first-of-type .chatBubble {
border-top-right-radius: 1rem;
border-bottom-left-radius: 0px;
}
.chatStamp {
font-size: var(--font-size-small);
color: var(--color-secondary);
padding-top: calc(var(--spacer) / 8);
}

View File

@ -0,0 +1,89 @@
import React from 'react'
import styles from './Conversation.module.css'
export default function DmConversation() {
const dummyData = [
{
name: 'realdatawhale.eth',
image: '/apple-touch-icon.png',
chat1: 'Hello friend whats up!',
chat2:
'I have this exact same issue with using brave browser. It wont prompt for metamask instead asking to connect to brave wallet.',
chat3: 'Hello!',
chat4: 'Yeah thats weird!',
chat5:
'Did you update your profile within Orbis or with an app you built?!',
timestamp: 'Jul 27, 2022, 3:39 AM'
}
]
return (
<>
{dummyData.map((dm, index) => (
<div className={styles.conversationBox} key={index}>
<div className={styles.conversationRecipient}>
<div className={styles.colAvatar}>
<img src={dm.image} alt="Avatar" className={styles.avatar}></img>
</div>
<div className={styles.colBubble}>
<div className={styles.chatBubbleItem}>
<div className={`${styles.chatBubble} ${styles.chatPrimary}`}>
{dm.chat1}
</div>
</div>
<div className={styles.chatBubbleItem}>
<div className={`${styles.chatBubble} ${styles.chatPrimary}`}>
{dm.chat2}
</div>
<div className={styles.chatStamp}>{dm.timestamp}</div>
</div>
</div>
</div>
<div className={styles.conversationSend}>
<div className={styles.colBubble}>
<div className={styles.chatBubbleItem}>
<div className={`${styles.chatBubble} ${styles.chatDefault}`}>
{dm.chat3}
</div>
</div>
<div className={styles.chatBubbleItem}>
<div className={`${styles.chatBubble} ${styles.chatDefault}`}>
{dm.chat4}
</div>
</div>
<div className={styles.chatBubbleItem}>
<div className={`${styles.chatBubble} ${styles.chatDefault}`}>
{dm.chat5}
</div>
<div className={styles.chatStamp}>{dm.timestamp}</div>
</div>
</div>
</div>
<div className={styles.conversationRecipient}>
<div className={styles.colAvatar}>
<img src={dm.image} alt="Avatar" className={styles.avatar}></img>
</div>
<div className={styles.colBubble}>
<div className={styles.chatBubbleItem}>
<div className={`${styles.chatBubble} ${styles.chatPrimary}`}>
{dm.chat1}
</div>
</div>
<div className={styles.chatBubbleItem}>
<div className={`${styles.chatBubble} ${styles.chatPrimary}`}>
{dm.chat4}
</div>
</div>
<div className={styles.chatBubbleItem}>
<div className={`${styles.chatBubble} ${styles.chatPrimary}`}>
{dm.chat2}
</div>
<div className={styles.chatStamp}>{dm.timestamp}</div>
</div>
</div>
</div>
</div>
))}
</>
)
}

View File

@ -1,5 +0,0 @@
import React from 'react'
export default function DmDetails() {
return <div>DmDetails</div>
}

View File

@ -9,23 +9,24 @@
right: 0;
bottom: 0;
left: 0;
transition: all 300ms ease 0s;
transition: transform 300ms ease 0s;
pointer-events: none;
z-index: 20;
}
.floating {
display: flex;
flex-direction: column;
pointer-events: auto;
width: 100%;
max-width: 400px;
height: 530px;
max-height: 80vh;
background-color: var(--brand-black);
background-color: var(--background-content);
border: 1px solid var(--border-color);
border-bottom: 0;
border-radius: var(--border-radius);
transform: translateY(0);
transition: all 0.3s ease-in-out;
}
.isClosed {
@ -36,6 +37,7 @@
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
padding: calc(0.35 * var(--spacer)) var(--spacer);
border-bottom: 1px solid var(--border-color);
box-shadow: var(--box-shadow);
@ -50,6 +52,22 @@
fill: var(--font-color-text);
}
.back {
margin-left: 0;
width: 1rem;
margin-right: calc(0.5 * var(--spacer));
fill: var(--font-color-text);
transform: rotate(180deg);
}
.btnBack {
border: none;
background-color: transparent;
padding: 0;
margin: 0;
cursor: pointer;
}
.toggle {
cursor: pointer;
margin-left: auto;
@ -68,9 +86,92 @@
transform: scaleY(-1);
}
.dmList {
position: relative;
overflow: auto;
height: 100%;
}
.dmItem {
padding: calc(var(--spacer) / 2);
display: flex;
padding: calc(var(--spacer) / 2) var(--spacer);
border-bottom: 1px solid var(--border-color);
cursor: pointer;
}
.dmDate {
font-size: var(--font-size-mini);
color: var(--font-color-text);
min-width: calc(var(--spacer) * 1.5);
text-align: right;
}
.dmCount {
background-color: var(--color-primary);
width: 20px;
height: 20px;
color: var(--brand-white);
border-radius: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: var(--font-size-mini);
font-weight: 600;
}
.accountAvatarSet .dmCount {
position: absolute;
bottom: -4px;
right: -4px;
}
.header .dmCount {
margin-left: calc(var(--spacer) / 4);
}
.accountInfo {
-webkit-box-flex: 1;
flex: 1;
padding-left: calc(var(--spacer) / 2);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
}
.accountHeading {
display: flex;
justify-content: space-between;
}
.accountAvatarSet {
position: relative;
flex-shrink: 0;
}
.accountAvatar {
aspect-ratio: 1/1;
border-radius: 100%;
border: 1px solid var(--border-color);
flex-shrink: 0;
width: calc(var(--font-size-large) * 2.5);
height: calc(var(--font-size-large) * 2.5);
margin-left: 0;
}
.accountName {
margin-bottom: calc(var(--spacer) / 6);
font-size: var(--font-size-medium);
color: var(--color-primary);
}
.accountChat {
font-size: var(--font-size-small);
color: var(--color-secondary);
margin-bottom: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dmDetails {
@ -79,7 +180,8 @@
left: 0;
right: 0;
bottom: 0;
background-color: var(--background-body);
height: 100%;
background-color: var(--background-content);
}
@media screen and (min-width: 42rem) {

View File

@ -1,16 +1,52 @@
import React, { useState } from 'react'
import ChatBubble from '@images/chatbubble.svg'
import ArrowBack from '@images/arrow.svg'
import ChevronDoubleUp from '@images/chevrondoubleup.svg'
import styles from './index.module.css'
import Conversation from './Conversation'
import ChatToolbar from './ChatToolbar'
export default function FloatingChat() {
const [opened, setOpened] = useState(false)
const [dmDetails, setDmDetails] = useState(null)
const dummyData = [{ name: 'John' }, { name: 'Jane' }]
const dummyData = [
{
name: '0xd30D…AFbD',
chat: 'Hello world!',
date: '15 Minutes Ago',
image: '/apple-touch-icon.png',
count: '3'
},
{
name: 'realdatawhale.eth',
chat: 'Getting some similar glitches with profile NFT. The current non-NFT photo works fine.',
date: '1 Day Ago',
image: '/apple-touch-icon.png',
count: '1'
},
{
name: 'hidetaka.eth',
chat: 'I already updated in the past.',
date: '1 Oct',
image: '/apple-touch-icon.png',
count: '0'
},
{
name: 'orbisclub.eth',
chat: 'Yeah that is weird, Did you update your profile within Orbis or with an app you built',
date: '1 Oct',
image: '/apple-touch-icon.png',
count: '0'
}
]
const openDetails = (name: string) => {
setDmDetails(name)
const sumCount = dummyData.reduce(function (prev, current) {
return prev + +current.count
}, 0)
function openDetails(id: string) {
setDmDetails(id)
}
return (
@ -19,6 +55,7 @@ export default function FloatingChat() {
<div className={styles.header}>
<ChatBubble role="img" aria-label="Chat" className={styles.icon} />
<span>Direct Messages</span>
{sumCount > 0 && <span className={styles.dmCount}>{sumCount}</span>}
<button
type="button"
className={styles.toggle}
@ -31,21 +68,65 @@ export default function FloatingChat() {
/>
</button>
</div>
<div style={{ position: 'relative' }}>
<div className={styles.dmList}>
{dummyData.map((dm, index) => (
<div
key={index}
className={styles.dmItem}
onClick={() => openDetails(dm.name)}
>
{dm.name}
<div className={styles.accountAvatarSet}>
<img
src={dm.image}
alt="Avatar"
className={styles.accountAvatar}
></img>
{dm.count > '0' && (
<div className={styles.dmCount}>{dm.count}</div>
)}
</div>
<div className={styles.accountInfo}>
<div className={styles.accountHeading}>
<h3 className={styles.accountName}>{dm.name}</h3>
<span className={styles.dmDate}>{dm.date}</span>
</div>
<p className={styles.accountChat}>{dm.chat}</p>
</div>
</div>
))}
{dmDetails && (
<div className={styles.dmDetails}>Details {dmDetails}</div>
)}
</div>
{dmDetails && (
<div className={styles.dmDetails}>
<div className={styles.header}>
<button
type="button"
aria-label="button"
className={styles.btnBack}
onClick={() => openDetails(null)}
>
<ArrowBack
role="img"
aria-label="arrow"
className={styles.back}
/>
</button>
<span>{dmDetails}</span>
<button
type="button"
className={styles.toggle}
onClick={() => setOpened(!opened)}
>
<ChevronDoubleUp
role="img"
aria-label="Toggle"
className={`${styles.icon} ${opened && styles.isFlipped}`}
/>
</button>
</div>
<Conversation />
<ChatToolbar />
</div>
)}
</div>
</div>
)