UI improvements #24

Merged
verbiricha merged 15 commits from ui into main 2023-01-10 12:58:14 +00:00
7 changed files with 108 additions and 34 deletions
Showing only changes of commit e6abbcbc44 - Show all commits

View File

@ -3,9 +3,11 @@ import useEventPublisher from "../feed/EventPublisher";
export default function FollowButton(props) { export default function FollowButton(props) {
const pubkey = props.pubkey; const pubkey = props.pubkey;
const className = props.className ? `btn ${props.className}` : "btn";
const publiser = useEventPublisher(); const publiser = useEventPublisher();
const follows = useSelector(s => s.login.follows); const follows = useSelector(s => s.login.follows);
let isFollowing = follows?.includes(pubkey) ?? false;
const baseClassName = isFollowing ? `btn btn-warn` : `btn btn-success`
const className = props.className ? `${baseClassName} ${props.className}` : `${baseClassName}`;
async function follow(pubkey) { async function follow(pubkey) {
let ev = await publiser.addFollow(pubkey); let ev = await publiser.addFollow(pubkey);
@ -17,7 +19,6 @@ export default function FollowButton(props) {
publiser.broadcast(ev); publiser.broadcast(ev);
} }
let isFollowing = follows?.includes(pubkey) ?? false;
return ( return (
<div className={className} onClick={() => isFollowing ? unfollow(pubkey) : follow(pubkey)}> <div className={className} onClick={() => isFollowing ? unfollow(pubkey) : follow(pubkey)}>
{isFollowing ? "Unfollow" : "Follow"} {isFollowing ? "Unfollow" : "Follow"}

View File

@ -78,7 +78,7 @@ export default function Note(props) {
} }
return ( return (
<div className={`note ${hightlight && "active"} ${isThread && "thread"}`}> <div className={`note ${hightlight ? "active" : ""} ${isThread ? "thread" : ""}`}>
{options.showHeader ? {options.showHeader ?
<div className="header flex"> <div className="header flex">
<ProfileImage pubkey={ev.RootPubKey} subHeader={replyTag()} /> <ProfileImage pubkey={ev.RootPubKey} subHeader={replyTag()} />

View File

@ -1,28 +1,29 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap');
:root { :root {
--font-color: #fff; --font-color: #FFF;
--bg-color: #000; --bg-color: #000;
--modal-bg-color: rgba(0,0,0, 0.8); --modal-bg-color: rgba(0,0,0, 0.8);
--gray-superlight: #eee; --gray-superlight: #EEE;
--gray-light: #999; --gray-light: #999;
--gray-medium: #666; --gray-medium: #666;
--gray: #333; --gray: #333;
--gray-secondary: #222; --gray-secondary: #222;
--gray-tertiary: #444; --gray-tertiary: #444;
--highlight: #bada55; --highlight: #A9E000;
--error: red; --error: #FF6053;
--success: green; --success: #2AD544;
} }
@media (prefers-color-scheme: light) { @media (prefers-color-scheme: light) {
:root { :root {
--font-color: #000; --font-color: #000;
--bg-color: #fff; --bg-color: #FFF;
--highlight: #ff9900; --highlight: #FF9B00;
--gray: #ccc; --modal-bg-color: rgba(240, 240, 240, 0.8);
--gray-secondary: #ddd; --gray: #CCC;
--gray-tertiary: #eee; --gray-secondary: #DDD;
--gray-tertiary: #EEE;
--gray-superlight: #333; --gray-superlight: #333;
--gray-light: #555; --gray-light: #555;
} }
@ -75,6 +76,14 @@ code {
display: inline-block; display: inline-block;
} }
.btn-warn {
border-color: var(--error);
}
.btn-success {
border-color: var(--success);
}
.btn.active { .btn.active {
border: 2px solid; border: 2px solid;
background-color: var(--gray-secondary); background-color: var(--gray-secondary);
@ -265,3 +274,31 @@ body.scroll-lock {
.error { .error {
color: var(--error); color: var(--error);
} }
.root-tabs {
position: fixed;
bottom: -16px;
left: 0;
background-color: var(--modal-bg-color);
height: 44px;
width: 100vw;
padding: 0 2px;
align-items: center;
justify-content: flex-start;
}
.root-tab {
border-bottom: 3px solid var(--gray-secondary);
}
.root-tab.active {
border-bottom: 3px solid var(--highlight);
}
@media(min-width: 720px) {
.root-tabs {
position: initial;
width: 100%;
padding: 0;
background-color: transparent;
}
}

View File

@ -36,8 +36,18 @@
} }
.profile .website { .profile .website {
margin-bottom: 10px; padding-left: 0;
color: var(--highlight); color: var(--highlight);
margin-bottom: 2px;
}
.profile .lnurl {
padding-left: 0;
}
.profile .btn-icon {
padding: 2px 4px;
margin-left: 4px;
} }
.profile .website::before { .profile .website::before {
@ -45,20 +55,45 @@
font-size: 10px; font-size: 10px;
} }
.profile .lnurl::before {
content: '⚡️ ';
font-size: 10px;
}
@media(max-width: 720px) { @media(max-width: 720px) {
.profile { .profile {
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} }
.profile > div:last-child { .profile > div:last-child {
margin: 0; margin: 5px 0;
width: 100%; width: 100%;
} }
} }
@media(max-width: 420px) { @media(max-width: 360px) {
.profile .name { flex-direction: column; } .profile .name { flex-direction: column; }
.profile .name .btn { .profile .name .btn {
margin-top: 5px; margin-top: 5px;
} }
} }
.tabs {
display: flex;
justify-content: flex-start;
width: 100%;
margin: 10px 0;
}
.tabs > div {
margin-right: 0;
}
.tab {
margin: 0;
padding: 4px;
border-bottom: 3px solid var(--gray-secondary);
}
.tab.active {
border-bottom: 3px solid var(--highlight);
}

View File

@ -4,7 +4,7 @@ import Nostrich from "../nostrich.jpg";
import { useState } from "react"; import { useState } from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faQrcode } from "@fortawesome/free-solid-svg-icons"; import { faQrcode, faGear } from "@fortawesome/free-solid-svg-icons";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import useProfile from "../feed/ProfileFeed"; import useProfile from "../feed/ProfileFeed";
@ -36,22 +36,27 @@ export default function ProfilePage() {
{user?.nip05 && <Nip05 nip05={user.nip05} pubkey={user.pubkey} />} {user?.nip05 && <Nip05 nip05={user.nip05} pubkey={user.pubkey} />}
</div> </div>
<div> <div>
{isMe ? <div className="btn" onClick={() => navigate("/settings")}>Settings</div> : <FollowButton pubkey={id} />} {isMe ? (
<div className="btn btn-icon" onClick={() => navigate("/settings")}>
<FontAwesomeIcon icon={faGear} size="sm" />
</div>
) : <FollowButton pubkey={id} />
}
</div> </div>
</div> </div>
<p>{extractLinks([user?.about])}</p> <p>{extractLinks([user?.about])}</p>
{user?.website && ( {user?.website && (
<div className="website"> <div className="website f-ellipsis">
<a href={user.website} target="_blank" rel="noreferrer">{user.website}</a> <a href={user.website} target="_blank" rel="noreferrer">{user.website}</a>
</div> </div>
)} )}
{lnurl ? <div className="flex"> {lnurl ? <div className="lnurl f-ellipsis">
<div className="btn" onClick={(e) => setShowLnQr(true)}> {lnurl}
<FontAwesomeIcon icon={faQrcode} size="xl" /> <div className="btn btn-icon" onClick={(e) => setShowLnQr(true)}>
<FontAwesomeIcon icon={faQrcode} size="sm" />
</div> </div>
<div className="f-ellipsis">&nbsp; {lnurl}</div>
</div> : null} </div> : null}
<LNURLTip svc={lnurl} show={showLnQr} onClose={() => setShowLnQr(false)} /> <LNURLTip svc={lnurl} show={showLnQr} onClose={() => setShowLnQr(false)} />
</> </>
@ -70,10 +75,10 @@ export default function ProfilePage() {
</div> </div>
</div> </div>
<div className="tabs"> <div className="tabs">
<div className="btn active">Notes</div> <div className="tab f-1 active">Notes</div>
<div className="btn">Reactions</div> <div className="tab f-1">Reactions</div>
<div className="btn">Followers</div> <div className="tab f-1">Followers</div>
<div className="btn">Follows</div> <div className="tab f-1">Follows</div>
</div> </div>
<Timeline pubkeys={id} /> <Timeline pubkeys={id} />
</> </>

View File

@ -1,5 +1,4 @@
.root-tabs > div { .root-tabs > div {
padding: 5px 0; padding: 5px 0;
background-color: var(--gray); margin-right: 0;
border-radius: 10px;
} }

View File

@ -29,15 +29,12 @@ export default function RootPage() {
{pubKey ? <> {pubKey ? <>
<NoteCreator show={true}/> <NoteCreator show={true}/>
<div className="tabs root-tabs"> <div className="tabs root-tabs">
<div className={`f-1 ${tab === RootTab.Follows ? "active" : ""}`} onClick={() => setTab(RootTab.Follows)}> <div className={`root-tab f-1 ${tab === RootTab.Follows ? "active" : ""}`} onClick={() => setTab(RootTab.Follows)}>
Follows Follows
</div> </div>
<div className={`f-1 ${tab === RootTab.Global ? "active" : ""}`} onClick={() => setTab(RootTab.Global)}> <div className={`root-tab f-1 ${tab === RootTab.Global ? "active" : ""}`} onClick={() => setTab(RootTab.Global)}>
Global Global
</div> </div>
<div className="f-1">
Messages
</div>
</div></> : null} </div></> : null}
{followHints()} {followHints()}
<Timeline key={tab} pubkeys={follows} global={loggedOut || tab === RootTab.Global} /> <Timeline key={tab} pubkeys={follows} global={loggedOut || tab === RootTab.Global} />